Notes on Terraform
How to use flatten to iterate into a nested list
To simplify the configuration you could want a nested who is a map of list. This can be useful to associate, for example, a CNAME to multiple domains:
variable "cnames" {
description = "The CNAMEs associated with the domain"
type = map(list(string))
default = {
"toto" = [
"*",
"dolibarr",
"grafana",
"influxdb",
"iot",
],
"domotic" = [
"bitwarden",
"emby",
]
}
}
Using this structure, we can create associations like:
- toto -> dolibarr
- toto -> grafana
- etc…
To do this, we need a local variable, which can be declared like this:
# Flatten the cname to allow processing in a for each
locals {
cnames = flatten([
for target, cname_targets in var.cnames : [
for orign in cname_targets : {
origin = orign
target = target
}
]
]
)
}
This can be translated into python as:
cnames = []
for target, cname_targets in var.cnames:
for origin in cname_targets:
cnames.append({
"origin": origin,
"target": target,
})
So we transformed this:
{
"toto" = [
"*",
"dolibarr",
"grafana",
"influxdb",
"iot",
],
"domotic" = [
"bitwarden",
"emby",
]
}
to this:
[
{"origin": "toto", "target": "*"},
{"origin": "toto", "target": "dolibarr"},
{"origin": "toto", "target": "grafana"},
{"origin": "toto", "target": "influxdb"},
{"origin": "toto", "target": "iot"},
{"origin": "domotic", "target": "bitwarden"},
{"origin": "domotic", "target": "emby"},
]
This will allow us to use a for each in the resource:
resource "ovh_domain_zone_record" "cnames" {
for_each = { for cname_assoc in local.cnames : "${cname_assoc.origin}-${cname_assoc.target}" => cname_assoc }
zone = "moospirit.org"
subdomain = each.value.origin
fieldtype = "CNAME"
ttl = var.dns-ttl
target = each.value.target
}
The magic from this snippet:
{ for cname_assoc in local.cnames : "${cname_assoc.origin}-${cname_assoc.target}" => cname_assoc }
This instruction is to iterate in the local.cnames
list we have created earlier, and create a key-value pair in the for, with this form:
{"toto-dolibarr": {"origin": "toto", "target": "dolibarr"} }
We can create the key from the content of the map that has been flattened. Which in turn allow us to reference variable from the map with:
each.value.orign
To import, we need to use the bracket definition, ex:
terraform import ovh_domain_zone_record.cnames["toto-dolibar"] 126864.ovh.com