Looping through a Map to create route53 zone and records

Hi @jeffery,

A key issue with this situation is that count works with zero-based incrementing integers as instance identifiers, which is not compatible with a map that uses string keys. The first step here then is to translate the map into a list so that each element is assigned an index. That requires deciding on a suitable ordering for the items in that list, but if you don’t have a strong need for any particular ordering you can just accept the default lexical ordering of keys done by a for expression:

locals {
  reverse_zone_data = {"0.0.10.in-addr.arpa" = ["16,10.0.0.16,0", "17,10.0.0.17,1",]}
  reverse_zone_data_list = [for k, v in local.reverse_zone_data : {
    name    = k
    records = v
  }]
}
[
  {
    "name" = "0.0.10.in-addr.arpa"
    "records" = [
      "16,10.0.0.16,0",
      "17,10.0.0.17,1",
    ]
  },
]

You can then use reverse_zone_data_list with count. For example:

resource "aws_route53_zone" "reverse_zone" {
  count = length(local.reverse_zone_data_list)
  name  = local.reverse_zone_data_list[count.index]
}

The aws_route53_record resource is more complicated because you want to create these per-zone-per-record. The same general solution applies though: we need to flatten this down into a single list that we can count over. We can again use for expressions for this, but they’ll be a little more complicated this time:

locals {
  reverse_zone_data = {"0.0.10.in-addr.arpa" = ["16,10.0.0.16,0", "17,10.0.0.17,1",]}
  reverse_zone_data_list = [for k, v in local.reverse_zone_data : {
    name    = k
    records = v
  }]
  reverse_zone_data_records = flatten([for i, v in local.reverse_zone_data_list : [
    for record in v.records : {
      zone_index = i
      # Maybe you'd like to also split the string into separate
      # attributes here, if that's helpful to the expressions
      # in the aws_route53_record block. I'm just going to use
      # it directly because the meaning of those segments isn't
      # clear to me from your description.
      record = record
    }
  ]))
}
[
  {
    "record" = "16,10.0.0.16,0"
    "zone_index" = 0
  },
  {
    "record" = "17,10.0.0.17,1"
    "zone_index" = 0
  },
]

Now you can use this flattened list with count:

resource "aws_route53_record" "reverse_zone_record" {
  count = length(local.reverse_zone_data_records)
  # Not sure exactly how you wanted to decode that
  # comma-separated string, so this is just using it
  # directly for example even though that result is
  # nonsensical...
  name       = local.reverse_zone_data_records[count.index].record 
  type       = "PTR"
  records    = ...
  zone_id    = aws_route53_zone.reverse_zone[local.reverse_zone_data_records[count.index].zone_index].id
  ttl        = 300
}
1 Like