How can I return a list from a dict based on a sub items value?

How can I return a list from a dict based on a sub items value?

If I have a dictionary like this:

ospackages:
fail2ban:
state: “present”
Ubuntu:
1604: “fail2ban”
1804: “fail2ban”
Debian:
9: “fail2ban”
CentOS:
7: “fail2ban”
OracleLinux:
7: “fail2ban”
curl:
state: “present”
Ubuntu:
1604: “curl”
1804: “curl”
Debian:
9: “curl”
CentOS:
7: “curl”
OracleLinux:
7: “curl”
locate:
state: “absent”
Ubuntu:
1604: “mlocate”
1804: “mlocate”
Debian:
9: “mlocate”
CentOS:
7: “mlocate”
OracleLinux:
7: “mlocate”
ftp:
state: “absent”
Ubuntu:
1604: “ftp”
1804: “ftp”
Debian:
9: “ftp”
CentOS:
7: “ftp”
OracleLinux:
7: “ftp”

I’d like select only the items from that dictionary based on the value of “state”, and/or if a specific sub-dict has values.

I initially thought of this as a lookup plugin.

Something like:

lookup('dict_cond', ospackages, 'item.value.state == "present" and item.value.Ubuntu is defined and item.value.Ubuntu.1804 is defined', item.value.Ubuntu.1804)

would return:

[ fail2ban, curl ]

Use would be something like:

`

  • name: install Ubuntu 18.04 packages
    apt:
    pkg: “{{ lookup(‘dict_cond’, ospackages, ‘item.value.state == “present” and item.value.Ubuntu is defined and item.value.Ubuntu.1804 is defined’, item.value.Ubuntu.1804) }}”
    state: “present”
    update_cache: “yes”
    cache_valid_time: “14400”

  • name: yum - Install packages on CentOS 7
    yum:
    name: “{{ lookup(‘dict_cond’, ospackages, ‘item.value.state == “present” and item.value.CentOS is defined and item.value.CentOS.7 is defined’, item.value.CentOS.7) }}”
    state: “present”
    update_cache: True
    `

I took a look at plugins/lookup/dict.py and realized that I just don’t know enough Python to make a plugin myself.

Is there a way to do this with current plugins/modules/filters?

Any other ideas on how to get the same general result?

Would this be something to request as a new plugin via GitHub?

I’d be willing to try and code it myself if someone is willing to work with me. As long as you are willing to deal with newbie python questions. (I do know how to program, just not in Python.)

I should note that I have not yet tried using a task to filter through the dictionary, and register the result to a variable or maybe use set_fact in some manner.

I’d prefer not to get that complicated in the playbooks. Hence why I think a lookup plugin would be handy.

Plus, I really really dislike tasks that always say they’ve changed when running a play. I prefer it to stay idempotent as possible.

I would not recommend using dict in this matter, a easier solution is to use include_vars
https://docs.ansible.com/ansible/latest/modules/include_vars_module.html

If you still wanna use dist it will look something like this

  {{ ospackages | dict2items | selectattr('value.state', 'eq', 'present') | list | map(attribute='value.Ubuntu.1804') | list }}

Thanks! That got me to where I wanted.

  • David