Модуль настройки от ansible предоставляет факт ansible_interfaces
"ansible_interfaces": [
"lo",
"eth0",
"eth1"
],
И по интерфейсу некоторые факты:
"ansible_eth0": {
"active": true,
"device": "eth0",
"ipv4": {
"address": "192.168.10.2",
"broadcast": "192.168.10.255",
"netmask": "255.255.255.0",
"network": "192.168.10.0"
},
"macaddress": "52:54:00:5c:c1:36",
"module": "virtio_net",
"mtu": 1500,
"pciid": "virtio0",
"promisc": false,
"type": "ether"
}
Как использовать факт ansible_interfaces для циклического перебора доступных интерфейсов?
tasks:
- name: find interface facts
debug: msg=ansible_{{ item }}
with_items: "{{ ansible_interfaces }}"
Это явно не работает, потому что он распечатывает строки ansible_lo, ansible_eth0 и ansible_eth1, но я хочу, чтобы он печатал факты из этих интерфейсов. У некоторых серверов есть другие интерфейсы, например мосты, поэтому я заранее не знаю, какие интерфейсы использовать.
p.s. этот пример не очень полезен, но в конечном итоге я хочу использовать его для хранения фактов, таких как mac-адреса, в elasticsearch, чтобы упростить поиск, какой сервер имеет Mac-адрес.
Вы столкнулись с одним из ограничений шаблонов Jinja / Ansible, а именно, нет возможности оценивать выражения, которые потребовались бы для получения значения чего-то вроде ansible_{{ item }}
. Вы застряли на веревке.
К счастью, есть глобальный hostvars
объект, в котором вы можете получить доступ ко всем фактам по ключу, который является ... строкой.
Что-то в этом роде должно вас туда подвести:
tasks:
- name: find interface facts
debug:
msg: "{{ hostvars[inventory_hostname]['ansible_%s' | format(item)] }}"
with_items: "{{ ansible_interfaces }}"
Вы действительно можете это сделать. Вам просто нужно хорошо знать синтаксис j2, немного поискать и объединить его с некоторыми хаками. DOH. просто потерял 2 часа. Надеюсь, я сохраню его кому-нибудь!
Это можно сделать так:
- name: Display all interfaces
debug:
msg: "{{ msg.split('\n') }}"
vars:
msg: |
{% for iface in ansible_interfaces|sort %}
System interface {{ iface }}
{{ vars.ansible_facts[iface] | to_nice_json }}
{% endfor %}
И, как я подозреваю, люди, пытающиеся это сделать, хотят вычислить следующий бесплатный интерфейс (за которым я и искал).
У меня так получилось:
- name: calc next free interface
set_fact:
nextFreeIf: "{% set ifacePrefix = vars.ansible_default_ipv4.alias %}{% set ifaceNum = { 'cnt': 0 } %}{% macro increment(dct, key, inc=1)%}{% if dct.update({key: dct[key] + inc}) %} {% endif %}{% endmacro %}{% for iface in ansible_interfaces|sort %}{% if iface| regex_search('^' ~ vars.ansible_default_ipv4.alias) %}{{ increment(ifaceNum, 'cnt') }}{% endif %}{% endfor %}{{ifacePrefix}}:{{ifaceNum.cnt}}"
nextFreeIf находится в одной строке, потому что иначе вы получите пустые места и головную боль, чтобы обрезать его. Это некрасиво, но это работает.
Очень надеюсь сэкономить время. Ура.