Ansible在ansible_interfaces
這個事實中提供了一個接口列表。你可以使用它遍歷可用的接口,檢查每個給定的IP地址。
這最終是麻煩比它的聲音,因爲你需要構建事實上的名字,這意味着,而不是像一些簡單:
ansible_eth0
你,而不是需要:
hostvars[inventory_hostname]["ansible_%s" % item]
另外一個併發症是Ansible將ip地址分爲「主要」(即ansible_eth0.ipv4.address
)和「次要」(ansible_eth0.ipv4_secondaries
),其中後者是包含address
密鑰的字典列表。假設我們正在與item
集迭代到一個接口名稱,我們可以得到主地址是這樣的:
hostvars[inventory_hostname]["ansible_%s" % item].ipv4.address
但是!對於沒有分配ipv4地址的接口,或者出於某種原因沒有對應的接口,這會失敗。因此,我們需要與正常情況處理:
(hostvars[inventory_hostname]["ansible_%s" % item]|default({}).get('ipv4', {}).get('address')
它使用default
過濾器,以確保我們開始用一本字典,然後我們使用Python的.get(key, default)
方法的幾級。
檢查對輔助地址是相似的,但需要我們用map
濾波器,因爲ipv4_secondaries
給我們的詞典列表,我們真正想要的是地址的列表(這樣我們可以檢查,如果我們的目標地址是in
是列表):
((hostvars[inventory_hostname]['ansible_%s' % item]|default({}))
.get('ipv4_secondaries'))|map(attribute='address')|list
全部放在一起:
- hosts: localhost
vars:
target_address: 192.168.122.1
tasks:
- set_fact:
target_interface: "{{ item }}"
when: >
(hostvars[inventory_hostname]['ansible_%s' % item]|default({}))
.get('ipv4', {}).get('address') == target_address
or
target_address in ((hostvars[inventory_hostname]['ansible_%s' % item]|default({}))
.get('ipv4_secondaries'))|map(attribute='address')|list
with_items:
- "{{ ansible_interfaces }}"
- debug:
msg: >-
found interface {{ target_interface }}
with address {{ target_address }}
如果我在我的系統上運行此,在PlayBook運行的結尾是:
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": "found interface virbr0 with address 192.168.24.1"
}
如果我運行:
ansible-playbook playbook.yml -e target_address=192.168.1.75
我得到:
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": "found interface eth0 with address 192.168.1.75"
}
正如你可以從上面看到,這是不完全的那種Ansible是爲任務。將所有這些邏輯填充到Ansible模塊中可能會更好,這樣您可以使用Python(或其他語言)以更優雅的方式執行查找。
更新
Here是基於模塊的解決方案,同樣的問題。
非常感謝!這就是我正在尋找的。 – stefek143