Terraform – FotD – cidrsubnet()

This is part of an ongoing series of posts documenting the built-in interpolation functions in Terraform. For more information, check out the beginning post. In this post I am going to cover the cidrsubnet() function. The example file is on GitHub here.

What is it?

Function name: cidrsubnet(iprange,newbits,netnum)

Returns: Takes an IP address range in CIDR notation and adds the newbits to the the subnet mask. Then it finds the network in the original CIDR range with the network number in netnum. It returns the new subnet in CIDR notation. This is confusing at first, but it’s really meant to divide up a larger subnet into smaller subnets.

Example:

variable "iprange" {
  default = "10.0.0.0/16"
}

# Returns 10.0.1.0/24
output "cidrsubnet" {
  value = "${cidrsubnet(var.iprange,8,1)}"
}

Example file:

##############################################
# Function: cidrsubnet
##############################################
##############################################
# Variables
##############################################
variable "iprange" {
  default = "10.0.0.0/16"
}

variable "newbits" {
  default = 4
}

variable "netnum" {
  default = 0
}

##############################################
# Resources
##############################################

##############################################
# Outputs
##############################################
output "1_iprange" {
  value = "${var.iprange}"
}

output "2_newbits" {
  value = "${var.newbits}"
}

output "3_netnum" {
  value = "${var.netnum}"
}

output "4_cidrsubnet_output" {
  value = "${cidrsubnet(var.iprange,var.newbits,var.netnum)}"
}

Run the following from the cidrsubnet folder to get example output for a number of different cases:

terraform apply -var "iprange=172.16.0.0/24" -var "newbits=2" -var "netnum=0"

terraform apply -var "iprange=172.16.0.0/24" -var "newbits=4" -var "netnum=2"

terraform apply -var "iprange=172.16.0.0/24" -var "newbits=-8" -var "netnum=20"

terraform apply -var "iprange=10.0.0.0/8" -var "newbits=16" -var "netnum=40"

#Fails with negative number for netnum
terraform apply -var "iprange=172.16.0.0/24" -var "newbits=2" -var "netnum=-1"

#Fails with invalid subnet net number
terraform apply -var "iprange=172.16.0.0/24" -var "newbits=2" -var "netnum=255"

#Results in the 0.0.0.0 address range
terraform apply -var "iprange=172.16.0.0/0" -var "newbits=2" -var "netnum=0"

Why use it?

Whenever I am creating a new network in AWS or Azure and need to parcel out subnets, this function is my best friend. My most common use case is using the cidrsubnet function with the count.index to split a large subnet range into private and public subnets in a VPC.

Lessons Learned

The function does not like getting a negative number for the netnum. I thought it would count backwards from the highest subnet, like cidrhost does, but it errors out instead. The interesting thing I found was submitting a CIDR network with 0 as the subnet mask results in the function returning 0.0.0.0 for the network. It doesn’t handle that value well, so maybe don’t do that. It is also possible to submit a negative number for the newbits, though I have no idea why you would want to do that.

Coming up next is the coalesce() function, which is one of my favorite words and bands.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.