1. Introduction

As system administrators, it’s our responsibility to manage the network interface data so that design and troubleshooting are made easier.

However, gathering this information from several systems requires more time and often results in repetitive procedures. Ansible is a popular open-source automation tool for managing complex IT environments using declarative YAML playbooks.

In this tutorial, we’ll focus on how to get network interfaces in Ansible, a crucial task for managing devices. We’ll explore the various approaches to gathering network interface data using Ansible.

2. What Is Ansible?

Ansible is a simple, agentless, and powerful automation tool that helps manage the IT infrastructure, which can be a laborious and time-consuming operation, particularly on large-scale networks. It uses an agentless management strategy. Therefore, there is no installation required on any remote hosts. For connecting to the remote hosts and running the tasks, it employs straightforward SSH or WinRM.

Additionally, the Ansible Playbooks use YAML, an easy-to-understand syntax, to indicate the actions that must be carried out on the end host computers in order to capture the data.

Now, let’s learn how to use Ansible playbooks to obtain various kinds of network data.

3. Get All the Network Interfaces

Here, we are retrieving the default network interfaces using a basic Ansible playbook. It targets all hosts in the inventory files under the webservers group. Finally, it uses the debug module to display, and it will gather facts about the target machines and store them in memory.

The ansible default_ipv4.interface variable from the gather_facts module will then be used to retrieve all interfaces for each host in the webservers group. The playbook will then use the debug module and the var option to display the default interface name:

$ cat get_all_available_interfaces.yml
---
- name: Get all network interfaces name
  hosts: webservers
  gather_facts: yes

  tasks:
  - name: Display all interfaces name
    debug:
      var: ansible_facts.interfaces

Internally, Ansible uses a configuration file called inventory to specify the hosts and groups it will manage. The inventory file can be generated instantly by a dynamic script, or it can be a static file. In our case, the inventory file is static and lists only a single host, webserver1, with the IP address 180.87.34.99, in the webservers group. The host’s IP address is specified in the ansible_host option, which Ansible will use to connect to the host.

Moreover, the inventory file can be structured in many ways to contain a variety of hosts and groups, depending on the infrastructure and requirements of the environment that Ansible is controlling:

$ cat inventory
[webservers]
webserver1 ansible_host=180.87.34.99

3.1. Execution of Ansible Playbook

Let’s run the get_default_interface_info.yml playbook using the ansible-playbook command with the below options:

  • -i [inventory]: specifies the inventory file path to identify the hosts and groups that the playbook will target
  • -l [webservers]: limits the playbook execution to the hosts in the webservers group defined in the inventory file
  • -u [tools]: specifies the remote user account that Ansible will use to connect to the target hosts. In this case, the username is tools
  • -k: prompts the user to enter the password for the remote user account specified with the -u option
  • –syntax-check: without actually running the playbook, it validates the playbook syntax
$ ansible-playbook -i inventory -l webservers -u tools -k get_all_available_interfaces.yml --syntax-check
playbook: get_all_available_interfaces.yml

Let’s, execute the playbook without the –syntax-check option. This will give us all the available interfaces on the server’s network interfaces under the TASK section:

$ ansible-playbook -i inventory -l webservers -u tools -k get_all_available_interfaces.yml
SSH password:

PLAY [Get all network interfaces name] ***************************************************************************

TASK [Gathering Facts] *******************************************************************************************
ok: [webserver1]

TASK [Display all interfaces name] *******************************************************************************
ok: [webserver1] => {
    "ansible_facts.interfaces": [
        "docker0",
        "lo",
        "ens224",
        "ens160",
        "ens256",
        "ens192",
        "virbr0"
    ]
}

PLAY RECAP *******************************************************************************************************
webserver1                 : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

4. Using Custom Filters on Playbook

Let’s move on and concentrate on another playbook to learn more about the IP address and MAC address of the network interfaces. There are three tasks defined in this playbook.

The MAC and IP addresses of network interfaces are displayed in the first task using the built-in debug module. The ansible_facts dictionary serves to collect the IPv4 address and MAC address of each network interface. Further, the with_items parameter loops through each network interface that the ansible_interfaces fact has returned.

