How to Filter Specific Network Interface Facts in Ansible Using the Setup Module


7 views

When working with Ansible's setup module, many users struggle to extract specific network interface details using command-line filters. The standard documentation often demonstrates playbook usage like {{ ansible_eth0.ipv4.address }}, but doesn't clearly explain the equivalent filter syntax for ad-hoc commands.

Ansible's setup module uses a glob-style pattern matching for filters, not the dot notation you'd use in playbooks. To get the IPv4 address of eth0, you would use:

ansible all -m setup -a "filter=ansible_eth0"

This returns the entire interface structure. For more targeted filtering, you need to understand Ansible's fact structure.

Here are some real-world examples:

# Get all network interfaces
ansible all -m setup -a "filter=ansible_interfaces"

# Get specific interface details (eth0 in this case)
ansible all -m setup -a "filter=ansible_eth0"

# Get just the IPv4 information for eth0
ansible all -m setup -a "filter=ansible_eth0.ipv4"

The setup module's filter parameter doesn't support the exact same syntax as playbook variable access because:

  • It uses shell glob patterns, not Python dictionary access
  • Filters operate on the raw JSON structure before variable magic happens
  • You can only filter at the top level of fact categories

When you need specific fields, consider these alternatives:

# Pipe to jq for advanced filtering
ansible all -m setup | jq '.ansible_facts.ansible_eth0.ipv4.address'

# Use a debug task in a playbook
- hosts: all
  tasks:
    - debug:
        var: ansible_eth0.ipv4.address
  • For one-time checks, use the setup module with broad filters
  • For complex extractions, prefer playbooks with debug or set_fact
  • Cache facts when working with large inventories
  • Combine with jq or other JSON processors for advanced filtering

When working with Ansible's setup module, the filter parameter allows you to extract specific subsets of system facts. However, the syntax differs slightly from what you'd use in playbooks.

The challenge lies in properly filtering network interface facts. While playbooks accept dot notation like ansible_eth0.ipv4.address, the setup module requires a different approach.

To get IPv4 address information for eth0:

ansible all -m setup -a "filter=ansible_eth0"

For a more targeted approach using wildcards:

ansible all -m setup -a "filter=ansible_*_ipv4"

When you need specific nested elements, combine multiple filters:

ansible all -m setup -a "filter=ansible_eth0" | jq '.ansible_facts.ansible_eth0.ipv4.address'

For more complex extractions, pipe the output to jq:

ansible all -m setup | jq '.ansible_facts | {interface: .ansible_default_ipv4.interface, address: .ansible_default_ipv4.address}'
  • Use wildcards (*) when you're unsure of exact interface names
  • Combine with jq for complex JSON parsing
  • Test filters in debug mode before running in production

This playbook snippet shows both CLI and playbook approaches:

---
- name: Gather and display network facts
  hosts: all
  tasks:
    - name: Display IPv4 address using setup module output
      debug:
        msg: "{{ ansible_eth0.ipv4.address }}"
        
    - name: Alternative syntax
      debug:
        msg: "{{ ansible_eth0['ipv4']['address'] }}"