【问题标题】:Check if variable exists - Terraform template syntax检查变量是否存在 - Terraform 模板语法
【发布时间】:2020-05-30 03:25:33
【问题描述】:
我正在尝试使用 terraform 模板语法检查模板文件中是否存在变量,但出现 This object does not have an attribute named "proxy_set_header 错误。
$ cat nginx.conf.tmpl
%{ for location in jsondecode(locations) }
location ${location.path} {
%{ if location.proxy_set_header }
proxy_set_header ${location.proxy_set_header};
%{ endif }
}
%{ endfor }
我尝试使用if location.proxy_set_header != "" 和if location.proxy_set_header 没有成功。
如何使用字符串模板检查变量是否存在?
【问题讨论】:
标签:
terraform
terraform-template-file
【解决方案1】:
如果您使用的是 Terraform 0.12.20 或更高版本,则可以使用新功能 can 简洁地编写如下检查:
%{ for location in jsondecode(locations) }
location ${location.path} {
%{ if can(location.proxy_set_header) }
proxy_set_header ${location.proxy_set_header};
%{ endif }
}
%{ endfor }
can 函数如果给定表达式可以无错误地计算,则返回 true。
文档确实建议在大多数情况下首选try,但在这种特殊情况下,如果该属性不存在,您的目标是什么都不显示,因此我认为与try 等效的方法是,对于未来的读者来说更难理解:
%{ for location in jsondecode(locations) }
location ${location.path} {
${ try("proxy_set_header ${location.proxy_set_header};", "") }
}
%{ endfor }
除了(主观上)对意图更加不透明之外,这忽略了 try 文档中关于仅将其用于属性查找和类型转换表达式的建议。因此,我认为上面的 can 用法是合理的,因为它相对清晰,但任何一种方式都应该有效。
【解决方案2】:
我会使用contains 和keys 执行以下操作
%{ for location in jsondecode(locations) }
location ${location.path} {
%{ if contains(keys(location), "proxy_set_header") }
proxy_set_header ${location.proxy_set_header};
%{ endif }
}
%{ endfor }
解析后的 JSON 本质上变成了 map,可以检查关键内容。
我用以下代码对此进行了测试
data "template_file" "init" {
template = file("${path.module}/file.template")
vars = {
locations = <<DOC
[
{
"path": "foo",
"proxy_set_header": "foohdr"
},
{
"path": "bar"
}
]
DOC
}
}
output "answer" {
value = data.template_file.init.rendered
}
它有以下输出
Outputs:
answer =
location foo {
proxy_set_header foohdr;
}
location bar {
}