I have an object like that
objs: - { key1: value1, key2: [value2, value3] } - { key1: value4, key2: [value5, value6] }
And I'd like to create the following files
value1/value2 value1/value3 value4/value5 value4/value6
but I have no idea how to do a double loop using with_items
Ansible's syntax also supports the idea of nested looping. Nested loops in many ways are similar in nature to a set of arrays that would be iterated over using the with_nested operator. Nested loops provide us with a succinct way of iterating over multiple lists within a single task.
Ansible loop is used to repeat any task or a part of code multiple times in an Ansible-playbook. It includes the creation of multiple users using the user module, installing multiple packages using apt or yum module or changing permissions on several files or folders using the file module.
What is Ansible with_items? The Ansible with_items is a handy plugin to perform loop operations in a playbook. The plugin accepts items and then passes them to the calling module. For example, you can pass a list of packages to install and then give each item in the list to the install task.
Take a look at with_subelements
in Ansible's docs for loops.
objs
and create files:Here is an example:
--- - hosts: localhost gather_facts: no vars: objs: - { key1: value1, key2: [ value2, value3] } - { key1: value4, key2: [ value5, value6] } tasks: - name: create directories file: path="{{ item.key1 }}" state=directory with_items: objs - name: create files file: path="{{ item.0.key1 }}/{{ item.1 }}" state=touch with_subelements: - objs - key2
An output is pretty self explanatory, the second loop iterates through the values the way you need it:
PLAY [localhost] ************************************************************** TASK: [create files] ********************************************************** changed: [localhost] => (item={'key2': ['value2', 'value3'], 'key1': 'value1'}) changed: [localhost] => (item={'key2': ['value5', 'value6'], 'key1': 'value4'}) TASK: [create files] ********************************************************** changed: [localhost] => (item=({'key1': 'value1'}, 'value2')) changed: [localhost] => (item=({'key1': 'value1'}, 'value3')) changed: [localhost] => (item=({'key1': 'value4'}, 'value5')) changed: [localhost] => (item=({'key1': 'value4'}, 'value6')) PLAY RECAP ******************************************************************** localhost : ok=2 changed=2 unreachable=0 failed=0
In fact you can't. Loops in Ansible are one-dimensional. There is a trick which used to work in previous versions and will again work in Ansible 2.0:
You can have one loop together with an include
statement and in that included yml you have the 2nd loop. So something along these lines:
main.yml:
- include: nested_loop.yml obj={{ item }} with_items: objs
nested_loop.yml:
- name: create files file: path={{obj.key1 }}/{{ item }} state=touch with_items: obj.key2
Again, this will not work in the current version (1.9.2) of Ansible. The feature was dropped as it caused some problems but will be supported again in Ansible 2.0, so it should be available when you use the devel branch from github.
You can install from github source with this:
git clone https://github.com/ansible/ansible.git --recursive cd ./ansible source ./hacking/env-setup sudo make install
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With