Bookmark this page

Using Filters to Work with Network Addresses

Objectives

  • Use filters to inspect, validate, and manipulate variables containing networking information.

Gathering and Processing Networking Information

A number of filters and lookup plug-ins are available to collect and process network information for Ansible automation. These filters and plug-ins can be useful with fact gathering when you configure the network devices on your managed hosts.

The standard ansible.builtin.setup module, which automatically gathers facts at the start of many plays, collects a lot of network-related information from each managed host.

The ansible_facts['interfaces'] fact is a list of all the network interface names on the system. You can use this list to examine the details of each of the network interfaces on the system. For example, if enp11s0 is an interface on the system, then it has a fact called ansible_facts['enp11s0'], which is a dictionary containing information about the interface such as the MAC address, IPv4 and IPv6 addresses, kernel module, and so on.

The following facts are useful to remember:

Table 7.1. Selected Networking Facts

Fact nameDescription
ansible_facts['dns']['nameservers'] The DNS name servers used for name resolution by the managed host (included in the min subset).
ansible_facts['domain'] The domain for the managed host.
ansible_facts['all_ipv4_addresses'] All the IPv4 addresses configured on the managed host.
ansible_facts['all_ipv6_addresses'] All the IPv6 addresses configured on the managed host.
ansible_facts['fqdn'] The fully qualified domain name (DNS name) of the managed host.
ansible_facts['hostname'] The unqualified hostname; the string in the FQDN before the first period.

The following playbook shows an example of using network facts:

---
- name: Set up web servers
  hosts: web_servers
  become: true

  tasks:
    - name: Configure web server status page
      ansible.builtin.copy:
        content: "Server: {{ ansible_facts['fqdn'] }} at {{ ansible_facts['default_ipv4']['address'] }}"
        dest: /var/www/html/status.html
        owner: apache
        group: apache
        mode: '0444'

    - name: Ensure httpd is installed
      ansible.builtin.yum:
        name: httpd
        state: installed

    - name: Start and enable webserver
      ansible.builtin.service:
        name: httpd
        state: started
        enabled: true

    - name: Notify root of server provisioning
      community.general.mail:
        subject: >
          System {{ ansible_facts['hostname'] }} has
          been successfully provisioned.

Network Information Filters

You can validate and manipulate networking-related data stored in variables and facts with the ansible.utils.ipaddr filter. The ansible.utils.ipaddr filter can validate the syntax of IP addresses, filter out bad data, convert from VLSM subnet masks to CIDR subnet prefix notation, perform subnet math, or find the next usable address in a network range.

Comprehensive documentation for this filter is available at "ipaddr filter", but this section explores some of its uses.

Note

The ansible.utils.ipaddr filter needs the netaddr Python module, provided by the python3-netaddr package in Red Hat Enterprise Linux 8.

This Python module is installed by default in the ansible-automation-platform-22/ee-supported-rhel8 execution environment. Ensure that the Python module is installed on your control node if you are using the ansible-playbook command, or if you are using the ansible-navigator command with the execution environment disabled.

Testing IP Addresses

In its simplest form, the ansible.utils.ipaddr filter with no arguments accepts a single value. If the value is an IP address, then the filter returns the IP address. If the value is not an IP address, then the filter returns false.

If the value is a list, then the filter returns the valid IP addresses but not the invalid ones. If all the items are invalid, then the filter returns an empty list.

{{ my_hosts_list | ansible.utils.ipaddr }}

You can also pass arguments to the ansible.utils.ipaddr filter. These arguments can make the filter return different information based on the data input.

Filtering Data

The following subsections explore some options that you can use with the ansible.utils.ipaddr filter. To better understand how they work, each of the following examples shows the output that results when that filter is used with a variation on the following task:

    - name: Filter example
      ansible.builtin.debug:
        msg: "{{ listips | ansible.utils.ipaddr }}"

The ipaddr filter in the msg line is replaced with a version that uses the appropriate option. For example, the following version of the line retrieves the network masks of the given addresses.

        msg: "{{ listips | ansible.utils.ipaddr('netmask') }}"

The listips variable used to generate the examples contains the following list:

    listips:
      - 192.168.2.1
      - 10.0.0.128/25
      - 172.24.10.0/255.255.255.0
      - 172.24.10.0/255.255.255.255
      - ff02::1
      - ::1
      - 2001::1/64
      - 2001::/64
      - learn.spidernet.pl
host

Outputs only valid individual IP addresses, in the correct CIDR prefix format for host addresses.

    "msg": [
        "192.168.2.1/32",
        "172.24.11.0/32",
        "ff02::1/128",
        "::1/128",
        "2001::1/64"
    ]
net

Filters out values that are not valid network specifications, converting the netmask into a CIDR prefix if necessary.

    "msg": [
        "10.0.0.128/25",
        "172.24.10.0/24",
        "2001::/64"
    ]
