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

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



  1. Ansible documentation for ipaddr filter:
    http://docs.ansible.com/ansible/latest/playbooks_filters_ipaddr.html ↩︎