运行时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}"
}
最佳答案
解释
此错误通常是由将列表传递给 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}"
}
可以重新排列为 map 的列表如果输入是一个列表,但很容易重新排列为 map ,这通常是最好的方法。
假设我们有一个这样的列表
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
定义的资源.在这种情况下,可以像这样使用 countresource "aws_ssm_parameter" "foo" {
count = length(local.my_list)
name = my_list[count.index].name
type = "String"
value = my_list[count.index].value
}
它适用于包含名称和值作为键的映射列表。但是,通常情况下,将列表转换为 map 更合适,而不是像这样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 的资源。
关于amazon-web-services - Terraform 因无效的 for_each 参数而失败/给定的 "for_each"参数值不合适,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62264013/