Create a varaible list conditionally from dictionary items

Hi,

I’ve tried searching everything but can’t find a possible solution. I have a yml that defines all my variables for a playbook and I need to do something like the following inside of it:

I think you want something like:

my_list: “{{ my_dict|selectattr(‘item_en’)|map(attribute=‘name’)|list }}”

Matt’s solution is fine (and elegant!) for simple cases like this particular one. However, I found myself needing to filter items on some more complex conditions a few times and started using the Jinja do extension to effectively turn variable assignments into arbitrary computations:

`
my_list: |
{%- set names = -%}
{%- for item in my_dict if item.item_en -%}
{%- do names.append(item.name) -%}
{%- endfor -%}
{{ names }}

`

It’s important to do proper whitespace-control (the dashes in {%- … -%}) because in the end the string assigned to my_list must be “[‘name1’, ‘name3’]” and not something like " [‘name1’, ‘name3’]“. In the former case, Ansible converts it to a proper list (because the value starts with ‘[’), in the latter my_list would be assigned the actual string " […]”.

And you need to enable the Jinja extension in your ansible.cfg:

`
[defaults]
jinja2_extensions = jinja2.ext.do

`

As mentioned in the beginning, this isn’t really necessary in this case and certainly isn’t very much in Ansible’s spirit of simplicity, but it has saved me from duplicating information across multiple variables several times.

Why not something like this?

do_something_with: item.name
with_items: your_dict
when: item.item_en == True

Thanks guys,

Christian is your solution doable in a regular yml? I thought jinja constructs were only allowed in jinja templates? What I have is a regular .yml that defines all my variables.

Shawn I believe your solution requires creating a task to loop over my_dict, I prefer to do it outside of the playbook.

Also, another quick question. If I was using my_dict in a task loop, could i put a condition on:

with_items: my_dict
when: item.key is defined

will that work?

Also, another quick question. If I was using my_dict in a task loop, could i put a condition on:

Right that is my example. Here it is in code when item_en is false the item is skipped.

TASK: [Loop] ******************************************************************
changed: [127.0.0.1] => (item={‘key’: ‘value1’, ‘type’: ‘type1’, ‘name’: ‘name1’, ‘item_en’: True})
skipping: [127.0.0.1] => (item={‘key’: ‘value2’, ‘type’: ‘type2’, ‘name’: ‘name2’, ‘item_en’: False})
changed: [127.0.0.1] => (item={‘key’: ‘value3’, ‘type’: ‘type3’, ‘name’: ‘name3’, ‘item_en’: True})

https://gist.github.com/shawnferry/572c4f733a3f06f86a37

Yes, I have that stuff in my group_vars/all and in various vars.yml files. There no special magic to it except that you have to enable the do extension in ansible.cfg.

Every string variable in Ansible is fed through the templating engine:

`

Right thanks guys. And what about using a condition that checks if my_dict contains a entry with name == name2 ? Its not a loop, just a conditional for file include so I need a one liner.