【问题标题】: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】:

      我会使用containskeys 执行以下操作

      %{ 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 {
      
      }
      
      

      【讨论】:

        猜你喜欢
        • 2013-06-07
        • 2010-09-23
        • 2017-03-24
        • 2011-07-01
        • 1970-01-01
        • 2014-09-08
        • 2013-07-14
        • 2011-09-07
        相关资源
        最近更新 更多