Ansible Jinja2模板处理YAML防火墙规则时groups字段报错求助
Ansible Jinja2模板引用防火墙规则groups字段报错解决
问题
在Ansible中对inventory中的防火墙规则做Jinja2模板化,部分规则包含groups列表元素。原模板未引用groups字段时可正常输出规则,但添加groups字段引用后,执行时报错:'dict object has no attribute 'groups''。
数据集
# inventory item details: lighthouse2: ansible_host: nebula_ip: 10.222.222.253 nebula_domain: skynet groups: lighthouse firewall: web443: port: 443 protocol: any host: any groups: - admin - lighthouse web80: port: 80 protocol: any host: any
可正常运行的模板(不含groups)
{% if firewall is defined %} # Begin rules from ansible inventory {% for rulename, ruledata in firewall.items() -%} #Allow {{ rulename }} - port: {{ ruledata.port }} protocol: {{ ruledata.protocol }} host: {{ ruledata.host }} {% endfor %} # End rules from ansible inventory {% endif %}
添加groups后的报错模板
{% if firewall is defined %} # Begin rules from ansible inventory {% for rulename, ruledata in firewall.items() -%} #Allow {{ rulename }} - port: {{ ruledata.port }} protocol: {{ ruledata.protocol }} host: {{ ruledata.host }} groups: {{ ruledata.groups }} {% endfor %} # End rules from ansible inventory {% endif %}
错误输出
TASK [create some file] ****************************************************************** An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ansible.errors.AnsibleUndefinedVariable: 'dict object' has no attribute 'groups' fatal: [lighthouse2 -> localhost]: FAILED! => {"changed": false, "msg": "AnsibleUndefinedVariable: 'dict object' has no attribute 'groups'"}
解决方法
问题根源是**web80规则没有定义groups字段**,Jinja2默认会对未定义的变量抛出错误。需要在模板中处理字段缺失的情况,有两种常用方式:
方式1:判断字段存在再输出
只在groups字段存在时才渲染这一行:
{% if firewall is defined %} # Begin rules from ansible inventory {% for rulename, ruledata in firewall.items() -%} #Allow {{ rulename }} - port: {{ ruledata.port }} protocol: {{ ruledata.protocol }} host: {{ ruledata.host }} {% if ruledata.groups is defined %} groups: {{ ruledata.groups }} {% endif %} {% endfor %} # End rules from ansible inventory {% endif %}
方式2:使用default过滤器设置默认值
给groups字段设置一个默认值(比如空列表),避免未定义报错:
{% if firewall is defined %} # Begin rules from ansible inventory {% for rulename, ruledata in firewall.items() -%} #Allow {{ rulename }} - port: {{ ruledata.port }} protocol: {{ ruledata.protocol }} host: {{ ruledata.host }} groups: {{ ruledata.groups | default([]) }} {% endfor %} # End rules from ansible inventory {% endif %}
两种方式都能解决报错,选择哪种取决于你的需求:如果希望没有groups的规则完全不输出这一行,用方式1;如果希望统一输出groups字段(即使是空列表),用方式2。
内容的提问来源于stack exchange,提问作者J P
相关产品推荐
相关产品推荐

