For loop returns list of map of maps

Trying to return a list of maps but keep getting a of map of maps.

locals {
  emails = {
    us-east-1 = {
      prod_account = {
        me-at-example-com = {
          "xxx._domainkey.goodrx.com" = "xxx.dkim.amazonses.com",
          "yyy._domainkey.goodrx.com" = "yyy.dkim.amazonses.com",
          "zzz._domainkey.goodrx.com" = "zzz.dkim.amazonses.com"
        },
      },
    },
    us-west-2 = {
      dev_account = {
        other-at-example-com = {
          "xxx._domainkey.goodrx.com" = "xxx.dkim.amazonses.com",
          "yyy._domainkey.goodrx.com" = "yyy.dkim.amazonses.com",
          "zzz._domainkey.goodrx.com" = "zzz.dkim.amazonses.com",
        },
      },
      prod_account = {
        me-at-example-com = {
          "xxx._domainkey.goodrx.com" = "xxx.dkim.amazonses.com",
          "yyy._domainkey.goodrx.com" = "yyy.dkim.amazonses.com",
          "zzz._domainkey.goodrx.com" = "zzz.dkim.amazonses.com",
        },
      },
    }
  }
}
output "emails" {
  value = flatten([
    for region, accounts in local.emails: [
      for account, emails in accounts: {
        for email, records in emails: "${region}_${account}_${email}" => records
      }
    ]
  ])
}

Output results in list of maps of maps. When I just want a list of maps.

emails = [
  {
    "us-east-1_prod_account_me-at-example-com" = {
      "xxx._domainkey.goodrx.com" = "xxx.dkim.amazonses.com"
      "yyy._domainkey.goodrx.com" = "yyy.dkim.amazonses.com"
      "zzz._domainkey.goodrx.com" = "zzz.dkim.amazonses.com"
    }
  },
  {
    "us-west-2_dev_account_other-at-example-com" = {
      "xxx._domainkey.goodrx.com" = "xxx.dkim.amazonses.com"
      "yyy._domainkey.goodrx.com" = "yyy.dkim.amazonses.com"
      "zzz._domainkey.goodrx.com" = "zzz.dkim.amazonses.com"
    }
  },
  {
    "us-west-2_prod_account_me-at-example-com" = {
      "xxx._domainkey.goodrx.com" = "xxx.dkim.amazonses.com"
      "yyy._domainkey.goodrx.com" = "yyy.dkim.amazonses.com"
      "zzz._domainkey.goodrx.com" = "zzz.dkim.amazonses.com"
    }
  },
]

Looking to get

emails = {
    "us-east-1_prod_account_me-at-example-com" = {
      "xxx._domainkey.goodrx.com" = "xxx.dkim.amazonses.com"
      "yyy._domainkey.goodrx.com" = "yyy.dkim.amazonses.com"
      "zzz._domainkey.goodrx.com" = "zzz.dkim.amazonses.com"
    },
    "us-west-2_dev_account_other-at-example-com" = {
      "xxx._domainkey.goodrx.com" = "xxx.dkim.amazonses.com"
      "yyy._domainkey.goodrx.com" = "yyy.dkim.amazonses.com"
      "zzz._domainkey.goodrx.com" = "zzz.dkim.amazonses.com"
    }
    "us-west-2_prod_account_me-at-example-com" = {
      "xxx._domainkey.goodrx.com" = "xxx.dkim.amazonses.com"
      "yyy._domainkey.goodrx.com" = "yyy.dkim.amazonses.com"
      "zzz._domainkey.goodrx.com" = "zzz.dkim.amazonses.com"
    }
  }

The data structure you show that you’re looking to get is not a list of maps, it’s a map of maps.

But, I’m not able to construct it either - I’m stuck because merge() takes a number of maps as input but it doesn’t accept a list-of-maps :frowning:

Hello,

You can expand a list of arguments using the ... operator

> merge([{a="a"},{b="b"}]...)
{
  "a" = "a"
  "b" = "b"
}
1 Like

@jbardin Awesome! Always some little feature I didn’t think of…

@mhumeSF Something like this maybe:

locals {
  records = merge(flatten([
    for region, accounts in local.emails: [
      for account, emails in accounts: {
        for email, records in emails: "${region}_${account}_${email}" => records
      }
    ]
  ])...)
}

output "records" {
  value = local.records
}
$ terraform apply

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

records = {
  "us-east-1_prod_account_me-at-example-com" = {
    "xxx._domainkey.goodrx.com" = "xxx.dkim.amazonses.com"
    "yyy._domainkey.goodrx.com" = "yyy.dkim.amazonses.com"
    "zzz._domainkey.goodrx.com" = "zzz.dkim.amazonses.com"
  }
  "us-west-2_dev_account_other-at-example-com" = {
    "xxx._domainkey.goodrx.com" = "xxx.dkim.amazonses.com"
    "yyy._domainkey.goodrx.com" = "yyy.dkim.amazonses.com"
    "zzz._domainkey.goodrx.com" = "zzz.dkim.amazonses.com"
  }
  "us-west-2_prod_account_me-at-example-com" = {
    "xxx._domainkey.goodrx.com" = "xxx.dkim.amazonses.com"
    "yyy._domainkey.goodrx.com" = "yyy.dkim.amazonses.com"
    "zzz._domainkey.goodrx.com" = "zzz.dkim.amazonses.com"
  }
}
$

Had no idea about the ... operator. This is awesome!

Thanks @jbardin and @bentterp