I feel like this is really easy and obvious, but for the life of me I can’t figure out how I should be approaching it.
I have a list of environments I wish to build ["env1", "env2"…], and then I have a map that specifies the values used for a specific environment.
"wanted_envs": ["env1", "env2"]
"envs": {
"env1": {
"type": "prod",
"backend": "cust-prod-backend-vpc",
"backend_subnet": "192.168.0.0/22",
"k8_pod_subnet": "192.168.35.16.0/20",
"k8_service_subnet": "192.168.40.0/20",
"gateway_subnet": "1.2.3.0/27",
"dmz": "env1"
},
"env2": {
"type": "prod",
"backend": "cust-prod-backend-vpc",
"backend_subnet": "192.168.0.0/22",
"k8_pod_subnet": "192.168.35.16.0/20",
"k8_service_subnet": "192.168.40.0/20",
"gateway_subnet": "1.2.3.0/27",
"dmz": "env2"
},
"env3": {
"type": "prod",
"backend": "cust-prod-backend-vpc",
"backend_subnet": "192.168.0.0/22",
"k8_pod_subnet": "192.168.35.16.0/20",
"k8_service_subnet": "192.168.40.0/20",
"gateway_subnet": "1.2.3.0/27",
"dmz": "env3"
},
......
I simply need to create a local variable, which contains the details of the environments I wish to build (listed in my list of strings) copied from the map in envs.
In my locals definition I’ve tried various forms of for_each thinking I can get the value from the list of required envs, but I can’t quite figure it out without just getting errors from doing the ‘wrong’ thing with terraform.
I would end up with a map, containing only the values for the envs listed in wanted_envs.
Like so:
"envs_to_build": {
"env1": {
"type": "prod",
"backend": "cust-prod-backend-vpc",
"backend_subnet": "192.168.0.0/22",
"k8_pod_subnet": "192.168.35.16.0/20",
"k8_service_subnet": "192.168.40.0/20",
"gateway_subnet": "1.2.3.0/27",
"dmz": "env1"
},
"env2": {
"type": "prod",
"backend": "cust-prod-backend-vpc",
"backend_subnet": "192.168.0.0/22",
"k8_pod_subnet": "192.168.35.16.0/20",
"k8_service_subnet": "192.168.40.0/20",
"gateway_subnet": "1.2.3.0/27",
"dmz": "env2"
}
}
>Solution :
Using a for expression can get you what you need. Consider the following shortened example.
locals {
envs = {
env1 = {
prop = "foo"
},
env2 = {
prop = "bar"
},
env3 = {
prop = "baz"
}
}
targets = ["env1", "env3"]
}
output "target_envs" {
value = [for k, v in local.envs : v if contains(local.targets, k)]
}
This yields the output of:
Changes to Outputs:
+ target_envs = [
+ {
+ prop = "foo"
},
+ {
+ prop = "baz"
},
]
And if you want to maintain the keys, as in your edit, one can do it like so:
locals {
envs = {
env1 = {
prop = "foo"
},
env2 = {
prop = "bar"
},
env3 = {
prop = "baz"
}
}
targets = ["env1", "env3"]
}
output "target_envs" {
value = { for k, v in local.envs : k => v if contains(local.targets, k) }
}
which yields:
Changes to Outputs:
+ target_envs = {
+ env1 = {
+ prop = "foo"
}
+ env3 = {
+ prop = "baz"
}
}