When I had a single hosted zone it was easy for me to create the zone and then create the NS records for the zone in the delegating account by referencing the hosted zone by name.
Now I need to create multiple hosted zones and pass the nameserver records back to the parent account and I am not sure if its possible (or how if it is) to reference multiple resources. Reading this probably doesn't make a whole lot of sense, so the code below is as far as I have got.
I now have a for_each
loop which will loop over a list of strings and create a hosted zone for each string, and I want to then create corresponding NS records in another account, notice that I am using a separate provider provider = aws.management_account
to connect to the management account and this works fine for a single hosted zone.
I do not know how to reference the hosted zones, is there some syntax for this or is my approach wrong?
resource "aws_route53_zone" "public_hosted_zone" {
for_each = local.aws_zones
name = "${each.value}.${var.domain}"
}
resource "aws_route53_record" "ns_records" {
for_each = local.aws_zones
provider = aws.management_account
allow_overwrite = true
name = "${each.value}.${var.domain}"
ttl = 30
type = "NS"
zone_id = data.aws_ssm_parameter.public_hosted_zone_id.value
records = [
aws_route53_zone.public_hosted_zone.name_servers[0], # Here is my old code which works for a single hosted zone but I cannot work out how to reference multiples created above
aws_route53_zone.public_hosted_zone.name_servers[1],
aws_route53_zone.public_hosted_zone.name_servers[2],
aws_route53_zone.public_hosted_zone.name_servers[3]
]
}
Since your local.aws_zones
is set ["dev", "test", "qa"], your aws_route53_zone.public_hosted_zone
will be a map with keys "dev", "test", "qa".
Therefore, to use it in your aws_route53_record
, you can try:
resource "aws_route53_record" "ns_records" {
for_each = local.aws_zones
# other attributes
records = aws_route53_zone.public_hosted_zone[each.key].name_servers
}
In this case it seems like your intent is to say "there is one zone per entry in local.aws_zones
and then one NS recordset per zone".
In situations like that, a concise way to write that down is to use one resource as the for_each
of the next, like this:
resource "aws_route53_zone" "public_hosted_zone" {
for_each = local.aws_zones
name = "${each.value}.${var.domain}"
}
resource "aws_route53_record" "ns_records" {
provider = aws.management_account
for_each = aws_route53_zone.public_hosted_zone
allow_overwrite = true
name = each.value.name
ttl = 30
type = "NS"
zone_id = data.aws_ssm_parameter.public_hosted_zone_id.value
records = each.value.name_servers
}
By using for_each
inside resource "aws_route53_zone" "public_hosted_zone"
you make aws_route53_zone.public_hosted_zone
be a map from zone keys to zone objects, which is itself compatible with the expectations of for_each
and so you can pass that map downstream to another resource.
An important advantage of this approach is that each.value
in the resource "aws_route53_record" "ns_records"
block is the corresponding zone object directly, and so we can write each.value.name
to get the derived name
argument from the zone without having to duplicate that expression again, and we can write each.value.name_servers
to get the exported set of nameservers for each of the zones. That then avoids writing more complex expressions to look up zones by each.key
, because Terraform has already done the necessary lookup to populate each.value
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With