首页 > 解决方案 > 如何让 Terraform 用默认值替换空值?

问题描述

Terraform 文档表明这应该已经发生了:

https://www.terraform.io/docs/language/expressions/types.html

null:代表缺席或遗漏的值。如果您将资源或模块的参数设置为 null,Terraform 的行为就好像您完全省略了它一样 - 如果参数有默认值,它将使用该参数的默认值,如果该参数是强制性的,则会引发错误。

我正在调用具有以下变量文件的模块“foo”:

variable "bar" {
  type    = string
  default = "HelloWorld"
}

示例 1

当我使用此代码调用它时:

module "foo" {
  source = "../modules/foo"
  bar = null
}

结果是一个错误。“str”参数的值无效:参数不能为空。使用 bar 时触发。

示例 2

当我使用此代码调用它时(省略它,而不是将它归零):

module "foo" {
  source = "../modules/foo"
  # bar = null
}

结果是它起作用了。“bar”变量默认为“HelloWorld”。

这似乎是 Terraform 中的一个错误,其他人也提出了但没有解决。 https://github.com/hashicorp/terraform/issues/27730

有谁知道解决方案或解决方法?

版本信息:

Terraform v1.0.5
on linux_amd64
+ provider registry.terraform.io/hashicorp/google v3.51.0
+ provider registry.terraform.io/hashicorp/null v3.1.0
+ provider registry.terraform.io/hashicorp/random v3.1.0
+ provider registry.terraform.io/hashicorp/time v0.7.2

解决方法

根据@Matt Schuchard 的评论和一些研究,使用条件检查有一个丑陋的解决方案:

variable "foo" {
  type    = string
  default = "HelloWorld"
}
locals {
  foo = var.foo == null ? "HelloWorld" : var.foo
}

为什么

我的用例是试图避免重复代码。我有 2 个非常相似的模块,一个是另一个的子集。我正在使用的解决方案是将模块按顺序调用每个模块,即祖父母、父母和孩子。

我想让“祖父母”可以使用这些变量,但如果它们被省略,那么“子”下面的模块应该使用默认值设置它们,例如“HelloWorld”。但是要在整个家族中一直暴露这些变量,我必须将它们包含在所有模块和高级模块(祖父母和父母)中,我想将它们默认为空,允许它们是可选的,但仍然使它们成为在“子”中设置为默认值。

...我想我需要一个图表。

标签: terraform

解决方案


您可以通过函数将默认值设置为null并设置真正的默认值localcoalesce

variable "foo" {
  type    = string
  default = null
}

locals {
  # return var.foo if it's not null
  # return "HelloWorld" if var.foo is null
  foo = coalesce(var.foo, "HelloWorld")
}

output "foo" {
  value = local.foo
}

null使用return的默认值HelloWorld

$ terraform apply -auto-approve

...

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

foo = "HelloWorld"

使用新值会否定local

$ terraform apply -auto-approve -var="foo=HelloUniverse"

...

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

foo = "HelloUniverse"

推荐阅读