AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible selectattr Filter: Filter Lists by Attributes (Guide)

By Luca Berton · Published 2024-01-01 · Category: installation

How to use Ansible selectattr filter to filter lists by attributes. Select items matching conditions, combine with map and reject filters with examples.

Ansible selectattr Filter: Filter Lists by Attributes (Guide)

How to Filter A List By Its Attributes in an Ansible Playbook?

I'm going to show you a live Playbook with some simple Ansible code. I'm Luca Berton and welcome to today's episode of Ansible Pilot.

See also: Automate Redmine Installation on Ubuntu LTS 22.04 with Ansible

selectattr filter in Ansible Playbook?

{{ users|selectattr("is_active") }}{{ users|selectattr("email", "none") }}

Today we're talking about Ansible selectattr Jinja filter. Filters a sequence of objects by applying a test to the specified attribute of each object, and only selecting the objects with the test succeeding. If no test is specified, the attribute's value will be evaluated as a boolean. The two examples explain how-to for a specific attribute or value using a users list example.

Links

Data manipulationJinja selectattr

## Playbook

How to filter a list by its attributes in an Ansible Playbook. I'm going to use the selectattr filter to select only one information from Ansible System Information (Facts). Specifically, I'm going to filter only for enabled features in a network interface (eth1).

code

---
- name: selectattr Playbook
  hosts: all
  gather_facts: true
  tasks:
    - name: all features
      ansible.builtin.debug:
        var: 'ansible_facts.eth1.features'
    - name: filter enabled
      ansible.builtin.debug:
        msg: "{{ (ansible_facts.eth1.features | dict2items | selectattr('value', 'match', 'on') ) }}"

execution

ansible-pilot $ ansible-playbook -i virtualmachines/demo/inventory variables/selectattr.yml
PLAY [selectattr Playbook] ****************************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [demo.example.com]
TASK [all features] *******************************************************************************
ok: [demo.example.com] => {
    "ansible_facts.eth1.features": {
        "esp_hw_offload": "off [fixed]",
        "esp_tx_csum_hw_offload": "off [fixed]",
        "fcoe_mtu": "off [fixed]",
        "generic_receive_offload": "on",
        "generic_segmentation_offload": "on",
        "highdma": "off [fixed]",
        "hw_tc_offload": "off [fixed]",
        "l2_fwd_offload": "off [fixed]",
        "large_receive_offload": "off [fixed]",
        "loopback": "off [fixed]",
        "netns_local": "off [fixed]",
        "ntuple_filters": "off [fixed]",
        "receive_hashing": "off [fixed]",
        "rx_all": "off",
        "rx_checksumming": "off",
        "rx_fcs": "off",
        "rx_gro_hw": "off [fixed]",
        "rx_gro_list": "off",
        "rx_udp_gro_forwarding": "off",
        "rx_udp_tunnel_port_offload": "off [fixed]",
        "rx_vlan_filter": "on [fixed]",
        "rx_vlan_offload": "on",
        "rx_vlan_stag_filter": "off [fixed]",
        "rx_vlan_stag_hw_parse": "off [fixed]",
        "scatter_gather": "on",
        "tcp_segmentation_offload": "on",
        "tls_hw_record": "off [fixed]",
        "tls_hw_rx_offload": "off [fixed]",
        "tls_hw_tx_offload": "off [fixed]",
        "tx_checksum_fcoe_crc": "off [fixed]",
        "tx_checksum_ip_generic": "on",
        "tx_checksum_ipv4": "off [fixed]",
        "tx_checksum_ipv6": "off [fixed]",
        "tx_checksum_sctp": "off [fixed]",
        "tx_checksumming": "on",
        "tx_esp_segmentation": "off [fixed]",
        "tx_fcoe_segmentation": "off [fixed]",
        "tx_gre_csum_segmentation": "off [fixed]",
        "tx_gre_segmentation": "off [fixed]",
        "tx_gso_list": "off [fixed]",
        "tx_gso_partial": "off [fixed]",
        "tx_gso_robust": "off [fixed]",
        "tx_ipxip4_segmentation": "off [fixed]",
        "tx_ipxip6_segmentation": "off [fixed]",
        "tx_lockless": "off [fixed]",
        "tx_nocache_copy": "off",
        "tx_scatter_gather": "on",
        "tx_scatter_gather_fraglist": "off [fixed]",
        "tx_sctp_segmentation": "off [fixed]",
        "tx_tcp6_segmentation": "off [fixed]",
        "tx_tcp_ecn_segmentation": "off [fixed]",
        "tx_tcp_mangleid_segmentation": "off",
        "tx_tcp_segmentation": "on",
        "tx_tunnel_remcsum_segmentation": "off [fixed]",
        "tx_udp_segmentation": "off [fixed]",
        "tx_udp_tnl_csum_segmentation": "off [fixed]",
        "tx_udp_tnl_segmentation": "off [fixed]",
        "tx_vlan_offload": "on [fixed]",
        "tx_vlan_stag_hw_insert": "off [fixed]",
        "vlan_challenged": "off [fixed]"
    }
}
TASK [filter enabled] *****************************************************************************
ok: [demo.example.com] => {
    "msg": [
        {
            "key": "tx_checksumming",
            "value": "on"
        },
        {
            "key": "tx_checksum_ip_generic",
            "value": "on"
        },
        {
            "key": "scatter_gather",
            "value": "on"
        },
        {
            "key": "tx_scatter_gather",
            "value": "on"
        },
        {
            "key": "tcp_segmentation_offload",
            "value": "on"
        },
        {
            "key": "tx_tcp_segmentation",
            "value": "on"
        },
        {
            "key": "generic_segmentation_offload",
            "value": "on"
        },
        {
            "key": "generic_receive_offload",
            "value": "on"
        },
        {
            "key": "rx_vlan_offload",
            "value": "on"
        },
        {
            "key": "tx_vlan_offload",
            "value": "on [fixed]"
        },
        {
            "key": "rx_vlan_filter",
            "value": "on [fixed]"
        }
    ]
}
PLAY RECAP ****************************************************************************************
demo.example.com           : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
ansible-pilot $

