For_each for expression in json syntax

Hello,

I programmatically create the terraform config files into json which has worked really successfully for me. I’ve currently trying to upgrade to 0.13 and AWS 3.0 but I’m hitting an issue converting this syntax to the json syntax. Can anyone help with how this example would be written in the json syntax?

Thank you!

resource "aws_route53_record" "example" {
  for_each = {
    for dvo in aws_acm_certificate.example.domain_validation_options : dvo.domain_name => {
      name    = dvo.resource_record_name
      record  = dvo.resource_record_value
      type    = dvo.resource_record_type
      zone_id = dvo.domain_name == "example.org" ? data.aws_route53_zone.example_org.zone_id : data.aws_route53_zone.example_com.zone_id
    }
  }

  allow_overwrite = true
  name            = each.value.name
  records         = [each.value.record]
  ttl             = 60
  type            = each.value.type
  zone_id         = each.value.zone_id
}

Ok I managed to work it out in the end, need to specify expression with ${ then using { the start of the for expression return as an object.

 {
  "resource": {
    "aws_route53_record": {
      "example": {
        "for_each": "${{for dvo in aws_acm_certificate.example.domain_validation_options : dvo.domain_name => {name    = dvo.resource_record_namerecord  = dvo.resource_record_valuetype    = dvo.resource_record_typezone_id = dvo.domain_name == \"example.org\" ? data.aws_route53_zone.example_org.zone_id : data.aws_route53_zone.example_com.zone_id}}}",
        "allow_overwrite": true,
        "name": "${each.value.name}",
        "records": [
          "${each.value.record}"
        ],
        "zone_id": "${each.value.zone_id}"
      }
    }
  }
}

Hi @jdempster! I’m glad you figured it out.

In case it’s useful to you or anyone else who finds this topic in future, I just wanted to note that for_each is similar to resource-type-specific arguments inside a resource block in that it is interpreted per the JSON Expression Mapping.

In your case, that meant that you needed to write a string template containing a single ${ ... } sequence containing the expression you needed to evaluate. It does look a little “funny” in this case because the ${ and the { together look a little unusual; I might put a space after the ${ and before the }, and the same for the two closing }, just to create a visual separation to suggest that these are two separate tokens rather than one long token.

Hi @apparentlymart !
Will it be possible for you to include an example of for_each on this page: JSON Configuration Syntax - Configuration Language - Terraform by HashiCorp ?
In addition to having to look this up, should avoid newline / whitespace issues in the way this page is rendered. I see this as 1 line (Firefox 88.0.1):

        "for_each": "${{for dvo in aws_acm_certificate.example.domain_validation_options : dvo.domain_name => {name    = dvo.resource_record_namerecord  = dvo.resource_record_valuetype    = dvo.resource_record_typezone_id = dvo.domain_name == \"example.org\" ? data.aws_route53_zone.example_org.zone_id : data.aws_route53_zone.example_com.zone_id}}}",

With current versions of Terraform, the example is more complicated than needed.
While the top level of a for_each won’t accept a set of objects, it’s perfectly fine with a mapping from string to object. (probably objects can’t be keys)

         "validation_record": {
            "allow_overwrite": true,
            "for_each": "${{for dvo in resource.aws_acm_certificate.funkenspiel.domain_validation_options : dvo.domain_name => dvo}}",
            "name": "${each.value.resource_record_name}",
            "records": [
               "${each.value.resource_record_value}"
            ],
            "ttl": 60,
            "type": "${each.value.resource_record_type}",
            "zone_id": "${resource.aws_route53_zone.funkenspiel.zone_id}"
         }