首页 > 解决方案 > 将集合转换为列表会产生不可预测的元素数量

问题描述

Terraform v0.13.7

你好,

我正在尝试从 AWS 提供程序插件的 2.70.0 版迁移到 3.X 版。这需要处理 aws_acm_certificate 的 domain_validation_options 属性的更改,该属性变为集合而不是列表。

除了主证书名称之外,我还有管理具有 3 个 SAN 的证书的代码。正如预期的那样,使用 AWS 提供程序插件的 2.70.0 版本,这会生成一个四元素列表,如terraform show -json planfile的此输出所示:

                "domain_validation_options": [
                  {
                    "domain_name": "example.net",
                    "resource_record_name": "blah-1.example.net.",
                    "resource_record_type": "CNAME",
                    "resource_record_value": "blah-1.acm-validations.aws."
                  },
                  {
                    "domain_name": "*.a.example.net",
                    "resource_record_name": "blah-2.a.example.net.",
                    "resource_record_type": "CNAME",
                    "resource_record_value": "blah-2.acm-validations.aws."
                  },
                  {
                    "domain_name": "*.b.example.net",
                    "resource_record_name": "blah-3.b.example.net.",
                    "resource_record_type": "CNAME",
                    "resource_record_value": "blah-3.acm-validations.aws."
                  },
                  {
                    "domain_name": "*.c.example.net",
                    "resource_record_name": "blah-4.c.example.net.",
                    "resource_record_type": "CNAME",
                    "resource_record_value": "blah-4.acm-validations.aws."
                  }
                ],

同样正如预期的那样,我可以通过索引来处理这些列表元素中的每一个,例如:

aws_acm_certificate.sslcert.domain_validation_options[0]

但是,当我安装 3.X 版本的插件时,会返回一组。我试图通过使用 tolist() 函数将其转换为列表来使事情变得简单。这将返回一个按字典顺序排列的列表——这是预期的。

                "domain_validation_options": [
                  {
                    "domain_name": "*.a.example.net",
                    "resource_record_name": "blah-2.a.example.net.",
                    "resource_record_type": "CNAME",
                    "resource_record_value": "blah-2.acm-validations.aws."
                  },
                  {
                    "domain_name": "*.b.example.net",
                    "resource_record_name": "blah-3.b.example.net.",
                    "resource_record_type": "CNAME",
                    "resource_record_value": "blah-3.acm-validations.aws."
                  },
                  {
                    "domain_name": "*.c.example.net",
                    "resource_record_name": "blah-4.c.example.net.",
                    "resource_record_type": "CNAME",
                    "resource_record_value": "blah-4.acm-validations.aws."
                  },
                 {
                    "domain_name": "example.net",
                    "resource_record_name": "blah-1.example.net.",
                    "resource_record_type": "CNAME",
                    "resource_record_value": "blah-1.acm-validations.aws."
                  },
                ],

出乎意料的是 Terraform 报告说它是一个二元素而不是四元素列表。当我尝试访问上面引用的第二个terraform show -json planfile output ("domain_name": "example.net")中的最后一个元素时,它给了我以下错误:

  on common/certificate/certificate.tf line 14, in locals:
  14:   vopt = tolist(aws_acm_certificate.sslcert.domain_validation_options)[3]

aws_acm_certificate.sslcert.domain_validation_options is set of object with 2 elements

谁能帮我理解为什么会这样?还有比浏览terraform show -json planfile的输出更可靠的方法来检查变量吗?

谢谢!

更新

抱歉,我可能应该分享产生我的问题的代码。这是它的匿名版本。

调用模块:

module "sslcert-example_net" {
  source = "./common/certificate"
  name   = "example.net"

  SAN = [
    "*.a.example.net",
    "*.b.example.net",
    "*.c.example.net",
  ]
}

子模块:

resource "aws_acm_certificate" "sslcert" {
  domain_name = var.name

  subject_alternative_names = var.SAN

  validation_method = "DNS"

  lifecycle {
    create_before_destroy = true
  }
}

locals {
  vopt = tolist(aws_acm_certificate.sslcert.domain_validation_options)[3]
}

resource "ns1_record" "dnsvalidation-sslcert" {
  depends_on = [aws_acm_certificate.sslcert]
  zone       = var.name

  domain = substr(
    local.vopt["resource_record_name"],
    0,
    length(local.vopt["resource_record_name"]) - 1,
  )
  type = "CNAME"

  answers {
    answer = local.vopt["resource_record_value"]
  }
}

标签: amazon-web-servicesterraform

解决方案


推荐阅读