从 ansible_default_ipv4.macaddress 过滤数据

filter data From ansible_default_ipv4.macaddress

亲爱的社区,我请求你的帮助。

我会创建一个剧本,它将采用输入中给定的 macaddress,它应该遵循 Unix 格式。然后,如果给定的地址符合要求的格式,另一个任务将检查给定的 macaddress 是否与主机中的现有地址匹配,**如果存在,它将显示 the interface related to that macaddress 如果不存在,任务将失败并显示错误消息"No interfaces found with mac address '$MACADDRESS'. Fatal error."

这是我做的,我不知道应该怎么做才能达到目标:

- 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)

  1. 您通常不会注册 debug 任务的结果(因为它没有用)。如果您想在有人输入无效的 MAC 地址时失败,请使用 fail 任务:

    - name: check mac address syntax
      fail:
          msg: "Invalid mac address syntax"
      when: not MACADDRESS|ansible.utils.hwaddr('unix')
    
  2. 您已将 gather_facts 设置为 false,但有事实收集 禁用的 Ansible 不会为您提供任何事实。你需要 如果您希望 Ansible 为您提供 有关主机接口的信息。

  3. 我不完全确定您在 check local mac 任务中尝试做什么,但这似乎完成了您的询问:

    - 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)
    

运行 我系统上的上述剧本,它有一个地址为 a2:29:ab:4e:e7:74 的接口,看起来像这样:

$ 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   

如果我 运行 使用我的系统中不存在的 MAC 地址,我得到:

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   

收集网络的事实并获取接口列表。例如,

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

给予

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

把下面的声明写成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_valid: "{{ _dev_mac_valid|map('zip', ['dev', 'mac', 'valid'])|
                                  map('map', 'reverse')|
                                  map('community.general.dict') }}"
dev_mac: "{{ dev_mac_valid|items2dict(key_name='dev', value_name='mac') }}"
mac_dev: "{{ dev_mac_valid|items2dict(key_name='mac', value_name='dev') }}"

例如,这些计算结果为

_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_valid:
  - dev: wlan0
    mac: 00:12:00:34:56:78
    valid: true

dev_mac:
  wlan0: 00:12:00:34:56:78

mac_dev:
  00:12:00:34:56:78: wlan0

问:“检查给定的地址是否与主机中的现有地址匹配”

答:使用词典mac_dev。例如,

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

如果有更多的主机声明所有主机的字典

mac_dev_hosts: "{{ dict(ansible_play_hosts|
                        zip(ansible_play_hosts|
                            map('extract', hostvars, 'mac_dev'))) }}"

然后,把它们放在一起,例如剧本

- hosts: test_11,test_12,test_13
  gather_facts: false
  vars:
    _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_valid: "{{ _dev_mac_valid|map('zip', ['dev', 'mac', 'valid'])|
                                      map('map', 'reverse')|
                                      map('community.general.dict') }}"
    dev_mac: "{{ dev_mac_valid|items2dict(key_name='dev', value_name='mac') }}"
    mac_dev: "{{ dev_mac_valid|items2dict(key_name='mac', value_name='dev') }}"
    mac_dev_hosts: "{{ dict(ansible_play_hosts|
                            zip(ansible_play_hosts|
                                map('extract', hostvars, 'mac_dev'))) }}"

  tasks:
    - setup:
        gather_subset: network
    - set_fact:
        mac_dev: "{{ mac_dev }}"

    - block:
        - debug:
            var: mac_dev_hosts|to_nice_yaml
        - pause:
            prompt: "Enter MAC address"
          register: result
        - set_fact:
            macaddress: "{{ result.user_input }}"
        - assert:
            that: macaddress|ansible.utils.hwaddr('bool')
            fail_msg: Wrong MAC address
        - assert:
            that: macaddress in mac_dev_hosts|json_query('*.keys(@)')|flatten
            fail_msg: "No interface found with mac address {{ macaddress }}"
        - debug:
            msg: "Interface {{ dev }} found with mac address {{ macaddress }}
                  at {{ hst }}"
          vars:
            itm: "{{ mac_dev_hosts|dict2items|
                     selectattr('value', 'contains', macaddress)|first }}"
            hst: "{{ itm.key }}"
            dev: "{{ itm.value[macaddress] }}"
      run_once: true

给予

PLAY [test_11,test_12,test_13] ***************************************************************

TASK [setup] *********************************************************************************
ok: [test_13]
ok: [test_12]
ok: [test_11]

TASK [set_fact] ******************************************************************************
ok: [test_13]
ok: [test_11]
ok: [test_12]

TASK [debug] *********************************************************************************
ok: [test_11] => 
  mac_dev_hosts|to_nice_yaml: |-
    test_11:
        00:12:00:34:56:AA: wlan0
    test_12:
        00:12:00:34:56:BB: wlan0
    test_13:
        00:12:00:34:56:CC: wlan0

TASK [pause] *********************************************************************************
[pause]
Enter MAC address:
00:12:00:34:56:CC^Mok: [test_11]

TASK [set_fact] ******************************************************************************
ok: [test_11]

TASK [assert] ********************************************************************************
ok: [test_11] => changed=false 
  msg: All assertions passed

TASK [assert] ********************************************************************************
ok: [test_11] => changed=false 
  msg: All assertions passed

TASK [debug] *********************************************************************************
ok: [test_11] => 
  msg: Interface wlan0 found with mac address 00:12:00:34:56:CC at test_13

PLAY RECAP ***********************************************************************************
test_11: ok=8    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_12: ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_13: ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

如果缺少 MAC 播放将失败,例如

TASK [assert] ********************************************************************************
fatal: [test_11]: FAILED! => changed=false 
  assertion: macaddress in mac_dev_hosts|json_query('*.keys(@)')|flatten
  evaluated_to: false
  msg: No interface found with mac address 00:12:00:34:56:FF