我正在使用 Terraform 来管理 Github 组织。我们有一个标准的“通用存储库”模块,用于确保我们的存储库共享通用配置。我想添加对配置 GitHub 页面的支持,这需要对pages
元素的支持,如下所示:
pages {
build_type = "legacy"
cname = "example.com"
source {
branch = "master"
path = "/docs"
}
}
一切都是可选的。特别是,source
只有在 时才是必需的build_type == "legacy" || build_type == null
,整个pages
块可以省略。我不知道如何进行source
条件化,所以我最终将其拆分成两个dynamic
块,如下所示:
# There are two `dynamic "pages"` blocks here to account for the fact that `source` is only required
# if `build_type` is "legacy". The `for_each` at the top of each block will only enable the block when
# the necessary conditions are met.
dynamic "pages" {
# enable this block if `pages` is not null and `build_type` is "legacy" (or null)
for_each = var.pages == null ? [] : var.pages.build_type == "legacy" || var.pages.build_type == null ? ["enabled"] : []
content {
source {
branch = var.pages.source.branch
path = var.pages.source.path
}
cname = var.pages.cname
build_type = var.pages.build_type
}
}
dynamic "pages" {
# enable this block if `pages` is not null and `build_type` is "workflow"
for_each = var.pages == null ? [] : var.pages.build_type == "workflow" ? ["enabled"] : []
content {
cname = var.pages.cname
build_type = var.pages.build_type
}
}
pages
我在模块中定义变量如下:
variable "pages" {
description = "Configuration for github pages"
type = object({
source = optional(object({
branch = string
path = string
}))
build_type = optional(string, "legacy")
cname = optional(string)
})
default = null
}
有没有更好的方法来解决这个问题?
您的输入变量声明已经确保了
build_type
本身不能为空,因为如果为空,Terraform 将使用默认值"legacy"
。我还建议添加一个验证规则来强制执行,该规则source
只能在 为build_type
时设置"legacy"
,如下所示:有了这个,您可以放心地假设模块中的其他地方
var.pages.source
总是会是,null
除非var.pages.build_type
是"legacy"
,并且var.pages.build_type
永远不会是null
。我认为此时其余的问题可以简化为:
pages
仅当var.pages
不为空时才声明块,并且仅当不为空时才声明source
块内的块,可以这样写:pages
var.pages.source
将
[*]
运算符应用于不属于列表、元组或集合类型的值会导致 Terraform 返回一个包含零个或一个元素的元组,具体取决于操作数是否为null
。此处理记录在单值为列表中。例如,如果
var.pages
为空,则上面的最外层块实际上具有for_each = []
,而如果var.pages
为非空,则为for_each
包含相同对象的单元素列表var.pages
,因此这实际上声明了零个或一个pages
块。嵌套块也是如此dynamic "source"
。附加奖励:
[*]
将单个值转换为零或一个元素的元组的行为在函数形式上one
具有逆。尽管在这种情况下这没有直接用处,但如果模块中的其他内容稍后需要引用先前使用 转换为元组的内容,则这两个功能通常会一起出现在模块中
[*]
,如与“Splat”运算符的关系中所示。因此,我认为值得学习它们,因为它们允许您在可能为空的单个值和零个或一个元素的序列之间自由地来回移动,就像您使用其他 Terraform 语言功能一样,这些功能期望与您当前持有的任何功能相反。
零或一元素序列本质上具有与可能为空的单个值相同的表达能力,但许多 Terraform 语言功能优先使用序列,因为它们可以推广到支持任意数量的元素。