Skip to content

Commit

Permalink
Fix #120, implement #154
Browse files Browse the repository at this point in the history
  • Loading branch information
Nuru committed May 12, 2022
1 parent f3ce75d commit 0c54dcc
Show file tree
Hide file tree
Showing 8 changed files with 37 additions and 18 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ Available targets:
| <a name="input_label_value_case"></a> [label\_value\_case](#input\_label\_value\_case) | Controls the letter case of ID elements (labels) as included in `id`,<br>set as tag values, and output by this module individually.<br>Does not affect values of tags passed in via the `tags` input.<br>Possible values: `lower`, `title`, `upper` and `none` (no transformation).<br>Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs.<br>Default value: `lower`. | `string` | `null` | no |
| <a name="input_labels_as_tags"></a> [labels\_as\_tags](#input\_labels\_as\_tags) | Set of labels (ID elements) to include as tags in the `tags` output.<br>Default is to include all labels.<br>Tags with empty values will not be included in the `tags` output.<br>Set to `[]` to suppress all generated tags.<br>**Notes:**<br> The value of the `name` tag, if included, will be the `id`, not the `name`.<br> Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be<br> changed in later chained modules. Attempts to change it will be silently ignored. | `set(string)` | <pre>[<br> "default"<br>]</pre> | no |
| <a name="input_map_public_ip_on_launch"></a> [map\_public\_ip\_on\_launch](#input\_map\_public\_ip\_on\_launch) | If `true`, instances launched into a public subnet will be assigned a public IPv4 address | `bool` | `true` | no |
| <a name="input_max_nats"></a> [max\_nats](#input\_max\_nats) | Maximum number of NAT Gateways or NAT instances to create | `number` | `999` | no |
| <a name="input_max_subnet_count"></a> [max\_subnet\_count](#input\_max\_subnet\_count) | Sets the maximum number of each type (public or private) of subnet to deploy.<br>0 will reserve a CIDR for every Availability Zone (excluding Local Zones) in the region, and<br>deploy a subnet in each availability zone specified in `availability_zones` or `availability_zone_ids`,<br>or every zone if none are specified. We recommend setting this equal to the maximum number of AZs you anticipate using,<br>to avoid causing subnets to be destroyed and recreated with smaller IPv4 CIDRs when AWS adds an availability zone.<br>Due to Terraform limitations, you can not set `max_subnet_count` from a computed value, you have to set it<br>from an explicit constant. For most cases, `3` is a good choice. | `number` | `0` | no |
| <a name="input_metadata_http_endpoint_enabled"></a> [metadata\_http\_endpoint\_enabled](#input\_metadata\_http\_endpoint\_enabled) | Whether the metadata service is available on the created NAT instances | `bool` | `true` | no |
| <a name="input_metadata_http_put_response_hop_limit"></a> [metadata\_http\_put\_response\_hop\_limit](#input\_metadata\_http\_put\_response\_hop\_limit) | The desired HTTP PUT response hop limit (between 1 and 64) for instance metadata requests on the created NAT instances | `number` | `1` | no |
Expand Down
12 changes: 11 additions & 1 deletion docs/migration-v1-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,14 @@ Also, the default values have changed from `2m` and `5m` to `5m` and `10m` respe
### `root_block_device_encrypted`

For clarity, `root_block_device_encrypted` is deprecated in favor of
`nat_instance_root_block_device_encrypted`.
`nat_instance_root_block_device_encrypted`.

## Deprecated outputs

### `nat_gateway_public_ips`

This module now uses the same EIPs for both NAT Gateways and NAT instances, so
that switching from one to the other is possible without changing IPs.
Therefore the `nat_gateway_public_ips` output is deprecated in favor
of the `nat_ips` output.

1 change: 1 addition & 0 deletions docs/terraform.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
| <a name="input_label_value_case"></a> [label\_value\_case](#input\_label\_value\_case) | Controls the letter case of ID elements (labels) as included in `id`,<br>set as tag values, and output by this module individually.<br>Does not affect values of tags passed in via the `tags` input.<br>Possible values: `lower`, `title`, `upper` and `none` (no transformation).<br>Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs.<br>Default value: `lower`. | `string` | `null` | no |
| <a name="input_labels_as_tags"></a> [labels\_as\_tags](#input\_labels\_as\_tags) | Set of labels (ID elements) to include as tags in the `tags` output.<br>Default is to include all labels.<br>Tags with empty values will not be included in the `tags` output.<br>Set to `[]` to suppress all generated tags.<br>**Notes:**<br> The value of the `name` tag, if included, will be the `id`, not the `name`.<br> Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be<br> changed in later chained modules. Attempts to change it will be silently ignored. | `set(string)` | <pre>[<br> "default"<br>]</pre> | no |
| <a name="input_map_public_ip_on_launch"></a> [map\_public\_ip\_on\_launch](#input\_map\_public\_ip\_on\_launch) | If `true`, instances launched into a public subnet will be assigned a public IPv4 address | `bool` | `true` | no |
| <a name="input_max_nats"></a> [max\_nats](#input\_max\_nats) | Maximum number of NAT Gateways or NAT instances to create | `number` | `999` | no |
| <a name="input_max_subnet_count"></a> [max\_subnet\_count](#input\_max\_subnet\_count) | Sets the maximum number of each type (public or private) of subnet to deploy.<br>0 will reserve a CIDR for every Availability Zone (excluding Local Zones) in the region, and<br>deploy a subnet in each availability zone specified in `availability_zones` or `availability_zone_ids`,<br>or every zone if none are specified. We recommend setting this equal to the maximum number of AZs you anticipate using,<br>to avoid causing subnets to be destroyed and recreated with smaller IPv4 CIDRs when AWS adds an availability zone.<br>Due to Terraform limitations, you can not set `max_subnet_count` from a computed value, you have to set it<br>from an explicit constant. For most cases, `3` is a good choice. | `number` | `0` | no |
| <a name="input_metadata_http_endpoint_enabled"></a> [metadata\_http\_endpoint\_enabled](#input\_metadata\_http\_endpoint\_enabled) | Whether the metadata service is available on the created NAT instances | `bool` | `true` | no |
| <a name="input_metadata_http_put_response_hop_limit"></a> [metadata\_http\_put\_response\_hop\_limit](#input\_metadata\_http\_put\_response\_hop\_limit) | The desired HTTP PUT response hop limit (between 1 and 64) for instance metadata requests on the created NAT instances | `number` | `1` | no |
Expand Down
11 changes: 9 additions & 2 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ locals {
subnet_possible_availability_zones = local.az_option_map[local.subnet_availability_zone_option]

# Adjust list according to `max_subnet_count`
subnet_availability_zones = slice(local.subnet_possible_availability_zones, 0, var.max_subnet_count > 0 ? var.max_subnet_count : length(local.subnet_possible_availability_zones))
subnet_availability_zones = (
var.max_subnet_count == 0 || var.max_subnet_count >= length(local.subnet_possible_availability_zones)
) ? (
local.subnet_possible_availability_zones
) : slice(local.subnet_possible_availability_zones, 0, var.max_subnet_count)


subnet_az_count = local.e ? length(local.subnet_availability_zones) : 0
subnet_count = ((local.public_enabled ? 1 : 0) + (local.private_enabled ? 1 : 0)) * local.subnet_az_count
Expand Down Expand Up @@ -162,7 +167,9 @@ locals {

# A NAT device is needed to NAT from private IPv4 to public IPv4 or to perform NAT64 for IPv6,
# but since it must be placed in a public subnet, we consider it not required if we are not creating public subnets.
nat_required = local.public_enabled && (local.private4_enabled || local.public_dns64_enabled)
nat_required = local.public_enabled && (local.private4_enabled || local.public_dns64_enabled)
nat_count = min(local.subnet_az_count, var.max_nats)

nat_gateway_enabled = local.nat_required && var.nat_gateway_enabled
# An AWS NAT instance does not perform NAT64, and we choose not to try to support NAT64 via NAT instances at this time.
# It does not make sense to create both a NAT Gateway and a NAT instance, since they perform the same function
Expand Down
12 changes: 5 additions & 7 deletions nat-gateway.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module "nat_label" {
}

resource "aws_nat_gateway" "default" {
count = local.nat_gateway_enabled ? local.subnet_az_count : 0
count = local.nat_gateway_enabled ? local.nat_count : 0

allocation_id = local.nat_eip_allocations[count.index]
subnet_id = aws_subnet.public[count.index].id
Expand All @@ -20,16 +20,14 @@ resource "aws_nat_gateway" "default" {
}
)

lifecycle {
create_before_destroy = true
}
depends_on = [aws_eip_association.nat_instance]
}

resource "aws_route" "nat4" {
count = local.nat_gateway_enabled && local.ipv4_enabled ? local.private_route_table_count : 0

route_table_id = local.private_route_table_ids[count.index]
nat_gateway_id = aws_nat_gateway.default[count.index].id
nat_gateway_id = element(aws_nat_gateway.default.*.id, count.index)
destination_cidr_block = "0.0.0.0/0"
depends_on = [aws_route_table.private]

Expand All @@ -43,7 +41,7 @@ resource "aws_route" "private_nat64" {
count = local.nat_gateway_enabled && local.private_dns64_enabled ? local.private_route_table_count : 0

route_table_id = local.private_route_table_ids[count.index]
nat_gateway_id = aws_nat_gateway.default[count.index].id
nat_gateway_id = element(aws_nat_gateway.default.*.id, count.index)
destination_ipv6_cidr_block = local.nat64_cidr
depends_on = [aws_route_table.private]

Expand All @@ -57,7 +55,7 @@ resource "aws_route" "public_nat64" {
count = local.nat_gateway_enabled && local.public_dns64_enabled ? local.public_route_table_count : 0

route_table_id = local.public_route_table_ids[count.index]
nat_gateway_id = aws_nat_gateway.default[count.index].id
nat_gateway_id = element(aws_nat_gateway.default.*.id, count.index)
destination_ipv6_cidr_block = local.nat64_cidr
depends_on = [aws_route_table.public]

Expand Down
10 changes: 3 additions & 7 deletions nat-instance.tf
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ data "aws_ami" "nat_instance" {
# https://docs.aws.amazon.com/vpc/latest/userguide/VPC_NAT_Instance.html
# https://dzone.com/articles/nat-instance-vs-nat-gateway
resource "aws_instance" "nat_instance" {
count = local.nat_instance_enabled ? local.subnet_az_count : 0
count = local.nat_instance_enabled ? local.nat_count : 0

ami = local.nat_instance_ami_id
instance_type = var.nat_instance_type
Expand All @@ -96,10 +96,6 @@ resource "aws_instance" "nat_instance" {
#bridgecrew:skip=BC_AWS_LOGGING_26: Skipping requirement for detailed monitoring of NAT instance.
associate_public_ip_address = true #tfsec:ignore:AWS012

lifecycle {
create_before_destroy = true
}

metadata_options {
http_endpoint = var.metadata_http_endpoint_enabled ? "enabled" : "disabled"
http_put_response_hop_limit = var.metadata_http_put_response_hop_limit
Expand All @@ -122,7 +118,7 @@ resource "aws_instance" "nat_instance" {
}

resource "aws_eip_association" "nat_instance" {
count = local.nat_instance_enabled ? local.subnet_az_count : 0
count = local.nat_instance_enabled ? local.nat_count : 0

instance_id = aws_instance.nat_instance[count.index].id
allocation_id = local.nat_eip_allocations[count.index]
Expand All @@ -132,7 +128,7 @@ resource "aws_route" "nat_instance" {
count = local.nat_instance_enabled ? local.private_route_table_count : 0

route_table_id = local.private_route_table_ids[count.index]
network_interface_id = aws_instance.nat_instance[count.index].primary_network_interface_id
network_interface_id = element(aws_instance.nat_instance.*.primary_network_interface_id, count.index)
destination_cidr_block = "0.0.0.0/0"
depends_on = [aws_route_table.private]

Expand Down
2 changes: 1 addition & 1 deletion outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,4 @@ output "nat_ips" {
output "nat_eip_allocation_ids" {
description = "Elastic IP allocations in use by NAT"
value = local.nat_eip_allocations
}
}
6 changes: 6 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ variable "max_subnet_count" {
default = 0
}

variable "max_nats" {
type = number
description = "Maximum number of NAT Gateways or NAT instances to create"
default = 999
}

variable "private_subnets_enabled" {
type = bool
description = "If false, do not create private subnets (or NAT gateways or instances)"
Expand Down

0 comments on commit 0c54dcc

Please sign in to comment.