Skip to content

Commit 655698b

Browse files
authored
Merge pull request #51 from aws-ia/ipam-netmask-cidr
IPAM Provisioned Pool Cidrs from Netmask value
2 parents b7ef5c7 + efbf4fb commit 655698b

File tree

12 files changed

+37
-41
lines changed

12 files changed

+37
-41
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,13 @@ The IPAM `operating_region` variable must be set for the primary Region in your
113113
| Name | Version |
114114
|------|---------|
115115
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.0 |
116-
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.73.0 |
116+
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 4.53.0 |
117117

118118
## Providers
119119

120120
| Name | Version |
121121
|------|---------|
122-
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.73.0 |
122+
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 4.53.0 |
123123

124124
## Modules
125125

@@ -146,12 +146,13 @@ The IPAM `operating_region` variable must be set for the primary Region in your
146146
| <a name="input_create_ipam"></a> [create\_ipam](#input\_create\_ipam) | Determines whether to create an IPAM. If `false`, you must also provide a var.ipam\_scope\_id. | `bool` | `true` | no |
147147
| <a name="input_ipam_scope_id"></a> [ipam\_scope\_id](#input\_ipam\_scope\_id) | (Optional) Required if `var.ipam_id` is set. Determines which scope to deploy pools into. | `string` | `null` | no |
148148
| <a name="input_ipam_scope_type"></a> [ipam\_scope\_type](#input\_ipam\_scope\_type) | Which scope type to use. Valid inputs include `public` or `private`. You can alternatively provide your own scope ID. | `string` | `"private"` | no |
149-
| <a name="input_pool_configurations"></a> [pool\_configurations](#input\_pool\_configurations) | A multi-level, nested map describing nested IPAM pools. Can nest up to three levels with the top level being outside the `pool_configurations` in vars prefixed `top_`. If arugument descriptions are omitted, you can find them in the [official documentation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipam_pool#argument-reference).<br><br>- `ram_share_principals` = (optional, list(string)) of valid organization principals to create ram shares to.<br>- `name` = (optional, string) name to give the pool, the key of your map in var.pool\_configurations will be used if omitted.<br>- `description` = (optional, string) description to give the pool, the key of your map in var.pool\_configurations will be used if omitted.<br>- `cidr` = (optional, list(string)) list of CIDRs to provision into pool.<br><br>- `locale` = (optional, string) locale to set for pool.<br>- `auto_import` = (optional, string)<br>- `tags` = (optional, map(string))<br>- `allocation_default_netmask_length` = (optional, string)<br>- `allocation_max_netmask_length` = (optional, string)<br>- `allocation_min_netmask_length` = (optional, string)<br>- `allocation_resource_tags` = (optional, map(string))<br><br>The following arguments are available but only relevant for public ips<br>- `cidr_authorization_context` = (optional, map(string)) Details found in [official documentation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipam_pool_cidr#cidr_authorization_context).<br>- `aws_service` = (optional, string)<br>- `publicly_advertisable` = (optional, bool)<br><br>- `sub_pools` = (nested repeats of pool\_configuration object above) | `any` | `{}` | no |
149+
| <a name="input_pool_configurations"></a> [pool\_configurations](#input\_pool\_configurations) | A multi-level, nested map describing nested IPAM pools. Can nest up to three levels with the top level being outside the `pool_configurations` in vars prefixed `top_`. If arugument descriptions are omitted, you can find them in the [official documentation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipam_pool#argument-reference).<br><br>- `ram_share_principals` = (optional, list(string)) of valid organization principals to create ram shares to.<br>- `name` = (optional, string) name to give the pool, the key of your map in var.pool\_configurations will be used if omitted.<br>- `description` = (optional, string) description to give the pool, the key of your map in var.pool\_configurations will be used if omitted.<br>- `cidr` = (optional, list(string)) list of CIDRs to provision into pool. Conflicts with `netmask_length`.<br>- `netmask_length` = (optional, number) netmask length to request provisioned into pool. Conflicts with `cidr`.<br><br>- `locale` = (optional, string) locale to set for pool.<br>- `auto_import` = (optional, string)<br>- `tags` = (optional, map(string))<br>- `allocation_default_netmask_length` = (optional, string)<br>- `allocation_max_netmask_length` = (optional, string)<br>- `allocation_min_netmask_length` = (optional, string)<br>- `allocation_resource_tags` = (optional, map(string))<br><br>The following arguments are available but only relevant for public ips<br>- `cidr_authorization_context` = (optional, map(string)) Details found in [official documentation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipam_pool_cidr#cidr_authorization_context).<br>- `aws_service` = (optional, string)<br>- `publicly_advertisable` = (optional, bool)<br><br>- `sub_pools` = (nested repeats of pool\_configuration object above) | `any` | `{}` | no |
150150
| <a name="input_tags"></a> [tags](#input\_tags) | Tags to add to the aws\_vpc\_ipam resource. | `any` | `{}` | no |
151151
| <a name="input_top_auto_import"></a> [top\_auto\_import](#input\_top\_auto\_import) | `auto_import` setting for top-level pool. | `bool` | `null` | no |
152152
| <a name="input_top_cidr_authorization_context"></a> [top\_cidr\_authorization\_context](#input\_top\_cidr\_authorization\_context) | A signed document that proves that you are authorized to bring the specified IP address range to Amazon using BYOIP. Document is not stored in the state file. For more information, refer to https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipam_pool_cidr#cidr_authorization_context. | `any` | `null` | no |
153153
| <a name="input_top_description"></a> [top\_description](#input\_top\_description) | Description of top-level pool. | `string` | `""` | no |
154154
| <a name="input_top_name"></a> [top\_name](#input\_top\_name) | Name of top-level pool. | `string` | `null` | no |
155+
| <a name="input_top_netmask_length"></a> [top\_netmask\_length](#input\_top\_netmask\_length) | Top-level netmask length to request. Not possible to use for IPv4. Only possible to use with amazon provided ipv6. | `number` | `null` | no |
155156
| <a name="input_top_ram_share_principals"></a> [top\_ram\_share\_principals](#input\_top\_ram\_share\_principals) | Principals to create RAM shares for top-level pool. | `list(string)` | `null` | no |
156157

157158
## Outputs

examples/single_scope_ipv4/README.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@ The example code shows you how to deploy IPAM with pools in 2 regions. The compa
99

1010
## Requirements
1111

12-
| Name | Version |
13-
|------|---------|
14-
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.15.0 |
15-
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.73.0 |
12+
No requirements.
1613

1714
## Providers
1815

examples/single_scope_ipv4/main.tf

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,17 @@ module "basic" {
2727
}
2828
}
2929
dev = {
30-
cidr = ["10.1.0.0/20"]
30+
netmask_length = 20
3131

3232
sub_pools = {
3333
team_a = {
34-
cidr = ["10.1.0.0/24"]
34+
netmask_length = 24
3535
ram_share_principals = var.prod_account # prod account
3636
locale = "us-west-2"
3737
}
3838

3939
team_b = {
40-
cidr = ["10.1.1.0/24"]
40+
netmask_length = 26
4141
ram_share_principals = var.prod_account # prod account
4242
}
4343
}

main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ module "level_zero" {
5353
description = var.top_description
5454
cidr_authorization_context = var.top_cidr_authorization_context
5555
name = var.top_name
56+
netmask_length = var.top_netmask_length
5657
}
5758
}
5859

modules/sub_pool/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
| Name | Version |
55
|------|---------|
66
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.0 |
7-
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.73.0 |
7+
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 4.53.0 |
88

99
## Providers
1010

1111
| Name | Version |
1212
|------|---------|
13-
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.73.0 |
13+
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 4.53.0 |
1414

1515
## Modules
1616

@@ -32,7 +32,7 @@ No modules.
3232
|------|-------------|------|---------|:--------:|
3333
| <a name="input_address_family"></a> [address\_family](#input\_address\_family) | IPv4/6 address family. | `string` | n/a | yes |
3434
| <a name="input_ipam_scope_id"></a> [ipam\_scope\_id](#input\_ipam\_scope\_id) | IPAM Scope ID to attach the pool to. | `string` | n/a | yes |
35-
| <a name="input_pool_config"></a> [pool\_config](#input\_pool\_config) | Configuration of the Pool you want to deploy. All aws\_vpc\_ipam\_pool arguments are available as well as ram\_share\_principals list and sub\_pools map (up to 3 levels). | <pre>object({<br> cidr = list(string)<br> ram_share_principals = optional(list(string))<br><br> locale = optional(string)<br> allocation_default_netmask_length = optional(string)<br> allocation_max_netmask_length = optional(string)<br> allocation_min_netmask_length = optional(string)<br> auto_import = optional(string)<br> aws_service = optional(string)<br> description = optional(string)<br> name = optional(string)<br> publicly_advertisable = optional(bool)<br><br> allocation_resource_tags = optional(map(string))<br> tags = optional(map(string))<br> cidr_authorization_context = optional(map(string))<br><br> sub_pools = optional(any)<br> })</pre> | n/a | yes |
35+
| <a name="input_pool_config"></a> [pool\_config](#input\_pool\_config) | Configuration of the Pool you want to deploy. All aws\_vpc\_ipam\_pool arguments are available as well as ram\_share\_principals list and sub\_pools map (up to 3 levels). | <pre>object({<br> cidr = optional(list(string))<br> ram_share_principals = optional(list(string))<br><br> locale = optional(string)<br> allocation_default_netmask_length = optional(string)<br> allocation_max_netmask_length = optional(string)<br> allocation_min_netmask_length = optional(string)<br> auto_import = optional(string)<br> aws_service = optional(string)<br> description = optional(string)<br> name = optional(string)<br> netmask_length = optional(number)<br> publicly_advertisable = optional(bool)<br><br> allocation_resource_tags = optional(map(string))<br> tags = optional(map(string))<br> cidr_authorization_context = optional(map(string))<br><br> sub_pools = optional(any)<br> })</pre> | n/a | yes |
3636
| <a name="input_source_ipam_pool_id"></a> [source\_ipam\_pool\_id](#input\_source\_ipam\_pool\_id) | IPAM parent pool ID to attach the pool to. | `string` | n/a | yes |
3737
| <a name="input_implied_description"></a> [implied\_description](#input\_implied\_description) | Description is implied from the pool tree name <parent>/<child> unless specified on the pool\_config. | `string` | `null` | no |
3838
| <a name="input_implied_locale"></a> [implied\_locale](#input\_implied\_locale) | Locale is implied from a parent pool even if another is specified. Its not possible to set child pools to different locales. | `string` | `"None"` | no |

modules/sub_pool/main.tf

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ locals {
77
)
88

99
ram_share_enabled = try(length(var.pool_config.ram_share_principals), 0) > 0
10+
pool_cidrs = var.pool_config.cidr == null ? [var.pool_config.netmask_length] : var.pool_config.cidr
1011
}
1112

1213
resource "aws_vpc_ipam_pool" "sub" {
@@ -28,10 +29,11 @@ resource "aws_vpc_ipam_pool" "sub" {
2829
}
2930

3031
resource "aws_vpc_ipam_pool_cidr" "sub" {
31-
for_each = toset(var.pool_config.cidr)
32+
for_each = toset(local.pool_cidrs)
3233

33-
ipam_pool_id = aws_vpc_ipam_pool.sub.id
34-
cidr = each.key
34+
ipam_pool_id = aws_vpc_ipam_pool.sub.id
35+
cidr = length(regexall("/", each.key)) > 0 ? each.key : null
36+
netmask_length = length(regexall("/", each.key)) == 0 ? each.key : null
3537

3638
dynamic "cidr_authorization_context" {
3739
for_each = var.pool_config.cidr_authorization_context == null ? [] : [1]

examples/single_scope_ipv4/versions.tf renamed to modules/sub_pool/providers.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ terraform {
33
required_providers {
44
aws = {
55
source = "hashicorp/aws"
6-
version = ">= 3.73.0"
6+
version = ">= 4.53.0"
77
}
88
}
99
}

modules/sub_pool/variables.tf

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
variable "pool_config" {
22
description = "Configuration of the Pool you want to deploy. All aws_vpc_ipam_pool arguments are available as well as ram_share_principals list and sub_pools map (up to 3 levels)."
33
type = object({
4-
cidr = list(string)
4+
cidr = optional(list(string))
55
ram_share_principals = optional(list(string))
66

77
locale = optional(string)
@@ -12,6 +12,7 @@ variable "pool_config" {
1212
aws_service = optional(string)
1313
description = optional(string)
1414
name = optional(string)
15+
netmask_length = optional(number)
1516
publicly_advertisable = optional(bool)
1617

1718
allocation_resource_tags = optional(map(string))
@@ -21,18 +22,13 @@ variable "pool_config" {
2122
sub_pools = optional(any)
2223
})
2324

24-
# Validation to ensure keys
25-
# if specify type = object() keys are silently dropped, no validation required but also no error if improper keys
26-
# if speicy type = any we can validate which provides an error opportunity BUT values are not defaulted, makes code complex
27-
# validation {
28-
# condition = (length(setsubtract(keys(var.pool_config), [
29-
# "name", "cidr", "locale", "ram_share_principals", "auto_import", "aws_service", "description",
30-
# "publicly_advertisable", "allocation_resource_tags", "tags", "cidr_authorization_context",
31-
# "sub_pools", "allocation_default_netmask_length", "allocation_max_netmask_length",
32-
# "allocation_min_netmask_length"]
33-
# )) == 0)
34-
# error_message = "Can only accept certain parameters. See modules/sub_pool/variables.tf for `pool_config` options."
35-
# }
25+
validation {
26+
condition = anytrue([
27+
(var.pool_config.cidr != null && var.pool_config.netmask_length == null),
28+
(var.pool_config.cidr == null && var.pool_config.netmask_length != null)
29+
])
30+
error_message = "Pool Name: ${var.pool_config.name == null ? "Unamed" : var.pool_config.name} - must define exactly one of `cidr` or `netmask_length`."
31+
}
3632
}
3733

3834
variable "implied_locale" {

modules/sub_pool/versions.tf renamed to providers.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ terraform {
33
required_providers {
44
aws = {
55
source = "hashicorp/aws"
6-
version = ">= 3.73.0"
6+
version = ">= 4.53.0"
77
}
88
}
99
}

test/examples_single_scope_ipv4_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,5 @@ func TestExamplesIPv4Basic(t *testing.T) {
3232

3333
defer terraform.Destroy(t, terraformOptions)
3434
terraform.InitAndApply(t, terraformOptions)
35+
terraform.ApplyAndIdempotent(t, terraformOptions)
3536
}

0 commit comments

Comments
 (0)