Похоже, что aws_acm_certificate изменил свое состояние вывода, возможно, из-за обновления поставщика - я сейчас делаю это неправильно? - PullRequest
4 голосов
/ 03 августа 2020
Terraform v0.12.12
+ provider.aws v3.0.0
+ provider.template v2.1.2

Раньше я делал это:

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
}

И это отлично работало у меня около недели go.

Я только что составил план и получил ошибку :

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

This value does not have any indices.

Сейчас я не закрепляю версии провайдера, поэтому предполагаю, что вытащил более новую версию, и ресурс изменился.

После борьбы с этим и осознания того, что это не список (хотя при выполнении 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
} 

Это не привело ни к каким изменениям, что хорошо. Но если я использую пример для этого из документов, которые они теперь используют 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]
}

Правильный ли приведенный выше способ сделать это сейчас? Собираюсь ли я столкнуться с проблемами, делая это так, как сейчас? Выполнение этого, как указано выше, приведет к уничтожению / воссозданию (думаю, я мог бы импортировать его сам, но это болезненно).

Делаю это по-моему, не приведет к неожиданным различиям?

Изменить

Итак, c подробнее по моей проблеме. Вот что я вижу, когда смотрю на состояние:

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."
        },
    ]
    ... 

Используя сортировку, я эффективно использую счетчик, который, конечно, приводит к уничтожению / воссозданию, если порядок изменяется. Но в моем случае это маловероятно ?? Я также не совсем понимаю разницу между использованием значений из конфигурации проверки с использованием подстановочных знаков и их обоих.

Ответы [ 3 ]

5 голосов
/ 03 августа 2020

Провайдер AWS Terraform был недавно обновлен до версии 3.0. Эта версия имеет список критических изменений . Я рекомендую обратиться к руководству по обновлению AWS provider 3.0 .

Проблема, с которой вы столкнулись, заключается в том, что атрибут domain_validation_options теперь является набором, а не списком. Из этого руководства:

Поскольку атрибут domain_validation_options изменен со списка на набор, а наборы не могут быть проиндексированы в Terraform, рекомендуется обновить конфигурацию для использования более стабильного ресурса for_each support вместо count

Я рекомендую использовать новый синтаксис foreach, как рекомендует руководство по обновлению, чтобы избежать неожиданных различий. В руководстве указано, что вам нужно будет использовать terraform state mv для перемещения старого состояния конфигурации в новую конфигурацию, чтобы предотвратить воссоздание ресурсов.

1 голос
/ 26 августа 2020

Это та же проблема, с которой мы столкнулись только что ... мы используем for_each для определения хостинга для нескольких сайтов в соответствии с предоставленными локальными переменными, теперь, поскольку мы уже используем for_each, мы не можем использовать его для обхода их изменений .. к сожалению.

Я не хотел go с сортировкой, поэтому я проверил, что написал Джимми, но в этом случае это не сработало из-за того, что вывод был индексным, я исправил это, используя [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
}

теперь у нас работает;)

0 голосов
/ 14 августа 2020

Вы также можете обмануть с помощью tolist.

, например, перезаписать aws_acm_certificate.mycert.domain_validation_options[*].resource_record_name как tolist(aws_acm_certificate.mycert.domain_validation_options)[*].resource_record_name

Мне пришлось сделать это в модуле, так как этот конкретный ресурс модуля уже имел count в нем, и я знал, что у меня будет только одна запись.

...