I am wondering that given the following vars, would it be possible to create a map of lists
variable “subnets” {
type = list(object())
default [
{
name = “subnet1”
cidr_block = “10.0.1.0/24”
},
{
name = “subnet2”
cidr_block = “10.0.2.0/24”
},
]
variable “zones” {
type = list(string)
default = [“zone1”, “zone2”]
}
so this would leave me with something like:
variable "subnets_mapped" {
{
name = "subnet1"
cidr_block = "10.0.1.0/24"
zone = zone1
},
{
name = "subnet1"
cidr_block = "10.0.1.0/24"
zone = zone2
},
{
name = "subnet2"
cidr_block = "10.0.2.0/24"
zone = zone1
},
{
name = "subnet2"
cidr_block = "10.0.2.1/24"
zone = zone2
},
hope I’m coming across right here
Hi @21andrewmitchell,
I think something like the following would get a result like that:
variable "subnets" {
type = list(object({
name = string
cidr_block = string
}))
}
variable "zones" {
type = list(string)
validation {
condition = length(var.zones) > 0
error_message = "At least one zone name is required."
}
}
locals {
subnets_in_zones = tolist([
for i, sn in var.subnets : {
name = sn.name
cidr_block = sn.cidr_block
zone = element(var.zones, i)
}
])
}
The above is relying on the special behavior of the element
function where it responds to an index greater than the maximum list index by wrapping around to the start of the list using a modulo operation. Since i
in this for
expression will count up 0, 1, 2, 3, it’ll end up selecting var.zones
elements 0, 1, 0, 1, which I think matches the result you were hoping for.
Because the element
function requires a list with at least one element, I also added a custom validation rule to variable "zones"
which should then reject an empty list at a source location in the calling module, rather than directly at the element
call.
Hi @apparentlymart I have this a shot and it doesn’t seem to give the desired output, so what I am getting from thee above example where zones is a list of three zones is
subnets_in_zones = [
{
cidr_block = "10.0.0.0/24
name = "subnet1"
zone = "zone1"
},
{
cidr_block = "10.0.1.0/24
name = "subnet2"
zone = "zone2"
}
so rather than giving me 6 objects I am getting two
Aha, sorry I understand better now what your intent was… it sounds like you want to find every combination of subnet and zone, rather than to assign one zone to each subnet (which is what I implemented before).
Aside from the object types being different, I think what you are looking for here essentially matches the problem being described in setproduct
: Finding combinations for for_each
, and so hopefully the long-form explanation there will tell you about the building blocks for solving this, and then you can adapt it to your situation. If you run into problems adapting that example, please let me know what you’ve tried and I’ll try to see what’s missing. Thanks!