Ansible select & selectattr Filters: Filter Lists by Condition (Guide)
By Luca Berton ยท Published 2024-01-01 ยท Category: troubleshooting
How to filter lists in Ansible with select, selectattr, and map filters. Filter by attribute, test conditions, chain filters.
๐ฏ Filtering Data in Ansible: selectattr and map(attribute)
selectattr in Ansible is a Jinja2 filter that filters a list of dictionaries down to only the items whose attribute matches a test, such as equalto, defined, match, or search.
When working with lists of dictionaries in Ansible, filtering and extracting specific values is a common requirement. Jinja2 provides two powerful filters to accomplish this:
selectattrโ Filters the list based on a condition.map(attribute)โ Extracts a specific field from the filtered result.
- โ
How to filter lists of dictionaries in Ansible using
selectattr - โ
How to extract specific values using
map(attribute) - โ
How to handle missing values safely using
default()
See also: Ansible map vs selectattr vs json_query: Filter Data the Right Way
๐ Understanding selectattr and map(attribute)
Before jumping into Ansible playbooks, let's break down these Jinja2 filters.
โ
selectattr('name', 'equalto', search_name')
- Filters a list of dictionaries to select only the ones where
name == search_name.
โ
map(attribute='folder')
- Extracts the
folderfield from the filtered result.
โ Example Syntax
{{ variable | selectattr('name', 'equalto', search_name) | map(attribute='folder') | list }}selectattrfilters the list wherenameequalssearch_name.map(attribute='folder')extracts only thefoldervalues.listensures the result is returned as a list.
๐ฅ Example Use Case
Scenario
You have a list of users and their home directories (folder). You want to search for a specific user and get their folder path.
Example Data
variable:
- name: alice
folder: /home/alice
- name: bob
folder: /home/bob
- name: charlie
folder: /home/charlieUsing selectattr and map(attribute) in Ansible
- name: Search for a name and get its folder
hosts: localhost
gather_facts: no
vars:
variable:
- name: alice
folder: /home/alice
- name: bob
folder: /home/bob
- name: charlie
folder: /home/charlie
search_name: alice
tasks:
- name: Get folder for a specific user
debug:
msg: "{{ variable | selectattr('name', 'equalto', search_name) | map(attribute='folder') | list }}"---
See also: Ansible 2.16.0: Major Enhancements and Updates
๐ฏ Expected Output
selectattr returns a filtered list containing only the dictionaries that match the condition; piping that result through map(attribute='folder') reduces it to a plain YAML list of the matched folder values, as shown below. When the Ansible playbook executes the selectattr filter successfully, it extracts the matching folder path and displays it in the task result. Here's what you'll see for each scenario:
When search_name: alice:
TASK [Get folder for a specific user] *********************************************
ok: [localhost] => {
"msg": [
"/home/alice"
]
}When search_name: bob:
TASK [Get folder for a specific user] *********************************************
ok: [localhost] => {
"msg": [
"/home/bob"
]
}---
๐น Getting a Single Value Instead of a List
By default, the output is a list with one value. If you need only the string value, add.0:
- name: Get a single folder for a user
debug:
msg: "{{ (variable | selectattr('name', 'equalto', search_name) | map(attribute='folder') | list).0 }}"๐ Expected Output
TASK [Get a single folder for a user] *********************************************
ok: [localhost] => {
"msg": "/home/alice"
}---
See also: Ansible selectattr Filter: Filter Lists by Attributes (Guide)
๐จ Handling Missing Values Gracefully
If thesearch_name does not exist in the list, you may encounter an error. To prevent this, use default():
- name: Get folder safely
debug:
msg: "{{ (variable | selectattr('name', 'equalto', search_name) | map(attribute='folder') | list | default(['/not-found'])).0 }}"๐ Expected Output When search_name is Missing
TASK [Get folder safely] *********************************************
ok: [localhost] => {
"msg": "/not-found"
}---
โ Summary Table
| Method | Output | |
|---|---|---|
| list | ["/home/alice"] |
.0 | "/home/alice" | |
default(['/not-found']) | "/not-found" if no match |
๐ Why Use This Approach?
โ Filters data dynamically โ Extracts only necessary values โ Handles missing values safely โ Works efficiently with lists of dictionariesThese Jinja2 filters are invaluable when working with structured data in Ansible playbooks!
Related Articles
Category: troubleshooting