I want to create Hosted zones and Route53 records in it in AWS.
For that reason I am creating such a variable:
variable "hosted_zones_domains" {
description = "Map of hosted zones to their domains and corresponding IPs"
type = map(map(string))
default = {
"first-example.com" = {
"beta.first-example.com" = "192.168.0.1",
"stage.first-example.com" = "192.168.0.2",
"prod.first-example.com" = "192.168.0.3"
},
"second-example.com" = {
"beta.second-example.com" = "192.168.1.1",
"stage.second-example.com" = "192.168.1.2",
"prod.second-example.com" = "192.168.1.3"
}
}
}
I am able to create Hosted zones
resource "aws_route53_zone" "subdomain_zone" {
for_each = var.hosted_zones_domains
name = each.key
tags = {
Environment = var.environment
}
}
But I have no idea how to iterate through the inner map to get records names and values and use it in aws_route53_record resource.
2
Answers
OK, so this is how I make that to work.
in my root directory I've added locals
Then passed that to submodule zone_domain_pairs = local.zone_domain_pairs
And then in submodule something like that
Thanks guys for your help!
The main rule for
for_each
is that you need a map with one element per instance of the resource you want to declare.In this case, your
for_each
meets that requirement for the zones — each element of the top-level map represents one zone — but it’s not yet suitable for declaring the records themselves. You’ll need to derive a new map that has one element per record across all of the zones.You can derive a suitable flattened map with one element per recordset (which Route53 confusingly calls a "record") like this:
With the default value you showed for the variable, the value of
local.all_records
would be the following:Notice that the zone names are now part of the values of the map, and that the records themselves are toplevel.
Your record names already include the name of the zone they belong to, so the record name alone is a sufficient unique key for tracking each element, which avoids the usual need to concatenate multiple keys together when doing flattening in this way. If you’d like to see an example which does need key concatenation (In case you need to solve a similar problem in future where the inner keys are not sufficiently unique, refer to Flattening nested structures for
for_each
for another example which achieves a similar effect in a different way.)You can then use
local.all_records
as thefor_each
for your Route53 zone resource:Notice that
each.value.zone_name
will always match one of the keys from the originalvar.hosted_zones_domains
value, and so will also match one of the instance keys ofaws_route53_zone.subdomain_zone
. Therefore you can use this connection to correlate the records with the zones so that each record ends up attached to the zone it ought to be attached to.