aws_acm_certificate seems to have changed its state output possibly due to a provider update- am I doing this wrong now?

The AWS Terraform provider was recently upgraded to version 3.0. This version comes with a list of breaking changes. I recommend consulting the AWS provider 3.0 upgrade guide.

The issue you are encountering is because the domain_validation_options attribute is now a set instead of a list. From that guide:

Since the domain_validation_options attribute changed from a list to a set and sets cannot be indexed in Terraform, the recommendation is to update the configuration to use the more stable resource for_each support instead of count

I recommend using the new foreach syntax, as the upgrade guide recommends, in order to avoid unexpected diffs. The guide states that you will need to use terraform state mv to move the old configuration state to the new configuration, in order to prevent the resources from being recreated.


This is the same problem we were facing just now.. we use for_each to define hosting for multiple sites according to provided local variables, now, since we already use for_each we can't use it for workaround of their changes.. unfortunate.

I didn't want to go with sort so I checked what Jimmy wrote but it didn't work for this case due to output being index, I fixed it by using [0] instead of [*]:

resource "aws_route53_record" "cert_validation" {
  for_each = local.web_pages
  allow_overwrite = true
  name            = tolist(aws_acm_certificate.cert[each.key].domain_validation_options)[0].resource_record_name
  type            = tolist(aws_acm_certificate.cert[each.key].domain_validation_options)[0].resource_record_type
  records         = [tolist(aws_acm_certificate.cert[each.key].domain_validation_options)[0].resource_record_value]
  zone_id         = var.aws_hosted_zone
  ttl             = 60
}

works for us now ;)


You can also cheat with tolist.

e.g. rewrite aws_acm_certificate.mycert.domain_validation_options[*].resource_record_name as tolist(aws_acm_certificate.mycert.domain_validation_options)[*].resource_record_name

I had to do this in a module, as this particular module resource already had a count in it, and I knew I'd only ever have one entry.