yaml - 使用 terraform yamldecode 访问多级元素
问题描述
我有一个 yaml 文件(也用于 azure devops 管道,因此需要采用这种格式),其中包含一些我想直接从我的 terraform 模块访问的设置。
该文件类似于:
variables:
- name: tenantsList
value: tenanta,tenantb
- name: unitName
value: canary
我想要一个这样的模块来访问设置,但我看不到如何进入底层:
locals {
settings = yamldecode(file("../settings.yml"))
}
module "infra" {
source = "../../../infra/terraform/"
unitname = local.settings.variables.unitName
}
但是这样的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.
解决方案
看起来这很困难的主要原因是因为这个 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
})
}
}
上面使用for
表达式name
将映射列表投影到使用值作为键的单个映射中。
将地图列表转换为单个地图后,您可以按照最初尝试的方式访问它:
module "infra" {
source = "../../../infra/terraform/"
unitname = local.settings.variables.unitName
}
如果您要将转换后的值输出local.settings
为 YAML,它看起来像这样,这就是为什么现在可以直接访问地图元素的原因:
variables:
tenantsList: tenanta,tenantb
unitName: canary
这仅name
在您输入中的所有字符串都是唯一的情况下才有效,因为否则每个元素都不会有唯一的映射键。
(编写这样的规范化表达式也可以作为对该 YAML 文件形状的一些隐式验证:如果variables
不是列表或值不是全部相同类型,则 Terraform 会引发类型错误评估该表达式。即使不需要转换,我还是喜欢写出这种表达式,因为它可以作为 YAML 文件预期具有的形状的一些文档,而不是在整个配置的其余部分中研究对它的所有引用。 )
推荐阅读
- jquery - jQuery 附加由 AJAX 数据问题制成的表
- r - 根据 dplyr 中旧变量的水平创建新的因子变量
- r - R:在堆栈栏上显示字符或类别
- java - 使用 Spring 处理许多类似的数据库表时的最佳实践
- python - 使用 Selenium 登录 TradingView.com
- javascript - line-height 小于 font-size 时的边框
- unity3d - 如何修复统一 3D raycast 子弹不准确性
- c++ - 如何指示容器中的多态函子完成其工作并返回结果?
- php - 如何使用 AJAX 提交 Blade.php 表单
- javascript - 过滤数组,并添加搜索功能