Recently I was working on my Netbox automation using Ansible. I prepared task, which collects information about network interfaces that looks like below:
"interface_ips": {
"br0": {
"ipv4": [
"10.0.0.10",
"10.0.0.11"
],
"ipv6": [],
"mac": "aa:bb:cc:dd:ee:ff",
"mtu": "1500",
"type": "bridge"
},
"lxcbr0": {
"ipv4": [
"10.100.0.10"
],
"ipv6": [],
"mac": "ff:ee:dd:cc:bb:aa",
"mtu": "1500",
"type": "bridge"
}
}
I wanted to iterate over collected IPs (IPv4 + IPv6) and return interface name for corresponding IP.
The output I want is the following:
Some interfaces might have multiple IPs assigned, so it's very important to iterate over every IP.
I managed to do following task, but it doesn't iterate over every address, only first ipv4 address.
- name: Extract IPv4 addresses and interface names
set_fact:
ip_interface_map: "{{ ip_interface_map | default({}) | combine({item.value.ipv4[0]: item.key}) }}"
loop: "{{ interface_ips | dict2items }}"
Can this be done easily somehow?
interface_ips | dict2items:
- key: br0
value:
ipv4: [10.0.0.10, 10.0.0.11]
ipv6: []
mac: aa:bb:cc:dd:ee:ff
mtu: '1500'
type: bridge
- key: lxcbr0
value:
ipv4: [10.100.0.10]
ipv6: []
mac: ff:ee:dd:cc:bb:aa
mtu: '1500'
type: bridge
- debug:
msg: "{{ item.1 }} - {{ item.0.key }}"
loop: "{{ interface_ips | dict2items | subelements('value.ipv4') }}"
gives (abridged)
msg: 10.0.0.10 - br0
msg: 10.0.0.11 - br0
msg: 10.100.0.10 - lxcbr0
The same loop with subelements('value.ipv6') will be skipped because all ipv6 lists are empty
- debug:
msg: "{{ item.1 }} - {{ item.0.key }}"
loop: "{{ interface_ips | dict2items | subelements('value.ipv6') }}"
ip_interface_map: "{{ dict(interface_ips | dict2items |
json_query('[].[key,
[value.ipv4, value.ipv6]|[]]')) }}"
gives
ip_interface_map:
br0:
- 10.0.0.10
- 10.0.0.11
lxcbr0:
- 10.100.0.10
- debug:
msg: "{{ item.1 }} - {{ item.0.key }}"
loop: "{{ ip_interface_map | dict2items | subelements('value') }}"
gives (abridged) the same result
msg: 10.0.0.10 - br0
msg: 10.0.0.11 - br0
msg: 10.100.0.10 - lxcbr0
Example of a complete playbook for testing
- hosts: all
vars:
interface_ips:
br0:
ipv4: [10.0.0.10, 10.0.0.11]
ipv6: []
mac: aa:bb:cc:dd:ee:ff
mtu: '1500'
type: bridge
lxcbr0:
ipv4: [10.100.0.10]
ipv6: []
mac: ff:ee:dd:cc:bb:aa
mtu: '1500'
type: bridge
ip_interface_map: "{{ dict(interface_ips | dict2items |
json_query('[].[key,
[value.ipv4, value.ipv6]|[]]')) }}"
tasks:
- debug:
msg: "{{ item.1 }} - {{ item.0.key }}"
loop: "{{ interface_ips | dict2items | subelements('value.ipv4') }}"
- debug:
msg: "{{ item.1 }} - {{ item.0.key }}"
loop: "{{ interface_ips | dict2items | subelements('value.ipv6') }}"
- debug:
var: ip_interface_map
- debug:
msg: "{{ item.1 }} - {{ item.0.key }}"
loop: "{{ ip_interface_map | dict2items | subelements('value') }}"