code with ❤️ in GitHub

See also: Ansible selectattr & map Filters: Filter Data from Lists (Complete Guide)

Conclusion

Now you know how to Filter A List By Its Attributes in an Ansible Playbook.

Basic selectattr

- vars:
    users:
      - { name: alice, role: admin, active: true }
      - { name: bob, role: user, active: true }
      - { name: charlie, role: admin, active: false }
  debug:
    msg:
      - "Admins: {{ users | selectattr('role', 'eq', 'admin') | list }}"
      - "Active: {{ users | selectattr('active') | list }}"
      - "Admin names: {{ users | selectattr('role', 'eq', 'admin') | map(attribute='name') | list }}"
      # ['alice', 'charlie']
      # [alice_dict, bob_dict]
      # ['alice', 'charlie']

See also: Ansible Scheduled Tasks: Cron Jobs & at Module for Timed Execution

Test Operators

| Operator | Example | Description | |----------|---------|-------------| | eq / equalto | selectattr('role', 'eq', 'admin') | Equals | | ne | selectattr('status', 'ne', 'disabled') | Not equals | | match | selectattr('name', 'match', '^web') | Regex match | | search | selectattr('desc', 'search', 'important') | Regex search | | in | selectattr('env', 'in', ['prod', 'staging']) | In list | | defined | selectattr('email', 'defined') | Attribute exists | | undefined | selectattr('phone', 'undefined') | Attribute missing | | truthy | selectattr('active') | Truthy value |

rejectattr (Inverse)

# Exclude inactive users
- debug:
    msg: "{{ users | rejectattr('active', 'eq', false) | list }}"

# Exclude admins - debug: msg: "{{ users | rejectattr('role', 'eq', 'admin') | map(attribute='name') | list }}"

Chain with map

- vars:
    servers:
      - { name: web1, env: prod, ip: 10.0.1.10 }
      - { name: web2, env: prod, ip: 10.0.1.11 }
      - { name: dev1, env: dev, ip: 10.0.2.10 }
  set_fact:
    prod_ips: "{{ servers | selectattr('env', 'eq', 'prod') | map(attribute='ip') | list }}"
    # ['10.0.1.10', '10.0.1.11']

Complex Filtering

# Multiple conditions (chain selectattr)
- set_fact:
    target: "{{ servers | selectattr('env', 'eq', 'prod') | selectattr('role', 'eq', 'web') | list }}"

# Select + sort - set_fact: sorted_prod: "{{ servers | selectattr('env', 'eq', 'prod') | sort(attribute='name') | list }}"

