Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Double loop Ansible

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

like image 576
Ajouve Avatar asked Jul 22 '15 14:07

Ajouve


People also ask

How do you use multiple loops in Ansible?

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.

What are loops in Ansible?

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 With_item in Ansible?

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.


2 Answers

Take a look at with_subelements in Ansible's docs for loops.

  1. You need to create directories:
  2. Iterate though 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  
like image 58
Vor Avatar answered Oct 15 '22 20:10

Vor


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 
like image 28
udondan Avatar answered Oct 15 '22 19:10

udondan