🎯 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.
In this article, you'll learn:
- ✅ 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()
📌 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/charlie
Using 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 }}"
🎯 Expected Output
When search_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"
}
🚨 Handling Missing Values Gracefully
If the search_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` |
.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 dictionaries
These Jinja2 filters are invaluable when working with structured data in Ansible playbooks!