Skip to content

Commit

Permalink
Merge pull request #45 from aws-ia/tgw
Browse files Browse the repository at this point in the history
Tgw
  • Loading branch information
drewmullen authored May 20, 2022
2 parents 16c01c1 + a977fd7 commit 0639b34
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 8 deletions.
9 changes: 9 additions & 0 deletions .tflint.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,12 @@ rule "terraform_standard_module_structure" {
rule "terraform_workspace_remote" {
enabled = true
}

# seems to be a bug when a resource is not created
rule "aws_route_not_specified_target" {
enabled = false
}

rule "aws_route_specified_multiple_targets" {
enabled = false
}
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,18 @@ The above example will cause only creating 2 new subnets in az `c` of the region
| [aws_internet_gateway.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/internet_gateway) | resource |
| [aws_nat_gateway.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/nat_gateway) | resource |
| [aws_route.private_to_nat](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource |
| [aws_route.private_to_tgw](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource |
| [aws_route.public_to_igw](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource |
| [aws_route.public_to_tgw](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource |
| [aws_route.tgw_to_nat](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource |
| [aws_subnet.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet) | resource |
| [aws_subnet.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet) | resource |
| [aws_subnet.tgw](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet) | resource |
| [aws_vpc.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc) | resource |
| [aws_vpc_ipv4_cidr_block_association.secondary](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipv4_cidr_block_association) | resource |
| [awscc_ec2_route_table.private](https://registry.terraform.io/providers/hashicorp/awscc/latest/docs/resources/ec2_route_table) | resource |
| [awscc_ec2_route_table.public](https://registry.terraform.io/providers/hashicorp/awscc/latest/docs/resources/ec2_route_table) | resource |
| [awscc_ec2_route_table.tgw](https://registry.terraform.io/providers/hashicorp/awscc/latest/docs/resources/ec2_route_table) | resource |
| [awscc_ec2_subnet_route_table_association.private](https://registry.terraform.io/providers/hashicorp/awscc/latest/docs/resources/ec2_subnet_route_table_association) | resource |
| [awscc_ec2_subnet_route_table_association.public](https://registry.terraform.io/providers/hashicorp/awscc/latest/docs/resources/ec2_subnet_route_table_association) | resource |
| [aws_availability_zones.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |
Expand Down Expand Up @@ -149,6 +153,7 @@ The above example will cause only creating 2 new subnets in az `c` of the region

| Name | Description |
|------|-------------|
| <a name="output_nat_gateways_by_az"></a> [nat\_gateways\_by\_az](#output\_nat\_gateways\_by\_az) | Map of nat gateway resource attributes by AZ. |
| <a name="output_private_subnet_attributes_by_az"></a> [private\_subnet\_attributes\_by\_az](#output\_private\_subnet\_attributes\_by\_az) | Map of all private subnets containing their attributes. |
| <a name="output_public_subnet_attributes_by_az"></a> [public\_subnet\_attributes\_by\_az](#output\_public\_subnet\_attributes\_by\_az) | Map of all public subnets containing their attributes. |
| <a name="output_route_table_by_subnet_type"></a> [route\_table\_by\_subnet\_type](#output\_route\_table\_by\_subnet\_type) | Map of route tables by type => az => route table attributes. Example usage: module.vpc.route\_table\_by\_subnet\_type.private.id |
Expand Down
2 changes: 1 addition & 1 deletion examples/ipam/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ No resources.
| Name | Description |
|------|-------------|
| <a name="output_subnets"></a> [subnets](#output\_subnets) | Map of subnet types with key/value az = cidr. |
<!-- END_TF_DOCS -->
<!-- END_TF_DOCS -->
2 changes: 1 addition & 1 deletion examples/private_only/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ No inputs.
|------|-------------|
| <a name="output_subnet_attributes"></a> [subnet\_attributes](#output\_subnet\_attributes) | n/a |
| <a name="output_subnets"></a> [subnets](#output\_subnets) | Map of subnet types with key/value az = cidr. |
<!-- END_TF_DOCS -->
<!-- END_TF_DOCS -->
2 changes: 1 addition & 1 deletion examples/public_only/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ No inputs.
| Name | Description |
|------|-------------|
| <a name="output_subnets"></a> [subnets](#output\_subnets) | Map of subnet types with key/value az = cidr. |
<!-- END_TF_DOCS -->
<!-- END_TF_DOCS -->
2 changes: 1 addition & 1 deletion examples/public_private_flow_logs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ No resources.
| Name | Description |
|------|-------------|
| <a name="output_subnets"></a> [subnets](#output\_subnets) | Map of subnet types with key/value az = cidr. |
<!-- END_TF_DOCS -->
<!-- END_TF_DOCS -->
2 changes: 1 addition & 1 deletion examples/secondary_cidr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ No inputs.
| Name | Description |
|------|-------------|
| <a name="output_secondary_subnets"></a> [secondary\_subnets](#output\_secondary\_subnets) | Map of subnet types with key/value az = cidr. |
<!-- END_TF_DOCS -->
<!-- END_TF_DOCS -->
19 changes: 17 additions & 2 deletions examples/transit_gateway/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,24 @@ module "vpc" {
az_count = 2

subnets = {
public = {
netmask = 24
nat_gateway_configuration = "single_az"
route_to_transit_gateway = ["10.1.0.0/16"]
}

private = {
netmask = 24
route_to_nat = true
route_to_transit_gateway = ["10.1.0.0/16"]
}

transit_gateway = {
netmask = 24
transit_gateway_id = aws_ec2_transit_gateway.example.id
netmask = 24
transit_gateway_id = aws_ec2_transit_gateway.example.id
route_to_nat = false
transit_gateway_default_route_table_association = true
transit_gateway_default_route_table_propagation = true
}
}
}
Expand Down
44 changes: 44 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,18 @@ resource "awscc_ec2_route_table" "private" {
)
}

resource "awscc_ec2_route_table" "tgw" {
for_each = try(local.subnets.transit_gateway, {})

vpc_id = local.vpc.id

tags = concat(
[{ "key" = "Name", "value" = "${local.subnet_names["transit_gateway"]}-${each.key}" }],
module.tags.tags
)
}


resource "awscc_ec2_route_table" "public" {
for_each = try(local.subnets.public, {})

Expand Down Expand Up @@ -150,6 +162,28 @@ resource "aws_route" "private_to_nat" {
nat_gateway_id = try(aws_nat_gateway.main[each.key].id, aws_nat_gateway.main[local.nat_configuration[0]].id)
}

resource "aws_route" "tgw_to_nat" {
# if `route_to_nat` exists & `true` apply to private subnets per az, else do not apply
for_each = try(var.subnets.transit_gateway.route_to_nat, false) ? try(local.subnets.public, {}) : {}

route_table_id = awscc_ec2_route_table.tgw[each.key].id
destination_cidr_block = "0.0.0.0/0"
# try to get nat for AZ, else use singular nat
nat_gateway_id = try(aws_nat_gateway.main[each.key].id, aws_nat_gateway.main[local.nat_configuration[0]].id)
}


resource "aws_route" "private_to_tgw" {
# TODO: move logic to locals once `route_to_transit_gateway` can accept more than 1 list item
for_each = try(var.subnets.private.route_to_transit_gateway, []) != [] ? toset([
for _, key in keys(local.subnets.private) : "${key}:${var.subnets.private.route_to_transit_gateway[0]}"
]) : toset([])

route_table_id = awscc_ec2_route_table.private[split(":", each.key)[0]].id
destination_cidr_block = var.subnets.private.route_to_transit_gateway[0]
transit_gateway_id = var.subnets.transit_gateway.transit_gateway_id
}

resource "aws_route" "public_to_igw" {
for_each = try(local.subnets.public, {})

Expand All @@ -158,6 +192,16 @@ resource "aws_route" "public_to_igw" {
gateway_id = aws_internet_gateway.main[0].id
}

resource "aws_route" "public_to_tgw" {
for_each = try(var.subnets.public.route_to_transit_gateway, []) != [] ? toset([
for _, key in keys(local.subnets.public) : "${key}:${var.subnets.public.route_to_transit_gateway[0]}"
]) : toset([])

route_table_id = awscc_ec2_route_table.public[split(":", each.key)[0]].id
destination_cidr_block = var.subnets.public.route_to_transit_gateway[0]
transit_gateway_id = var.subnets.transit_gateway.transit_gateway_id
}

resource "aws_ec2_transit_gateway_vpc_attachment" "tgw" {
count = contains(keys(local.subnets), "transit_gateway") ? 1 : 0

Expand Down
5 changes: 5 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,8 @@ output "route_table_by_subnet_type" {
"public" = awscc_ec2_route_table.public
}
}

output "nat_gateways_by_az" {
description = "Map of nat gateway resource attributes by AZ."
value = try(aws_nat_gateway.main, null)
}
15 changes: 14 additions & 1 deletion variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ variable "subnets" {
"netmask",
"name_prefix",
"nat_gateway_configuration",
"route_to_transit_gateway",
"tags"
])) == 0
}
Expand All @@ -118,6 +119,7 @@ variable "subnets" {
"netmask",
"name_prefix",
"route_to_nat",
"route_to_transit_gateway",
"tags"
])) == 0
}
Expand All @@ -129,6 +131,7 @@ variable "subnets" {
"cidrs",
"netmask",
"name_prefix",
"route_to_nat",
"transit_gateway_id",
"transit_gateway_default_route_table_association",
"transit_gateway_default_route_table_propagation",
Expand All @@ -155,6 +158,17 @@ variable "subnets" {
error_message = "Any subnet type `name_prefix` must not contain \"/\"."
condition = alltrue([for _, v in var.subnets : !can(regex("/", try(v.name_prefix, "")))])
}

validation {
error_message = "Private subnet cannot set `route_to_transit_gateway` = \"0.0.0.0/.\" if `route_to_nat` = true."
condition = try(var.subnets.private.route_to_nat, false) ? try(var.subnets.private.route_to_transit_gateway[0] != "0.0.0.0/0", true) : null
}

# TODO: remove once `route_to_transit_gateway` can accept more than 1 argument
validation {
error_message = "Argument `route_to_transit_gateway` cannot accept more than 1 string."
condition = try(length(var.subnets.private.route_to_transit_gateway), 0) <= 1 || try(length(var.subnets.public.route_to_transit_gateway), 0) <= 1
}
}

variable "tags" {
Expand All @@ -165,7 +179,6 @@ variable "tags" {

variable "vpc_flow_logs" {
description = "Whether or not to create VPC flow logs and which type. Options: \"cloudwatch\", \"s3\", \"none\". By default creates flow logs to `cloudwatch`. Variable overrides null value types for some keys, defined in defaults.tf."
nullable = false

type = object({
log_destination = optional(string)
Expand Down

0 comments on commit 0639b34

Please sign in to comment.