How about this structure for network interface facts:
“interfaces”: {
“eth0”: {
“macaddress”: xxxx…,
“mtu”: 1500,
“ipv4”: [
{
“address”: “192.168.1.1”,
“netmask”: “255.255.255.0”,
“network”: “192.168.1.0”,
“alias”: “eth0”
},
{
“address”: “192.168.1.2”,
“netmask”: “255.255.255.0”,
“network”: “192.168.1.0”,
“alias”: “eth0”
},
{
“address”: “192.168.1.3”,
“netmask”: “255.255.255.0”,
“network”: “192.168.1.0”,
“alias”: “eth0:0”
}
],
“ipv6”: [
{
No changes
“address”: … ,
“prefix”: … ,
“scope”: …
},
{
…
}
]
}, # close interfaces.eth0
“eth1”: {
…
},
“default_ipv4”: {
“interface”: “eth0”,
“address”: “192.168.1.3”,
“netmask”: “255.255.255.0”,
“alias”: “eth0:0”
},
“default_ipv6”: {
“interface”: “eth1”,
“address”: … ,
“prefix”: … ,
“scope”: …
}
} # close interfaces
Advantages:
1. Backwords compatible
You can still iterate over ‘ansible_interfaces’ as before to get the same result. This does not affect ‘ansible_eth0’-type facts, which can be deprecated but kept available for a couple more releases.
2. Easy to iterate over all interfaces’ information
Currently it is not straightforward to iterate over all addresses of all interfaces, because each interface has its own ansible_$iface fact. With this new structure, each interface can be explored using ansible_interfaces[$iface].
3. More natural representation of aliased interfaces
With this new structure, all IPv4 addresses assigned to an interface, whether as additional addresses for the same interface via ‘ip addr add’, or as interface aliases (eth0:0), are listed together in one list, with an alias key to be able to tell aliased interfaces apart. This structures resembles the output of the ‘ip addr’ command:
2: venet0: <BROADCAST,POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
link/void
inet 127.0.0.2/32 scope host venet0
inet <…>/32 scope global venet0:0
4. Differentiates multiple IPv4 addresses assigned to one interface from aliased interfaces
The current structure represents additional IPv4 addresses that are assigned to one interface as if they were assigned to an alias: it creates eth0:0 for the second IPv4 assigned to eth0, although there may not be a et0:0 in the underlying system. Worse, if there were an actual eth0:0, it would be named eth0:1, because eth0:0 had already been used.
The new structure lists all those addresses under the main interface, and distinguishes those assigned to an aliased interface using the ‘alias’ key.
5. Easier queries
Get all IPv4 addresses assigned to eth0:
[i[‘address’] for i in ansible_interfaces[‘eth0’][‘ipv4’]]
Get all IPv4 addresses assigned only to eth0, and not to any of its aliases:
[i[‘address’] for i in ansible_interfaces[‘eth0’][‘ipv4’] if i[‘alias’] == ‘eth0’]
6. Straightforward default interface information
With the current structure, using an exact copy of an interface tree for ‘default_ipv6’ is not enough, because that tree may have multiple addresses. Also, getting the actual IPv4 default interface is a little awkward:
ansible_default_ipv4_interface[‘ipv4’][‘device’]
Compared to:
ansible_interfaces[‘default_ipv4’][‘interface’]
7. No “device”
Avoid using the ‘device’ key which was used to map aliased interfaces to their real interfaces. ‘device’ vs. ‘interface’ can get confusing.
8. Consistent: ipv4 vs. ipv6, multi-ip vs. alias
More overall consistency. IPv4 data has the same structure as IPv6. Multiple IPv4 addresses assigned to the same interface are listed together, whether they are assigned to the interface or one of its aliases.
9. Portability to BSD
https://github.com/ansible/ansible/issues/842#issuecomment-7656871
Let me know if this structure is missing anything, or if it breaks any currently working use cases.