是否有一种方法可以将所有x资源的列表提供给terraform中的模块?



我们为datadog使用了terraform,并且我们为每个团队设置了文件夹/模块。对于Datadog合成测试,我们在地形项目根中为每个环境/区域组合(dev/pre-prod/prod-1/prod-2)设置了一个datadog_synthetics_private_location

每个团队都可以为他们的产品域设置他们自己的合成测试,模块应该使用那些预定义的合成位置id,而不是将它们硬编码为字符串。

我想做的是将项目中存在的datadog_synthetics_private_location的所有3个(未来可能是n)实例作为列表提供给每个模块,而无需在每个模块中创建n变量。

我知道在terraform中的*语法,但我敢说它只适用于count的资源,我们没有在我们的情况下,因为我们希望能够识别出我们引用的n中的哪个资源:

# works (if my_location has a count):
location_ids = datadog_synthetics_private_location.my_location.*.id
# what I want to do:
# hand over to module:
locations = datadog_synthetics_private_location.*
# use:
locations = [
var.locations.my_dev_location.id
]

这可能吗?这是一个糟糕的设计吗?它需要一个丑陋的hack吗?使用datadog_synthetics_locations数据源是更好的方法吗?如果是,怎么做?看起来它在一个映射中检索了所有这些,然后我必须过滤以检索特定的一个。

标识符datadog_synthetics_private_location单独不表示一个值,因此如果在表达式中不跟在至少一个资源名后面,就不能使用它。Terraform使用这些引用来自动推断依赖关系图,所以引用必须总是静态编写的。

如果你确实需要一个包含多个资源对象的集合值,那么你可以自己构造一个本地值:

locals {
locations = {
a = datadog_synthetics_private_location.a
b = datadog_synthetics_private_location.b
c = datadog_synthetics_private_location.c
}
}

这个方法可以工作,因为Terraform可以看到local.locations依赖于所有这三种资源,所以任何你引用local.locationsTerraform的地方都可以推断出你间接地依赖于所有这三种资源。一旦你在一个地方写出了这个数据结构,你就可以在其他地方使用它作为一个正常的值,包括将它作为一个整体传递给一个模块,或者将它与任何terrform语言操作符或函数一起使用,这些操作符或函数会接受这个类型的值。


上面定义的local.locations的自动类型将是具有abc属性的对象类型,其自身的类型是datadog_synthetics_private_location的有效对象类型。

但是,当将这样的结构传递给子模块时,依赖Terraform的结构类型系统只描述模块实际依赖的数据结构的子集是常见的和习惯的,而不是试图准确地描述该类型,因为Terraform会推断它。

这涉及到参考datadog_synthetics_private_location的文档来决定哪些属性是您的模块完成其工作所需的最小值,然后声明一个基于此类型的变量。

例如,如果你认为你的模块只需要idname,那么你可以这样声明:

variable "locations" {
type = map(object({
id   = string
name = string
}))
}

如果你将locations = local.locations传递给子模块,那么Terraform将自动将原始推断对象类型转换为具有你指定属性的对象映射,忽略任何其他属性,因为模块没有声明它需要它们。

在模块内部,var.locations将作为该对象类型的映射出现,并且您可以依赖于这种情况,否则Terraform将在调用module块时引发类型错误。

最新更新