Skip to main content
Latest Documentation
This is the latest documentation for the Cloud Posse Reference Architecture. To determine which version you're currently using, please see Version Identification.

Module: ipam

Terraform module to provision:

Introduction​

The pool hierarchy​

IPAM pools form a tree: a top-level pool holds a supernet, Regional pools draw from it, and workload pools draw from those. This module takes that tree as a flat map(object) keyed by your own name for each pool, where a pool names its parent rather than being physically nested inside it:

pools = {
core = { cidrs = { primary = { cidr = "10.0.0.0/8" } } }
regional = { parent = "core", locale = "us-east-2", cidrs = { primary = { netmask_length = 12 } } }
env = { parent = "regional", locale = "us-east-2", cidrs = { primary = { netmask_length = 16 } } }
}

Two reasons it is flat rather than nested:

  1. Terraform cannot express a recursive type. A nested sub_pools attribute forces type = any, which gives up schema documentation, IDE completion, and terraform-docs output. That is exactly what happened to aws-ia/ipam, whose central pool_configurations input is type = any with a 25-line prose schema in a comment. Every input in this module is concretely typed.
  2. Keys stay stable. Adding or removing a pool does not disturb the for_each keys of its siblings, and the pool_ids output stays keyed by the names you chose.

Map keys must be known at plan time — they come from your configuration, not from another resource's attributes.

Following a convention, and setting one​

Worth being precise about which is which:

  • The input shape follows an existing Cloud Posse convention. A flat map(object) keyed by a logical name, concretely typed, default = {}, nullable = false, key semantics in an inline comment, and the plan-time-key caveat stated in the description is terraform-aws-eks-cluster's access_entry_map applied to a new domain.
  • The per-depth materialisation sets one. No Cloud Posse module had previously modelled a hierarchy, so aws_vpc_ipam_pool.level_0 … .level_3, the depth partition in locals, and the precondition guards are new. They follow the spirit of two existing patterns rather than any direct precedent: terraform-aws-dynamic-subnets duplicates a near-identical resource set across a structural dimension in-repo (public.tf / private.tf) with the branching precomputed in locals, and terraform-aws-vpc already splits level 0 from level N for a single concept — a count-gated aws_vpc.default plus a for_each-keyed aws_vpc_ipv4_cidr_block_association.default referencing it, which is structurally one pool tier.

Why tiers are resources here, not a child module​

