Ansible: циклическая переменная, на которую ссылаются в другом цикле

#ansible

Вопрос:

Есть ли способ ссылаться на другую переменную в loop1, которая будет использоваться в loop2?

Вот мой фиктивный учебник, который не работает:

 
---
- name: test
  hosts: localhost
  vars:
    - br:
      - dir1
      - dir2
    - folders:
      - /folder1/"{{ item.1 }}"/sub1
      - /folder1/"{{ item.1 }}"/sub2
    tasks:
    - name:
      debug:
        msg: "{{ item.0 }}"
      with_nested:
        - "{{ folders }}"
        - "{{ br }}"
 

Результат, которого я пытаюсь достичь, таков:

 /folder1/dir1/sub1
/folder1/dir1/sub2
/folder1/dir2/sub1
/folder1/dir2/sub2


Thank you. Appreciate your response.
 

Комментарии:

1. Я вижу здесь только один цикл ( with_nested цикл для вашей debug задачи).

2. @larsks Я на самом деле тоже пробовал loop и несколько других with_X , но, похоже, не могу получить нужный мне результат.

Ответ №1:

Я понимаю, что у вас нет требований к используемым переменным, вы просто хотите получить предоставленный список папок эффективным способом (с помощью цикла). Вы можете использовать эти переменные, чтобы получить желаемый результат с помощью with_nested цикла:

 ---
- hosts: localhost
  gather_facts: false
  vars:
    - folders:
      - dir1
      - dir2
    - subfolders:
      - sub1
      - sub2
  tasks:
  - name:
    debug:
      msg: "/folder1/{{ item.0 }}/{{ item.1 }}"
    with_nested:
      - "{{ folders }}"
      - "{{ subfolders }}"
 

овации

Ответ №2:

Вы ищете перекрестный продукт ваших двух списков, чтобы вы могли написать:

 - name: test
  hosts: localhost
  vars:
    - br:
      - dir1
      - dir2
    - folders:
      - /folder1/%s/sub1
      - /folder1/%s/sub2
  tasks:
    - name:
      debug:
        msg: "{{ item.1 % item.0 }}"
      loop: "{{ br|product(folders) }}"
 

При этом используется форматирование строк в стиле Python (например "Hello %s" % "world" ) для замены нужного значения в выводе.

Это приводит к выходу:

 
PLAY [test] ********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => (item=['dir1', '/folder1/%s/sub1']) => {
    "msg": "/folder1/dir1/sub1"
}
ok: [localhost] => (item=['dir1', '/folder1/%s/sub2']) => {
    "msg": "/folder1/dir1/sub2"
}
ok: [localhost] => (item=['dir2', '/folder1/%s/sub1']) => {
    "msg": "/folder1/dir2/sub1"
}
ok: [localhost] => (item=['dir2', '/folder1/%s/sub2']) => {
    "msg": "/folder1/dir2/sub2"
}

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
 

Комментарии:

1. Спасибо @larsks. Ценю ваш ответ.

Ответ №3:

Вы можете использовать Jinja для создания структуры, например

 - hosts: localhost
  vars:
    root:
      - folder1
    br:
      - dir1
      - dir2
    sub:
      - sub1
      - sub2
    _folders: |-
      {% for r in root %}
      {% for b in br %}
      {% for s in sub %}
      - /{{ r }}/{{ b }}/{{ s }}
      {% endfor %}
      {% endfor %}
      {% endfor %}
    folders: "{{ _folders|from_yaml }}"
  tasks:
    - debug:
        var: folders
 

дает то, что ты хочешь

   folders:
  - /folder1/dir1/sub1
  - /folder1/dir1/sub2
  - /folder1/dir2/sub1
  - /folder1/dir2/sub2
 

Вы можете скрыть его в файле и отделить динамические данные от кода, например, воспроизведение ниже дает тот же результат

 shell> cat my_vars.yml
root:
  - folder1
br:
  - dir1
  - dir2
sub:
  - sub1
  - sub2
_folders: |-
  {% for r in root %}
  {% for b in br %}
  {% for s in sub %}
  - /{{ r }}/{{ b }}/{{ s }}
  {% endfor %}
  {% endfor %}
  {% endfor %}
folders: "{{ _folders|from_yaml }}"
 
 shell> cat playbook.yml
- hosts: localhost
  vars_files:
    - my_vars.yml
  tasks:
    - debug:
        var: folders