Hi,
This can be quite tricky to get a good understanding of in Terraform, so I will illustrate one possible solution and then try and explain the ‘clever’ bit.
Your required result is to have an ovh_domain_zone_record
resource created for each pair of domain+a_record therefore you need to pass an appropriately formed map to the for_each of this resource block such that it can iterate through and create all of the records across the domains:
locals {
# Source Local Variable containing a list of domains with a list of A records and CNAME records
dns = {
server_ip = "172.168.10.1"
domains = [
{
domain = "mydomain1.fr"
a_records = ["fred", "bob", "alice"]
cname_records = []
},
{
domain = "mydomain2.de"
a_records = ["janet", "joe", "jill"]
cname_records = []
}
]
}
}
locals {
# local variable that merges the domain and a_record lists to provide a unique key for each domain+a_record pair
# use this variable as your input to for_each (or copy the expression directly into for_each)
zone_records = merge(
[ for domain in local.dns.domains :
{ for a_record in domain.a_records :
"${domain.domain}_${a_record}" => {
domain = domain.domain
a_record = a_record }
}
]
...)
}
resource "ovh_domain_zone_record" "a_records" {
for_each = local.zone_records
zone = each.value.domain
subdomain = each.value.a_record
fieldtype = "A"
ttl = 300
target = var.dns.server_ip
}
output "zone_records" {
value = local.zone_records
}
Explanation
What this is doing is creating a map containing a maps of objects (given the above inputs) where each map item has a ‘composite’ key, composed of the domain
and the a_record
, and each map value contains an object with a_record
and domain
properties:
{
"mydomain1.fr_alice" = {
"a_record" = "alice"
"domain" = "mydomain1.fr"
}
"mydomain1.fr_bob" = {
"a_record" = "bob"
"domain" = "mydomain1.fr"
}
"mydomain1.fr_fred" = {
"a_record" = "fred"
"domain" = "mydomain1.fr"
}
"mydomain2.de_janet" = {
"a_record" = "janet"
"domain" = "mydomain2.de"
}
"mydomain2.de_jill" = {
"a_record" = "jill"
"domain" = "mydomain2.de"
}
"mydomain2.de_joe" = {
"a_record" = "joe"
"domain" = "mydomain2.de"
}
}
The clever bit is this:
merge(
[ for domain in local.dns.domains :
{ for a_record in domain.a_records :
"${domain.domain}_${a_record}" => {
domain = domain.domain
a_record = a_record }
}
]
...)
merge(
- I will describe this separately below
- “
[ for domain in local.dns.domains :
” - Loop over each item in local.dns.domains creating a list
- Within this outer loop
“{ for a_record in domain.a_records :
” - Loop over each item in domain.a_records creating a map
- Within this inner loop
“"${domain.domain}_${a_record}" => {
” Create map entry with composite key containing an object
- Object contains a
domain
and a_record
property with the appropriate values }
}
Close the Map
]
Close the list
The merge([list]...)
takes the output of the above steps which now is structured like this:
[
{
"mydomain1.fr_alice" = {
"a_record" = "alice"
"domain" = "mydomain1.fr"
}
"mydomain1.fr_bob" = {
"a_record" = "bob"
"domain" = "mydomain1.fr"
}
"mydomain1.fr_fred" = {
"a_record" = "fred"
"domain" = "mydomain1.fr"
}
},
{
"mydomain2.de_janet" = {
"a_record" = "janet"
"domain" = "mydomain2.de"
}
"mydomain2.de_jill" = {
"a_record" = "jill"
"domain" = "mydomain2.de"
}
"mydomain2.de_joe" = {
"a_record" = "joe"
"domain" = "mydomain2.de"
}
},
]
Which is a list(map(object()))
“merge()
” merges each map into a single map after first expanding “...
” each item in the list into a separate argument for input into the merge function. Which results in a map(map(object())
When using nested for loops and trying to create a flattened data structure from a complex collection that is able to be used as a input for a for_each
iteration it is usually better to break the problem down into smaller parts.
You can use the terraform console to experiment but I usually create a separate simple module with a single main.tf file and work through the problem using local variables and outputs until I have got to my desired structure. This can then be ‘ported’ into my main terraform module with a good understanding.
Hope that helps!
Happy Terraforming