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:
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 thefail
task:- name: check mac address syntax fail: msg: "Invalid mac address syntax" when: not MACADDRESS|ansible.utils.hwaddr('unix')
You have
gather_facts
set tofalse
, 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.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