Commit d7224309 authored by Anton Babenko's avatar Anton Babenko Committed by GitHub

Add secondary CIDR block support (#163)

* Add secondary CIDR block support using a local variable to derive the vpc id to ensure the CIDR block operations are applied before the CIDR operations

* Add secondary cidr block outputs to module output

* Add the wonderful examples from matthiasr's PR located at https://github.com/terraform-aws-modules/terraform-aws-vpc/pull/162 all credit goes to them for this wonderful example

* From copy and paste accidentally used variable name that differed from these variables

* Resolve typo in secondary_cidr_blocks

* Fixed README formatting

* Followups for #161

* Added local.vpc_id with description
parent 553d76ae
...@@ -221,6 +221,7 @@ Terraform version 0.10.3 or newer is required for this module to work. ...@@ -221,6 +221,7 @@ Terraform version 0.10.3 or newer is required for this module to work.
| redshift_subnet_tags | Additional tags for the redshift subnets | string | `<map>` | no | | redshift_subnet_tags | Additional tags for the redshift subnets | string | `<map>` | no |
| redshift_subnets | A list of redshift subnets | list | `<list>` | no | | redshift_subnets | A list of redshift subnets | list | `<list>` | no |
| reuse_nat_ips | Should be true if you don't want EIPs to be created for your NAT Gateways and will instead pass them in via the 'external_nat_ip_ids' variable | string | `false` | no | | reuse_nat_ips | Should be true if you don't want EIPs to be created for your NAT Gateways and will instead pass them in via the 'external_nat_ip_ids' variable | string | `false` | no |
| secondary_cidr_blocks | List of secondary CIDR blocks to associate with the VPC to extend the IP Address pool | string | `<list>` | no |
| single_nat_gateway | Should be true if you want to provision a single shared NAT Gateway across all of your private networks | string | `false` | no | | single_nat_gateway | Should be true if you want to provision a single shared NAT Gateway across all of your private networks | string | `false` | no |
| tags | A map of tags to add to all resources | string | `<map>` | no | | tags | A map of tags to add to all resources | string | `<map>` | no |
| vpc_tags | Additional tags for the VPC | string | `<map>` | no | | vpc_tags | Additional tags for the VPC | string | `<map>` | no |
...@@ -280,6 +281,7 @@ Terraform version 0.10.3 or newer is required for this module to work. ...@@ -280,6 +281,7 @@ Terraform version 0.10.3 or newer is required for this module to work.
| vpc_id | VPC | | vpc_id | VPC |
| vpc_instance_tenancy | Tenancy of instances spin up within VPC | | vpc_instance_tenancy | Tenancy of instances spin up within VPC |
| vpc_main_route_table_id | The ID of the main route table associated with this VPC | | vpc_main_route_table_id | The ID of the main route table associated with this VPC |
| vpc_secondary_cidr_blocks | List of secondary CIDR blocks of the VPC |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK --> <!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
......
# Simple VPC with secondary CIDR blocks
Configuration in this directory creates set of VPC resources across multiple CIDR blocks.
There is a public and private subnet created per availability zone in addition to single NAT Gateway shared between all 3 availability zones.
## Usage
To run this example you need to execute:
```bash
$ terraform init
$ terraform plan
$ terraform apply
```
Note that this example may create resources which can cost money (AWS Elastic IP, for example). Run `terraform destroy` when you don't need these resources.
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Outputs
| Name | Description |
|------|-------------|
| nat_public_ips | NAT gateways |
| private_subnets | Subnets |
| public_subnets | List of IDs of public subnets |
| vpc_cidr_block | CIDR blocks |
| vpc_id | VPC |
| vpc_secondary_cidr_blocks | List of secondary CIDR blocks of the VPC |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
provider "aws" {
region = "eu-west-1"
}
module "vpc" {
source = "../../"
name = "secondary-cidr-blocks-example"
cidr = "10.0.0.0/16"
secondary_cidr_blocks = ["10.1.0.0/16", "10.2.0.0/16"]
azs = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
private_subnets = ["10.0.1.0/24", "10.1.2.0/24", "10.2.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.1.102.0/24", "10.2.103.0/24"]
assign_generated_ipv6_cidr_block = true
enable_nat_gateway = true
single_nat_gateway = true
public_subnet_tags = {
Name = "overridden-name-public"
}
tags = {
Owner = "user"
Environment = "dev"
}
vpc_tags = {
Name = "vpc-name"
}
}
# VPC
output "vpc_id" {
description = "The ID of the VPC"
value = "${module.vpc.vpc_id}"
}
# CIDR blocks
output "vpc_cidr_block" {
description = "The CIDR block of the VPC"
value = ["${module.vpc.vpc_cidr_block}"]
}
output "vpc_secondary_cidr_blocks" {
description = "List of secondary CIDR blocks of the VPC"
value = ["${module.vpc.vpc_secondary_cidr_blocks}"]
}
# Subnets
output "private_subnets" {
description = "List of IDs of private subnets"
value = ["${module.vpc.private_subnets}"]
}
output "public_subnets" {
description = "List of IDs of public subnets"
value = ["${module.vpc.public_subnets}"]
}
# NAT gateways
output "nat_public_ips" {
description = "List of public Elastic IPs created for AWS NAT Gateway"
value = ["${module.vpc.nat_public_ips}"]
}
...@@ -5,6 +5,9 @@ terraform { ...@@ -5,6 +5,9 @@ terraform {
locals { locals {
max_subnet_length = "${max(length(var.private_subnets), length(var.elasticache_subnets), length(var.database_subnets), length(var.redshift_subnets))}" max_subnet_length = "${max(length(var.private_subnets), length(var.elasticache_subnets), length(var.database_subnets), length(var.redshift_subnets))}"
nat_gateway_count = "${var.single_nat_gateway ? 1 : (var.one_nat_gateway_per_az ? length(var.azs) : local.max_subnet_length)}" nat_gateway_count = "${var.single_nat_gateway ? 1 : (var.one_nat_gateway_per_az ? length(var.azs) : local.max_subnet_length)}"
# Use `local.vpc_id` to give a hint to Terraform that subnets should be deleted before secondary CIDR blocks can be free!
vpc_id = "${element(concat(aws_vpc_ipv4_cidr_block_association.this.*.vpc_id, aws_vpc.this.*.id, list("")), 0)}"
} }
###### ######
...@@ -22,6 +25,14 @@ resource "aws_vpc" "this" { ...@@ -22,6 +25,14 @@ resource "aws_vpc" "this" {
tags = "${merge(map("Name", format("%s", var.name)), var.vpc_tags, var.tags)}" tags = "${merge(map("Name", format("%s", var.name)), var.vpc_tags, var.tags)}"
} }
resource "aws_vpc_ipv4_cidr_block_association" "this" {
count = "${var.create_vpc && length(var.secondary_cidr_blocks) > 0 ? length(var.secondary_cidr_blocks) : 0}"
vpc_id = "${aws_vpc.this.id}"
cidr_block = "${element(var.secondary_cidr_blocks, count.index)}"
}
################### ###################
# DHCP Options Set # DHCP Options Set
################### ###################
...@@ -43,7 +54,7 @@ resource "aws_vpc_dhcp_options" "this" { ...@@ -43,7 +54,7 @@ resource "aws_vpc_dhcp_options" "this" {
resource "aws_vpc_dhcp_options_association" "this" { resource "aws_vpc_dhcp_options_association" "this" {
count = "${var.create_vpc && var.enable_dhcp_options ? 1 : 0}" count = "${var.create_vpc && var.enable_dhcp_options ? 1 : 0}"
vpc_id = "${aws_vpc.this.id}" vpc_id = "${local.vpc_id}"
dhcp_options_id = "${aws_vpc_dhcp_options.this.id}" dhcp_options_id = "${aws_vpc_dhcp_options.this.id}"
} }
...@@ -53,7 +64,7 @@ resource "aws_vpc_dhcp_options_association" "this" { ...@@ -53,7 +64,7 @@ resource "aws_vpc_dhcp_options_association" "this" {
resource "aws_internet_gateway" "this" { resource "aws_internet_gateway" "this" {
count = "${var.create_vpc && length(var.public_subnets) > 0 ? 1 : 0}" count = "${var.create_vpc && length(var.public_subnets) > 0 ? 1 : 0}"
vpc_id = "${aws_vpc.this.id}" vpc_id = "${local.vpc_id}"
tags = "${merge(map("Name", format("%s", var.name)), var.igw_tags, var.tags)}" tags = "${merge(map("Name", format("%s", var.name)), var.igw_tags, var.tags)}"
} }
...@@ -64,7 +75,7 @@ resource "aws_internet_gateway" "this" { ...@@ -64,7 +75,7 @@ resource "aws_internet_gateway" "this" {
resource "aws_route_table" "public" { resource "aws_route_table" "public" {
count = "${var.create_vpc && length(var.public_subnets) > 0 ? 1 : 0}" count = "${var.create_vpc && length(var.public_subnets) > 0 ? 1 : 0}"
vpc_id = "${aws_vpc.this.id}" vpc_id = "${local.vpc_id}"
tags = "${merge(map("Name", format("%s-public", var.name)), var.public_route_table_tags, var.tags)}" tags = "${merge(map("Name", format("%s-public", var.name)), var.public_route_table_tags, var.tags)}"
} }
...@@ -88,7 +99,7 @@ resource "aws_route" "public_internet_gateway" { ...@@ -88,7 +99,7 @@ resource "aws_route" "public_internet_gateway" {
resource "aws_route_table" "private" { resource "aws_route_table" "private" {
count = "${var.create_vpc && local.max_subnet_length > 0 ? local.nat_gateway_count : 0}" count = "${var.create_vpc && local.max_subnet_length > 0 ? local.nat_gateway_count : 0}"
vpc_id = "${aws_vpc.this.id}" vpc_id = "${local.vpc_id}"
tags = "${merge(map("Name", (var.single_nat_gateway ? "${var.name}-private" : format("%s-private-%s", var.name, element(var.azs, count.index)))), var.private_route_table_tags, var.tags)}" tags = "${merge(map("Name", (var.single_nat_gateway ? "${var.name}-private" : format("%s-private-%s", var.name, element(var.azs, count.index)))), var.private_route_table_tags, var.tags)}"
...@@ -105,7 +116,7 @@ resource "aws_route_table" "private" { ...@@ -105,7 +116,7 @@ resource "aws_route_table" "private" {
resource "aws_route_table" "database" { resource "aws_route_table" "database" {
count = "${var.create_vpc && var.create_database_subnet_route_table && length(var.database_subnets) > 0 ? 1 : 0}" count = "${var.create_vpc && var.create_database_subnet_route_table && length(var.database_subnets) > 0 ? 1 : 0}"
vpc_id = "${aws_vpc.this.id}" vpc_id = "${local.vpc_id}"
tags = "${merge(var.tags, var.database_route_table_tags, map("Name", "${var.name}-database"))}" tags = "${merge(var.tags, var.database_route_table_tags, map("Name", "${var.name}-database"))}"
} }
...@@ -116,7 +127,7 @@ resource "aws_route_table" "database" { ...@@ -116,7 +127,7 @@ resource "aws_route_table" "database" {
resource "aws_route_table" "redshift" { resource "aws_route_table" "redshift" {
count = "${var.create_vpc && var.create_redshift_subnet_route_table && length(var.redshift_subnets) > 0 ? 1 : 0}" count = "${var.create_vpc && var.create_redshift_subnet_route_table && length(var.redshift_subnets) > 0 ? 1 : 0}"
vpc_id = "${aws_vpc.this.id}" vpc_id = "${local.vpc_id}"
tags = "${merge(var.tags, var.redshift_route_table_tags, map("Name", "${var.name}-redshift"))}" tags = "${merge(var.tags, var.redshift_route_table_tags, map("Name", "${var.name}-redshift"))}"
} }
...@@ -127,7 +138,7 @@ resource "aws_route_table" "redshift" { ...@@ -127,7 +138,7 @@ resource "aws_route_table" "redshift" {
resource "aws_route_table" "elasticache" { resource "aws_route_table" "elasticache" {
count = "${var.create_vpc && var.create_elasticache_subnet_route_table && length(var.elasticache_subnets) > 0 ? 1 : 0}" count = "${var.create_vpc && var.create_elasticache_subnet_route_table && length(var.elasticache_subnets) > 0 ? 1 : 0}"
vpc_id = "${aws_vpc.this.id}" vpc_id = "${local.vpc_id}"
tags = "${merge(var.tags, var.elasticache_route_table_tags, map("Name", "${var.name}-elasticache"))}" tags = "${merge(var.tags, var.elasticache_route_table_tags, map("Name", "${var.name}-elasticache"))}"
} }
...@@ -138,7 +149,7 @@ resource "aws_route_table" "elasticache" { ...@@ -138,7 +149,7 @@ resource "aws_route_table" "elasticache" {
resource "aws_route_table" "intra" { resource "aws_route_table" "intra" {
count = "${var.create_vpc && length(var.intra_subnets) > 0 ? 1 : 0}" count = "${var.create_vpc && length(var.intra_subnets) > 0 ? 1 : 0}"
vpc_id = "${aws_vpc.this.id}" vpc_id = "${local.vpc_id}"
tags = "${merge(map("Name", "${var.name}-intra"), var.intra_route_table_tags, var.tags)}" tags = "${merge(map("Name", "${var.name}-intra"), var.intra_route_table_tags, var.tags)}"
} }
...@@ -149,7 +160,7 @@ resource "aws_route_table" "intra" { ...@@ -149,7 +160,7 @@ resource "aws_route_table" "intra" {
resource "aws_subnet" "public" { resource "aws_subnet" "public" {
count = "${var.create_vpc && length(var.public_subnets) > 0 && (!var.one_nat_gateway_per_az || length(var.public_subnets) >= length(var.azs)) ? length(var.public_subnets) : 0}" count = "${var.create_vpc && length(var.public_subnets) > 0 && (!var.one_nat_gateway_per_az || length(var.public_subnets) >= length(var.azs)) ? length(var.public_subnets) : 0}"
vpc_id = "${aws_vpc.this.id}" vpc_id = "${local.vpc_id}"
cidr_block = "${var.public_subnets[count.index]}" cidr_block = "${var.public_subnets[count.index]}"
availability_zone = "${element(var.azs, count.index)}" availability_zone = "${element(var.azs, count.index)}"
map_public_ip_on_launch = "${var.map_public_ip_on_launch}" map_public_ip_on_launch = "${var.map_public_ip_on_launch}"
...@@ -163,7 +174,7 @@ resource "aws_subnet" "public" { ...@@ -163,7 +174,7 @@ resource "aws_subnet" "public" {
resource "aws_subnet" "private" { resource "aws_subnet" "private" {
count = "${var.create_vpc && length(var.private_subnets) > 0 ? length(var.private_subnets) : 0}" count = "${var.create_vpc && length(var.private_subnets) > 0 ? length(var.private_subnets) : 0}"
vpc_id = "${aws_vpc.this.id}" vpc_id = "${local.vpc_id}"
cidr_block = "${var.private_subnets[count.index]}" cidr_block = "${var.private_subnets[count.index]}"
availability_zone = "${element(var.azs, count.index)}" availability_zone = "${element(var.azs, count.index)}"
...@@ -176,7 +187,7 @@ resource "aws_subnet" "private" { ...@@ -176,7 +187,7 @@ resource "aws_subnet" "private" {
resource "aws_subnet" "database" { resource "aws_subnet" "database" {
count = "${var.create_vpc && length(var.database_subnets) > 0 ? length(var.database_subnets) : 0}" count = "${var.create_vpc && length(var.database_subnets) > 0 ? length(var.database_subnets) : 0}"
vpc_id = "${aws_vpc.this.id}" vpc_id = "${local.vpc_id}"
cidr_block = "${var.database_subnets[count.index]}" cidr_block = "${var.database_subnets[count.index]}"
availability_zone = "${element(var.azs, count.index)}" availability_zone = "${element(var.azs, count.index)}"
...@@ -199,7 +210,7 @@ resource "aws_db_subnet_group" "database" { ...@@ -199,7 +210,7 @@ resource "aws_db_subnet_group" "database" {
resource "aws_subnet" "redshift" { resource "aws_subnet" "redshift" {
count = "${var.create_vpc && length(var.redshift_subnets) > 0 ? length(var.redshift_subnets) : 0}" count = "${var.create_vpc && length(var.redshift_subnets) > 0 ? length(var.redshift_subnets) : 0}"
vpc_id = "${aws_vpc.this.id}" vpc_id = "${local.vpc_id}"
cidr_block = "${var.redshift_subnets[count.index]}" cidr_block = "${var.redshift_subnets[count.index]}"
availability_zone = "${element(var.azs, count.index)}" availability_zone = "${element(var.azs, count.index)}"
...@@ -222,7 +233,7 @@ resource "aws_redshift_subnet_group" "redshift" { ...@@ -222,7 +233,7 @@ resource "aws_redshift_subnet_group" "redshift" {
resource "aws_subnet" "elasticache" { resource "aws_subnet" "elasticache" {
count = "${var.create_vpc && length(var.elasticache_subnets) > 0 ? length(var.elasticache_subnets) : 0}" count = "${var.create_vpc && length(var.elasticache_subnets) > 0 ? length(var.elasticache_subnets) : 0}"
vpc_id = "${aws_vpc.this.id}" vpc_id = "${local.vpc_id}"
cidr_block = "${var.elasticache_subnets[count.index]}" cidr_block = "${var.elasticache_subnets[count.index]}"
availability_zone = "${element(var.azs, count.index)}" availability_zone = "${element(var.azs, count.index)}"
...@@ -243,7 +254,7 @@ resource "aws_elasticache_subnet_group" "elasticache" { ...@@ -243,7 +254,7 @@ resource "aws_elasticache_subnet_group" "elasticache" {
resource "aws_subnet" "intra" { resource "aws_subnet" "intra" {
count = "${var.create_vpc && length(var.intra_subnets) > 0 ? length(var.intra_subnets) : 0}" count = "${var.create_vpc && length(var.intra_subnets) > 0 ? length(var.intra_subnets) : 0}"
vpc_id = "${aws_vpc.this.id}" vpc_id = "${local.vpc_id}"
cidr_block = "${var.intra_subnets[count.index]}" cidr_block = "${var.intra_subnets[count.index]}"
availability_zone = "${element(var.azs, count.index)}" availability_zone = "${element(var.azs, count.index)}"
...@@ -308,7 +319,7 @@ data "aws_vpc_endpoint_service" "s3" { ...@@ -308,7 +319,7 @@ data "aws_vpc_endpoint_service" "s3" {
resource "aws_vpc_endpoint" "s3" { resource "aws_vpc_endpoint" "s3" {
count = "${var.create_vpc && var.enable_s3_endpoint ? 1 : 0}" count = "${var.create_vpc && var.enable_s3_endpoint ? 1 : 0}"
vpc_id = "${aws_vpc.this.id}" vpc_id = "${local.vpc_id}"
service_name = "${data.aws_vpc_endpoint_service.s3.service_name}" service_name = "${data.aws_vpc_endpoint_service.s3.service_name}"
} }
...@@ -345,7 +356,7 @@ data "aws_vpc_endpoint_service" "dynamodb" { ...@@ -345,7 +356,7 @@ data "aws_vpc_endpoint_service" "dynamodb" {
resource "aws_vpc_endpoint" "dynamodb" { resource "aws_vpc_endpoint" "dynamodb" {
count = "${var.create_vpc && var.enable_dynamodb_endpoint ? 1 : 0}" count = "${var.create_vpc && var.enable_dynamodb_endpoint ? 1 : 0}"
vpc_id = "${aws_vpc.this.id}" vpc_id = "${local.vpc_id}"
service_name = "${data.aws_vpc_endpoint_service.dynamodb.service_name}" service_name = "${data.aws_vpc_endpoint_service.dynamodb.service_name}"
} }
...@@ -421,7 +432,7 @@ resource "aws_route_table_association" "public" { ...@@ -421,7 +432,7 @@ resource "aws_route_table_association" "public" {
resource "aws_vpn_gateway" "this" { resource "aws_vpn_gateway" "this" {
count = "${var.create_vpc && var.enable_vpn_gateway ? 1 : 0}" count = "${var.create_vpc && var.enable_vpn_gateway ? 1 : 0}"
vpc_id = "${aws_vpc.this.id}" vpc_id = "${local.vpc_id}"
tags = "${merge(map("Name", format("%s", var.name)), var.vpn_gateway_tags, var.tags)}" tags = "${merge(map("Name", format("%s", var.name)), var.vpn_gateway_tags, var.tags)}"
} }
...@@ -429,7 +440,7 @@ resource "aws_vpn_gateway" "this" { ...@@ -429,7 +440,7 @@ resource "aws_vpn_gateway" "this" {
resource "aws_vpn_gateway_attachment" "this" { resource "aws_vpn_gateway_attachment" "this" {
count = "${var.vpn_gateway_id != "" ? 1 : 0}" count = "${var.vpn_gateway_id != "" ? 1 : 0}"
vpc_id = "${aws_vpc.this.id}" vpc_id = "${local.vpc_id}"
vpn_gateway_id = "${var.vpn_gateway_id}" vpn_gateway_id = "${var.vpn_gateway_id}"
} }
......
...@@ -59,6 +59,11 @@ output "vpc_main_route_table_id" { ...@@ -59,6 +59,11 @@ output "vpc_main_route_table_id" {
// value = "${element(concat(aws_vpc.this.*.ipv6_cidr_block, list("")), 0)}" // value = "${element(concat(aws_vpc.this.*.ipv6_cidr_block, list("")), 0)}"
//} //}
output "vpc_secondary_cidr_blocks" {
description = "List of secondary CIDR blocks of the VPC"
value = ["${aws_vpc_ipv4_cidr_block_association.this.*.cidr_block}"]
}
# Subnets # Subnets
output "private_subnets" { output "private_subnets" {
description = "List of IDs of private subnets" description = "List of IDs of private subnets"
......
...@@ -18,6 +18,11 @@ variable "assign_generated_ipv6_cidr_block" { ...@@ -18,6 +18,11 @@ variable "assign_generated_ipv6_cidr_block" {
default = false default = false
} }
variable "secondary_cidr_blocks" {
description = "List of secondary CIDR blocks to associate with the VPC to extend the IP Address pool"
default = []
}
variable "instance_tenancy" { variable "instance_tenancy" {
description = "A tenancy option for instances launched into the VPC" description = "A tenancy option for instances launched into the VPC"
default = "default" default = "default"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment