web-dev-qa-db-fra.com

Double boucle Ansible

J'ai un objet comme ça

objs:
    - { key1: value1, key2: [value2, value3] }
    - { key1: value4, key2: [value5, value6] }

Et je voudrais créer les fichiers suivants

value1/value2
value1/value3
value4/value5
value4/value6

mais je ne sais pas comment faire une double boucle en utilisant with_items

19
Ajouve

Oui. Vous pouvez.

Jeter un coup d'œil à with_subelements ici http://docs.ansible.com/ansible/playbooks_loops.html#nested-loops

  1. Vous devez créer un dossier:
  2. Itérer si objs et créer des fichiers:

Voici un exemple:

---

- 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

Une sortie est assez explicite, la deuxième boucle parcourt les valeurs comme vous en avez besoin:

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 
23
Vor

En fait, vous ne pouvez pas. Les boucles dans Ansible sont unidimensionnelles. Il existe une astuce qui fonctionnait dans les versions précédentes et fonctionnera à nouveau dans Ansible 2.0:

Vous pouvez avoir une boucle avec une instruction include et dans ce yml inclus vous avez la 2ème boucle. Donc quelque chose dans ce sens:

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

Encore une fois, cela ne fonctionnera pas dans la version actuelle (1.9.2) d'Ansible. La fonctionnalité a été supprimée car elle a causé des problèmes mais sera à nouveau prise en charge dans Ansible 2.0, elle devrait donc être disponible lorsque vous utilisez branche de développement de github .

Vous pouvez installer à partir de la source github avec ceci:

git clone https://github.com/ansible/ansible.git --recursive
cd ./ansible
source ./hacking/env-setup
Sudo make install
9
udondan

Ajout à la réponse d'udondan (N'ayez pas le représentant pour commenter ci-dessus):

L'utilisation de with_items peut conduire à des résultats inattendus, car la boucle externe et la boucle interne partagent une variable commune 'item'.

Vous voudrez utiliser 'loop_control' pour éviter un conflit de variables.

Par exemple

- include: nested_loop.yml obj={{ outside_item }}
  with_items: objs
  loop_control:
    loop_var: outside_item
2
Joel Griffiths