Home > other >  Access all resource created by for_each in other for loop Terraform
Access all resource created by for_each in other for loop Terraform

Time:09-05

I want to create multiple acm certificates and route53 records for its validation, just cant figure out how can I reference to all acm resources created by for_each in route53 resource block which is looping in acm resource to get all the DNS _validation attributes, code is working fine if I will set one cert in variable and reference it directly with name, but how can I loop to all domain names for referencing it in for loop? Issue is this line

for dvo in aws_acm_certificate.web[for i in keys(var.certificates) : i]

which is returning

The index operator must end with a closing bracket ("]").

Adding a second bracket like this

for dvo in aws_acm_certificate.web[[for i in keys(var.certificates) : i]]

returns error

│
│   on main.tf line 21, in resource "aws_route53_record" "domain_validation":
│   21:     for dvo in aws_acm_certificate.web[[for i in keys(var.certificates) : i]].domain_validation_options : dvo.domain_name => {
│     ├────────────────
│     │ aws_acm_certificate.web is object with 2 attributes
│     │ var.certificates is object with 2 attributes
│
│ The given key does not identify an element in this collection value: string
│ required.```
resource "aws_acm_certificate" "web" {
  for_each = var.certificates
  domain_name       = "${replace(each.key, var.search_period, var.replace_period)}"
  subject_alternative_names = each.value.subject_alternative_names
  validation_method = "DNS"
}


resource "aws_route53_record" "domain_validation" {
  for_each = var.dns_validation ? {
    for dvo in aws_acm_certificate.web[[for i in keys(var.certificates) : i]].domain_validation_options : dvo.domain_name => {
      name   = dvo.resource_record_name
      record = dvo.resource_record_value
      type   = dvo.resource_record_type
    }
  } : {}

  allow_overwrite = true
  name            = each.value.name #aws_acm_certificate.web[each.key].domain_validation_options.0.resource_record_name
  records         = [each.value.record] #aws_acm_certificate.web[each.key].domain_validation_options.0.resource_record_value
  ttl             = 60
  type            = each.value.type #aws_acm_certificate.web[each.key].domain_validation_options.0.resource_record_type
  zone_id         = data.aws_route53_zone.selected[[for i in keys(var.certificates) : i]].zone_id
}

var.certificates looks like this:

certificates  = {
        "xxx.com" = {
            subject_alternative_names = ["*.xxx.com","*.dev.xxx.com","*.stage.xxx.com","*.preprod.xxx.com"]
        },
        "zzz.com" = {
            subject_alternative_names = ["*.dev.zzz.com","*.zzz.com"]
        },


       
    }


aws_acm_certificate.web in console looks like this:

``` 
> aws_acm_certificate.web
{
  "test.com" = {
    "arn" = "arn:aws:acm:eu-west-1:584637875403:certificate/a6fed-01c6-4f2c-ad87-59c04877bd0b"
    "certificate_authority_arn" = ""
    "certificate_body" = tostring(null)
    "certificate_chain" = tostring(null)
    "domain_name" = "test.com"
    "domain_validation_options" = toset([
      {
        "domain_name" = "*.test.com"
        "resource_record_name" = "_d5e2266fa07c911501b806f3d19e.test.com."
        "resource_record_type" = "CNAME"
        "resource_record_value" = "_fcc7913c9269201f77625b7f71ec.ltyvprtsjl.acm-validations.aws."
      },
      {
        "domain_name" = "*.dev.test.com"
        "resource_record_name" = "_f2aa63aabaae8cd721bf0143dee6.dev.test.com."
        "resource_record_type" = "CNAME"
        "resource_record_value" = "_f461eca5849d2a3e218dea91955.ltyvprtsjl.acm-validations.aws."
      },
      {
        "domain_name" = "*.preprod.test.com"
        "resource_record_name" = "_2747174805245587c6f9811a1180.preprod.test.com."
        "resource_record_type" = "CNAME"
        "resource_record_value" = "_7d3ccdf1006b12074ebcbc9c3d1.ltyvprtsjl.acm-validations.aws."
      },
      {
        "domain_name" = "*.stage.test.com"
        "resource_record_name" = "_6f571d29f334dcccfe098a2371c.stage.test.com."
        "resource_record_type" = "CNAME"
        "resource_record_value" = "_9c9657a4839d827d1ff6db0ffd0.ltyvprtsjl.acm-validations.aws."
      },
      {
        "domain_name" = "test.com"
        "resource_record_name" = "_d5e2266fa07c91bad71501bd19e.test.com."
        "resource_record_type" = "CNAME"
        "resource_record_value" = "_fcc7913c926926efc05b7f71ec.ltyvprtsjl.acm-validations.aws."
      },
    ])
    "id" = "arn:aws:acm:eu-west-1:584637875403:certificate/a6fed5981c6-4f2c-ad87-59c04877bd0b"
    "options" = tolist([
      {
        "certificate_transparency_logging_preference" = "ENABLED"
      },
    ])
    "private_key" = (sensitive)
    "status" = "ISSUED"
    "subject_alternative_names" = toset([
      "*.test.com",
      "*.dev.test.com",
      "*.preprod.test.com",
      "*.stage.test.com",
    ])
    "tags" = tomap({})
    "tags_all" = tomap({})
    "validation_emails" = tolist([])
    "validation_method" = "DNS"
  }
}
``` 

CodePudding user response:

You have to flatten your aws_acm_certificate.web first. For example:

locals {
  certificate_web_flat = merge([
    for hzone, certs in aws_acm_certificate.web:   {
        for domain_validation_option in certs.domain_validation_options:
          "${hzone}-${domain_validation_option.domain_name}" => {
            "hzone" = hzone
            "domain_name" = domain_validation_option.domain_name
             resource_record_name   = domain_validation_option.resource_record_name
             resource_record_value = domain_validation_option.resource_record_value
             resource_record_type   = domain_validation_option.resource_record_type            
          }
      }
  ]...)
}

then

resource "aws_route53_record" "domain_validation" {
  for_each = var.dns_validation ? local.certificate_web_flat : {}

  allow_overwrite = true
  name            = each.value.resource_record_name
  records         = [each.value.resource_record_value] 
  ttl             = 60
  type            = each.value.resource_record_type 
  zone_id         = data.aws_route53_zone.selected[each.value.hzone].zone_id
}
  • Related