Terraform for_each over list of objects

terraform

We have a list of objects defined in vars.tf:

variable "sendgrid_dns_records" {
  type = list(object({
    type  = string
    name  = string
    value = string
  }))
  description = "DNS Records for sendgrid.com"
}

variable "cloudflare_zone_id" {
  type        = string
  description = "cloudflare zone id"
}

And have recorded their values in xyz.tfvars:

sendgrid_dns_records = [
    {"name": "url3415.netletic.xyz", "value": "sendgrid.net", "type": "CNAME"},
    {"name": "29342668.netletic.xyz", "value": "sendgrid.net", "type": "CNAME"},
    {"name": "em9437.netletic.xyz", "value": "u29342668.wl169.sendgrid.net", "type": "CNAME"},
    {"name": "s1._domainkey.netletic.xyz", "value": "s1.domainkey.u29342668.wl169.sendgrid.net", "type": "CNAME"},
    {"name": "s2._domainkey.netletic.xyz", "value": "s2.domainkey.u29342668.wl169.sendgrid.net", "type": "CNAME"},
]

Now we want to create DNS records for each of these in Cloudflare:

resource "cloudflare_record" "this" {
  for_each = {
    for index, dns_record in var.sendgrid_dns_records:
      dns_record.name => dns_record
  }

  zone_id  = var.cloudflare_zone_id
  name     = each.value.name
  value    = each.value.value
  type     = each.value.type
  ttl      = 300
}

This works because we use for_each to create a new dictionary (map), where the key=dns_record.name, and the value=the entire object. Something like:

{'29342668.netletic.xyz': {'name': '29342668.netletic.xyz',
                           'type': 'CNAME',
                           'value': 'sendgrid.net'},
 'url3415.netletic.xyz': {'name': 'url3415.netletic.xyz',
                          'type': 'CNAME',
                          'value': 'sendgrid.net'}
...}

So when we use for_each. We can refer to each.name, each.type, and each.value for each iteration. We don't care about each.key as it's the same as each.value.name.

See StackOverflow for more info


You might be interested in these notes:

  • Couldn't find similar notes.