iterating a hash in an ansible task
This is no longer needed as the with_dict
iterator is available in ansible core since version 1.5
.
I'd been stuck on the problem of iterating over a hash in a task.
Vars:
var:
item1:
name: one
value: 1
item2:
name: two
value: 2
Taks:
name: my loop
action: shell echo ${item.name}
with_items: $var
The above sample will generate an error
with_items expects a list
Now the obvious solution to this might be to rewrite the vars as
var:
- name: one
value: 1
- name: two
value: 2
However, there is one main use case I've encountered that can't be satisfied by a list of hashes. This is when I want the same var
to be added to by different roles.
By default ansible uses the replace
strategy when combining variable definitions. However, if the ansible variable hash_behaviour
is set to merge
the final variable state is created by recursively merging all hashes.
Getting back to the topic at hand, iterating over the hash can be achieved by creating a custom jinja2 filter.
First create a structure similar to
custom
└── filter_plugins
├── __init__.py
└── hash.py
in your ansible repository.
Add the following snippet to hash.py
def hash_to_tuples(h):
return h.items()
def hash_keys(h):
return h.keys()
def hash_values(h):
return h.values()
class FilterModule(object):
''' utility filters for operating on hashes '''
def filters(self):
return {
'hash_to_tuples' : hash_to_tuples
,'hash_keys' : hash_keys
,'hash_values' : hash_values
}
Then, add filter_plugins=./custom/filter_plugins
to your ansible.cfg
file.
Finally, update your task to look like
name: my loop
action: shell echo ${item[1].name}
with_items: "{{var|hash_to_tuples}}"
Written by Ali-Akber Saifee
Related protips
5 Responses
Hi,
Nice, I am looking for the same thing.
However, I am not familiar with the ansible.cfg file and when I look at the doc, it does not help a lot.
When I just insert this line "filterplugins=./custom/filterplugins" into my ansible.cfg, it does not work. I have an error about no headers...
What does your all ansible.cfg file contain?
Thanks
Hi,
Refer to the sample config file in the ansible repository. The filterplugins
property goes under the [defaults]
section.
This "solution" is NOT needed anymore since with_dict was introduced in ansible version 1.5 ( Feb 2014 ).
With the variable from your example ...
name: my loop
action: shell echo ${item.name}
with_dict: var
... will work perfectly.
See the documentation chapter Looping over Hashes
@nifr: thanks! good to see that it's in the built-ins now!
withdict is useful to iterate through keys, values but what if I want to store in a variable only the list of the values?
mydict:
ka: "a"
kb: "b"
And I would like to create a "my_values" variable that will be a list of the values only: ["a", "b"]