Двойной цикл

У меня есть такой объект

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

И я хотел бы создать следующие файлы

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

но я понятия не имею, как сделать двойной цикл, используя with_items

Ответы

Ответ 1

Да. Вы можете.

Взгляните на with_subelements здесь http://docs.ansible.com/ansible/playbooks_loops.html#nested-loops

  1. Вам необходимо создать папки:
  2. objs и создайте файлы:

Вот пример:

---

- 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

Вывод довольно понятен, второй цикл перебирает значения так, как вам нужно:

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 

Ответ 2

На самом деле вы не можете. Циклы в Ansible одномерны. Существует трюк, который использовался для работы в предыдущих версиях и снова будет работать в Ansible 2.0:

У вас может быть один цикл вместе с оператором include, а в том числе yml у вас есть второй цикл. Итак, что-то в этом роде:

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

Опять же, это не будет работать в текущей версии (1.9.2) Ansible. Функция была отброшена, так как вызвала некоторые проблемы, но будет поддерживаться снова в Ansible 2.0, поэтому она должна быть доступна, если вы используете ветвь devel из github.

Вы можете установить из источника github с помощью этого:

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

Ответ 3

Добавление к ответу на удондан (нет представителя, чтобы комментировать выше):

Использование with_items может привести к неожиданным результатам, потому что внешний цикл и внутренний цикл имеют общую переменную 'item'.

Вы захотите использовать 'loop_control', чтобы предотвратить конфликт переменных.

Например

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