Home > Blockchain >  filter data From ansible_default_ipv4.macaddress
filter data From ansible_default_ipv4.macaddress

Time:06-02

Dear community i ask for your help please.

I would create a playbook that will take a macaddress given in input and it should respect the Unix format. Then, if the address given respects the required format, another task will check if the given macaddress match an existed one in the hosts, **if it exists it will show the interface related to that macaddress if not the task will fail with an error message "No interfaces found with mac address '$MACADDRESS'. Fatal error."

here is what was done by me, i don't what should be done to achieve the goal:

- hosts: all
  gather_facts: no
  vars_prompt:
    - name: "MACADDRESS"
      prompt: "mac address?(please use Unix format ex- 1a:2b:3c:4d:5e:6f )"
      private: no


  tasks:
    - name: check macaddresssyntax
      debug:
        msg: "{{ MACADDRESS | ansible.utils.hwaddr('unix') }}"
      register: mac_syntax
      failed_when: mac_syntax failed


    - name: check local mac
      debug:
        var: mac_syntax |intersect (ansible_facts['default_ipv4']|selectattr('macaddress') | map(attribute='interface')|list)

CodePudding user response:

Collect the network's facts and get the list of interfaces. For example,

    - setup:
        gather_subset: network
    - debug:
        var: ansible_facts.interfaces

gives

ansible_facts.interfaces:
  - lo0
  - lo1
  - pflog0
  - wlan0

Put the declaration below as appropriate

_ifcs: "{{ ansible_facts.interfaces|map('extract', ansible_facts)|list }}"
_macs: "{{ _ifcs|json_query('[].macaddress') }}"
_devs: "{{ _ifcs|json_query('[].device') }}"
_macs_valid: "{{ _macs|map('ansible.utils.hwaddr', 'bool')|
                       map('ternary', true, false)|list }}"
_dev_mac_valid: "{{ _devs|zip(_macs)|zip(_macs_valid)|
                          map('flatten')|
                          selectattr(2) }}"
dev_mac: "{{ _dev_mac_valid|map('zip', ['dev', 'mac', 'valid'])|
                            map('map', 'reverse')|
                            map('community.general.dict') }}"
dev_mac_dict: "{{ dev_mac|items2dict(key_name='dev', value_name='mac') }}"
mac_dev_dict: "{{ dev_mac|items2dict(key_name='mac', value_name='dev') }}"

For example, these evaluate to

_macs: [unknown, unknown, unknown, '00:12:00:34:56:78']
_macs_valid: [false, false, false, true]
_devs: [lo0, lo1, pflog0, wlan0]
_dev_mac_valid:
  - [wlan0, '00:12:00:34:56:78', true]

dev_mac:
  - dev: wlan0
    mac: 00:12:00:34:56:78
    valid: true

dev_mac_dict:
  wlan0: 00:12:00:34:56:78

mac_dev_dict:
  00:12:00:34:56:78: wlan0

Q: "Check if the given macaddress match an existing one in the hosts"

A: Use the dictionary mac_dev_dict. For example,

    - pause:
        prompt: "Enter MAC address"
      register: result
    - assert:
        that: result.user_input|ansible.utils.hwaddr('bool')
        fail_msg: Wrong MAC address
    - assert:
        that: result.user_input in mac_dev_dict.keys()|list
        fail_msg: "No interfaces found with mac address {{ result.user_input }}"
        success_msg: "Interfaces {{ mac_dev_dict[result.user_input] }} found
                      with mac address {{ result.user_input }}"

CodePudding user response:

  1. You don't normally register the result of a debug task (because it's not useful). If you want to fail when someone enters an invalid MAC address, use the fail task:

    - name: check mac address syntax
      fail:
          msg: "Invalid mac address syntax"
      when: not MACADDRESS|ansible.utils.hwaddr('unix')
    
  2. You have gather_facts set to false, but with fact gathering disabled Ansible won't provide you with any facts. You need to enable fact gathering if you want Ansible to provide you with information about host interfaces.

  3. I'm not entirely sure what you're trying to do in your check local mac task, but this seems to accomplish what you were asking about:

    - hosts: localhost
      gather_facts: true
      vars_prompt:
        - name: "MACADDRESS"
          prompt: "mac address?(please use Unix format ex- 1a:2b:3c:4d:5e:6f )"
          private: no
    
      tasks:
        - name: check macaddresssyntax
          fail:
            msg: "Invalid mac address syntax"
          when: not MACADDRESS | ansible.utils.hwaddr('unix')
    
        # In this task, we loop over `ansible_interfaces`, which is
        # a list of interface names. We set the `matched_interface`
        # variable to the current interface name if it has a
        # matching MAC address.
        - name: check local mac
          set_fact:
            matched_interface: "{{ ifname }}"
          when: >-
            lookup('vars', 'ansible_{}'.format(ifname)).macaddress|default(false) == MACADDRESS
          vars:
            # For whatever reason, ansible replaces `-` in interface
            # names with `_`.
            ifname: "{{ item.replace('-', '_') }}"
          loop: "{{ ansible_interfaces }}"
    
        - debug:
            msg: "the interface related to {{ MACADDRESS }} is {{ matched_interface }}"
          when: matched_interface|default(false)
    
        - fail:
            msg: "no interfaces found with mac address {{ MACADDRESS }}"
          when: not matched_interface|default(false)
    

Running the above playbook on my system, which has an interface with address a2:29:ab:4e:e7:74, looks like this:

$ ansible-playbook playbook.yaml -e MACADDRESS='a2:29:ab:4e:e7:74
PLAY [localhost] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [check macaddresssyntax] **************************************************
skipping: [localhost]

TASK [check local mac] *********************************************************
skipping: [localhost] => (item=veth92b9a89f) 
...
ok: [localhost] => (item=example)
skipping: [localhost] => (item=lo) 
...

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "the interface related to a2:29:ab:4e:e7:74 is example"
}

TASK [fail] ********************************************************************
skipping: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=2    rescued=0    ignored=0   

If I run it with a MAC address that doesn't exist on my system, I get:

TASK [check local mac] *********************************************************
skipping: [localhost] => (item=veth168ad56c) 
...

TASK [debug] *******************************************************************
skipping: [localhost]

TASK [fail] ********************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "no interfaces found with mac address a2:29:ab:4e:e7:77"}

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=1    skipped=3    rescued=0    ignored=0   

  • Related