假设我有一个 Terragrunt 配置位于所有平台边界 Databricks 项目之上,并且正在运行集群模块。该模块循环遍历每个 PB
main.tf
中定义的 locals 块,如下所示:
locals {
#... other local vars
clusters = {
clusterA = {
name = "clusterA"
#... other cluster config
},
clusterB = {
name = "clusterB"
#... other cluster config
}, ...
}
}
## main.tf
所有集群名称都是唯一的。我现在希望从特定平台边界删除除 clusterX 之外的每个集群。
我的目标是基本上将集群模块中的
for_each
设置为空集,只要我不这样做,它就不会循环遍历这个特定的集群,但如果它碰到它,我希望执行该模块。
我正在努力为此提出正确的条件,我最接近的解决方案如下:
locals{
run_cluster_module = contains(keys(local.clusters), "clusterX")
}
module "cluster" {
for_each = local.run_cluster_module ? local.clusters : {}
#... other module attributes
## terragrunt.hcl
这会以某种方式引发不一致的类型错误。有什么建议吗?
{ ... }
语法生成对象类型的值。在某些情况下,Terraform 能够自动推断您打算使用地图值并对其进行转换,但在这种情况下,Terraform 不太确定您打算做什么,因此它不会执行任何自动转换。错误消息随后描述了两种不同对象类型之间的不匹配情况,希望它能帮助您添加适当的类型转换或其他信息,以阐明您希望条件表达式生成什么数据类型。
在这种情况下,我建议将这两个值显式转换为地图。例如:
locals {
#... other local vars
clusters = tomap({
clusterA = {
name = "clusterA"
#... other cluster config
},
clusterB = {
name = "clusterB"
#... other cluster config
}, ...
})
}
module "cluster" {
for_each = local.run_cluster_module ? local.clusters : tomap({})
# ...
}
这告诉 Terraform 您希望 local.clusters
成为对象的地图而不是对象本身。我无法准确预测仅使用
local.clusters
的部分值的类型,但仅使用
name
属性,如您在代码片段中所示,
local.clusters
将具有以下类型:
map(object({
name = string
}))
tomap({})
的特殊之处在于它生成“未知类型的映射”——这里没有足够的信息来推断元素类型应该是什么——但是条件表达式应该注意到一个结果具有已知的元素类型并且另一个则不然,因此它可以自动将未知元素类型的映射专门化为与
local.clusters
的类型匹配的已知元素类型的映射。
特别请注意,对象映射中的所有对象必须具有“相同的对象类型”,这意味着它们必须具有相同的属性名称和类型。如果某些属性仅适用于集群的子集,您可以将它们设置为
null
以使类型一致,同时仍表示某些属性未填充。