Skip to content

Commit

Permalink
Merge pull request #51 from aws-ia/ipam-netmask-cidr
Browse files Browse the repository at this point in the history
IPAM Provisioned Pool Cidrs from Netmask value
  • Loading branch information
tlindsay42 authored Feb 6, 2023
2 parents b7ef5c7 + efbf4fb commit 655698b
Show file tree
Hide file tree
Showing 12 changed files with 37 additions and 41 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,13 @@ The IPAM `operating_region` variable must be set for the primary Region in your
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.73.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 4.53.0 |

## Providers

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

## Modules

Expand All @@ -146,12 +146,13 @@ The IPAM `operating_region` variable must be set for the primary Region in your
| <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 |
| <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 |
| <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 |
| <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 |
| <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 |
| <a name="input_tags"></a> [tags](#input\_tags) | Tags to add to the aws\_vpc\_ipam resource. | `any` | `{}` | no |
| <a name="input_top_auto_import"></a> [top\_auto\_import](#input\_top\_auto\_import) | `auto_import` setting for top-level pool. | `bool` | `null` | no |
| <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 |
| <a name="input_top_description"></a> [top\_description](#input\_top\_description) | Description of top-level pool. | `string` | `""` | no |
| <a name="input_top_name"></a> [top\_name](#input\_top\_name) | Name of top-level pool. | `string` | `null` | no |
| <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 |
| <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 |

## Outputs
Expand Down
5 changes: 1 addition & 4 deletions examples/single_scope_ipv4/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ The example code shows you how to deploy IPAM with pools in 2 regions. The compa

## Requirements

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

## Providers

Expand Down
6 changes: 3 additions & 3 deletions examples/single_scope_ipv4/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,17 @@ module "basic" {
}
}
dev = {
cidr = ["10.1.0.0/20"]
netmask_length = 20

sub_pools = {
team_a = {
cidr = ["10.1.0.0/24"]
netmask_length = 24
ram_share_principals = var.prod_account # prod account
locale = "us-west-2"
}

team_b = {
cidr = ["10.1.1.0/24"]
netmask_length = 26
ram_share_principals = var.prod_account # prod account
}
}
Expand Down
1 change: 1 addition & 0 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ module "level_zero" {
description = var.top_description
cidr_authorization_context = var.top_cidr_authorization_context
name = var.top_name
netmask_length = var.top_netmask_length
}
}

Expand Down
6 changes: 3 additions & 3 deletions modules/sub_pool/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.73.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 4.53.0 |

## Providers

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

## Modules

Expand All @@ -32,7 +32,7 @@ No modules.
|------|-------------|------|---------|:--------:|
| <a name="input_address_family"></a> [address\_family](#input\_address\_family) | IPv4/6 address family. | `string` | n/a | yes |
| <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 |
| <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 |
| <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 |
| <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 |
| <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 |
| <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 |
Expand Down
8 changes: 5 additions & 3 deletions modules/sub_pool/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ locals {
)

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

resource "aws_vpc_ipam_pool" "sub" {
Expand All @@ -28,10 +29,11 @@ resource "aws_vpc_ipam_pool" "sub" {
}

resource "aws_vpc_ipam_pool_cidr" "sub" {
for_each = toset(var.pool_config.cidr)
for_each = toset(local.pool_cidrs)

ipam_pool_id = aws_vpc_ipam_pool.sub.id
cidr = each.key
ipam_pool_id = aws_vpc_ipam_pool.sub.id
cidr = length(regexall("/", each.key)) > 0 ? each.key : null
netmask_length = length(regexall("/", each.key)) == 0 ? each.key : null

dynamic "cidr_authorization_context" {
for_each = var.pool_config.cidr_authorization_context == null ? [] : [1]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 3.73.0"
version = ">= 4.53.0"
}
}
}
22 changes: 9 additions & 13 deletions modules/sub_pool/variables.tf
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
variable "pool_config" {
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)."
type = object({
cidr = list(string)
cidr = optional(list(string))
ram_share_principals = optional(list(string))

locale = optional(string)
Expand All @@ -12,6 +12,7 @@ variable "pool_config" {
aws_service = optional(string)
description = optional(string)
name = optional(string)
netmask_length = optional(number)
publicly_advertisable = optional(bool)

allocation_resource_tags = optional(map(string))
Expand All @@ -21,18 +22,13 @@ variable "pool_config" {
sub_pools = optional(any)
})

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

variable "implied_locale" {
Expand Down
2 changes: 1 addition & 1 deletion modules/sub_pool/versions.tf → providers.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 3.73.0"
version = ">= 4.53.0"
}
}
}
1 change: 1 addition & 0 deletions test/examples_single_scope_ipv4_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ func TestExamplesIPv4Basic(t *testing.T) {

defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
terraform.ApplyAndIdempotent(t, terraformOptions)
}
9 changes: 8 additions & 1 deletion variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ variable "pool_configurations" {
- `ram_share_principals` = (optional, list(string)) of valid organization principals to create ram shares to.
- `name` = (optional, string) name to give the pool, the key of your map in var.pool_configurations will be used if omitted.
- `description` = (optional, string) description to give the pool, the key of your map in var.pool_configurations will be used if omitted.
- `cidr` = (optional, list(string)) list of CIDRs to provision into pool.
- `cidr` = (optional, list(string)) list of CIDRs to provision into pool. Conflicts with `netmask_length`.
- `netmask_length` = (optional, number) netmask length to request provisioned into pool. Conflicts with `cidr`.
- `locale` = (optional, string) locale to set for pool.
- `auto_import` = (optional, string)
Expand All @@ -31,6 +32,12 @@ variable "top_cidr" {
type = list(string)
}

variable "top_netmask_length" {
description = "Top-level netmask length to request. Not possible to use for IPv4. Only possible to use with amazon provided ipv6."
type = number
default = null
}

variable "top_ram_share_principals" {
description = "Principals to create RAM shares for top-level pool."
type = list(string)
Expand Down
9 changes: 0 additions & 9 deletions versions.tf

This file was deleted.

0 comments on commit 655698b

Please sign in to comment.