Terraform for_each 位于 for_each 内?

发布于 2025-01-17 13:58:37 字数 2990 浏览 4 评论 0原文

我有此代码:

locals {
  portals = ["c" "a" "b"]
}

resource "aws_acm_certificate" "example" {
  for_each    = toset(local.portals)
  domain_name = "${each.value}.aws.${var.environment}.abc.com"
  subject_alternative_names = [
    "${each.value}.${var.environment}-aws.abc.com"
  ]
  validation_method = "DNS"

  lifecycle {
    create_before_destroy = true
  }
}

这创建了3个ACM AWS证书。

现在,我需要/想要做的是为证书创建的所有DNS创建DNS记录。我所拥有的代码是:

resource "aws_route53_record" "example-verify-acm" {
  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
    }
  }

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

现在,当我运行Terraform计划时,我会收到错误:

│ Error: Missing resource instance key
│ 
│   on  line 24, in resource "aws_route53_record" "example-verify-acm":
│   24:     for dvo in aws_acm_certificate.example.domain_validation_options : dvo.domain_name => {
│ 
│ Because aws_acm_certificate.example has "for_each" set, its attributes must be accessed on specific instances.
│ 
│ For example, to correlate with indices of a referring resource, use:
│     aws_acm_certificate.example[each.key]

然后,正如错误所说的“ AWS_ACM_CERTIFICATE.example.example [every.key]” ..我在代码中添加了这一点:

    for dvo in aws_acm_certificate.website[each.key].domain_validation_options : dvo.domain_name => {

然后我会收到错误:

│ Error: Reference to "each" in context without for_each
│ 
│   on ../../modules/web/acm.tf line 24, in resource "aws_route53_record" "example-verify-acm":
│   24:     for dvo in aws_acm_certificate.example[each.key].domain_validation_options : dvo.domain_name => {
│ 
│ The "each" object can be used only in "module" or "resource" blocks, and only when the "for_each" argument is set.

如果我添加:

    for dvo in aws_acm_certificate.example[each.value].domain_validation_options : dvo.domain_name => {

我会收到错误:

 Error: each.value cannot be used in this context
│ 
│   on ../../modules/web/acm.tf line 24, in resource "aws_route53_record" "example-verify-acm":
│   24:     for dvo in aws_acm_certificate.example[each.value].domain_validation_options : dvo.domain_name => {
│ 
│ A reference to "each.value" has been used in a context in which it unavailable, such as when the configuration no longer contains
│ the value in its "for_each" expression. Remove this reference to each.value in your configuration to work around this error.

因此,我不知道如何使用“ AWS_ROUTE53_RECORD”的所有3个证书中的所有3个证书传递“ domain_validation_options”。 有没有办法解决这些错误? 还是有其他方法可以完成此操作?

I have this code:

locals {
  portals = ["c" "a" "b"]
}

resource "aws_acm_certificate" "example" {
  for_each    = toset(local.portals)
  domain_name = "${each.value}.aws.${var.environment}.abc.com"
  subject_alternative_names = [
    "${each.value}.${var.environment}-aws.abc.com"
  ]
  validation_method = "DNS"

  lifecycle {
    create_before_destroy = true
  }
}

and this created 3 ACM AWS certs.

Now, what I need/want to do is to create DNS records for all the DNS created by the certs. The code for that I have is:

resource "aws_route53_record" "example-verify-acm" {
  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
    }
  }

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

Now, I when I run terraform plan, I get the error:

│ Error: Missing resource instance key
│ 
│   on  line 24, in resource "aws_route53_record" "example-verify-acm":
│   24:     for dvo in aws_acm_certificate.example.domain_validation_options : dvo.domain_name => {
│ 
│ Because aws_acm_certificate.example has "for_each" set, its attributes must be accessed on specific instances.
│ 
│ For example, to correlate with indices of a referring resource, use:
│     aws_acm_certificate.example[each.key]

Then, as the error says to use "aws_acm_certificate.example[each.key]" .. I added that in my code:

    for dvo in aws_acm_certificate.website[each.key].domain_validation_options : dvo.domain_name => {

then I get the error:

│ Error: Reference to "each" in context without for_each
│ 
│   on ../../modules/web/acm.tf line 24, in resource "aws_route53_record" "example-verify-acm":
│   24:     for dvo in aws_acm_certificate.example[each.key].domain_validation_options : dvo.domain_name => {
│ 
│ The "each" object can be used only in "module" or "resource" blocks, and only when the "for_each" argument is set.

and if I add:

    for dvo in aws_acm_certificate.example[each.value].domain_validation_options : dvo.domain_name => {

I get the error:

 Error: each.value cannot be used in this context
│ 
│   on ../../modules/web/acm.tf line 24, in resource "aws_route53_record" "example-verify-acm":
│   24:     for dvo in aws_acm_certificate.example[each.value].domain_validation_options : dvo.domain_name => {
│ 
│ A reference to "each.value" has been used in a context in which it unavailable, such as when the configuration no longer contains
│ the value in its "for_each" expression. Remove this reference to each.value in your configuration to work around this error.

So, I do not know how to pass in the "domain_validation_options" for all the 3 certs using this one resource of "aws_route53_record".
Is there a way to fix these errors?
or Is there a different way to get this done?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

野侃 2025-01-24 13:58:37

您必须扁平 aws_acm_certificate。例如:

locals {
  flat_records = merge([
      for cert in aws_acm_certificate.example: {
        for dvo in cert.domain_validation_options: 
          "${cert.domain_name}-${dvo.resource_record_name}" => {
            name   = dvo.resource_record_name
            record = dvo.resource_record_value
            type   = dvo.resource_record_type
          }        
      }
    ]...)
}

然后

resource "aws_route53_record" "example-verify-acm" {
  for_each        = local.flat_records 

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

You have to flatten your aws_acm_certificate. For example:

locals {
  flat_records = merge([
      for cert in aws_acm_certificate.example: {
        for dvo in cert.domain_validation_options: 
          "${cert.domain_name}-${dvo.resource_record_name}" => {
            name   = dvo.resource_record_name
            record = dvo.resource_record_value
            type   = dvo.resource_record_type
          }        
      }
    ]...)
}

then

resource "aws_route53_record" "example-verify-acm" {
  for_each        = local.flat_records 

  allow_overwrite = true
  name            = each.value.name
  records         = [each.value.record]
  ttl             = 60
  type            = each.value.type
  zone_id         = data.aws_route53_zone.management_zone.zone_id
}
叹倦 2025-01-24 13:58:37

我找不到一个很好的解决方案。感谢@marcin的出色建议。但是,我经历的道路是创建一个Terraform模块,该模块共同创建ACM,记录并进行验证。

然后,我只是使用for_each来调用模块。

locals {
  portals = ["c" "a" "b"]
}

I was not able to find a good solution for this. Thank you to @Marcin for the great suggestion.. but the path I went through for this was to create a terraform module which creates the ACM, the records and does the validation, all together.

Then, I just called the module using a for_each .. with:

locals {
  portals = ["c" "a" "b"]
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文