Назад | Перейти на главную страницу

Шаблон 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']}}"

Но это вызывает ошибку при заполнении шаблона. Как мне обратиться к подэлементам словаря, пожалуйста?

Я, вероятно, могу установить факты в цикле в playbook, поскольку отладка, похоже, может ссылаться на подэлементы, но я бы предпочел сохранить все в шаблоне.

Вот как выглядит весь объект:

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 не существует. Я узнаю, как ограничить, когда у интерфейса есть адрес, и напишу ответ на свой вопрос.

Вот что требуется:

{% 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, хотя его нет.

Надеюсь, это поможет кому-то другому.