private

Displays input IP addresses or network ranges that are in ranges reserved by IANA to be private. This includes RFC 1918 address spaces and IPv6 site-local addresses at a minimum.

    "msg": [
        "192.168.2.1",
        "10.0.0.128/25",
        "172.24.10.0/255.255.255.0",
        "172.24.10.0/255.255.255.255"
    ]
public

Outputs addresses and networks in public (globally routable) address spaces, according to IANA. (This example has no IPv4 addresses in the public space.)

    "msg": [
        "2001::1/64",
        "2001::/64"
    ]

The ansible.utils.ipwrap filter puts brackets around the address part of items that appear to be IPv6 addresses. The filter passes all other values unchanged. This is useful in templates for certain configuration files that expect this syntax for IPv6 addresses.

    "msg": [
        "192.168.2.1",
        "10.0.0.128/25",
        "172.24.10.0/255.255.255.0",
        "172.24.10.0/255.255.255.255",
        "[ff02::1]",
        "[::1]",
        "[2001::1]/64",
        "[2001::]/64",
        "learn.spidernet.pl"
    ]

Note

Most of the filters in the preceding examples remove the learn.spidernet.pl list item, which is not an IP address. The ansible.utils.ipwrap filter does not do this, but you could use the ansible.utils.ipaddr filter first to handle this scenario:

"{{ listips | ansible.utils.ipaddr | ansible.utils.ipwrap }}"

Manipulating IP Addresses

You can use a number of the ansible.utils.ipaddr options to format networking data from an IPv4 or IPv6 address.

For example:

  • To return the address part, 192.0.2.1:

    "{{ '192.0.2.1/24' | ansible.utils.ipaddr('address') }}"
  • To return the variable-length subnet mask, 255.255.255.0:

    "{{ '192.0.2.1/24' | ansible.utils.ipaddr('netmask') }}"
  • To return the CIDR prefix, 24:

    "{{ '192.0.2.1/24' | ansible.utils.ipaddr('prefix') }}"
  • To return the network's broadcast address, 192.0.2.255:

    "{{ '192.0.2.1/24' | ansible.utils.ipaddr('broadcast') }}"
  • To return the network's network address, 192.0.2.0:

    "{{ '192.0.2.1/24' | ansible.utils.ipaddr('network') }}"
  • To return the IP address in DNS PTR record format, 1.2.0.192.in-addr.arpa.:

    "{{ '192.0.2.1/24' | ansible.utils.ipaddr('revdns') }}"

This correctly converts IPv6 addresses as well.

If you pass a list of items to ansible.utils.ipaddr, it attempts to convert the items that appear to be valid addresses and filter out items that are not.

Important

The broadcast option should not be used with an IPv6 address/prefix because that protocol does not assign a broadcast address. Other options should work with IPv6 addresses as expected.

Reformatting or Calculating Network Information

You can display an IP address on a given network by passing an integer to the ansible.utils.ipaddr filter. The following returns the fifth address (192.0.2.5/24) on the 192.0.2.0/24 network.

"{{ '192.0.2.0/24' | ansible.utils.ipaddr(5) }}"

You can convert the network specification to a range of usable addresses for hosts with the range_usable option. The following example returns the 192.0.2.1-192.0.2.254 address range:

"{{ '192.0.2.0/24' | ansible.utils.ipaddr('range_usable') }}"

If you pass a network specification to the ansible.utils.network_in_usable filter, you can specify a particular address as an option to determine if that address is usable for hosts on that network (meaning, the address is not reserved for broadcasts or other uses). The following example returns the Boolean value true:

"{{ '192.0.2.0/24' | ansible.utils.network_in_usable('192.0.2.5') }}"

If you replace 192.0.2.5 with 192.0.2.255 (the reserved broadcast address) or 192.0.3.2 (not on the network), it returns the Boolean value false.

You can also find the next host on a network. The following example returns the 192.0.2.6/24 address:

"{{ '192.0.2.5/24' | ansible.utils.ipaddr('next_usable') }}"

When the end of the network is reached, it returns an empty value.

Network administrators can use the ansible.utils.cidr_merge filter to aggregate a list of subnets and individual hosts into the minimal representation. For example, consider the following list:

  mynetworks:
    - 10.0.1.0/24
    - 10.0.2.0/24
    - 10.0.3.0/24
    - 10.0.100.0/24
    - 2001:db8::/64
    - 2001:db8:0:1::/64

You can use the "{{ mynetworks | ansible.utils.cidr_merge }}" expression to return the following list:

    "msg": [
        "10.0.1.0/24",
        "10.0.2.0/23",
        "10.0.100.0/24",
        "2001:db8::/63"
    ]

More filters, as well as more options for the preceding filters, are available in the ansible.utils collection. Find more information about using these filters in the References note at the end of this section.

Revision: do374-2.2-82dc0d7