aws_acm_certificate 似乎已经改变了它的状态输出,可能是由于提供者更新——我做错了吗?

red*_*888 12 amazon-web-services amazon-route53 terraform

Terraform v0.12.12
+ provider.aws v3.0.0
+ provider.template v2.1.2
Run Code Online (Sandbox Code Playgroud)

在我这样做之前:

resource "aws_route53_record" "derps" {
  name    = aws_acm_certificate.mycert[0].resource_record_name
  type    = aws_acm_certificate.mycert[0].resource_record_type
  zone_id = var.my_zone_id
  records = aws_acm_certificate.mycert[0].resource_record_value
  ttl     = 60
}
Run Code Online (Sandbox Code Playgroud)

大约一周前,这对我来说效果很好。

我刚刚做了一个计划,却出现了错误:

records = [aws_acm_certificate.mycert.domain_validation_options[0].resource_record_value]

This value does not have any indices.
Run Code Online (Sandbox Code Playgroud)

现在我不固定提供者版本,所以我假设我拉了一个更新的版本并且资源发生了变化。

在与这个斗争并意识到它不是一个列表(即使这样做show state时看起来确实像一个列表)我现在这样做是为了使它成为一个列表:

resource "aws_route53_record" "derps" {
  name    = sort(aws_acm_certificate.mycert.domain_validation_options[*].resource_record_name)[0]
  type    = sort(aws_acm_certificate.mycert.domain_validation_options[*].resource_record_type)[0]
  zone_id = var.my_zone_id
  records = [sort(aws_acm_certificate.mycert.domain_validation_options[*].resource_record_value)[0]]
  ttl     = 60
} 
Run Code Online (Sandbox Code Playgroud)

这导致没有变化,这是好的。但是,如果我使用他们现在使用 for_each 的文档中的示例来执行此操作:https : //registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate_validation

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
}

resource "aws_acm_certificate_validation" "example" {
  certificate_arn         = aws_acm_certificate.example.arn
  validation_record_fqdns = [for record in aws_route53_record.example : record.fqdn]
}
Run Code Online (Sandbox Code Playgroud)

以上是现在执行此操作的正确方法吗?我会不会以现在的方式遇到问题?像上面那样做会导致破坏/重新创建(我想我可以自己导入它,但这很痛苦)。

以我的方式这样做不会导致意外的差异吗?

编辑

所以,更具体地针对我的问题。这是我在查看状态时看到的:

terraform state show aws_acm_certificate.mycert

    ...
    domain_name               = "*.mydom.com"
    domain_validation_options = [
        {
            domain_name           = "*.mydom.com"
            resource_record_name  = "_11111111111.mydom.com."
            resource_record_type  = "CNAME"
            resource_record_value = "_1111111111.11111111.acm-validations.aws."
        },
        {
            domain_name           = "mydom.com"
            resource_record_name  = "_11111111111.mydom.com."
            resource_record_type  = "CNAME"
            resource_record_value = "_1111111111.111111111.acm-validations.aws."
        },
    ]
    ... 
Run Code Online (Sandbox Code Playgroud)

通过使用排序,我有效地使用了计数,如果顺序发生变化,这当然会导致销毁/重新创建。但就我而言,我认为这不太可能??我也不完全理解仅使用通配符验证配置中的值与同时使用它们之间的区别。

Mar*_*k B 8

AWS Terraform 提供程序最近升级到版本 3.0。此版本附带了一系列重大更改。我建议咨询AWS provider 3.0 upgrade guide

您遇到的问题是因为该domain_validation_options属性现在是一个集合而不是一个列表。从该指南:

由于domain_validation_options属性从列表变为集合并且集合无法在 Terraform 中建立索引,因此建议更新配置以使用更稳定的资源for_each支持,而不是count

我建议使用foreach升级指南推荐的新语法,以避免出现意外差异。该指南指出,您需要使用terraform state mv将旧配置状态移动到新配置,以防止重新创建资源。


小智 6

这与我们刚才面临的问题相同.. 我们使用 for_each 根据提供的局部变量为多个站点定义托管,现在,由于我们已经使用 for_each 我们不能使用它来解决他们的更改..不幸。

我不想使用 sort ,所以我检查了 Jimmy 写的内容,但由于输出是索引,它不适用于这种情况,我使用 [0] 而不是 [*] 来修复它:

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
}
Run Code Online (Sandbox Code Playgroud)

现在为我们工作;)