首页 > 解决方案 > terraform 抛出错误:运行计划时出现“不正确的属性值类型”

问题描述

我使用来自https://github.com/Oxalide/terraform-fargate-example的terraform 。

当我按原样运行时出现错误:

Error: Incorrect attribute value type

  on main.tf line, in resource "aws_alb" "main":
  :   subnets         = ["${aws_subnet.public.*.id}"]

Inappropriate value for attribute "subnets": element 0: string required.

此行中的代码:

resource "aws_alb" "main" {
  name            = "tf-ecs-chat"
  subnets         = ["${aws_subnet.public.*.id}"] # <--- here is the error
  security_groups = ["${aws_security_group.lb.id}"]
}

根据文档示例,这似乎是正确的。

resource "aws_lb" "test" {
  name               = "test-lb-tf"
  internal           = false
  load_balancer_type = "application"
  security_groups    = ["${aws_security_group.lb_sg.id}"]
  subnets            = ["${aws_subnet.public.*.id}"]
  ...
 

错误是什么意思?如何解决?

标签: amazon-web-servicesterraformterraform-provider-aws

解决方案


这个例子似乎是为旧版本的 Terraform 编写的,不幸的是,它依赖于该早期版本的配置语言错误,该错误已被修复。

该表达式从 的所有实例中生成属性值aws_subnet.public.*.id列表。如果将该表达式放在列表构造括号中,则 Terraform 会将其理解为列表列表,如下所示:idaws_subnet.public[ ]

[
  [
    "i-abc123",
    "i-def456",
    "i-ghi789",
  ],
]

然后aws_alb资源类型拒绝将其作为 的值subnets,因为该参数被定义为期望字符串列表,而不是字符串列表列表。

因为aws_subnet.public.*.id已经返回了一个列表,你可以直接使用它作为 的值subnets

  subnets         = aws_subnet.public.*.id

另请注意,我们不需要字符串插值语法,因为我们只是直接使用列表值,而不是从模板构造字符串。

您的示例中的security_groups参数使用类似的语法,但在这种情况下aws_security_group.lb.id已经是单个 ID 字符串而不是列表,因此在这种情况[ ]需要使用列表括号来构造列表。但是,我们仍然可以通过删除不必要的模板插值语法来清理它,得到以下结果:

resource "aws_alb" "main" {
  name            = "tf-ecs-chat"
  subnets         = aws_subnet.public.*.id
  security_groups = [aws_security_group.lb.id]
}

Terraform 提供程序文档中的一些示例仍在使用旧版本 Terraform 的语法,特别是在相关提供程序仍与旧版本兼容的情况下,我相信当时的 AWS 提供程序就是这种情况。我写这个。

在大多数情况下,这只会导致不必要的冗长语法,但不幸的是,在某些情况下,示例依赖于以前版本中的错误,该错误现已修复,因此示例本身在当前 Terraform 中不再正常工作版本。

如果您发现此类情况,您可以按照 Terraform Registry 中提供者页面上的“报告问题”链接报告错误。在这种情况下,有问题的提供者是hashicorp/aws


推荐阅读