aws-ia/ipam solves the same recursion problem by calling a shared ./modules/sub_pool child module once per depth. This module uses four resources in the root instead, deliberately:

  • A sub_pool module has no standalone value. Every modules/* in the Cloud Posse fleet is separately documented and separately consumable; a deduplication helper is not.
  • It keeps resource addresses shallow and predictable — aws_vpc_ipam_pool.level_1["core"] rather than module.level_one["core"].aws_vpc_ipam_pool.sub[0]. That matters concretely: a consumer migrating between modules has to hand-write moved blocks against these addresses, because a moved block can only name addresses relative to its own module instance and so cannot be shipped here. Burying addresses one module deep is precisely what makes migrating off aws-ia/ipam painful, so reproducing it would be self-defeating.
  • A child module would need its own context.tf, versions.tf and README.md, and CI runs the full bats and tflint matrix over every directory containing a .tf file.

Depth is capped at 4​

A pool hierarchy in this module can be four levels deep: a top-level pool plus three generations beneath it. This is a Terraform limitation rather than an AWS one. A resource cannot reference itself, so source_ipam_pool_id = aws_vpc_ipam_pool.this[each.value.parent].id inside aws_vpc_ipam_pool.this is a cycle. The module instead partitions your map by computed depth and declares four tiers: aws_vpc_ipam_pool.level_0 through .level_3.

A deeper tree, a parent that names no existing pool, and a cycle in the parent links are each rejected at plan time by a separate check that names the offending pools — the three are reported distinctly rather than lumped together, since a cycle is not a depth problem. Raising the cap later is a non-breaking change: one more tier, no input or output shape change, no state movement for existing pools.

Create and destroy ordering​

CIDR provisioning is tiered alongside the pools, so creation runs pool → its CIDRs → child pool → child's CIDRs, and destruction runs exactly backwards. This is not cosmetic: DeprovisionIpamPoolCidr fails while any allocation exists against a CIDR, and a child pool's provisioned CIDR is such an allocation. Manual reservations likewise carry an explicit depends_on to the pool CIDRs, because an allocation that references only ipam_pool_id gets no dependency edge to the CIDR it consumes. Getting this wrong does not fail fast — it burns the provider's 32-minute allocation-release timeout and then fails.

The module cannot order things it cannot see. A VPC or subnet created from one of these pools makes an allocation outside this module's graph, and AWS takes up to 20 minutes to release it after the consumer is deleted. Keep such consumers in the same configuration with a depends_on, or expect a cold destroy to sit in that wait.

Provider floor​

The module requires AWS provider >= 6.56.0. The strict floor for the complete argument surface is 6.48.0, which added tags to aws_vpc_ipam_pool_cidr_allocation. The higher floor buys two fixes that matter to IPAM specifically: aws_subnet now waits for IPAM to release its CIDR on delete — the one destroy-ordering hazard no amount of depends_on inside this module can fix — and resource-planning pools no longer fail when the VPC lives in another account. Pin lower only if you use neither IPAM-backed subnets nor cross-account source_resource pools.

Migrating from aws-ia/ipam​

See docs/migration-aws-ia-v1.md for the input mapping, the moved blocks to write in your root module, and state mv / import fallbacks.

Usage​

Here's how to invoke this module in your projects:

module "ipam" {
source = "cloudposse/ipam/aws"
# Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x"

operating_regions = ["us-east-2", "us-west-2"]

pools = {
core = {
cidrs = {
primary = { cidr = "10.0.0.0/8" }
}
}

use2 = {
parent = "core"
locale = "us-east-2"
cidrs = {
primary = { netmask_length = 12 }
}

# Share this pool with the whole organization
ram_share = {
principals = ["arn:aws:organizations::123456789012:organization/o-abcde12345"]
}
}

use2_prod = {
parent = "use2"
locale = "us-east-2"
allocation_default_netmask_length = 24

cidrs = {
primary = { netmask_length = 16 }
}

# Hold space inside the pool without attaching it to anything
allocations = {
reserved = { netmask_length = 20, description = "Held for future use" }
}
}
}

context = module.this.context
}

Consumers index the pool_ids output by the names they supplied:

module "vpc" {
source = "cloudposse/vpc/aws"
version = "2.2.0"

ipv4_primary_cidr_block_association = {
ipv4_ipam_pool_id = module.ipam.pool_ids["use2_prod"]
ipv4_netmask_length = 20
}

context = module.this.context
}

Quick Start​

The smallest useful configuration is an IPAM with a single pool:

module "ipam" {
source = "cloudposse/ipam/aws"
# version = "x.x.x"

pools = {
core = {
cidrs = {
primary = { cidr = "10.0.0.0/8" }
}
}
}

context = module.this.context
}

This creates the IPAM (which brings its own public scope, private scope, default resource discovery, and default association), one top-level pool in the private default scope, and provisions 10.0.0.0/8 into it. Grow the tree by adding entries that name core as their parent.

Note that the provider defaults an IPAM to the billable advanced tier. Set ipam_tier = "free" if that is what you want.

Examples​

Here is an example of using this module:

  • examples/complete - builds a full four-level pool hierarchy in a named private scope, provisions a CIDR into each tier, holds a manual reservation in the deepest pool, and creates a resource discovery

For automated tests of the complete example using Terratest (which tests and deploys the example on AWS), see test.

Variables​

Required Variables​

Optional Variables​

create_ipam (bool) optional

Whether to create an aws_vpc_ipam.


Set to false to build pools inside an IPAM that already exists — the usual
shape for a second instance of this module in another Region, or for pools
managed separately from the IPAM itself. When false, supply
existing_ipam_scope_id, and existing_ipam_id as well if you need the
IPAM-level outputs or any resource discovery association



Default value: true

create_resource_discovery (bool) optional

Whether to create an aws_vpc_ipam_resource_discovery.


Only needed for cross-account or cross-organization monitoring. Every account
already gets a default resource discovery and a default association to its own
IPAM; those surface as the default_resource_discovery_id and
default_resource_discovery_association_id outputs and are not managed here



Default value: false

existing_ipam_id (string) optional

ID of an existing aws_vpc_ipam to build against. Only consulted when create_ipam is false


Default value: null

existing_ipam_scope_id (string) optional

ID of an existing IPAM scope that top-level pools default into. Only consulted
when create_ipam is false.


Required whenever create_ipam is false and pools contains a top-level
pool that does not resolve a scope of its own. Scope IDs are attributes of the
aws_vpc_ipam resource, so there is no way to look a default scope up from an
IPAM ID alone — a caller binding to an existing IPAM has to pass one through



Default value: null

ipam_cascade_enabled (bool) optional

Whether to enable cascade delete on the IPAM.


Delete-time only. The provider reads this solely in its Delete path, so
toggling it produces no API call and no observable change until a destroy.


On destroy it tears down every private scope, every pool inside them, and every
allocation inside those — including address space that is in live use. Without
it, destroying a non-empty IPAM fails, which is usually what you want. Leave
false unless you are deliberately building a disposable environment



Default value: false

ipam_description (string) optional

Description for the IPAM. Defaults to the null-label ID. Only used when create_ipam is true


Default value: null

ipam_tier (string) optional

IPAM tier. Valid values: free, advanced.


Leaving this null inherits the provider's own default of advanced, which is
the billable tier — set free explicitly if that is what you want. Mutable in
place



Default value: null

ipam_timeouts optional

Operation timeouts for the aws_vpc_ipam resource. null entries inherit the provider defaults of 3m each


Type:

object({
create = optional(string, null)
update = optional(string, null)
delete = optional(string, null)
})

Default value: { }

metered_account (string) optional

Which account is metered for IPAM usage. Valid values: ipam-owner,
resource-owner.


Optional and Computed in the provider, so leaving it null never produces a
diff



Default value: null

operating_regions (list(string)) optional

Regions the IPAM may discover, monitor, and allocate from.


The provider requires this to include the Region the module is applied into,
and enforces that at create time only — removing the current Region later
is not blocked by Terraform, though the API may still reject it. When empty,
the module registers just the current Region.


Fully mutable: the provider diffs the set and sends add/remove to ModifyIpam,
so growing or shrinking this list never replaces the IPAM



Default value: [ ]

pool_cidr_timeouts optional

Operation timeouts applied to every aws_vpc_ipam_pool_cidr. null entries
inherit the provider defaults of create 10m and delete 32m.


Do not lower the 32m delete. That budget is the up-to-20-minute window AWS
takes to release VPC and subnet allocations after the consuming resource is
deleted, plus the deprovision wait. Shortening it turns a slow destroy into a
failed one



Type:

object({
create = optional(string, null)
delete = optional(string, null)
})

Default value: { }

pool_timeouts optional

Operation timeouts applied to every aws_vpc_ipam_pool. null entries inherit
the provider defaults.


The provider's 35m create default is not padding — pool provisioning is
genuinely slow. Do not shorten it without a reason



Type:

object({
create = optional(string, null)
update = optional(string, null)
delete = optional(string, null)
})

Default value: { }

pools optional

IPAM pools to create, as a flat map keyed by your own name for each pool.
Keys must be known at plan time.


Hierarchy is expressed by naming another entry in this same map as a pool's
parent, rather than by physically nesting the objects. A pool with no
parent is top-level and sits directly in a scope. A flat keyed map is used
because Terraform cannot express a recursive type — nesting would force
type = any and give up schema documentation and IDE completion — and because
the keys stay stable as pools are added and removed.


Nesting is capped at a depth of 4: a top-level pool plus three generations
beneath it. The cap is a Terraform limitation rather than an AWS one — a
resource cannot reference itself, so an arbitrarily deep tree cannot be built
from a single aws_vpc_ipam_pool block. The module partitions this map by
computed depth and declares four tiers, aws_vpc_ipam_pool.level_0 through
.level_3. A deeper tree, a parent naming no existing pool, and a cycle in
the parent links are each rejected at plan time by a separate check that
names the offending pools.


Each pool's provisioned CIDRs nest under its cidrs, its manual reservations
under its allocations, and its RAM sharing under ram_share



Type:

map(object({
# key is your own name for the pool. It is the key of the `pool_ids`,
# `pool_arns` and `pool_cidrs` outputs, and the value another entry names in
# its `parent`. Keys must be known at `plan` time, and are a compatibility
# contract with your consumers: renaming one replaces the pool.

# Name of the entry in this same map that is this pool's parent. Omit for a
# top-level pool. Nesting is capped at a depth of 4 — see the validations.
parent = optional(string, null)

# --- identity. All ForceNew: changing any of these replaces the pool, and the
# --- replacement cascades to every CIDR, allocation and child pool beneath it.
address_family = optional(string, "ipv4")
locale = optional(string, null)

# Scope selection, in precedence order: an explicit `ipam_scope_id` wins, then
# `scope` naming a key of `var.scopes`, then the parent pool's scope for a
# child, then the IPAM's private default scope.
ipam_scope_id = optional(string, null)
scope = optional(string, null)

# Public-scope pools only. `aws_service` accepts `ec2` or `global-services` —
# the provider validates against the SDK enum, which carries both, even though
# the upstream documentation lists only `ec2`.
aws_service = optional(string, null)
public_ip_source = optional(string, null)

# Cannot be validated from configuration: the provider does a live scope lookup
# during apply and only sends this when `address_family` is `ipv6`, the scope is
# public, and `public_ip_source` is not `amazon`. Setting it when unavailable
# can report erroneous differences.
publicly_advertisable = optional(bool, null)

# VPC resource-planning pool. The block and all four fields are ForceNew, and
# `resource_region` must equal this pool's `locale`.
source_resource = optional(object({
resource_id = string
resource_owner = string
resource_region = string
resource_type = optional(string, "vpc")
}), null) # source_resource

# --- mutable in place. These six are the entire payload `ModifyIpamPool` ever
# --- receives; every other argument above replaces the pool.
#
# Provider defect: the Update path reads these with `d.GetOk` rather than
# `d.HasChange`, and `GetOk` reports a zero value as unset. Resetting
# `auto_import` to `false`, any netmask length to `0`, or `description` to `""`
# is silently dropped — the API never receives it and the old value persists.
# Treat them as one-way; to clear one, replace the pool.
allocation_default_netmask_length = optional(number, null)
allocation_max_netmask_length = optional(number, null)
allocation_min_netmask_length = optional(number, null)
allocation_resource_tags = optional(map(string), {})
auto_import = optional(bool, null)
description = optional(string, null)

# Delete-time only, exactly as `ipam_cascade_enabled`. On destroy this tears
# down the pool's provisioned CIDRs, allocations and child pools. Note the
# pool's own Delete does not *wait* for children the way the CIDR resource
# waits for allocations — without cascade it simply fails on a non-empty pool.
cascade = optional(bool, false)

tags = optional(map(string), {})

# --- CIDRs provisioned into this pool, keyed by an arbitrary name. Every
# --- argument is ForceNew; the resource has no Update function at all.
cidrs = optional(map(object({
# `cidr` and `netmask_length` are mutually exclusive. Set neither and the pool
# must carry `allocation_default_netmask_length` or the apply fails.
cidr = optional(string, null)
netmask_length = optional(number, null)

# BYOIP proof of ownership: the RIR/X.509-signed message and its signature,
# needed solely when provisioning a public BYOIP range into a public-scope
# pool. Never needed for private space, and never for
# `public_ip_source = "amazon"`. Not persisted to state, so it cannot drift.
cidr_authorization_context = optional(object({
message = optional(string, null)
signature = optional(string, null)
}), null) # cidr_authorization_context
})), {}) # cidrs

# --- manual reservations against this pool, keyed by an arbitrary name.
# --- Everything except `tags` is ForceNew; the Update function is a stub that
# --- calls no API.
allocations = optional(map(object({
cidr = optional(string, null)
netmask_length = optional(number, null)

# Ranges IPAM must skip when *choosing* a block. Inert unless paired with
# `netmask_length` — with an explicit `cidr` it does nothing, silently.
disallowed_cidrs = optional(set(string), null)

description = optional(string, null)
tags = optional(map(string), {})
})), {}) # allocations

# --- RAM sharing. Set `principals` to share this pool with other accounts,
# --- organizational units, or the whole organization.
ram_share = optional(object({
principals = optional(set(string), [])
allow_external_principals = optional(bool, false)
permission_arns = optional(set(string), null)
tags = optional(map(string), {})
}), null) # ram_share
}))

Default value: { }

private_gua_enabled (bool) optional

Whether IPAM treats your own globally-unique IPv6 ranges (from 2000::/3) as
private address space. Maps to the provider's enable_private_gua. Mutable in
place



Default value: null

ram_share_permission_arns (list(string)) optional

Default RAM permission ARNs applied to every pool share that does not set its
own permission_arns. Leave empty to let RAM apply its default managed
permission for IPAM pools



Default value: [ ]

region (string) optional

AWS Region for every resource this module creates. Leave null to inherit the
Region from the provider configuration.


Changing this replaces every resource in the module. The provider applies
ForceNew to region through a CustomizeDiff interceptor rather than a schema
flag, so it does not show up as ForceNew in the resource documentation



Default value: null

resource_discovery_associations optional

Resource discoveries to associate with this IPAM, keyed by name. Keys must be
known at plan time. This is the bind step that lets an IPAM in one account see
resources discovered in another. ipam_id defaults to this module's IPAM.


Both IDs are Required but not ForceNew, and the provider's Update function
makes zero API calls — changing either would otherwise plan an in-place update
that does nothing and then reverts on the next refresh. The module forces
replacement itself with replace_triggered_by, so changing an ID here replaces
the association instead of silently doing nothing



Type:

map(object({
# key names the association and fills the null-label `attributes` slot
ipam_id = optional(string, null)
ipam_resource_discovery_id = string
tags = optional(map(string), {})
}))

Default value: { }

resource_discovery_description (string) optional

Description for the resource discovery. Defaults to the null-label ID. Only used when create_resource_discovery is true


Default value: null

resource_discovery_operating_regions (list(string)) optional

Regions the resource discovery monitors. When empty, falls back to
operating_regions, and then to the current Region.


Independent of operating_regions: the provider keeps the two sets in no sync
whatsoever. The IPAM's set governs which locale values pools may use; this
one governs which Regions get discovered and monitored. A discovery can watch a
Region the IPAM cannot allocate into, and vice versa.


Like the IPAM's set, this must include the current Region at create time, and
that rule is enforced on create only



Default value: [ ]

resource_discovery_organizational_unit_exclusions (list(string)) optional

AWS Organizations entity paths to exclude from discovery — Organizations IDs
joined by /. End a path with /* to exclude all child OUs. Subject to the
documented IPAM quota on exclusions



Default value: [ ]

scopes optional

Additional private IPAM scopes to create, keyed by name. Keys must be known
at plan time.


Additional public scopes cannot be created — CreateIpamScope only ever
produces a private scope, and there is no scope-type argument anywhere in the
provider schema. The single public scope is the one IPAM creates alongside
itself; consume it read-only through the public_default_scope_id output.


Only description is mutable; it is the one field ModifyIpamScope accepts



Type:

map(object({
# key is the scope name, used for the null-label `attributes` slot, as the key
# of the `scope_ids` output, and as the value a pool's `scope` names
description = optional(string, null)
tags = optional(map(string), {})
}))

Default value: { }

Context Variables​

The following variables are defined in the context.tf file of this module and part of the terraform-null-label pattern.

additional_tag_map (map(string)) optional

Additional key-value pairs to add to each map in tags_as_list_of_maps. Not added to tags or id.
This is for some rare cases where resources want additional configuration of tags
and therefore take a list of maps with tag key, value, and additional configuration.


Required: No

Default value: { }

attributes (list(string)) optional

ID element. Additional attributes (e.g. workers or cluster) to add to id,
in the order they appear in the list. New attributes are appended to the
end of the list. The elements of the list are joined by the delimiter
and treated as a single ID element.


Required: No

Default value: [ ]

context (any) optional

Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as null to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional_tag_map, which are merged.


Required: No

Default value:

{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"descriptor_formats": {},
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"labels_as_tags": [
"unset"
],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {},
"tenant": null
}
delimiter (string) optional

Delimiter to be used between ID elements.
Defaults to - (hyphen). Set to "" to use no delimiter at all.


Required: No

Default value: null

descriptor_formats (any) optional

Describe additional descriptors to be output in the descriptors output map.
Map of maps. Keys are names of descriptors. Values are maps of the form
\{<br/> format = string<br/> labels = list(string)<br/> \}
(Type is any so the map values can later be enhanced to provide additional options.)
format is a Terraform format string to be passed to the format() function.
labels is a list of labels, in order, to pass to format() function.
Label values will be normalized before being passed to format() so they will be
identical to how they appear in id.
Default is {} (descriptors output will be empty).


Required: No

Default value: { }

enabled (bool) optional

Set to false to prevent the module from creating any resources
Required: No

Default value: null

environment (string) optional

ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'
Required: No

Default value: null

id_length_limit (number) optional

Limit id to this many characters (minimum 6).
Set to 0 for unlimited length.
Set to null for keep the existing setting, which defaults to 0.
Does not affect id_full.


Required: No

Default value: null

label_key_case (string) optional

Controls the letter case of the tags keys (label names) for tags generated by this module.
Does not affect keys of tags passed in via the tags input.
Possible values: lower, title, upper.
Default value: title.


Required: No

Default value: null

label_order (list(string)) optional

The order in which the labels (ID elements) appear in the id.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present.


Required: No

Default value: null

label_value_case (string) optional

Controls the letter case of ID elements (labels) as included in id,
set as tag values, and output by this module individually.
Does not affect values of tags passed in via the tags input.
Possible values: lower, title, upper and none (no transformation).
Set this to title and set delimiter to &#34;&#34; to yield Pascal Case IDs.
Default value: lower.


Required: No

Default value: null

labels_as_tags (set(string)) optional

Set of labels (ID elements) to include as tags in the tags output.
Default is to include all labels.
Tags with empty values will not be included in the tags output.
Set to [] to suppress all generated tags.
Notes:
The value of the name tag, if included, will be the id, not the name.
Unlike other null-label inputs, the initial setting of labels_as_tags cannot be
changed in later chained modules. Attempts to change it will be silently ignored.


Required: No

Default value:

[
"default"
]
name (string) optional

ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
This is the only ID element not also included as a tag.
The "name" tag is set to the full id string. There is no tag with the value of the name input.


Required: No

Default value: null

namespace (string) optional

ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique
Required: No

Default value: null

regex_replace_chars (string) optional

Terraform regular expression (regex) string.
Characters matching the regex will be removed from the ID elements.
If not set, &#34;/[^a-zA-Z0-9-]/&#34; is used to remove all characters other than hyphens, letters and digits.


Required: No

Default value: null

stage (string) optional

ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'
Required: No

Default value: null

tags (map(string)) optional

Additional tags (e.g. {&#39;BusinessUnit&#39;: &#39;XYZ&#39;}).
Neither the tag keys nor the tag values will be modified by this module.


Required: No

Default value: { }

tenant (string) optional

ID element (Rarely used, not included by default). A customer identifier, indicating who this instance of a resource is for
Required: No

Default value: null

Outputs​

allocation_cidrs

Map from &lt;pool name&gt;/&lt;allocation name&gt; to the CIDR reserved by each manual reservation

allocation_ids

Map from &lt;pool name&gt;/&lt;allocation name&gt; to the AWS allocation ID of each
manual reservation.


This is ipam_pool_allocation_id, not the Terraform resource ID — the latter
is the composite &lt;allocation id&gt;_&lt;pool id&gt; and is what terraform import
takes


allocations

Map from &lt;pool name&gt;/&lt;allocation name&gt; to the full aws_vpc_ipam_pool_cidr_allocation resource (all attributes), including resource_id, resource_owner, resource_type and netmask_length

default_resource_discovery_association_id

ID of the resource discovery association IPAM creates alongside itself. Not managed by this module

default_resource_discovery_id

ID of the resource discovery IPAM creates alongside itself. Not managed by this module

ipam

The full aws_vpc_ipam resource created by this module (all attributes). null when create_ipam is false

ipam_arn

ARN of the IPAM created by this module. null when create_ipam is false

ipam_id

ID of the IPAM — the one created here, or existing_ipam_id when create_ipam is false

pool_arns

Map from the keys of pools to the ARN of each created pool, flattened across every depth tier

pool_cidr_ids

Map from &lt;pool name&gt;/&lt;cidr name&gt; to the Terraform ID of each provisioned pool CIDR, which is the composite &lt;cidr&gt;_&lt;pool id&gt;

pool_cidrs

Map from the keys of pools to the list of CIDRs provisioned into that pool.


A pool with no provisioned CIDRs maps to an empty list. Values for CIDRs
requested by netmask_length are chosen by IPAM and so are only known after
apply


pool_cidrs_detail

Map from &lt;pool name&gt;/&lt;cidr name&gt; to the full aws_vpc_ipam_pool_cidr resource (all attributes), flattened across every depth tier

pool_ids

Map from the keys of pools to the ID of each created pool, flattened across
every depth tier.


This is the module's primary interface. The keys are the ones you supplied, so
a downstream component can re-export this map whole and let its own consumers
index it by name without knowing anything about the pool hierarchy


pool_names

Map from the keys of pools to the null-label ID generated for each pool —
the value used as that pool's Name tag and as its default description


pool_scope_ids

Map from the keys of pools to the scope each pool was created in, flattened across every depth tier

pool_states

Map from the keys of pools to the state of each created pool, flattened across every depth tier

pools

Map from the keys of pools to the full aws_vpc_ipam_pool resource (all attributes), flattened across every depth tier

private_default_scope_id

ID of the IPAM's private default scope, which top-level pools land in unless they name another

public_default_scope_id

ID of the IPAM's public default scope. Read-only: additional public scopes
cannot be created, so this is the only public scope there will ever be.
null when create_ipam is false


ram_resource_share_arns

Map from the keys of pools that requested RAM sharing to the ARN of that pool's resource share

ram_resource_shares

Map from the keys of pools that requested RAM sharing to the full aws_ram_resource_share resource (all attributes)

resource_discovery

The full aws_vpc_ipam_resource_discovery resource created by this module (all attributes, including owner_id and is_default). null when create_resource_discovery is false

resource_discovery_arn

ARN of the resource discovery created by this module. null when create_resource_discovery is false

resource_discovery_association_ids

Map from the keys of resource_discovery_associations to the ID of each association

resource_discovery_associations

Map from the keys of resource_discovery_associations to the full aws_vpc_ipam_resource_discovery_association resource (all attributes, including state, owner_id and ipam_arn)

resource_discovery_id

ID of the resource discovery created by this module. null when create_resource_discovery is false

scope_arns

Map from the keys of scopes to the ARN of each created scope

scope_count

Number of scopes on the IPAM, including the two default ones

scope_ids

Map from the keys of scopes to the ID of each created scope

scopes

Map from the keys of scopes to the full aws_vpc_ipam_scope resource (all attributes)

Dependencies​

Requirements​

  • terraform, version: >= 1.4.0
  • aws, version: >= 6.56.0

Providers​

  • aws, version: >= 6.56.0
  • terraform

Modules​

NameVersionSourceDescription
pool_label0.25.0cloudposse/label/nulln/a
resource_discovery_association_label0.25.0cloudposse/label/nulln/a
scope_label0.25.0cloudposse/label/nulln/a
this0.25.0cloudposse/label/nulln/a

Resources​

The following resources are used by this module:

Data Sources​

The following data sources are used by this module: