Ansible jinja2 模板:如何循环遍历接口事实的子元素

Ansible jinja2 模板:如何循环遍历接口事实的子元素

有一个不被重视但非常有用的答案这里它解释了如何循环遍历任意数量接口的接口事实。

基本上可以归结为以下几点:

debug:
  msg: "{{ hostvars[inventory_hostname]['ansible_%s' | format(item)] }}"
with_items: "{{ ansible_interfaces }}"

这很棒,但我想访问接口信息的各个项目 - 例如地址和 MTU。我不知道如何提取这些字段。我期望使用类似以下内容:

msg: "{{ hostvars[inventory_hostname]['ansible_%s' | format(item)] ['ipv4']['address']}}"

但在模板填充时会产生错误。请问我该如何处理字典的子元素?

我可能可以在剧本中循环设置事实,因为调试似乎能够引用子元素,但我宁愿将所有内容保留在模板中。

整个对象的外观如下:

bond0 :
    {u'lacp_rate': u'slow', u'macaddress': u'00:24:e8:58:36:12', u'features': {u'generic_receive_offload': u'off', u'tx_checksumming': u'on', u'large_receive_offload': u'on', u'rx_checksumming': u'on',         u'udp_fragmentation_offload': u'off', u'generic_segmentation_offload': u'off', u'tcp_segmentation_offload': u'on', u'scatter_gather': u'on', u'ntuple_filters': u'off', u'receive_hashing': u'off'}, u'm
    iimon': u'100', u'speed': 1000, u'mtu': 1500, u'active': True, u'promisc': False, u'mode': u'active-backup', u'slaves': [u'eth0', u'eth1'], u'device': u'bond0', u'type': u'bonding', u'ipv4': {u'broadca
    st': u'10.138.162.255', u'netmask': u'255.255.255.0', u'network': u'10.138.162.0', u'address': u'10.138.162.11'}}

更新:我可以像这样获取 mtu:

MTU: {{ hostvars[inventory_hostname]['ansible_%s'|format(iface)]['mtu'] }}

但如果我尝试像这样获取地址信息:

{{ {{ hostvars[inventory_hostname]['ansible_%s'|format(iface)]['ipv4'] }} }}

产生这个错误:

fatal: [server_name]: FAILED! => {"changed": false, "failed": true, "msg": "AnsibleUndefinedVariable: 'dict object' has no attribute 'ipv4'"}

进一步更新:我突然顿悟:有些接口没有地址,所以 ipv4 不存在。我会找出如何限制接口何时有地址,并写下我的问题的答案。

答案1

这是需要的:

{% for iface in ansible_interfaces %}
 {{ iface}} :
 {% if  hostvars[inventory_hostname]['ansible_%s'|format(iface)]['ipv4'] is defined %}
   {{ hostvars[inventory_hostname]['ansible_%s'|format(iface)]['ipv4']['address'] }}
 {% else %}
   No ip address set
 {% endif %}
   MTU: {{ hostvars[inventory_hostname]['ansible_%s'|format(iface)]['mtu'] }}
{% endfor %}

这有效。请注意,您不能让条件检查(在本例中)“ipv4”的子元素,如下所示:

{% if ... ['ipv4']['address'] %}

因为这仍然假设字典中有一个元素“ipv4”,但事实并非如此。

我希望这对其他人有帮助。

相关内容