首页 > 解决方案 > Terraform Splat 表达式给出“无效的模板插值”

问题描述

我在 Terraform 中使用数据源来获取我的安全组的 id 列表,如下所示:

data "aws_security_groups" "test" {
  filter {
    name   = "group-name"
    values = ["the-name"]
  }
}

output "security_group_id" {
  value = "The id is ${data.aws_security_groups.test.ids[*]}"
}

但是,这给了我以下错误:

Error: Invalid template interpolation value

on main.tf line 11, in output "security_group_id":
  11:   value = "The id is ${data.aws_security_groups.test.ids[*]}"
    |----------------
    | data.aws_security_groups.test.ids is list of string with 1 element

Cannot include the given value in a string template: string required.

但如果我data.aws_security_groups.test.ids[0]改用它,它会显示 ID。

有人可以帮我显示 ID 列表吗?

标签: amazon-web-servicesterraformterraform-provider-awsaws-security-group

解决方案


首先,我想指出,如果您不想,则根本不需要将此列表与字符串消息组合,因为 Terraform 将接受任何类型的输出值:

output "security_group_ids" {
  value = data.aws_security_groups.test.ids
}

如果将它们作为更大字符串的一部分包含对您的潜在问题很重要,那么您需要决定如何在单个字符串中显示这些多个 id。有多种不同的方法可以做到这一点,具体取决于您打算如何处理这些信息。

一个相对简单的答案是使用 使字符串包含列表的 JSON 表示jsonencode,如下所示:

output "security_group_id_message" {
  value = "The ids are ${jsonencode(data.aws_security_groups.test.ids)}"
}

如果您想要更人性化的演示文稿,那么您可能更喜欢使用多行字符串,在这种情况下,您可以使用字符串模板自定义输出。

output "security_group_id_message" {
  value = <<-EOT
  The ids are:
  %{ for id in data.aws_security_groups.test.ids ~}
  - ${id}
  %{ endfor ~}
  EOT
}

或者,对于介于两者之间的答案,您可以使用join简单的分隔符将值连接在一起,如下所示:

output "security_group_id_message" {
  value = "The ids are ${join(",", data.aws_security_groups.test.ids)}"
}

请注意,我[*]在所有这些示例中从您的参考中删除了 ,因为它在这里实际上并没有做任何事情:data.aws_security_groups.test.ids它已经是一个可迭代的集合,因此与我在上面的示例中使用的所有语言特性兼容。

IIRC 提供者认为此ids属性是一组字符串而不是字符串列表,因此[*]如果您需要以这种方式键入该集合,则该后缀在其他情况下可能有用,可以强制将其转换为列表,尽管如果那是您的意图,那么我建议您改用以下方法之一,以便将来的读者更清楚它的作用:

  • sort(data.aws_security_groups.test.ids)(如果它的词法顺序对行为很重要;无论如何,Terraform 默认使用词法排序,但是sort对于不熟悉 Terraform 的读者来说,调用是一个很好的提示,可以查找该函数以查看实际的排序顺序是什么。)
  • tolist(data.aws_security_groups.test.ids)(当它是一组字符串时,功能上等同于sort上面,但避免暗示特定顺序很重要,如果重要的是它是一个列表,而不管顺序如何)

推荐阅读