Гнездо with_filetree и петля - PullRequest
0 голосов
/ 09 июля 2020

Как я могу вложить with_filetree и al oop?

Вот моя попытка с использованием блока:

- name: Deploy
  hosts: all
  connection: ssh
  become: true

  vars:
    instances:
      abcd:
        admin_port: 12345
  
  tasks:
    - name: Template cfg
      vars:
        file_path: "{{ item.path }}"
      block:
        - name: Templating config files
          vars:
            instance: "{{ item.value }}"
          template:
            src: "config-templates/{{ file_path }}"
            dest: "{{ install_dir }}/{{ instance.name }}/"
          loop: "{{ instances | dict2items }}"
      with_filetree: "config-templates"
      when: item.state == 'file'

Но ansible жалуется:

ERROR! 'with_filetree' is not a valid attribute for a Block

Мне, должно быть, не хватает чего-то очевидного, но я не понимаю, как это сделать. Кажется, это не работает с использованием with_nested / with_cartesian.

Пожалуйста, помогите.

Ответы [ 2 ]

1 голос
/ 09 июля 2020

Использование включения для вложения циклов - единственное жизнеспособное решение, когда у вас есть несколько циклов в задаче включения.

Между тем, в большинстве сценариев, включая ваш, вы можете сократить объем работы до одного l oop. Основная идея c: вместо вложенных циклов вы создаете список со всеми элементами до l oop. В этом случае фильтр product должен сработать.

Другой "трюк" (поскольку в do c нет реальных примеров для filetree .. .) следует помнить, что with_<some_lookup> l oop обычно можно преобразовать в loop: {{ lookup|query('some_lookup', args....) }}.

Собирая все вместе, вот (не полностью протестированный) пример, который должен соответствовать вашим требованиям:

- name: Templating from filetree and instances
  vars:
    file: "{{ item.0 }}"
    instance: "{{ item.1.value }}"
  template:
    src: "config-templates/{{ file.path }}"
    dest: "{{ install_dir }}/{{ instance.name }}/"
  loop: "{{ lookup('filetree', 'templates/config') | product(instances | dict2items) | list }}"
  when: file.state == 'file'

Изменить : не пытаться сделать sh в направлении «МОЙ !!!» решение :), но если у вас не слишком много задач, вот возможный сценарий, чтобы сохранить все в одном файле.

Edit2 : вам даже не нужен задача, особенно если ваша игра нацелена на несколько хостов. Обновлено с полным примером псевдо-плейбука.

- name: Deploy
  hosts: all
  connection: ssh
  become: true

  vars:
    my_files: "{{ lookup('filetree', 'templates/config') | selectattr('state', 'eq', 'file') | list }}"
    action1_list: ['some', 'list']
    action2_list: ['other', 'list']
    
  tasks:
    - name: action 1
      debug:
        msg: action1
      vars:
        file: item.0
        action1_item: item.1
      loop: "{{ my_files | product(action1_list) | list }}"

    - name: action 2
      debug:
        msg: action2
      vars:
        file: item.0
        action2_item: item.1
      loop: "{{ my_files | product(action2_list) | list }}"
1 голос
/ 09 июля 2020

Благодаря комментарию Zeitounator я смог создать решение. Однако у него есть недостаток, заключающийся в том, что внутренние задачи l oop должны быть помещены в отдельный файл.

  tasks:
    - name: Template cfg
      include_tasks: inner-template-tasks.yaml
      with_filetree: "templates/config"
      when: item.state == 'file'

inner-template-tasks.yaml будет выглядеть примерно так:

- name: Templating {{ item.path }}
  vars:
    instance: "{{ loop_item.value }}"
  template:
    src: "config-templates/{{ item.path }}"
    dest: "{{ install_dir }}/{{ instance.name }}/"
  loop: "{{ instances | dict2items }}"
  loop_control:
    loop_var: loop_item

Интересно, почему ansible заставляет нас использовать для этого отдельный файл ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...