我有一个 yaml 文件(也在 azure devops 管道中使用,因此需要采用这种格式),其中包含一些我想直接从我的 terraform 模块访问的设置。
该文件类似于:
variables:
- name: tenantsList
value: tenanta,tenantb
- name: unitName
value: canary
Run Code Online (Sandbox Code Playgroud)
我想要一个这样的模块来访问设置,但我看不到如何到达底层:
locals {
settings = yamldecode(file("../settings.yml"))
}
module "infra" {
source = "../../../infra/terraform/"
unitname = local.settings.variables.unitName
}
Run Code Online (Sandbox Code Playgroud)
但是这个terraform plan错误:
Error: Unsupported attribute
on canary.tf line 16, in module "infra":
16: unitname = local.settings.variables.unitName
|----------------
| local.settings.variables is tuple with 2 elements
This value does not have any attributes.
Run Code Online (Sandbox Code Playgroud)
看起来这很困难的主要原因是因为这个 YAML 文件在逻辑上代表了一个单一的地图,但在物理上表现为一个 YAML 地图列表。
当从这样的单独文件中读取数据时,我喜欢编写一个显式表达式来规范化它,并有选择地转换它以便在 Terraform 模块的其余部分中更方便地使用。在这种情况下,似乎variables将地图作为 Terraform 值最有用的表示形式,因此我们可以编写这样的转换表达式:
locals {
raw_settings = yamldecode(file("${path.module}/../settings.yml"))
settings = {
variables = tomap({
for v in local.raw_settings.variables : v.name => v.value
})
}
}
Run Code Online (Sandbox Code Playgroud)
上面使用for表达式将映射列表投影到单个映射中,使用name值作为键。
将地图列表转换为单个地图后,您可以按照最初尝试的方式访问它:
module "infra" {
source = "../../../infra/terraform/"
unitname = local.settings.variables.unitName
}
Run Code Online (Sandbox Code Playgroud)
如果您将转换后的值作为 YAML输出local.settings,它将看起来像这样,这就是为什么现在可以直接访问地图元素:
variables:
tenantsList: tenanta,tenantb
unitName: canary
Run Code Online (Sandbox Code Playgroud)
这仅name在输入中的所有字符串都是唯一的情况下才有效,否则每个元素都不会有唯一的映射键。
(编写这样的规范化表达式也可以作为对该 YAML 文件形状的一些隐式验证:如果variables不是列表或者值不是所有相同类型,则 Terraform 会引发类型错误评估该表达式。即使不需要转换,无论如何我喜欢写出这种表达式,因为它可以作为 YAML 文件预期具有的形状的一些文档,而不必在整个配置的其余部分研究对它的所有引用。 )
| 归档时间: |
|
| 查看次数: |
3443 次 |
| 最近记录: |