In the second task, a variable called public_interface is set to the name of the network interface with the IP address 180.87.34.99/29. The when statement filters the network interfaces based on whether an IPv4 address is present with the specific IP address. The with_items argument loops through each network interface that the ansible_interfaces fact returns.

Lastly, the third task uses the debug module to showcase a message indicating whether the public network interface was discovered or not:

$ cat get_interfaces_with_custom_filter.yml
---
- name: Get Network Interfaces Playbook
  hosts: webservers
  tasks:
    - name: Task 1 | Get all the network interfaces with IPAddresses and MAC 
      ansible.builtin.debug:
        msg: "interface {{ item }}'s IPAddress is {{ ansible_facts[item]['ipv4']['address']|default(None) }} and MAC is {{ ansible_facts[item]['macaddress']|default(None) }}"
      with_items:
      - "{{ ansible_interfaces }}"

    - name: Task 2 | Figure out network device of public network
      set_fact:
        public_interface: "{{ hostvars[inventory_hostname]['ansible_' + item]['device'] }}"
      when:
        - hostvars[inventory_hostname]['ansible_' + item].ipv4 is defined
        - hostvars[inventory_hostname]['ansible_' + item]['ipv4']['address'] | ipaddr('180.87.34.99/29')
      with_items: "{{ ansible_interfaces }}"
    - name: Task 2 | print public network interface
      debug:
        msg: Interface {{ public_interface | default("not") }} found

4.1. Execution of Ansible Playbook

Similar to the above playbook, let’s check the syntax of the get_interfaces_with_custom_filter.yml playbook using the ansible-playbook command:

$ ansible-playbook -i inventory -l webservers -u tools -k get_interfaces_with_custom_filter.yml --syntax-check
playbook: get_interfaces_with_custom_filter.yml

Lastly, let’s run the playbook without the –syntax-check option. After running this, we’ll have all the available interfaces with IP addresses and MAC addresses and also will have identified the interfaces having that specific IP address under the respective TASK section:

$ ansible-playbook -i inventory -l webservers -u tools -k get_interfaces_with_custom_filter.yml
SSH password:

PLAY [Get Network Interfaces Playbook] ***************************************************************************

TASK [Gathering Facts] *******************************************************************************************
ok: [webserver1]

TASK [Task 1 | Get all the network interfaces with IPAddresses and MAC] ******************************************
...
... output truncated ...
...
ok: [webserver1] => (item=ens224) => {
    "msg": "interface ens224's IPAddress is 10.133.14.57 and MAC is 00:0c:29:23:6f:44"
}
ok: [webserver1] => (item=ens160) => {
    "msg": "interface ens160's IPAddress is 180.87.34.99 and MAC is 00:0c:29:23:6f:30"
}
ok: [webserver1] => (item=virbr0) => {
    "msg": "interface virbr0's IPAddress is 192.168.122.1 and MAC is 52:54:00:c3:b6:95"
}
...
... output truncated ...
...

TASK [Task 2 | Figure out network device of public network] ******************************************************
skipping: [webserver1] => (item=docker0)
skipping: [webserver1] => (item=lo)
skipping: [webserver1] => (item=ens224)
ok: [webserver1] => (item=ens160)
skipping: [webserver1] => (item=ens256)
skipping: [webserver1] => (item=ens192) 
skipping: [webserver1] => (item=virbr0)

TASK [Task 2 | print public network  interface] ******************************************************************
ok: [webserver1] => {
    "msg": "Interface ens160 found"
}

PLAY RECAP *******************************************************************************************************
webserver1                 : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

5. Conclusion

In this tutorial, we’ve successfully gathered all of the system’s network interfaces, which can now be analyzed and used to automate various network-related operations. The retrieval of IP and MAC addresses for all interfaces has also been addressed. Finally, we showcased how the with_items and when statements can be used to loop over and filter the data based on IP addresses.

Overall, Ansible offers a versatile and effective method for managing and automating network infrastructure, helping businesses increase the performance and dependability of their networks.