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

Как просмотреть факты об интерфейсе

Модуль настройки от 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 находится в одной строке, потому что иначе вы получите пустые места и головную боль, чтобы обрезать его. Это некрасиво, но это работает.

Очень надеюсь сэкономить время. Ура.