Estou usando o Terraform para gerenciar uma organização do Github. Temos um módulo padrão "repositório comum" que usamos para garantir que nossos repositórios compartilhem uma configuração comum. Gostaria de adicionar suporte para configurar páginas do GitHub, o que requer suporte para o pages
elemento , que se parece com isso:
pages {
build_type = "legacy"
cname = "example.com"
source {
branch = "master"
path = "/docs"
}
}
Tudo é opcional. Em particular, source
é necessário somente se build_type == "legacy" || build_type == null
, e o bloco inteiro pages
pode ser omitido. Não consegui descobrir como fazer source
condicional, então acabei dividindo isso em dois dynamic
blocos assim:
# 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
}
}
Onde eu defini a pages
variável no módulo assim:
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
}
Existe uma maneira melhor de abordar isso?
Sua declaração de variável de entrada já garante que
build_type
ela mesma não pode ser nula, já que o Terraform usará o valor padrão"legacy"
em vez disso, se for o caso. Eu sugeriria também adicionar uma regra de validação para impor quesource
só pode ser definida sebuild_type
is"legacy"
, assim:Com isso em vigor, você pode assumir com segurança que em outro lugar do módulo
var.pages.source
sempre será,null
a menosvar.pages.build_type
que seja"legacy"
, evar.pages.build_type
nunca poderá sernull
.Acredito que nesse ponto o resto do problema se reduz a: declarar o
pages
bloco somente sevar.pages
não for nulo, e declarar osource
bloco dentro delepages
somente sevar.pages.source
não for nulo, o que pode ser escrito assim:Aplicar o
[*]
operador a um valor que não é de um tipo de lista, tupla ou conjunto faz com que o Terraform retorne uma tupla com zero ou um elemento, dependendo se o operando énull
. Esse tratamento é documentado em Valores Únicos como Listas .Por exemplo, se
var.pages
for nulo, então o bloco mais externo acima efetivamente temfor_each = []
, enquanto sevar.pages
for não nulo, entãofor_each
é uma lista de elemento único contendo o mesmo objeto quevar.pages
contained, e então isso efetivamente declara zero ou umpages
bloco. O mesmo é verdade para o bloco aninhadodynamic "source"
.Conversa bônus: Esse
[*]
comportamento de transformar um único valor em uma tupla de zero ou um elemento tem um inverso na forma daone
função .Embora isso não seja diretamente útil neste caso, esses dois recursos geralmente aparecem juntos em um módulo se algo mais no módulo precisar posteriormente se referir a algo que foi previamente transformado em uma tupla usando
[*]
, conforme mostrado em Relação com o operador "Splat" .Portanto, acho que vale a pena aprender sobre os dois, pois juntos eles permitem que você se mova livremente entre valores únicos que podem ser nulos e sequências de zero ou um elemento, conforme você usa outros recursos da linguagem Terraform que esperam o oposto do que você está usando no momento.
Sequências de elementos zero ou um têm essencialmente o mesmo poder expressivo que valores únicos que podem ser nulos, mas muitos recursos da linguagem Terraform priorizam o trabalho com sequências porque podem ser generalizadas para oferecer suporte a números arbitrários de elementos.