Practical Examples

Find hosts needing updates

- set_fact:
    needs_update: "{{ host_info | selectattr('update_available', 'eq', true) | map(attribute='hostname') | list }}"

Filter packages by state

- set_fact:
    installed: "{{ packages | selectattr('state', 'eq', 'installed') | map(attribute='name') | list }}"
    missing: "{{ packages | rejectattr('state', 'eq', 'installed') | map(attribute='name') | list }}"

Find matching strings in list

# select (not selectattr) for simple lists
- set_fact:
    python_packages: "{{ all_packages | select('match', '^python.*') | list }}"

FAQ

selectattr vs select?

selectattr: Filter list of dicts by attribute • select: Filter simple list by test

Why do I need | list at the end?

selectattr returns a generator. Pipe to list to materialize it, especially when using length or accessing by index.

Can I use selectattr in when conditions?

when: (users | selectattr('name', 'eq', 'admin') | list | length) > 0

Basic selectattr

- vars:
    users:
      - { name: alice, role: admin, active: true }
      - { name: bob, role: user, active: true }
      - { name: charlie, role: admin, active: false }
      - { name: dave, role: user, active: false }
  debug:
    msg: "{{ users | selectattr('role', 'eq', 'admin') | list }}"
# [{"name": "alice", ...}, {"name": "charlie", ...}]

Common Tests

# Equal
"{{ users | selectattr('role', 'eq', 'admin') | list }}"

# Not equal "{{ users | rejectattr('role', 'eq', 'admin') | list }}"

# Truthy (boolean true) "{{ users | selectattr('active') | list }}"

# Defined "{{ users | selectattr('email', 'defined') | list }}"

# Contains (string) "{{ users | selectattr('name', 'contains', 'li') | list }}"

# Match (regex) "{{ users | selectattr('name', 'match', '^a.*') | list }}"

# Greater than "{{ servers | selectattr('cpu', 'gt', 4) | list }}"

# In list "{{ users | selectattr('role', 'in', ['admin', 'superadmin']) | list }}"

selectattr + map

# Get names of active admin users
- debug:
    msg: >-
      {{ users
         | selectattr('role', 'eq', 'admin')
         | selectattr('active')
         | map(attribute='name')
         | list }}
# ["alice"]

rejectattr (Inverse)

# Users who are NOT admins
"{{ users | rejectattr('role', 'eq', 'admin') | list }}"

# Inactive users "{{ users | rejectattr('active') | list }}"

Practical: Filter Services

- service_facts:

- set_fact: running_services: >- {{ ansible_facts.services.values() | selectattr('state', 'eq', 'running') | map(attribute='name') | list }}

- debug: msg: "Running: {{ running_services | length }} services"

Practical: Filter Inventory

# Hosts with enough memory
- set_fact:
    big_hosts: >-
      {{ groups['all']
         | map('extract', hostvars)
         | selectattr('ansible_memtotal_mb', 'defined')
         | selectattr('ansible_memtotal_mb', 'gt', 4096)
         | map(attribute='inventory_hostname')
         | list }}

Chain Multiple Filters

- vars:
    packages:
      - { name: nginx, version: "1.24", installed: true, critical: true }
      - { name: redis, version: "7.0", installed: true, critical: false }
      - { name: postgres, version: "15", installed: false, critical: true }
  set_fact:
    missing_critical: >-
      {{ packages
         | selectattr('critical')
         | rejectattr('installed')
         | map(attribute='name')
         | list }}
# ["postgres"]

With Loops

- user:
    name: "{{ item.name }}"
    state: present
  loop: "{{ users | selectattr('active') | list }}"
  become: true

FAQ

selectattr vs json_query?

selectattr is simpler — use for single-attribute filtering. json_query (JMESPath) handles complex nested queries. Start with selectattr, use json_query when needed.

How to filter by nested attribute?

selectattr doesn't support dot notation. Flatten the data first or use json_query:

"{{ data | json_query('[?server.status==`running`]') }}"

selectattr returns a generator?

Yes — always add | list at the end to materialize the result.

Related Articles

template lookups in Ansiblemanaging inventory in Ansiblelooping in Ansible playbooks

Category: installation

Watch the video: Ansible selectattr Filter: Filter Lists by Attributes (Guide) — Video Tutorial

Browse all Ansible tutorials · AnsiblePilot Home