Ansible - ipaddr filter
Ansible's ipaddr filter is something you will be using a lot when working with network devices and their configurations. This filter provides an interface to netaddr Python package and it allows you to do almost anything that package can do, which is to say, a lot. You need to have netaddr library installed on your machine, Ansible filter won't work without it.
I will show a few examples of how this filter could be used. You can refer to Ansible documentation [1] for the full list of available options.
Contents:
- Check if the string is a valid IP address
- Get first, second, n-th, address in the subnet
- Get network, address, prefix/netmask value
- GitHub repository with playbooks for this post
Check if the string is a valid IP address
Often we need to know if the string we're working with is a valid IP address. To achieve this we can use ipaddr filter aliases, ipv4 and ipv6, for IPv4 and IPv6 addresses, respectively.
These filters can take a string, or a list of strings. With single string, if it is a valid IP, the result will be that string, otherwise "false" will be returned.
With a list of strings, we get back a list with strings that are valid IPs, or an empty list if no valid IPs are found.
Let's see these filters in action.
Playbook:
---
- name: IP validation examples
hosts: localhost
vars:
single_ipv4_val: 10.1.1.45
single_ipv4_inv: 2.4.16.256
single_ipv6_val: ba0::bab
single_ipv6_inv: ce:d::ar
ipv4_list: [10.1.1.0/24, 172.16.1.9, 192.168.6.1/32, 10.3.5.777, 224.0.0.10]
ipv6_list: ['fe80::1', '2001:dba::/32', '::1', '2002::120a::af:0', 'ff02::5']
tasks:
- name: Check if a string is a valid IPv4
debug:
msg: "'single_ipv4_val': {{ single_ipv4_val | ipv4 }};
'single_ipv4_inv': {{ single_ipv4_inv | ipv4 }}"
- name: Check if a string is a valid IPv6
debug:
msg: "'single_ipv6_val': {{ single_ipv6_val | ipv6 }};
'single_ipv6_inv': {{ single_ipv6_inv | ipv6 }}"
- name: Show valid IPv4s in the list of strings
debug:
msg: "Valid IPv4 addresses in 'ipv4_list': {{ ipv4_list | ipv4 }}"
- name: Show valid IPv6s in the list of strings
debug:
msg: "Valid IPv6 addresses in 'ipv6_list': {{ ipv6_list | ipv6 }}"
Output:
[przemek@quasar ipaddr_filter]$ ansible-playbook validate_ip.yml
PLAY [IP validation examples] ****************************************************************************************************
TASK [Check if a string is a valid IPv4] *****************************************************************************************
ok: [localhost] => {
"msg": "'single_ipv4_val': 10.1.1.45; 'single_ipv4_inv': False"
}
TASK [Check if a string is a valid IPv6] *****************************************************************************************
ok: [localhost] => {
"msg": "'single_ipv6_val': ba0::bab; 'single_ipv6_inv': False"
}
TASK [Show valid IPv4s in the list of strings] ***********************************************************************************
ok: [localhost] => {
"msg": "Valid IPv4 addresses in 'ipv4_list': ['10.1.1.0/24', '172.16.1.9', '192.168.6.1/32', '224.0.0.10']"
}
TASK [Show valid IPv6s in the list of strings] ***********************************************************************************
ok: [localhost] => {
"msg": "Valid IPv6 addresses in 'ipv6_list': ['fe80::1', '2001:dba::/32', '::1', 'ff02::5']"
}
PLAY RECAP ***********************************************************************************************************************
localhost : ok=4 changed=0 unreachable=0 failed=0
Get first, second, n-th, address in the subnet
We can use ipaddr('n') to return 'n-th' address in the given subnet. This can be used to assign IPs from a given network to hosts. I use it to get real, and virtual, IP addresses in my VRRP/VARP setups. See example below.
Update 10-Jul-2019
Original post was based on Ansible 2.4. Syntax changed in the newer version of Ansible and instead of ipaddr('n') you should use ipaddr(n).
Playbook:
[przemek@quasar ipaddr_filter]$ cat generate_varp_ips.yml
---
- name: Get real and virtual IPs for VARP setup
hosts: localhost
vars:
vl_net: 10.99.6.0/24
tasks:
- name: Get virtual IP
debug:
msg: "{{ vl_net | ipaddr('1') }}"
- name: Get first real IP
debug:
msg: "{{ vl_net | ipaddr('2') }}"
- name: Get second real IP
debug:
msg: "{{ vl_net | ipaddr('3') }}"
Output:
[przemek@quasar ipaddr_filter]$ ansible-playbook generate_varp_ips.yml
PLAY [Get real and virtual IPs for VARP setup] ***********************************************************************************
TASK [Get virtual IP] ************************************************************************************************************
ok: [localhost] => {
"msg": "10.99.6.1/24"
}
TASK [Get first real IP] *********************************************************************************************************
ok: [localhost] => {
"msg": "10.99.6.2/24"
}
TASK [Get second real IP] ********************************************************************************************************
ok: [localhost] => {
"msg": "10.99.6.3/24"
}
PLAY RECAP ***********************************************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0
Get network, address, prefix/netmask value
Ipaddr filter allows us to get useful information about IP addresses/networks, like their address portion, netmask or broadcast address.
We can also check if an address format matches our restrictions, e.g. 'host/prefix' will not match a network address, or host address without prefix.
With these tools we can easily convert between net/pfx and net/netmask format, as some vendors configs use one but not the other.
A few examples showcasing the use of ipaddr filter can be found in the Playbook below.
Playbook:
---
- name: Getting values for network/host addresses
hosts: localhost
vars:
host_pfx: 10.5.0.5/24
net_mask: '172.24.0.0/255.255.0.0'
net_pfx: 192.168.84.0/24
addr_mix: ['10.3.2.1/24', '10.3.9.27', '10.5.20.0/24', '172.20.1.1/255.255.255.0']
tasks:
- name: Return host portion and network the host belongs to
debug:
msg: "host: {{ host_pfx | ipaddr('address') }},
network: {{ host_pfx | ipaddr('network/prefix') }}"
- name: Convert network/netmask to network/pfx format
debug:
msg: "Before: {{ net_mask }}, after: {{ net_mask | ipaddr('network/prefix') }}"
- name: Convert network/pfx to net/netmask format
debug:
msg: "Before: {{ net_pfx }}, after: {{ net_pfx | ipaddr('network') }}
{{ net_pfx | ipaddr('netmask')}}"
- name: Get broadcast address
debug:
msg: "Broadcast address for {{ net_pfx }}: {{ net_pfx | ipaddr('broadcast') }}"
- name: Return only host addresses with prefix/netmask
debug:
msg: "{{ addr_mix | ipaddr('host/prefix') }}"
Output:
[przemek@quasar ipaddr_filter]$ ansible-playbook get_address_values.yml
PLAY [Getting values for network/host addresses] *********************************************************************************
TASK [Return host portion and network the host belongs to] ***********************************************************************
ok: [localhost] => {
"msg": "host: 10.5.0.5, network: 10.5.0.0/24"
}
TASK [Convert network/netmask to network/pfx format] *****************************************************************************
ok: [localhost] => {
"msg": "Before: 172.24.0.0/255.255.0.0, after: 172.24.0.0/16"
}
TASK [Convert network/pfx to net/netmask format] *********************************************************************************
ok: [localhost] => {
"msg": "Before: 192.168.84.0/24, after: 192.168.84.0 255.255.255.0"
}
TASK [Get broadcast address] *****************************************************************************************************
ok: [localhost] => {
"msg": "Broadcast address for 192.168.84.0/24: 192.168.84.255"
}
TASK [Return only host addresses with prefix/netmask] ****************************************************************************
ok: [localhost] => {
"msg": [
"10.3.2.1/24",
"172.20.1.1/24"
]
}
PLAY RECAP ***********************************************************************************************************************
localhost : ok=5 changed=0 unreachable=0 failed=0
You can get full listings of the playbooks from my GitHub repository:
https://github.com/progala/ttl255.com/tree/master/ansible/ipaddr-filter
Ansible documentation for ipaddr filter:
http://docs.ansible.com/ansible/latest/playbooks_filters_ipaddr.html ↩︎