Есть недооцененный, но очень полезный ответ Вот в котором объясняется, как перебирать факты интерфейса для произвольного количества интерфейсов.
По сути, все сводится к следующему:
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, хотя его нет.
Надеюсь, это поможет кому-то другому.