Search code examples
ansibleansible-2.xansible-facts

Search for an interface using its MAC address


I'm working on a playbook to set a static IP address for an interface, which is identified using MAC address.
My logic was to loop through the interfaces from Ansible facts and set IP when my MAC address is found. But, it is throwing an error that the conditional check failed.
Looks like it is unable to evaluate value of mac address for when.

My code block:

- name: Identify mac addresses
  set_fact:
    target_mac_sanA: "00:11:22:33:44:55"

- name: Get interface name for SAN A
  debug:
    msg: "Interface identified - {{ iface }}"
    when: ansible_facts\[iface\]\['macaddress'\] == target_mac_sanA
    loop: "{{ ansible_interfaces }}"
    loop_control:
      loop_var: iface

But, I'm getting below error:

TASK [ test_cases/testbed_prepare ] [ Get interface name for SAN A ] ******************************************************************************************
TASK [ test_cases/testbed_prepare ] task path: /root/auto/dnit-automation/linux/test_cases/testbed_prepare/tasks/set_priv_ips.yml:17
TASK [ test_cases/testbed_prepare ] ok: [elab-l10-058140] =>  => (item=em3) =>
TASK [ test_cases/testbed_prepare ] {"msg": "Interface identified - em3"}
TASK [ test_cases/testbed_prepare ] fatal: [elab-l10-058140]: FAILED! =>
TASK [ test_cases/testbed_prepare ] {"msg": "The conditional check 'ansible_facts[iface]['macaddress'] == target_mac_sanA' failed. The error was: unable to evaluate conditional: ansible_facts[iface]['macaddress'] == target_mac_sanA\n\nThe error appears to be in '/root/auto/dnit-automation/linux/test_cases/testbed_prepare/tasks/set_priv_ips.yml': line 17, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Get interface name for SAN A\n  ^ here\n"}

Conditional seems to be working, even though the error is thrown. At fourth line of error message, it is correctly identifying the interface. And then it goes on to throw the error that the conditional failed.


Solution

  • Save yourself the cluttered output of skipped iterations caused by the usage of a loop and select the correct interface with the help of a couple of selectattr filters.

    1. Filter out only the interfaces in the Ansible facts
    2. Filter only the interfaces having a MAC address
    3. Get the interface you are interested in, given a MAC address

    So, for example, if you have a virtual tunnel having the MAC address 00:00:00:00, the task:

    - ansible.builtin.debug:
        msg: "Interface identified - {{ _interface.key }}"
      vars:
        _mac_address: 00:00:00:00
        _interface: >-
          {{
            ansible_facts
              | dict2items
              | selectattr('key', 'in', ansible_interfaces)
              | selectattr('value.macaddress', 'defined')
              | selectattr('value.macaddress', '==', _mac_address)
              | first
          }}
    

    Would yield:

    ok: [localhost] => 
      msg: Interface identified - tunl0