'terraform - how to make aws_subnet resource take next available cidr_block?

I am using this code:

resource "aws_subnet" "subnet" {
  vpc_id            = var.vpc_id
  cidr_block        = var.subnet_cidr_block
  availability_zone = var.availability_zone
}

And in variables.tf:

variable "subnet_cidr_block" {
  type = string
  default = "<some ip address>/<some number>"
    description = "the block for your subnet, please check on AWS which address is available in the VPC"
}

Since this is the default VPC there are several subsets inside it already, so every time when I use this code I need to log into AWS and check what is the next available address. Is there any way that transformer can pick up the next available address and take it? any function?

Thank you.



Solution 1:[1]

Terraform can only work with what the underlying AWS API provides, and as far as I know there is no mechanism in EC2 for explicitly tracking allocations of subnets in a way that allows you to request to be assigned a new one without deciding ahead of time what address it will have. If the EC2 API had such a feature then in principle you could omit cidr_block entirely when declaring a subnet and have the remote system determine automatically which range to use, in a similar manner to what happens if you declare an aws_instance without specifying a specific private_ip. However, there is no such feature in the API.

With Terraform itself, the best we can do is to make a single Terraform configuration that itself defines the whole address allocation scheme and then use that resulting data structure to populate all of the aws_subnet blocks. That does require you to centrally manage the address space all in one place, because otherwise there is nothing to keep track of what has already been allocated and what has not.

Because this is a common situation, HashiCorp offers a utility module hashicorp/subnets/cidr which takes a list of all of your subnet allocations and encapsulates the calculations needed to produce the CIDR block for each one:

module "subnet_addrs" {
  source = "hashicorp/subnets/cidr"

  base_cidr_block = "10.0.0.0/16"
  networks = [
    {
      name     = "us-west-2a"
      new_bits = 8
    },
    {
      name     = "us-west-2b"
      new_bits = 8
    },
  ]
}

resource "aws_vpc" "example" {
  cidr_block = module.subnet_addrs.base_cidr_block
}

resource "aws_subnet" "example" {
  for_each = module.subnet_addrs.network_cidr_blocks

  vpc_id            = aws_vpc.example.id
  availability_zone = each.key
  cidr_block        = each.value
}

The README for the module explains what rules you need to abide by in order to change the address space allocations over time without disrupting existing networks, so if you do choose to use this module be sure to read its documentation in addition to my example above (which I copied from the README).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Martin Atkins