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)
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
Whensearch_name: alice, the output will be:
TASK [Get folder for a specific user] *********************************************
ok: [localhost] => {
"msg": [
"/home/alice"
]
}When search_name: bob, the output will be:
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