Skip to content

Commit

Permalink
Merge pull request #81 from aws-ia/f-secondarycidr-nat
Browse files Browse the repository at this point in the history
Feature allow `connect_to_natgw` for secondary invocations
  • Loading branch information
drewmullen authored Aug 17, 2022
2 parents e37c01f + e25bf8e commit b1d5277
Show file tree
Hide file tree
Showing 13 changed files with 155 additions and 45 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ Please see our [developer documentation](https://github.com/aws-ia/terraform-aws
| <a name="input_vpc_ipv4_ipam_pool_id"></a> [vpc\_ipv4\_ipam\_pool\_id](#input\_vpc\_ipv4\_ipam\_pool\_id) | Set to use IPAM to get CIDR block. | `string` | `null` | no |
| <a name="input_vpc_ipv4_netmask_length"></a> [vpc\_ipv4\_netmask\_length](#input\_vpc\_ipv4\_netmask\_length) | Set to use IPAM to get CIDR block using a specified netmask. Must be set with var.vpc\_ipv4\_ipam\_pool\_id. | `string` | `null` | no |
| <a name="input_vpc_secondary_cidr"></a> [vpc\_secondary\_cidr](#input\_vpc\_secondary\_cidr) | If `true` the module will create a `aws_vpc_ipv4_cidr_block_association` and subnets for that secondary cidr. If using IPAM for both primary and secondary CIDRs, you may only call this module serially (aka using `-target`, etc). | `bool` | `false` | no |
| <a name="input_vpc_secondary_cidr_natgw"></a> [vpc\_secondary\_cidr\_natgw](#input\_vpc\_secondary\_cidr\_natgw) | When invoking module for a secondary\_cidr attachment, you can map your private / tgw subnets to set of nat gateways by passing a map of az : { id: "nat-<id>"} | `any` | `{}` | no |

## Outputs

Expand Down
8 changes: 8 additions & 0 deletions data.tf
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,16 @@ locals {
}
# if public subnets being built, check how many nats to create
# options defined by `local.nat_options`
# nat_configuration is a list of az names where a nat should be created
nat_configuration = contains(local.subnet_keys, "public") ? local.nat_options[try(var.subnets.public.nat_gateway_configuration, "none")] : local.nat_options["none"]

# used to reference which nat gateway id should be used in route
nat_per_az = (contains(local.subnet_keys, "public") && !var.vpc_secondary_cidr) ? (
# map of az : { id = <nat-id> }, ex: { "us-east-1a" : { "id": "nat-123" }}
{ for az in local.azs : az => { id : try(aws_nat_gateway.main[az].id, aws_nat_gateway.main[local.nat_configuration[0]].id) } }
) : (
var.vpc_secondary_cidr ? var.vpc_secondary_cidr_natgw : {}
)

##################################################################
# Feature toggles for whether:
Expand Down
19 changes: 12 additions & 7 deletions examples/secondary_cidr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ No requirements.

## Providers

No providers.
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | n/a |

## Modules

Expand All @@ -25,16 +27,19 @@ No providers.

## Resources

No resources.
| Name | Type |
|------|------|
| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |

## Inputs

No inputs.
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_natgw_id_1"></a> [natgw\_id\_1](#input\_natgw\_id\_1) | nat gw id for az 2 | `string` | n/a | yes |
| <a name="input_natgw_id_2"></a> [natgw\_id\_2](#input\_natgw\_id\_2) | nat gw id for az 2 | `string` | n/a | yes |
| <a name="input_vpc_id"></a> [vpc\_id](#input\_vpc\_id) | vpc id to create secondary cidr on | `string` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_private_subnets"></a> [private\_subnets](#output\_private\_subnets) | Map of private subnet attributes grouped by az. |
| <a name="output_public_subnets"></a> [public\_subnets](#output\_public\_subnets) | Map of public subnet attributes grouped by az. |
No outputs.
<!-- END_TF_DOCS -->
50 changes: 23 additions & 27 deletions examples/secondary_cidr/main.tf
Original file line number Diff line number Diff line change
@@ -1,35 +1,31 @@
# To test this example, uncomment the module blocks for "vpc" and "ipam_base_for_example_only"
data "aws_region" "current" {}

module "secondary" {
source = "aws-ia/vpc/aws"
version = ">= 2.0.0"

name = "secondary-cidr"

vpc_secondary_cidr = true
vpc_id = module.vpc.vpc.id
vpc_ipv4_ipam_pool_id = module.ipam_base_for_example_only.pool_id
vpc_ipv4_netmask_length = 20
az_count = 2

name = "secondary-cidr"
az_count = 2
cidr_block = "10.2.0.0/16"

vpc_secondary_cidr = true
vpc_id = var.vpc_id

# If referencing another instantiation of this module, you can use the output nat_gateway_attributes_by_az, example:
# vpc_secondary_cidr_natgw = module.vpc.nat_gateway_attributes_by_az
vpc_secondary_cidr_natgw = {
"${data.aws_region.current.name}a" : {
id : var.natgw_id_1
}
"${data.aws_region.current.name}b" : {
id : var.natgw_id_2
}
}
subnets = {
private = { netmask = 24 }
private = {
name_prefix = "secondary-private-natgw-connected"
netmask = 18
connect_to_public_natgw = true
}
}
}

# module "ipam_base_for_example_only" {
# source = "../../test/hcl_fixtures/ipam_base"
# }

# module "vpc" {
# source = "aws-ia/vpc/aws"
# version = ">= 1.0.0"

# name = "multi-az-vpc"
# cidr_block = "10.0.0.0/16"
# az_count = 3

# subnets = {
# private = { netmask = 24 }
# }
# }
9 changes: 0 additions & 9 deletions examples/secondary_cidr/outputs.tf
Original file line number Diff line number Diff line change
@@ -1,9 +0,0 @@
output "public_subnets" {
description = "Map of public subnet attributes grouped by az."
value = module.secondary.public_subnet_cidrs_by_az
}

output "private_subnets" {
description = "Map of private subnet attributes grouped by az."
value = module.secondary.private_subnet_attributes_by_az
}
14 changes: 14 additions & 0 deletions examples/secondary_cidr/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
variable "vpc_id" {
description = "vpc id to create secondary cidr on"
type = string
}

variable "natgw_id_1" {
description = "nat gw id for az 2"
type = string
}

variable "natgw_id_2" {
description = "nat gw id for az 2"
type = string
}
6 changes: 4 additions & 2 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ resource "aws_route" "private_to_nat" {
route_table_id = awscc_ec2_route_table.private[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[split("/", each.key)[1]].id, aws_nat_gateway.main[local.nat_configuration[0]].id)
nat_gateway_id = local.nat_per_az[split("/", each.key)[1]].id
//try(aws_nat_gateway.main[split("/", each.key)[1]].id, aws_nat_gateway.main[local.nat_configuration[0]].id)
}

resource "aws_route" "private_to_tgw" {
Expand Down Expand Up @@ -225,7 +226,8 @@ resource "aws_route" "tgw_to_nat" {
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)
nat_gateway_id = local.nat_per_az[each.key].id
//try(aws_nat_gateway.main[each.key].id, aws_nat_gateway.main[local.nat_configuration[0]].id)
}

resource "aws_ec2_transit_gateway_vpc_attachment" "tgw" {
Expand Down
39 changes: 39 additions & 0 deletions test/examples_secondary_cidr_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package test

import (
"testing"

"github.com/gruntwork-io/terratest/modules/terraform"
)

func TestExamplesSecondaryCidr(t *testing.T) {

primary := &terraform.Options{
TerraformDir: "./hcl_fixtures/secondary_cidr_base",
}
defer terraform.Destroy(t, primary)
terraform.InitAndApply(t, primary)

// region := terraform.Output(t, primary, "region")
vpcId := terraform.Output(t, primary, "vpc_id")
natgwId1 := terraform.Output(t, primary, "natgw_id_1")
natgwId2 := terraform.Output(t, primary, "natgw_id_2")

terraformOptions := &terraform.Options{
TerraformDir: "../examples/secondary_cidr",
Vars: map[string]interface{}{
"vpc_id": vpcId,
"natgw_id_1": natgwId1,
"natgw_id_2": natgwId2,
// "natgw_attrs": map[string]interface{}{
// fmt.Sprintf("%v%v", region, "a"): natgwId1,
// fmt.Sprintf("%v%v", region, "b"): natgwId2,
// },
},
}

defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
terraform.ApplyAndIdempotent(t, terraformOptions)

}
22 changes: 22 additions & 0 deletions test/hcl_fixtures/secondary_cidr_base/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
data "aws_availability_zones" "current" {}

module "vpc" {
source = "aws-ia/vpc/aws"
version = ">= 2.0.0"

name = "primary-az-vpc"
cidr_block = "10.0.0.0/16"
az_count = 2

subnets = {
public = {
name_prefix = "primary-vpc-public" # omit to prefix with "public"
netmask = 24
nat_gateway_configuration = "all_azs" # options: "single_az", "none"
}
private = {
netmask = 24
connect_to_public_natgw = true
}
}
}
15 changes: 15 additions & 0 deletions test/hcl_fixtures/secondary_cidr_base/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
output "vpc_id" {
description = "vpc id"
value = module.vpc.vpc_attributes.id

}

output "natgw_id_1" {
value = module.vpc.nat_gateway_attributes_by_az[data.aws_availability_zones.current.names[0]].id
description = "nat gateway attributes"
}

output "natgw_id_2" {
value = module.vpc.nat_gateway_attributes_by_az[data.aws_availability_zones.current.names[1]].id
description = "nat gateway attributes"
}
11 changes: 11 additions & 0 deletions test/hcl_fixtures/secondary_cidr_base/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
terraform {
required_version = ">= 1.0.7"
experiments = [module_variable_optional_attrs]
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 3.72.0"
}
}
}

Empty file.
6 changes: 6 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ variable "vpc_secondary_cidr" {
default = false
}

variable "vpc_secondary_cidr_natgw" {
type = any
description = "When invoking module for a secondary_cidr attachment, you can map your private / tgw subnets to set of nat gateways by passing a map of az : { id: \"nat-<id>\"}"
default = {}
}

variable "vpc_enable_dns_support" {
type = bool
description = "Indicates whether the DNS resolution is supported for the VPC. If enabled, queries to the Amazon provided DNS server at the 169.254.169.253 IP address, or the reserved IP address at the base of the VPC network range \"plus two\" succeed. If disabled, the Amazon provided DNS service in the VPC that resolves public DNS hostnames to IP addresses is not enabled. Enabled by default."
Expand Down

0 comments on commit b1d5277

Please sign in to comment.