Ansible - select attributes that match

May 29, 2015   #ansible 

Sometimes it’s useful to be able to access specific content from a dict based on values, rather than keys.

Take for example, a user dict that contains the following information.

---
users:
  - name: john
    email: john@example.com
  - name: jane
    email: jane@example.com
  - name: fred
    email: fred@example.com
    password: 123!abc

You might want to send an email to john and jane, suggesting they set a password.

Now you could get the emails to use from a template lookup. Looping the items in the list, checking the password attribute, and building a list based on it. e.g.

# get_emails.j2
[
{% for user in users %}
  {% if user.password is undefined %}
{{ user.email }},
  {% endif %}
{% endfor %}
]

which you might call using something like…

- set_fact:
    emails: "{{ lookup('template', './get_emails.j2' }}"

However that requires a jinja template file, and requires looking in two places to see the logic. If you don’t like that approach, you could use a filter

- set_fact:
    emails: "{{ users | selectattr('password', 'undefined') | map(attribute='email') | list }}"

which essentially says, select all list objects which have no password key, then from that selection get all email values, and return them in a list.

Note: the second attribute of selectattr must be a jinja2 builtin test