Ansible – How to Loop Through Interface Facts

ansible

The setup module from ansible provides the fact ansible_interfaces

"ansible_interfaces": [
    "lo", 
    "eth0",
    "eth1"
], 

And per interface some facts:

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

How do I use the ansible_interfaces fact to loop through the available interfaces?

  tasks:
    - name: find interface facts
      debug: msg=ansible_{{ item }}
      with_items: "{{ ansible_interfaces }}"

This is clearly not working, because it prints out the strings ansible_lo, ansible_eth0 and ansible_eth1, but I want it to print the facts from those interfaces. Some servers have other interfaces, like bridges, so I don't know in advance wich interfaces to use.

p.s. this example is not very usefull, but eventually I want to use it to store facts like macaddresses in elasticsearch for easy searching which server has which macaddress.

Best Answer

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