Skip to content

Commit 5e88357

Browse files
committed
rm ipam_netmask options, add docs
1 parent ee37b06 commit 5e88357

File tree

5 files changed

+110
-65
lines changed

5 files changed

+110
-65
lines changed

README.md

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,54 @@ Sometimes it is handy to have public access to Redshift clusters (for example if
179179

180180
It is possible to integrate this VPC module with [terraform-aws-transit-gateway module](https://github.com/terraform-aws-modules/terraform-aws-transit-gateway) which handles the creation of TGW resources and VPC attachments. See [complete example there](https://github.com/terraform-aws-modules/terraform-aws-transit-gateway/tree/master/examples/complete).
181181

182+
## VPC CIDR from AWS IP Address Manager (IPAM)
183+
184+
It is possible to have your VPC CIDR assigned from an [AWS IPAM Pool](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipam_pool). However, In order to build subnets within this module Terraform must know subnet CIDRs to properly plan the amount of resources to build. Since CIDR is derived by IPAM by calling CreateVpc this is not possible within a module unless cidr is known ahead of time. You can get around this by "previewing" the CIDR and then using that as the subnet values.
185+
186+
_Note: Due to race conditions with `terraform plan`, it is not possible to use `ipv4_netmask_length` or a pools `allocation_default_netmask_length` within this module. You must explicitly set the CIDRs for a pool to use._
187+
188+
```hcl
189+
# Find the pool RAM shared to your account
190+
# Info on RAM sharing pools: https://docs.aws.amazon.com/vpc/latest/ipam/share-pool-ipam.html
191+
data "aws_vpc_ipam_pool" "ipv4_example" {
192+
filter {
193+
name = "description"
194+
values = ["*mypool*"]
195+
}
196+
197+
filter {
198+
name = "address-family"
199+
values = ["ipv4"]
200+
}
201+
}
202+
203+
# Preview next CIDR from pool
204+
data "aws_vpc_ipam_preview_next_cidr" "previewed_cidr" {
205+
ipam_pool_id = data.aws_vpc_ipam_pool.ipv4_example.id
206+
netmask_length = 24
207+
}
208+
209+
data "aws_region" "current" {}
210+
211+
# Calculate subnet cidrs from previewed IPAM CIDR
212+
locals {
213+
partition = cidrsubnets(data.aws_vpc_ipam_preview_next_cidr.previewed_cidr.cidr, 2, 2)
214+
private_subnets = cidrsubnets(local.partition[0], 2, 2)
215+
public_subnets = cidrsubnets(local.partition[1], 2, 2)
216+
azs = formatlist("${data.aws_region.current.name}%s", ["a", "b"])
217+
}
218+
219+
module "vpc_cidr_from_ipam" {
220+
source = "../.."
221+
name = "vpc-cidr-from-ipam"
222+
ipv4_ipam_pool_id = data.aws_vpc_ipam_pool.ipv4_example.id
223+
azs = local.azs
224+
cidr = data.aws_vpc_ipam_preview_next_cidr.previewed_cidr.cidr
225+
private_subnets = local.private_subnets
226+
public_subnets = local.public_subnets
227+
}
228+
```
229+
182230
## Examples
183231

184232
- [Simple VPC](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/simple-vpc)
@@ -188,6 +236,7 @@ It is possible to integrate this VPC module with [terraform-aws-transit-gateway
188236
- [Network ACL](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/network-acls)
189237
- [VPC Flow Logs](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/vpc-flow-logs)
190238
- [VPC with Outpost](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/outpost)
239+
- [VPC CIDR from IPAM](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/ipam-vpc)
191240
- [Manage Default VPC](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/manage-default-vpc)
192241
- [Few tests and edge case examples](https://github.com/terraform-aws-modules/terraform-aws-vpc/tree/master/examples/issues)
193242

@@ -203,13 +252,13 @@ Full contributing [guidelines are covered here](.github/contributing.md).
203252
| Name | Version |
204253
|------|---------|
205254
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.13.1 |
206-
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.68 |
255+
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.73 |
207256

208257
## Providers
209258

210259
| Name | Version |
211260
|------|---------|
212-
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.68 |
261+
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.73 |
213262

214263
## Modules
215264

@@ -304,7 +353,7 @@ No modules.
304353
| <a name="input_amazon_side_asn"></a> [amazon\_side\_asn](#input\_amazon\_side\_asn) | The Autonomous System Number (ASN) for the Amazon side of the gateway. By default the virtual private gateway is created with the current default Amazon ASN. | `string` | `"64512"` | no |
305354
| <a name="input_assign_ipv6_address_on_creation"></a> [assign\_ipv6\_address\_on\_creation](#input\_assign\_ipv6\_address\_on\_creation) | Assign IPv6 address on subnet, must be disabled to change IPv6 CIDRs. This is the IPv6 equivalent of map\_public\_ip\_on\_launch | `bool` | `false` | no |
306355
| <a name="input_azs"></a> [azs](#input\_azs) | A list of availability zones names or ids in the region | `list(string)` | `[]` | no |
307-
| <a name="input_cidr"></a> [cidr](#input\_cidr) | (Optional) The IPv4 CIDR block for the VPC. CIDR can be explicitly set or it can be derived from IPAM using `ipv4_netmask_length` & `ipv4_ipam_pool_id` | `string` | `"0.0.0.0/0"` | no |
356+
| <a name="input_cidr"></a> [cidr](#input\_cidr) | (Optional) The IPv4 CIDR block for the VPC. CIDR can be explicitly set or it can be derived from IPAM using `ipv4_netmask_length` & `ipv4_ipam_pool_id` | `string` | `null` | no |
308357
| <a name="input_create_database_internet_gateway_route"></a> [create\_database\_internet\_gateway\_route](#input\_create\_database\_internet\_gateway\_route) | Controls if an internet gateway route for public database access should be created | `bool` | `false` | no |
309358
| <a name="input_create_database_nat_gateway_route"></a> [create\_database\_nat\_gateway\_route](#input\_create\_database\_nat\_gateway\_route) | Controls if a nat gateway route should be created to give internet access to the database subnets | `bool` | `false` | no |
310359
| <a name="input_create_database_subnet_group"></a> [create\_database\_subnet\_group](#input\_create\_database\_subnet\_group) | Controls if database subnet group should be created (n.b. database\_subnets must also be set) | `bool` | `true` | no |
@@ -403,7 +452,6 @@ No modules.
403452
| <a name="input_intra_subnet_tags"></a> [intra\_subnet\_tags](#input\_intra\_subnet\_tags) | Additional tags for the intra subnets | `map(string)` | `{}` | no |
404453
| <a name="input_intra_subnets"></a> [intra\_subnets](#input\_intra\_subnets) | A list of intra subnets | `list(string)` | `[]` | no |
405454
| <a name="input_ipv4_ipam_pool_id"></a> [ipv4\_ipam\_pool\_id](#input\_ipv4\_ipam\_pool\_id) | (Optional) The ID of an IPv4 IPAM pool you want to use for allocating this VPC's CIDR. | `string` | `null` | no |
406-
| <a name="input_ipv4_netmask_length"></a> [ipv4\_netmask\_length](#input\_ipv4\_netmask\_length) | (Optional) The netmask length of the IPv4 CIDR you want to allocate to this VPC. Requires specifying a ipv4\_ipam\_pool\_id. | `number` | `null` | no |
407455
| <a name="input_manage_default_network_acl"></a> [manage\_default\_network\_acl](#input\_manage\_default\_network\_acl) | Should be true to adopt and manage Default Network ACL | `bool` | `false` | no |
408456
| <a name="input_manage_default_route_table"></a> [manage\_default\_route\_table](#input\_manage\_default\_route\_table) | Should be true to manage default route table | `bool` | `false` | no |
409457
| <a name="input_manage_default_security_group"></a> [manage\_default\_security\_group](#input\_manage\_default\_security\_group) | Should be true to adopt and manage default security group | `bool` | `false` | no |

examples/ipam-vpc/main.tf

Lines changed: 40 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,28 @@ provider "aws" {
44

55
locals {
66
name = "ipam-vpc-example"
7+
azs = formatlist("${data.aws_region.current.name}%s", ["a", "b"])
78
}
89

9-
# IPAM Setup
1010
data "aws_region" "current" {}
1111

12-
resource "aws_vpc_ipam" "example" {
13-
operating_regions {
14-
region_name = data.aws_region.current.name
15-
}
16-
}
17-
18-
resource "aws_vpc_ipam_pool" "ipv4_example" {
19-
address_family = "ipv4"
20-
ipam_scope_id = aws_vpc_ipam.example.private_default_scope_id
21-
locale = data.aws_region.current.name
22-
allocation_default_netmask_length = 28
23-
}
12+
/*
13+
NOTES ON IPAM USAGE:
2414
25-
resource "aws_vpc_ipam_pool_cidr" "ipv4_example" {
26-
ipam_pool_id = aws_vpc_ipam_pool.ipv4_example.id
27-
cidr = "172.2.0.0/16"
28-
}
15+
In order to build subnets with your VPC Terraform must
16+
know subnet CIDRs to properly plan # of resources to build.
17+
Since CIDR is derived by IPAM by calling CreateVpc this is not
18+
possible within a module unless cidr is known ahead of time.
19+
We can get around this by "previewing" the CIDR and then using that
20+
as the subnet values.
2921
30-
# Usage Patterns
22+
In the example below we use `cidrsubnets()` to calculate a public
23+
and private "partitions" (group of cidrs) then calculate the specific
24+
CIDRs for each subnet type.
3125
32-
module "no_ipam_vpc_example" {
33-
source = "../.."
34-
name = "no-ipam-${local.name}"
35-
cidr = "172.2.0.32/28"
36-
}
26+
For an explanation on prolonged delete times on IPAM pools see 2nd
27+
*note* in terraform docs: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipam_pool_cidr
28+
*/
3729

3830
data "aws_vpc_ipam_preview_next_cidr" "previewed_cidr" {
3931
ipam_pool_id = aws_vpc_ipam_pool.ipv4_example.id
@@ -45,48 +37,44 @@ data "aws_vpc_ipam_preview_next_cidr" "previewed_cidr" {
4537
}
4638

4739
locals {
48-
partition = cidrsubnets(data.aws_vpc_ipam_preview_next_cidr.previewed_cidr.cidr, 2, 2)
40+
partition = cidrsubnets(data.aws_vpc_ipam_preview_next_cidr.previewed_cidr.cidr, 2, 2)
4941
private_subnets = cidrsubnets(local.partition[0], 2, 2)
50-
public_subnets = cidrsubnets(local.partition[1], 2, 2)
42+
public_subnets = cidrsubnets(local.partition[1], 2, 2)
5143
}
5244

53-
module "ipv4_ipam_calculate_subnets" {
45+
module "ipv4_ipam_explicit_cidrs_calculate_subnets" {
5446
source = "../.."
5547
name = "ipv4-calculated-subnets-${local.name}"
5648
ipv4_ipam_pool_id = aws_vpc_ipam_pool.ipv4_example.id
49+
azs = local.azs
5750
cidr = data.aws_vpc_ipam_preview_next_cidr.previewed_cidr.cidr
5851
private_subnets = local.private_subnets
5952
public_subnets = local.public_subnets
53+
6054
depends_on = [
6155
aws_vpc_ipam_pool_cidr.ipv4_example
6256
]
6357
}
6458

65-
# module "ipv4_ipam_explicit_cidr_vpc" {
66-
# source = "../.."
67-
# name = "ipv4-explicit-cidr-${local.name}"
68-
# ipv4_ipam_pool_id = aws_vpc_ipam_pool.ipv4_example.id
69-
# cidr = "172.2.0.32/28"
70-
# depends_on = [
71-
# aws_vpc_ipam_pool_cidr.ipv4_example
72-
# ]
73-
# }
59+
################################
60+
# IPAM Setup
61+
# Included for testing & example purposes only
62+
################################
7463

75-
# module "ipv4_ipam_explicit_netmask_vpc" {
76-
# source = "../.."
77-
# name = "ipv4-explicit-netmask-${local.name}"
78-
# ipv4_ipam_pool_id = aws_vpc_ipam_pool.ipv4_example.id
79-
# ipv4_netmask_length = 28
80-
# depends_on = [
81-
# aws_vpc_ipam_pool_cidr.ipv4_example
82-
# ]
83-
# }
64+
resource "aws_vpc_ipam" "example" {
65+
operating_regions {
66+
region_name = data.aws_region.current.name
67+
}
68+
}
69+
70+
resource "aws_vpc_ipam_pool" "ipv4_example" {
71+
address_family = "ipv4"
72+
ipam_scope_id = aws_vpc_ipam.example.private_default_scope_id
73+
locale = data.aws_region.current.name
74+
allocation_default_netmask_length = 28
75+
}
8476

85-
# module "ipv4_ipam_default_netmask_vpc" {
86-
# source = "../.."
87-
# name = "ipv4-default-netmask-${local.name}"
88-
# ipv4_ipam_pool_id = aws_vpc_ipam_pool.ipv4_example.id
89-
# depends_on = [
90-
# aws_vpc_ipam_pool_cidr.ipv4_example
91-
# ]
92-
# }
77+
resource "aws_vpc_ipam_pool_cidr" "ipv4_example" {
78+
ipam_pool_id = aws_vpc_ipam_pool.ipv4_example.id
79+
cidr = "172.2.0.0/16"
80+
}

examples/ipam-vpc/outputs.tf

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# VPC
2+
output "vpc_id" {
3+
description = "The ID of the VPC"
4+
value = module.ipv4_ipam_explicit_cidrs_calculate_subnets.vpc_id
5+
}
6+
7+
# Subnets
8+
output "private_subnets" {
9+
description = "List of IDs of private subnets"
10+
value = module.ipv4_ipam_explicit_cidrs_calculate_subnets.private_subnets
11+
}
12+
13+
output "public_subnets" {
14+
description = "List of IDs of public subnets"
15+
value = module.ipv4_ipam_explicit_cidrs_calculate_subnets.public_subnets
16+
}

main.tf

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,8 @@ locals {
2525
resource "aws_vpc" "this" {
2626
count = var.create_vpc ? 1 : 0
2727

28-
cidr_block = var.cidr
29-
ipv4_ipam_pool_id = var.ipv4_ipam_pool_id
30-
ipv4_netmask_length = var.ipv4_netmask_length
28+
cidr_block = var.cidr
29+
ipv4_ipam_pool_id = var.ipv4_ipam_pool_id
3130

3231
instance_tenancy = var.instance_tenancy
3332
enable_dns_hostnames = var.enable_dns_hostnames

variables.tf

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,9 +1180,3 @@ variable "ipv4_ipam_pool_id" {
11801180
type = string
11811181
default = null
11821182
}
1183-
1184-
variable "ipv4_netmask_length" {
1185-
description = "(Optional) The netmask length of the IPv4 CIDR you want to allocate to this VPC. Requires specifying a ipv4_ipam_pool_id."
1186-
type = number
1187-
default = null
1188-
}

0 commit comments

Comments
 (0)