How to loop through interface facts

Solution 1:

You came across one of the limitations of Jinja/Ansible templating, namely there is no way to evaluate expressions, which would be required to get to the value of something like ansible_{{ item }}. You're stuck with a string.

Fortunately there is the global hostvars object where you can access all the facts by key, which is... a string.

Something along these lines should get you there:

tasks:
  - name: find interface facts
    debug:
      msg: "{{ hostvars[inventory_hostname]['ansible_%s' | format(item)] }}"
    with_items: "{{ ansible_interfaces }}"

Solution 2:

You actually can do this.You just have to know j2 syntax pretty well, search a little bit and combine it with some hacks. DOH. just lost 2 hours. Hope I save it to someone!

It's doable like this:

    - 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 %}

And as I suspect, the people searching to do this, want to calculate the next free interface (which I was after for).

I did it like this:

    - 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}}"

the nextFreeIf is on one line, because, otherwise you get empty spaces and headaches to trim it. It's ugly, but hey, it works.

Really hope to save someones time. Cheers.

Tags:

Ansible