Working with list comprehensions can be pretty tricky. A few things
- Unable to map the value when i have nested map variable - #2 by wyardley This comment has the basic approach I like to take when solving things like this. Having that simple self-contained example and an output means you can test / iterate quickly
- Maybe a list of objects will work better than an object of objects? If not, though, you’ll probably need a compound key (like
application1-uksouth, and havename: application1within the nested object, since you can’t have two map / object elements with the same key. A lot of times, finding the right data structure is half the battle. - Check out
flatten()(flatten - Functions - Configuration Language | Terraform | HashiCorp Developer),merge(), and the spread operator (...).
This post might also be worth a look
This works for me as a basic POC to generate a list of anonymous objects:
locals {
apps = yamldecode(file("${path.root}/applications_config.yaml"))
test = flatten([
for name, properties in local.apps.applications : [
for region in properties.region : {
name = name,
region = region,
}
]
])
}
output "test" {
value = local.test
}
[
{
"name" = "application1"
"region" = "uksouth"
},
{
"name" = "application1"
"region" = "ukwest"
},
{
"name" = "application2"
"region" = "uksouth"
},
]
or you could do something like
test = [
for name, properties in local.apps.applications : {
for region in properties.region : "${name}-${region}" => {
name = name,
region = region,
}
}
]
which would give you
[
{
"application1-uksouth" = {
"name" = "application1"
"region" = "uksouth"
}
"application1-ukwest" = {
"name" = "application1"
"region" = "ukwest"
}
},
{
"application2-uksouth" = {
"name" = "application2"
"region" = "uksouth"
}
},
]
To further flatten the rest of the properties (and, full disclosure, asked an AI tool for this part vs. playing around with getting that final merge right here), you could do something like:
test = flatten([
for name, properties in local.apps.applications : [
for region in properties.region : merge(
properties,
{
application = name,
region = region
}
)
]
])
Which gets you:
[
{
"application" = "application1"
"install" = "install.bat"
"name" = "App1"
"region" = "uksouth"
"source" = "blob url"
"uninstall" = "uninstall.bat"
"version" = "1.0.0"
},
{
"application" = "application1"
"install" = "install.bat"
"name" = "App1"
"region" = "ukwest"
"source" = "blob url"
"uninstall" = "uninstall.bat"
"version" = "1.0.0"
},
{
"application" = "application2"
"install" = "install.bat"
"name" = "App2"
"region" = "uksouth"
"source" = "blob url"
"uninstall" = "uninstall.bat"
"version" = "1.0.1"
},
]
You could do something roughly equivalent with either a nested object or a list of objects, but this last one seems the easiest to work with to me.