diff --git a/.header.md b/.header.md index 4b18f5a..8bddc14 100644 --- a/.header.md +++ b/.header.md @@ -12,7 +12,7 @@ module "vpc" { versions = ">= 1.0.0" name = "multi-az-vpc" - vpc_cidr_block = "10.0.0.0/20" + cidr_block = "10.0.0.0/20" az_count = 3 subnets = { @@ -47,7 +47,7 @@ Example: Changing from 2 azs to 3 Before: ```hcl -vpc_cidr_block = "10.0.0.0/16" +cidr_block = "10.0.0.0/16" az_count = 2 subnets = { @@ -63,7 +63,7 @@ subnets = { After: ```hcl -vpc_cidr_block = "10.0.0.0/16" +cidr_block = "10.0.0.0/16" az_count = 3 subnets = { diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 83b8bcc..1285e20 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,6 +5,6 @@ minimum_pre_commit_version: "2.6.0" repos: - repo: https://github.com/aws-ia/pre-commit-configs - rev: ce5b80d2643c3510bd17bb309cb767b6b21dc5ea # frozen: 1.4 + rev: 82b2dd4f3c3c8b064ce15c7cc518e14c43f6a068 # frozen: v1.4.1 hooks: - id: aws-ia-meta-hook diff --git a/README.md b/README.md index b990fee..46dde38 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ module "vpc" { versions = ">= 1.0.0" name = "multi-az-vpc" - vpc_cidr_block = "10.0.0.0/20" + cidr_block = "10.0.0.0/20" az_count = 3 subnets = { @@ -48,7 +48,7 @@ Example: Changing from 2 azs to 3 Before: ```hcl -vpc_cidr_block = "10.0.0.0/16" +cidr_block = "10.0.0.0/16" az_count = 2 subnets = { @@ -64,7 +64,7 @@ subnets = { After: ```hcl -vpc_cidr_block = "10.0.0.0/16" +cidr_block = "10.0.0.0/16" az_count = 3 subnets = { @@ -92,8 +92,8 @@ The above example will cause only creating 2 new subnets in az `c` of the region | Name | Version | |------|---------| -| [aws](#provider\_aws) | 4.8.0 | -| [awscc](#provider\_awscc) | 0.16.0 | +| [aws](#provider\_aws) | >= 3.72.0 | +| [awscc](#provider\_awscc) | >= 0.15.0 | ## Modules @@ -115,6 +115,7 @@ The above example will cause only creating 2 new subnets in az `c` of the region | [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_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_subnet_route_table_association.private](https://registry.terraform.io/providers/hashicorp/awscc/latest/docs/resources/ec2_subnet_route_table_association) | resource | @@ -130,8 +131,8 @@ The above example will cause only creating 2 new subnets in az `c` of the region | [az\_count](#input\_az\_count) | Searches region for # of AZs to use and takes a slice based on count. Assume slice is sorted a-z. | `number` | n/a | yes | | [name](#input\_name) | Name to give VPC. Note: does not effect subnet names, which get assigned name based on name\_prefix. | `string` | n/a | yes | | [subnets](#input\_subnets) | Configuration of subnets to build in VPC. Valid key restriction information found in variables.tf. | `any` | n/a | yes | +| [cidr\_block](#input\_cidr\_block) | CIDR range to assign to VPC if creating VPC or to associte as a secondary CIDR. Overridden by var.vpc\_id output from data.aws\_vpc. | `string` | `null` | no | | [tags](#input\_tags) | Tags to apply to all resources. | `map(string)` | `{}` | no | -| [vpc\_cidr\_block](#input\_vpc\_cidr\_block) | CIDR range to assign to VPC if creating VPC. Overridden by var.vpc\_id output from data.aws\_vpc. | `string` | `null` | no | | [vpc\_enable\_dns\_hostnames](#input\_vpc\_enable\_dns\_hostnames) | Indicates whether the instances launched in the VPC get DNS hostnames. If enabled, instances in the VPC get DNS hostnames; otherwise, they do not. Disabled by default for nondefault VPCs. | `bool` | `true` | no | | [vpc\_enable\_dns\_support](#input\_vpc\_enable\_dns\_support) | 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. | `bool` | `true` | no | | [vpc\_flow\_logs](#input\_vpc\_flow\_logs) | 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. |
object({|
log_destination = optional(string)
iam_role_arn = optional(string)
kms_key_id = optional(string)
log_destination_type = string
retention_in_days = optional(number)
tags = optional(map(string))
traffic_type = optional(string)
destination_options = optional(object({
file_format = optional(string)
hive_compatible_partitions = optional(bool)
per_hour_partition = optional(bool)
}))
})
{| no | @@ -139,11 +140,12 @@ The above example will cause only creating 2 new subnets in az `c` of the region | [vpc\_instance\_tenancy](#input\_vpc\_instance\_tenancy) | The allowed tenancy of instances launched into the VPC. | `string` | `"default"` | no | | [vpc\_ipv4\_ipam\_pool\_id](#input\_vpc\_ipv4\_ipam\_pool\_id) | Set to use IPAM to get CIDR block. | `string` | `null` | no | | [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 | +| [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 | ## Outputs | Name | Description | |------|-------------| | [subnets](#output\_subnets) | Subnets grouped by type. | -| [vpc\_id](#output\_vpc\_id) | VPC Information | +| [vpc](#output\_vpc) | VPC Resource Information. Full output of aws\_vpc. | \ No newline at end of file diff --git a/data.tf b/data.tf index 17279b9..9332fea 100644 --- a/data.tf +++ b/data.tf @@ -21,19 +21,19 @@ locals { nat_configuration = contains(keys(local.subnets), "public") ? local.nat_options[try(var.subnets.public.nat_gateway_configuration, "none")] : local.nat_options["none"] # # if var.vpc_id is passed, assume create = `false` and cidr comes from data.aws_vpc - create_vpc = var.vpc_id == null ? true : false - vpc = local.create_vpc ? aws_vpc.main[0] : data.awscc_ec2_vpc.main[0] - vpc_cidr_block = var.vpc_ipv4_ipam_pool_id == null ? var.vpc_cidr_block : data.aws_vpc_ipam_preview_next_cidr.main[0].cidr + create_vpc = var.vpc_id == null ? true : false + vpc = local.create_vpc ? aws_vpc.main[0] : data.awscc_ec2_vpc.main[0] + /* + vpc = local.create_vpc ? aws_vpc.main[0] : ( + var.vpc_secondary_cidr ? aws_vpc_ipv4_cidr_block_association.secondary[0] : data.awscc_ec2_vpc.main[0] + ) + */ + cidr_block = var.vpc_ipv4_ipam_pool_id == null ? var.cidr_block : data.aws_vpc_ipam_preview_next_cidr.main[0].cidr create_flow_logs = (var.vpc_flow_logs == null || var.vpc_flow_logs.log_destination_type == "none") ? false : true } -data "aws_availability_zones" "current" { - filter { - name = "opt-in-status" - values = ["opt-in-not-required"] - } -} +data "aws_availability_zones" "current" {} # search for existing vpc with var.vpc_id if not creating data "awscc_ec2_vpc" "main" { diff --git a/examples/ipam/.header.md b/examples/ipam/.header.md index e69de29..3c582e0 100644 --- a/examples/ipam/.header.md +++ b/examples/ipam/.header.md @@ -0,0 +1,3 @@ +# Create VPC with a CIDR from AWS IPAM + +This example builds a VPC with a CIDR block from AWS IPAM. It builds public and private subnets in 3 availability zones, creates a nat gateway in each AZ and appropriately routes from each private to the nat gateway. diff --git a/examples/ipam/README.md b/examples/ipam/README.md index 1b539f9..249a093 100644 --- a/examples/ipam/README.md +++ b/examples/ipam/README.md @@ -1,4 +1,8 @@ +# Create VPC with a CIDR from AWS IPAM + +This example builds a VPC with a CIDR block from AWS IPAM. It builds public and private subnets in 3 availability zones, creates a nat gateway in each AZ and appropriately routes from each private to the nat gateway. + ## Requirements No requirements. diff --git a/examples/ipam/main.tf b/examples/ipam/main.tf index 7eed79e..624b4db 100644 --- a/examples/ipam/main.tf +++ b/examples/ipam/main.tf @@ -1,5 +1,4 @@ module "vpc" { - # source = "../.." source = "aws-ia/vpc/aws" version = ">= 1.0.0" diff --git a/examples/private_only/.header.md b/examples/private_only/.header.md index e69de29..548f614 100644 --- a/examples/private_only/.header.md +++ b/examples/private_only/.header.md @@ -0,0 +1,3 @@ +# Create VPC with private subnets + +This example builds a VPC with private subnets in 3 availability zones diff --git a/examples/private_only/README.md b/examples/private_only/README.md index 7546c36..8657df4 100644 --- a/examples/private_only/README.md +++ b/examples/private_only/README.md @@ -1,4 +1,8 @@ +# Create VPC with private subnets + +This example builds a VPC with private subnets in 3 availability zones + ## Requirements No requirements. diff --git a/examples/private_only/main.tf b/examples/private_only/main.tf index cd41478..bbcc636 100644 --- a/examples/private_only/main.tf +++ b/examples/private_only/main.tf @@ -2,9 +2,9 @@ module "vpc" { source = "aws-ia/vpc/aws" version = ">= 1.0.0" - name = "multi-az-vpc" - vpc_cidr_block = "10.0.0.0/20" - az_count = 3 + name = "multi-az-vpc" + cidr_block = "10.0.0.0/20" + az_count = 3 subnets = { private = { netmask = 24 } diff --git a/examples/public_only/.header.md b/examples/public_only/.header.md index e69de29..e1ad024 100644 --- a/examples/public_only/.header.md +++ b/examples/public_only/.header.md @@ -0,0 +1,3 @@ +# Create VPC with public subnets + +This example builds a VPC with public subnets in 3 availability zones. It creates an internet gateway and appropriately routes subnet traffic from "0.0.0.0/0" to the IGW. diff --git a/examples/public_only/README.md b/examples/public_only/README.md index 7546c36..4de4421 100644 --- a/examples/public_only/README.md +++ b/examples/public_only/README.md @@ -1,4 +1,8 @@ +# Create VPC with public subnets + +This example builds a VPC with public subnets in 3 availability zones. It creates an internet gateway and appropriately routes subnet traffic from "0.0.0.0/0" to the IGW. + ## Requirements No requirements. diff --git a/examples/public_only/main.tf b/examples/public_only/main.tf index b16fb80..1807d4a 100644 --- a/examples/public_only/main.tf +++ b/examples/public_only/main.tf @@ -2,17 +2,14 @@ module "vpc" { source = "aws-ia/vpc/aws" version = ">= 1.0.0" - name = "multi-az-vpc" - vpc_cidr_block = "10.0.0.0/20" - az_count = 3 + name = "multi-az-vpc" + cidr_block = "10.0.0.0/20" + az_count = 3 subnets = { public = { - name_prefix = "my-public" # omit to prefix with "public" - netmask = 24 - nat_gateway_configuration = "all_azs" # options: "single_az", "none" + name_prefix = "my-public" # omit to prefix with "public" + netmask = 24 } } - - } diff --git a/examples/public_private_flow_logs/.header.md b/examples/public_private_flow_logs/.header.md index e69de29..374b518 100644 --- a/examples/public_private_flow_logs/.header.md +++ b/examples/public_private_flow_logs/.header.md @@ -0,0 +1,5 @@ +# Create VPC flow logs + +This example builds a VPC with public and private subnets in 3 availability zones, creates a nat gateway in each AZ and appropriately routes from each private to the nat gateway. It creates an internet gateway and appropriately routes subnet traffic from "0.0.0.0/0" to the IGW. It creates encrypted VPC Flow Logs that are sent to cloud-watch and retained for 180 days. + +At this point, only cloud-watch logs are support, pending: https://github.com/aws-ia/terraform-aws-vpc/issues/35 diff --git a/examples/public_private_flow_logs/README.md b/examples/public_private_flow_logs/README.md index bdbcb16..2aa3aac 100644 --- a/examples/public_private_flow_logs/README.md +++ b/examples/public_private_flow_logs/README.md @@ -1,4 +1,10 @@ +# Create VPC flow logs + +This example builds a VPC with public and private subnets in 3 availability zones, creates a nat gateway in each AZ and appropriately routes from each private to the nat gateway. It creates an internet gateway and appropriately routes subnet traffic from "0.0.0.0/0" to the IGW. It creates encrypted VPC Flow Logs that are sent to cloud-watch and retained for 180 days. + +At this point, only cloud-watch logs are support, pending: https://github.com/aws-ia/terraform-aws-vpc/issues/35 + ## Requirements No requirements. @@ -11,7 +17,7 @@ No providers. | Name | Source | Version | |------|--------|---------| -| [vpc](#module\_vpc) | aws-ia/vpc/aws | >= 1.0.0 | +| [vpc](#module\_vpc) | ../.. | n/a | ## Resources diff --git a/examples/public_private_flow_logs/main.tf b/examples/public_private_flow_logs/main.tf index d5e1d5b..8f5ed48 100644 --- a/examples/public_private_flow_logs/main.tf +++ b/examples/public_private_flow_logs/main.tf @@ -1,10 +1,11 @@ module "vpc" { - source = "aws-ia/vpc/aws" - version = ">= 1.0.0" + # source = "aws-ia/vpc/aws" + # version = ">= 1.0.0" + source = "../.." - name = "multi-az-vpc" - vpc_cidr_block = "10.0.0.0/20" - az_count = 3 + name = "multi-az-vpc" + cidr_block = "10.0.0.0/20" + az_count = 3 subnets = { public = { diff --git a/examples/secondary_cidr/.header.md b/examples/secondary_cidr/.header.md new file mode 100644 index 0000000..9f2caa3 --- /dev/null +++ b/examples/secondary_cidr/.header.md @@ -0,0 +1,9 @@ +# Adding secondary CIDRs to pre-existing VPCs + +This example shows how you can use this module to apply a secondary CIDR to a pre-existing VPC. + +Note: If using IPAM, you can only build 1 secondary CIDR at a time. One method to do that is to use `-target`. Using the example you would uncomment the "vpc" and "ipam_base_for_example_only" modules then: + +1. terraform init +1. terraform apply -target module.vpc -target module.ipam_base_for_example_only +1. terraform apply -target module.secondary diff --git a/examples/secondary_cidr/README.md b/examples/secondary_cidr/README.md new file mode 100644 index 0000000..837ca5a --- /dev/null +++ b/examples/secondary_cidr/README.md @@ -0,0 +1,39 @@ + +# Adding secondary CIDRs to pre-existing VPCs + +This example shows how you can use this module to apply a secondary CIDR to a pre-existing VPC. + +Note: If using IPAM, you can only build 1 secondary CIDR at a time. One method to do that is to use `-target`. Using the example you would uncomment the "vpc" and "ipam\_base\_for\_example\_only" modules then: + +1. terraform init +1. terraform apply -target module.vpc -target module.ipam\_base\_for\_example\_only +1. terraform apply -target module.secondary + +## Requirements + +No requirements. + +## Providers + +No providers. + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [secondary](#module\_secondary) | aws-ia/vpc/aws | >= 1.0.0 | + +## Resources + +No resources. + +## Inputs + +No inputs. + +## Outputs + +| Name | Description | +|------|-------------| +| [secondary\_subnets](#output\_secondary\_subnets) | Map of subnet types with key/value az = cidr. | + \ No newline at end of file diff --git a/examples/secondary_cidr/main.tf b/examples/secondary_cidr/main.tf new file mode 100644 index 0000000..53e0a0b --- /dev/null +++ b/examples/secondary_cidr/main.tf @@ -0,0 +1,35 @@ +# To test this example, uncomment the module blocks for "vpc" and "ipam_base_for_example_only" + +module "secondary" { + source = "aws-ia/vpc/aws" + version = ">= 1.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 + + subnets = { + private = { netmask = 24 } + } +} + +# 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 } +# } +# } diff --git a/examples/secondary_cidr/outputs.tf b/examples/secondary_cidr/outputs.tf new file mode 100644 index 0000000..0ab51a4 --- /dev/null +++ b/examples/secondary_cidr/outputs.tf @@ -0,0 +1,4 @@ +output "secondary_subnets" { + description = "Map of subnet types with key/value az = cidr." + value = module.secondary.subnets +} diff --git a/examples/secondary_cidr/variables.tf b/examples/secondary_cidr/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/main.tf b/main.tf index f0acdf7..b59a486 100644 --- a/main.tf +++ b/main.tf @@ -1,7 +1,7 @@ module "calculate_subnets" { source = "./modules/calculate_subnets" - cidr = local.vpc.cidr_block + cidr = local.cidr_block azs = local.azs subnets = var.subnets @@ -10,7 +10,7 @@ module "calculate_subnets" { resource "aws_vpc" "main" { count = local.create_vpc ? 1 : 0 - cidr_block = local.vpc_cidr_block + cidr_block = local.cidr_block enable_dns_hostnames = var.vpc_enable_dns_hostnames enable_dns_support = var.vpc_enable_dns_support instance_tenancy = var.vpc_instance_tenancy @@ -22,6 +22,14 @@ resource "aws_vpc" "main" { module.tags.tags_aws) } +resource "aws_vpc_ipv4_cidr_block_association" "secondary" { + count = (var.vpc_secondary_cidr && !local.create_vpc) ? 1 : 0 + + vpc_id = var.vpc_id + cidr_block = local.cidr_block + ipv4_ipam_pool_id = var.vpc_ipv4_ipam_pool_id +} + resource "aws_subnet" "private" { for_each = try(local.subnets.private, {}) @@ -33,6 +41,10 @@ resource "aws_subnet" "private" { tags = merge({ Name = "${local.subnet_names["private"]}-${each.key}" }, module.tags.tags_aws) + + depends_on = [ + aws_vpc_ipv4_cidr_block_association.secondary + ] } resource "aws_subnet" "public" { @@ -64,7 +76,7 @@ resource "awscc_ec2_route_table" "public" { vpc_id = local.vpc.id tags = concat( - [{ "key" = "Name", "value" = "${local.subnet_names["public"]}}-${each.key}" }], + [{ "key" = "Name", "value" = "${local.subnet_names["public"]}-${each.key}" }], module.tags.tags ) } diff --git a/outputs.tf b/outputs.tf index 59b08fc..4afbe17 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,5 +1,5 @@ -output "vpc_id" { - description = "VPC Information" +output "vpc" { + description = "VPC Resource Information. Full output of aws_vpc." value = local.vpc } diff --git a/providers.tf b/providers.tf index 38e87ad..53df74f 100644 --- a/providers.tf +++ b/providers.tf @@ -12,11 +12,3 @@ terraform { } } } - -provider "awscc" { - user_agent = [{ - product_name = "terraform-awscc-vpc" - product_version = "0.0.1" - comment = "V1/AWS-D69B4015/376222146" - }] -} diff --git a/test/hcl_fixtures/ipam_base/main.tf b/test/hcl_fixtures/ipam_base/main.tf index 27e128a..d6e9f11 100644 --- a/test/hcl_fixtures/ipam_base/main.tf +++ b/test/hcl_fixtures/ipam_base/main.tf @@ -4,12 +4,12 @@ module "ipam" { source = "aws-ia/ipam/aws" version = ">= 1.0.0" - top_cidr = ["10.0.0.0/8"] + top_cidr = ["172.0.0.0/8"] pool_configurations = { "${data.aws_region.current.name}" = { description = "${data.aws_region.current.name} top level pool" - cidr = ["10.0.0.0/16"] + cidr = ["172.2.0.0/16"] locale = data.aws_region.current.name } } diff --git a/variables.tf b/variables.tf index c2d1d2e..dfbcf9b 100644 --- a/variables.tf +++ b/variables.tf @@ -3,8 +3,8 @@ variable "name" { description = "Name to give VPC. Note: does not effect subnet names, which get assigned name based on name_prefix." } -variable "vpc_cidr_block" { - description = "CIDR range to assign to VPC if creating VPC. Overridden by var.vpc_id output from data.aws_vpc." +variable "cidr_block" { + description = "CIDR range to assign to VPC if creating VPC or to associte as a secondary CIDR. Overridden by var.vpc_id output from data.aws_vpc." default = null type = string @@ -27,6 +27,12 @@ variable "vpc_enable_dns_hostnames" { default = true } +variable "vpc_secondary_cidr" { + type = bool + description = "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)." + default = false +} + 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."
"log_destination_type": "none"
}