Working with the cidrsubnets function in Terraform is a bit of a pain – but it’s so extremely handy for automated networking that it’s worth spending the time to figure it out. Suffice to say, I am not going to dig deep on how to use cidrsubnets; rather I am going to bring up a really handy and (as far as I can tell) “not documented” method for supplying a list of “newbits” values to this function.

Cidrsubnets has the following usage:

cidrsubnets(prefix, newbits...)



An example would be like this (all stolen from the Hashi documentation):

cidrsubnets("10.1.0.0/16", 4, 4, 8, 4)
[
  "10.1.0.0/20",
  "10.1.16.0/20",
  "10.1.32.0/24",
  "10.1.48.0/20",
]



I was creating a re-usable “quick networking” module and was using this function to do subnetting for me. I wanted to allow the module end-user to be able to supply a list of “newbits” as a variable input into my module. So the module call would look something like this:

module "easynetworking" {
  source = "../.."
  vnet = "10.25.0.0/16"
  subnets = [8,8]
}



The module itself (this is for Azure) would take that information (and some other stuff) and create a virtual network and however many subnets at the sizes specified in the input. Seemed like a great idea. Inside my module code I tried this:

locals {
  subnet_list = cidrsubnets(var.vnet, var.subnets)
}



Which (following the above examples) should have resulted in something like this happening…

cidrsubnets("10.25.0.0/16", 8, 8)
[
  "10.25.0.0/24",
  "10.25.1.0/24"
]



This doesn’t work. The cidrsubnets function won’t take a list input like that and I tried all manner of nonsense like these (non-working code examples):

locals {
  subnet_list = cidrsubnets(var.vnet, var.subnets[*])
}


locals {
  subnet_list = cidrsubnets(var.vnet, join("," , var.subnet_cidrs))
}

–and things just got more profane from here–

However, somewhere on the internet, probably in a random Stack Overflow post, someone posted the below syntax – which does work (I stumbled across this months ago and failed to document it, no idea where I found it…):

locals {
  subnet_list = cidrsubnets(var.vnet, var.subnets[*]...)
}

Note the triple dot notation “…” after the splat.


And just for the sake of completeness – here is a fully working local example:

locals {
  vnet        = "10.30.0.0/16"
  subnets     = [4,3,8]
  subnet_list = cidrsubnets(local.vnet, local.subnets[*]...)
}

output "subnet_list" {
   value = local.subnet_list
}



I have been looking through Hashi’s documentation and I can’t find that “[*]…” syntax – if you are reading this article and happen to know if and where it is documented, please respond and post the link. Better yet, tell me if there is a simpler way. For the time being, all I can say is that the above works in the cidersubnets function and it’s not nearly as ugly as some of the other things I attempted.

1 of 1

This post has no comments. Be the first to leave one!

Join the discussion

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