Search code examples
amazon-web-servicesterraformterraform-provider-aws

Iterate thru nested maps in Terraform


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.


Solution

  • OK, so this is how I make that to work.

    in my root directory I've added locals

    locals {
      name             = "eks"
      eks_cluster_name = "${local.name}-${var.environment}"
      hosted_zones_domains = {
        "first-example.com" = toset([
          "app1",
          "app2",
          "app3"
        ]),
        "second-example.com" = toset([
          "app1",
          "app2",
          "app3"
        ])
        }
      hosted_zones_domains_list = { for zone, domains in local.hosted_zones_domains : zone => tolist(domains) }
      zone_domain_pairs = flatten([
        for zone, domains in local.hosted_zones_domains_list : [
          for domain in domains : {
            zone   = zone
            domain = domain
          }
        ]
      ])
    }
    

    Then passed that to submodule zone_domain_pairs = local.zone_domain_pairs

    And then in submodule something like that

    resource "aws_route53_zone" "subdomain_zone" {
      for_each = toset([for pair in var.zone_domain_pairs : pair.zone])
    
      name     = each.key
    
      tags = {
        Environment = var.environment
      }
    }
    resource "aws_route53_record" "zone_records" {
      for_each = { for pair in var.zone_domain_pairs : "${pair.zone}.${pair.domain}" => pair }
    
      zone_id = aws_route53_zone.subdomain_zone[each.value.zone].id
      name    = each.value.domain
      type    = "CNAME"
      ttl     = 300
      records = [aws_lb.eks_alb.dns_name]
    }
    

    Thanks guys for your help!