Terraform 因 for_each 参数无效/给定的“for_each”参数值不合适而失败
Posted
技术标签:
【中文标题】Terraform 因 for_each 参数无效/给定的“for_each”参数值不合适而失败【英文标题】:Terraform failing with Invalid for_each argument / The given "for_each" argument value is unsuitable 【发布时间】:2020-09-27 12:47:54 【问题描述】:当运行terraform plan
或terraform apply
并提供给for_each
的列表时,会出现错误提示
Error: Invalid for_each argument
on main.tf line 2, in resource "aws_ssm_parameter" "foo":
2: for_each = ["a", "b"]
The given "for_each" argument value is unsuitable: the "for_each" argument
must be a map, or set of strings, and you have provided a value of type tuple.
重现此错误的最小示例如下:
resource "aws_ssm_parameter" "foo"
for_each = ["a", "b"]
name = "foo-$each.value"
type = "String"
value = "bar-$each.value"
【问题讨论】:
【参考方案1】:说明
此错误通常是由将列表传递给 for_each
引起的,但 for_each
仅适用于无序数据类型,即适用于集合和映射。
解决方案
解决办法视情况而定。
字符串列表
如果列表只是一个字符串列表,最简单的解决方法是添加一个toset()
-call 将列表转换为可以由for_each处理的集合,像这样
resource "aws_ssm_parameter" "foo"
for_each = toset(["a", "b"])
name = "foo-$each.value"
type = "String"
value = "bar-$each.value"
可以重新排列为地图的列表
如果输入是一个列表,但很容易重新排列为地图,这通常是最好的方法。 假设我们有一个这样的列表
locals
animals = [
name = "Bello"
age = 3
type = "dog"
,
name = "Minga"
age = 4
type = "cat"
,
]
那么适当的重组可能是这样的
locals
animals =
Bello :
age = 3
type = "dog"
,
Minga :
age = 4
type = "cat"
然后允许您定义
resource "aws_ssm_parameter" "foo"
for_each = local.animals
name = each.key
type = string
value = "This is a $each.value.type, $each.value.age years old."
不想重新排列的列表
有时有一个列表是很自然的,例如来自不受控制的模块的输出或来自使用count
定义的资源。在这种情况下,可以像这样使用 count
resource "aws_ssm_parameter" "foo"
count = length(local.my_list)
name = my_list[count.index].name
type = "String"
value = my_list[count.index].value
适用于包含名称和值作为键的映射列表。但是,通常情况下,将列表转换为地图更合适,而不是像这样
resource "aws_ssm_parameter" "foo"
for_each = for x in local.my_list: x.id => x
name = each.value.name
type = "String"
value = each.value.value
这里应该选择任何合适的东西来代替x.id
。如果my_list
是一个对象列表,那么通常有一些通用字段(例如名称或键)可以使用。这种方法有利于使用count
的优点是,在从列表中插入或删除元素时表现更好。 count
不会注意到插入或删除,因此会更新插入发生位置之后的所有资源,而 for_each
实际上只添加或删除具有新或已删除 id 的资源。
【讨论】:
我会更正错误不是“由将列表传递给 for_each 引起的”,而是因为for_each
仅适用于无序数据类型。列表是有序类型,集合或映射不是。
这很奇怪,您可以在动态块内列出地图列表,但如果您在外部使用 for_each 则会出现错误:(
我同意;这很奇怪。如果该语言能够迭代无序集合,那么世界上有什么可能阻止对有序集合的迭代呢? Terraform 不符合最小惊讶法则。以上是关于Terraform 因 for_each 参数无效/给定的“for_each”参数值不合适而失败的主要内容,如果未能解决你的问题,请参考以下文章
具有下游依赖项的 Terraform 条件“for_each”
将 aws 资源导入具有 for_each 的 terraform 模块
使用 terraform 在 for_each 嵌套资源中循环