如何在ansible / j2中缺少字典时检查变量是否已定义

时间:2018-01-16 14:52:12

标签: ansible jinja2

我有一个Ansible和Jinja2相关的问题。我有一个像这样的yml文件:

---
haproxy:
  global:
    maxconn: 30000
    ssl: true
  defaults:
    maxconn: 400
  server:
    maxconn: 200
    httpclose: true
  frontend:
    web:
      maxconn: 20000
      ssl: true

在J2模板中,我想做这样的事情:

{% if haproxy.frontend.web.maxconn is defined  %}
    maxconn {{ haproxy.frontend.web.maxconn }}
{% endif %}

这很有效,当定义了值时,但我们使用了几个环境,而在其中一些环境中,frontend字典未定义(那么,它将属于haproxy的默认值,这在开发中很好)当frontend丢失时,我在ansible中收到此错误:

"msg": "AnsibleUndefinedVariable: 'dict object' has no attribute 'frontend'"

此错误由if本身而非正文产生。

我知道frontend不存在,但逻辑上意味着变量未定义(因为它根本不存在)。请告诉我如何在缺少字典的情况下检查变量的存在/定义。

谢谢!

P.S。请不要告诉我做类似

的事情
{% if haproxy.frontend is defined and haproxy.frontend.web is defined and haproxy.frontend.web.maxconn is defined %}

2 个答案:

答案 0 :(得分:3)

你的条件来自“P.S.”不会因原来的原因而起作用。

您需要在嵌套语句中使用单独的条件:

{% if haproxy.frontend is defined %}
  {%- if haproxy.frontend.web is defined %}
    {%- if haproxy.frontend.web.maxconn is defined %}
      maxconn {{ haproxy.frontend.web.maxconn }}
    {%- endif %}
  {%- endif %}
{% endif %}"

除了default filter之外,还有一个丑陋的构造(参见this answer)。

这是对你案件的改编:

{% if ((haproxy.frontend|default({})).web|default({})).maxconn is defined %}
    maxconn {{ haproxy.frontend.web.maxconn }}
{% endif %}"

in运营商:

{% if 'maxconn' in (haproxy.frontend|default({})).web|default({}) %}
    maxconn {{ haproxy.frontend.web.maxconn }}
{% endif %}"

答案 1 :(得分:0)

如果您确定abc.cde从未定义过,则下面的内容同样适用:

{% if "xyz" in abc.cde %}
      storageClassName: {{ abc.cde.xyz }}
{% endif %}