Skip to content

Commit d722430

Browse files
authored
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 #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
1 parent 553d76a commit d722430

File tree

7 files changed

+139
-18
lines changed

7 files changed

+139
-18
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ Terraform version 0.10.3 or newer is required for this module to work.
221221
| redshift_subnet_tags | Additional tags for the redshift subnets | string | `<map>` | no |
222222
| redshift_subnets | A list of redshift subnets | list | `<list>` | no |
223223
| 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 |
224+
| secondary_cidr_blocks | List of secondary CIDR blocks to associate with the VPC to extend the IP Address pool | string | `<list>` | no |
224225
| 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 |
225226
| tags | A map of tags to add to all resources | string | `<map>` | no |
226227
| 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.
280281
| vpc_id | VPC |
281282
| vpc_instance_tenancy | Tenancy of instances spin up within VPC |
282283
| vpc_main_route_table_id | The ID of the main route table associated with this VPC |
284+
| vpc_secondary_cidr_blocks | List of secondary CIDR blocks of the VPC |
283285

284286
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
285287

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Simple VPC with secondary CIDR blocks
2+
3+
Configuration in this directory creates set of VPC resources across multiple CIDR blocks.
4+
5+
There is a public and private subnet created per availability zone in addition to single NAT Gateway shared between all 3 availability zones.
6+
7+
## Usage
8+
9+
To run this example you need to execute:
10+
11+
```bash
12+
$ terraform init
13+
$ terraform plan
14+
$ terraform apply
15+
```
16+
17+
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.
18+
19+
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
20+
21+
## Outputs
22+
23+
| Name | Description |
24+
|------|-------------|
25+
| nat_public_ips | NAT gateways |
26+
| private_subnets | Subnets |
27+
| public_subnets | List of IDs of public subnets |
28+
| vpc_cidr_block | CIDR blocks |
29+
| vpc_id | VPC |
30+
| vpc_secondary_cidr_blocks | List of secondary CIDR blocks of the VPC |
31+
32+
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
provider "aws" {
2+
region = "eu-west-1"
3+
}
4+
5+
module "vpc" {
6+
source = "../../"
7+
8+
name = "secondary-cidr-blocks-example"
9+
10+
cidr = "10.0.0.0/16"
11+
secondary_cidr_blocks = ["10.1.0.0/16", "10.2.0.0/16"]
12+
13+
azs = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
14+
private_subnets = ["10.0.1.0/24", "10.1.2.0/24", "10.2.3.0/24"]
15+
public_subnets = ["10.0.101.0/24", "10.1.102.0/24", "10.2.103.0/24"]
16+
17+
assign_generated_ipv6_cidr_block = true
18+
enable_nat_gateway = true
19+
single_nat_gateway = true
20+
21+
public_subnet_tags = {
22+
Name = "overridden-name-public"
23+
}
24+
25+
tags = {
26+
Owner = "user"
27+
Environment = "dev"
28+
}
29+
30+
vpc_tags = {
31+
Name = "vpc-name"
32+
}
33+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# VPC
2+
output "vpc_id" {
3+
description = "The ID of the VPC"
4+
value = "${module.vpc.vpc_id}"
5+
}
6+
7+
# CIDR blocks
8+
output "vpc_cidr_block" {
9+
description = "The CIDR block of the VPC"
10+
value = ["${module.vpc.vpc_cidr_block}"]
11+
}
12+
13+
output "vpc_secondary_cidr_blocks" {
14+
description = "List of secondary CIDR blocks of the VPC"
15+
value = ["${module.vpc.vpc_secondary_cidr_blocks}"]
16+
}
17+
18+
# Subnets
19+
output "private_subnets" {
20+
description = "List of IDs of private subnets"
21+
value = ["${module.vpc.private_subnets}"]
22+
}
23+
24+
output "public_subnets" {
25+
description = "List of IDs of public subnets"
26+
value = ["${module.vpc.public_subnets}"]
27+
}
28+
29+
# NAT gateways
30+
output "nat_public_ips" {
31+
description = "List of public Elastic IPs created for AWS NAT Gateway"
32+
value = ["${module.vpc.nat_public_ips}"]
33+
}

main.tf

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ terraform {
55
locals {
66
max_subnet_length = "${max(length(var.private_subnets), length(var.elasticache_subnets), length(var.database_subnets), length(var.redshift_subnets))}"
77
nat_gateway_count = "${var.single_nat_gateway ? 1 : (var.one_nat_gateway_per_az ? length(var.azs) : local.max_subnet_length)}"
8+
9+
# Use `local.vpc_id` to give a hint to Terraform that subnets should be deleted before secondary CIDR blocks can be free!
10+
vpc_id = "${element(concat(aws_vpc_ipv4_cidr_block_association.this.*.vpc_id, aws_vpc.this.*.id, list("")), 0)}"
811
}
912

1013
######
@@ -22,6 +25,14 @@ resource "aws_vpc" "this" {
2225
tags = "${merge(map("Name", format("%s", var.name)), var.vpc_tags, var.tags)}"
2326
}
2427

28+
resource "aws_vpc_ipv4_cidr_block_association" "this" {
29+
count = "${var.create_vpc && length(var.secondary_cidr_blocks) > 0 ? length(var.secondary_cidr_blocks) : 0}"
30+
31+
vpc_id = "${aws_vpc.this.id}"
32+
33+
cidr_block = "${element(var.secondary_cidr_blocks, count.index)}"
34+
}
35+
2536
###################
2637
# DHCP Options Set
2738
###################
@@ -43,7 +54,7 @@ resource "aws_vpc_dhcp_options" "this" {
4354
resource "aws_vpc_dhcp_options_association" "this" {
4455
count = "${var.create_vpc && var.enable_dhcp_options ? 1 : 0}"
4556

46-
vpc_id = "${aws_vpc.this.id}"
57+
vpc_id = "${local.vpc_id}"
4758
dhcp_options_id = "${aws_vpc_dhcp_options.this.id}"
4859
}
4960

@@ -53,7 +64,7 @@ resource "aws_vpc_dhcp_options_association" "this" {
5364
resource "aws_internet_gateway" "this" {
5465
count = "${var.create_vpc && length(var.public_subnets) > 0 ? 1 : 0}"
5566

56-
vpc_id = "${aws_vpc.this.id}"
67+
vpc_id = "${local.vpc_id}"
5768

5869
tags = "${merge(map("Name", format("%s", var.name)), var.igw_tags, var.tags)}"
5970
}
@@ -64,7 +75,7 @@ resource "aws_internet_gateway" "this" {
6475
resource "aws_route_table" "public" {
6576
count = "${var.create_vpc && length(var.public_subnets) > 0 ? 1 : 0}"
6677

67-
vpc_id = "${aws_vpc.this.id}"
78+
vpc_id = "${local.vpc_id}"
6879

6980
tags = "${merge(map("Name", format("%s-public", var.name)), var.public_route_table_tags, var.tags)}"
7081
}
@@ -88,7 +99,7 @@ resource "aws_route" "public_internet_gateway" {
8899
resource "aws_route_table" "private" {
89100
count = "${var.create_vpc && local.max_subnet_length > 0 ? local.nat_gateway_count : 0}"
90101

91-
vpc_id = "${aws_vpc.this.id}"
102+
vpc_id = "${local.vpc_id}"
92103

93104
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)}"
94105

@@ -105,7 +116,7 @@ resource "aws_route_table" "private" {
105116
resource "aws_route_table" "database" {
106117
count = "${var.create_vpc && var.create_database_subnet_route_table && length(var.database_subnets) > 0 ? 1 : 0}"
107118

108-
vpc_id = "${aws_vpc.this.id}"
119+
vpc_id = "${local.vpc_id}"
109120

110121
tags = "${merge(var.tags, var.database_route_table_tags, map("Name", "${var.name}-database"))}"
111122
}
@@ -116,7 +127,7 @@ resource "aws_route_table" "database" {
116127
resource "aws_route_table" "redshift" {
117128
count = "${var.create_vpc && var.create_redshift_subnet_route_table && length(var.redshift_subnets) > 0 ? 1 : 0}"
118129

119-
vpc_id = "${aws_vpc.this.id}"
130+
vpc_id = "${local.vpc_id}"
120131

121132
tags = "${merge(var.tags, var.redshift_route_table_tags, map("Name", "${var.name}-redshift"))}"
122133
}
@@ -127,7 +138,7 @@ resource "aws_route_table" "redshift" {
127138
resource "aws_route_table" "elasticache" {
128139
count = "${var.create_vpc && var.create_elasticache_subnet_route_table && length(var.elasticache_subnets) > 0 ? 1 : 0}"
129140

130-
vpc_id = "${aws_vpc.this.id}"
141+
vpc_id = "${local.vpc_id}"
131142

132143
tags = "${merge(var.tags, var.elasticache_route_table_tags, map("Name", "${var.name}-elasticache"))}"
133144
}
@@ -138,7 +149,7 @@ resource "aws_route_table" "elasticache" {
138149
resource "aws_route_table" "intra" {
139150
count = "${var.create_vpc && length(var.intra_subnets) > 0 ? 1 : 0}"
140151

141-
vpc_id = "${aws_vpc.this.id}"
152+
vpc_id = "${local.vpc_id}"
142153

143154
tags = "${merge(map("Name", "${var.name}-intra"), var.intra_route_table_tags, var.tags)}"
144155
}
@@ -149,7 +160,7 @@ resource "aws_route_table" "intra" {
149160
resource "aws_subnet" "public" {
150161
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}"
151162

152-
vpc_id = "${aws_vpc.this.id}"
163+
vpc_id = "${local.vpc_id}"
153164
cidr_block = "${var.public_subnets[count.index]}"
154165
availability_zone = "${element(var.azs, count.index)}"
155166
map_public_ip_on_launch = "${var.map_public_ip_on_launch}"
@@ -163,7 +174,7 @@ resource "aws_subnet" "public" {
163174
resource "aws_subnet" "private" {
164175
count = "${var.create_vpc && length(var.private_subnets) > 0 ? length(var.private_subnets) : 0}"
165176

166-
vpc_id = "${aws_vpc.this.id}"
177+
vpc_id = "${local.vpc_id}"
167178
cidr_block = "${var.private_subnets[count.index]}"
168179
availability_zone = "${element(var.azs, count.index)}"
169180

@@ -176,7 +187,7 @@ resource "aws_subnet" "private" {
176187
resource "aws_subnet" "database" {
177188
count = "${var.create_vpc && length(var.database_subnets) > 0 ? length(var.database_subnets) : 0}"
178189

179-
vpc_id = "${aws_vpc.this.id}"
190+
vpc_id = "${local.vpc_id}"
180191
cidr_block = "${var.database_subnets[count.index]}"
181192
availability_zone = "${element(var.azs, count.index)}"
182193

@@ -199,7 +210,7 @@ resource "aws_db_subnet_group" "database" {
199210
resource "aws_subnet" "redshift" {
200211
count = "${var.create_vpc && length(var.redshift_subnets) > 0 ? length(var.redshift_subnets) : 0}"
201212

202-
vpc_id = "${aws_vpc.this.id}"
213+
vpc_id = "${local.vpc_id}"
203214
cidr_block = "${var.redshift_subnets[count.index]}"
204215
availability_zone = "${element(var.azs, count.index)}"
205216

@@ -222,7 +233,7 @@ resource "aws_redshift_subnet_group" "redshift" {
222233
resource "aws_subnet" "elasticache" {
223234
count = "${var.create_vpc && length(var.elasticache_subnets) > 0 ? length(var.elasticache_subnets) : 0}"
224235

225-
vpc_id = "${aws_vpc.this.id}"
236+
vpc_id = "${local.vpc_id}"
226237
cidr_block = "${var.elasticache_subnets[count.index]}"
227238
availability_zone = "${element(var.azs, count.index)}"
228239

@@ -243,7 +254,7 @@ resource "aws_elasticache_subnet_group" "elasticache" {
243254
resource "aws_subnet" "intra" {
244255
count = "${var.create_vpc && length(var.intra_subnets) > 0 ? length(var.intra_subnets) : 0}"
245256

246-
vpc_id = "${aws_vpc.this.id}"
257+
vpc_id = "${local.vpc_id}"
247258
cidr_block = "${var.intra_subnets[count.index]}"
248259
availability_zone = "${element(var.azs, count.index)}"
249260

@@ -308,7 +319,7 @@ data "aws_vpc_endpoint_service" "s3" {
308319
resource "aws_vpc_endpoint" "s3" {
309320
count = "${var.create_vpc && var.enable_s3_endpoint ? 1 : 0}"
310321

311-
vpc_id = "${aws_vpc.this.id}"
322+
vpc_id = "${local.vpc_id}"
312323
service_name = "${data.aws_vpc_endpoint_service.s3.service_name}"
313324
}
314325

@@ -345,7 +356,7 @@ data "aws_vpc_endpoint_service" "dynamodb" {
345356
resource "aws_vpc_endpoint" "dynamodb" {
346357
count = "${var.create_vpc && var.enable_dynamodb_endpoint ? 1 : 0}"
347358

348-
vpc_id = "${aws_vpc.this.id}"
359+
vpc_id = "${local.vpc_id}"
349360
service_name = "${data.aws_vpc_endpoint_service.dynamodb.service_name}"
350361
}
351362

@@ -421,15 +432,15 @@ resource "aws_route_table_association" "public" {
421432
resource "aws_vpn_gateway" "this" {
422433
count = "${var.create_vpc && var.enable_vpn_gateway ? 1 : 0}"
423434

424-
vpc_id = "${aws_vpc.this.id}"
435+
vpc_id = "${local.vpc_id}"
425436

426437
tags = "${merge(map("Name", format("%s", var.name)), var.vpn_gateway_tags, var.tags)}"
427438
}
428439

429440
resource "aws_vpn_gateway_attachment" "this" {
430441
count = "${var.vpn_gateway_id != "" ? 1 : 0}"
431442

432-
vpc_id = "${aws_vpc.this.id}"
443+
vpc_id = "${local.vpc_id}"
433444
vpn_gateway_id = "${var.vpn_gateway_id}"
434445
}
435446

outputs.tf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ output "vpc_main_route_table_id" {
5959
// value = "${element(concat(aws_vpc.this.*.ipv6_cidr_block, list("")), 0)}"
6060
//}
6161

62+
output "vpc_secondary_cidr_blocks" {
63+
description = "List of secondary CIDR blocks of the VPC"
64+
value = ["${aws_vpc_ipv4_cidr_block_association.this.*.cidr_block}"]
65+
}
66+
6267
# Subnets
6368
output "private_subnets" {
6469
description = "List of IDs of private subnets"

variables.tf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ variable "assign_generated_ipv6_cidr_block" {
1818
default = false
1919
}
2020

21+
variable "secondary_cidr_blocks" {
22+
description = "List of secondary CIDR blocks to associate with the VPC to extend the IP Address pool"
23+
default = []
24+
}
25+
2126
variable "instance_tenancy" {
2227
description = "A tenancy option for instances launched into the VPC"
2328
default = "default"

0 commit comments

Comments
 (0)