Ansible – Print Facts from a Loop

ansible

Hoping someone can save my sanity as I've been Googling the snot out of this with no luck. Seems like it should be pretty simple. I'm trying to gather the duplex of all interfaces on a list of hosts using Ansible facts. Fortunately, we have chef everywhere and the ohai facts include this info.

My problem is I can't figure out how to loop through the interfaces to print this duplex info. Specifically, I need to print the fact [ohai_network.interfaces.{interface_name}.duplex]. Here's what I've tried:

  tasks:
  - name: Print interface duplex
    when: "{{ hostvars[ansible_fqdn]['ansible_'~item]['ipv4'] is defined }}"
    debug:
      msg="{{ ansible_hostname }} {{ item }} interface duplex is {{ ohai_network.interfaces.[item].duplex }}"
    with_items:
      - "{{ ansible_interfaces | map('replace', '-','_') | list }}"

It doesn't appear to appreciate my [item] variable thrown into the fact reference. Any help would be much appreciated!

UPDATE – The "map('replace', '-','_') | list" section was added in from another grab from elsewhere. I see the output seems fine without it. I've also modified the format of the fact reference so the playbook now looks like this:

  tasks:
    - name: Print interface duplex
      when: "{{ hostvars[ansible_fqdn]['ansible_'~item]['ipv4'] is defined }}"
      debug:
        msg="{{ ansible_hostname }} {{ item }} interface duplex is {{ ohai_network['interfaces'][item]['duplex'] }}"
      with_items:
        - "{{ ansible_interfaces }}"

I still get an error:

exception type: <class 'ansible.errors.AnsibleUndefinedVariable'>
exception: 'dict object' has no attribute 'duplex'

Here is the output from the var string that was asked for:

TASK [Print interface duplex] ********************************************************************************************************************
 [WARNING]: when statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found: {{
hostvars[ansible_fqdn]['ansible_'~item]['ipv4'] is defined }}
ok: [REDACTED] => (item=lo) => {
    "changed": false, 
    "item": "lo", 
    "ohai_network.interfaces": {
        "ens160": {
            "addresses": {
                "00:00:00:00:00:01": {
                    "family": "lladdr"
                }, 
                "10.204.76.244": {
                    "broadcast": "10.0.0.255", 
                    "family": "inet", 
                    "netmask": "255.0.0.0", 
                    "prefixlen": "8", 
                    "scope": "Global"
                }
            }, 
            "arp": {
                "10.204.76.1": "00:00:00:00:00:01", 
                "10.204.76.3": "00:00:00:00:00:01"
            }, 
            "auto_negotiation": "off", 
            "duplex": "Full", 
            "encapsulation": "Ethernet", 
            "flags": [
                "BROADCAST", 
                "MULTICAST", 
                "UP", 
                "LOWER_UP"
            ], 
            "link_speed": 10000, 
            "mdi_x": "Unknown", 
            "mtu": "1500", 
            "number": "0", 
            "port": "Twisted Pair", 
            "ring_params": {
                "current_rx": 256, 
                "current_rx_jumbo": 128, 
                "current_rx_mini": 0, 
                "current_tx": 512, 
                "max_rx": 4096, 
                "max_rx_jumbo": 4096, 
                "max_rx_mini": 0, 
                "max_tx": 4096
            }, 
            "routes": [
                {
                    "destination": "default", 
                    "family": "inet", 
                    "metric": "100", 
                    "proto": "static", 
                    "via": "10.0.0.1"
                }, 
                {
                    "destination": "10.0.0.0/8", 
                    "family": "inet", 
                    "metric": "100", 
                    "proto": "kernel", 
                    "scope": "link", 
                    "src": "10.0.0.2"
                }
            ], 
            "state": "up", 
            "transceiver": "internal", 
            "type": "ens16"
        }, 
        "lo": {
            "addresses": {
                "127.0.0.1": {
                    "family": "inet", 
                    "netmask": "255.0.0.0", 
                    "prefixlen": "8", 
                    "scope": "Node"
                }
            }, 
            "encapsulation": "Loopback", 
            "flags": [
                "LOOPBACK", 
                "UP", 
                "LOWER_UP"
            ], 
            "mtu": "65536", 
            "state": "unknown"
        }
    }
}
ok: [REDACTED] => (item=ens160) => {
    "changed": false, 
    "item": "ens160", 
    "ohai_network.interfaces": {
        "ens160": {
            "addresses": {
                "00:00:00:00:00:01": {
                    "family": "lladdr"
                }, 
                "10.204.76.244": {
                    "broadcast": "10.0.0.255", 
                    "family": "inet", 
                    "netmask": "255.0.0.0", 
                    "prefixlen": "8", 
                    "scope": "Global"
                }
            }, 
            "arp": {
                "10.0.0.1": "00:00:00:00:00:01", 
                "10.0.0.2": "00:00:00:00:00:01"
            }, 
            "auto_negotiation": "off", 
            "duplex": "Full", 
            "encapsulation": "Ethernet", 
            "flags": [
                "BROADCAST", 
                "MULTICAST", 
                "UP", 
                "LOWER_UP"
            ], 
            "link_speed": 10000, 
            "mdi_x": "Unknown", 
            "mtu": "1500", 
            "number": "0", 
            "port": "Twisted Pair", 
            "ring_params": {
                "current_rx": 256, 
                "current_rx_jumbo": 128, 
                "current_rx_mini": 0, 
                "current_tx": 512, 
                "max_rx": 4096, 
                "max_rx_jumbo": 4096, 
                "max_rx_mini": 0, 
                "max_tx": 4096
            }, 
            "routes": [
                {
                    "destination": "default", 
                    "family": "inet", 
                    "metric": "100", 
                    "proto": "static", 
                    "via": "10.0.0.1"
                }, 
                {
                    "destination": "10.0.0.0/8", 
                    "family": "inet", 
                    "metric": "100", 
                    "proto": "kernel", 
                    "scope": "link", 
                    "src": "10.0.0.2"
                }
            ], 
            "state": "up", 
            "transceiver": "internal", 
            "type": "ens16"
        }, 
        "lo": {
            "addresses": {
                "127.0.0.1": {
                    "family": "inet", 
                    "netmask": "255.0.0.0", 
                    "prefixlen": "8", 
                    "scope": "Node"
                }
            }, 
            "encapsulation": "Loopback", 
            "flags": [
                "LOOPBACK", 
                "UP", 
                "LOWER_UP"
            ], 
            "mtu": "65536", 
            "state": "unknown"
        }
    }
}

Best Answer

Slightly tough to tease out what is happening here. I am not clear how 'ohai_network.interfaces' is exposed in your host vars. If you were able to add a task that printed the host vars (- debug: var=hostvars[inventory_hostname]), and then add the ohai section from that output to your question, I should be able to give you the full solution.

The fragment below, should move you past some of the errors you have so far, but may fail to resolve the ohai data:

# As per the warning in your output, 'when' clauses should not be wrapped with curly braces. Also better to use 'inventory_hostname' in this case
- name: Print interface duplex
  debug:
    msg: "{{ ansible_hostname }} {{ item }} interface duplex is {{ ohai_network['interfaces'][item]['duplex'] | default('not_defined') }}"
  when: hostvars[inventory_hostname]['ansible_' + item]['ipv4'] is defined
  with_items: "{{ ansible_interfaces }}"

If that doesn't work, try:

msg: "{{ ansible_hostname }} {{ item }} interface duplex is {{ ohai_network.interfaces[item]['duplex'] | default('not_defined') }}"