Как зациклить несколько зависимых задач в Ansible

Я пытаюсь выполнить 2 задачи с использованием одних и тех же переменных, но со второй задачей, зависящей от результата первой задачи. Если я использую регистр, чтобы отметить результат первой задачи, я в конечном итоге создаю список, который вторая задача не может эффективно использовать, поскольку она создает связь цикла многие ко многим, когда я просто хочу, чтобы элемент сначала запускался в обеих задачах, тогда второй элемент для выполнения в обеих задачах, затем третий и т. д.

Например, найдите, существует ли каталог, и если он существует, измените его разрешения. У меня есть список каталогов, которые нужно просмотреть, чтобы проверить, существуют ли они, а затем изменить эти разрешения. Как мне сделать цикл в Ansible, чтобы он проходил только по каждому из них в списке в каждой задаче? Ниже моя последняя попытка.

- hosts: localhost
  vars:
    folders_to_change:
      - /Users/Documents/test_folder1
      - /Users/Documents/test_folder2
  tasks:
  - name: Ansible check file exists example.
    stat:
      path: "{{ item }}"
    register: file_details
    loop:
      "{{ folders_to_change }}"

  - name: Change permissions of folder
      file:
        path: "{{ folders_to_change[{{ item }}] }}"
        owner: root
        group: root
        mode: 777
        state: directory
    when: file_details.stat.exists.isdir["{{ item }}"]
    loop:
      "{{ range(0 - folders_to_change|len }}"

person fmakawa    schedule 16.12.2020    source источник
comment
У меня проблемы с пониманием file задачи, которую вы придумали. ваша цель - определить, существуют ли 2 папки в folders_to_change, и если да, запустить для них задачу file?   -  person ilias-sp    schedule 16.12.2020
comment
Да, это правильно   -  person fmakawa    schedule 17.12.2020


Ответы (1)


Вы близки, но кое-что у вас неуместно.

["{{ item }}"] находится не в том конце выражения, поскольку isdir - это просто атрибут, а не список, а file_details.results - это list

    when: file_details.results[item].stat.isdir

Также нет необходимости задействовать усы jinja2, поскольку when: уже является выражением jinja2, и наверняка не нужно указывать int, поскольку range испускает.

Это подводит нас к следующему пункту: range требует двух аргументов, но вы указали выражение 0 - len, которое будет иметь отрицательное число. Подразумевается начальный 0, поэтому на самом деле просто опустите его:

    when: file_details.results[item].stat.isdir
    loop:
      "{{ range(folders_to_change|length) }}"

Наконец, если вы предпочитаете этот стиль постоянного использования range и более простого обращения к глобальной переменной, вам больше возможностей, но список results отслеживает исходный item ключ в своих dict записях, таким образом:

  - name: Change permissions of folder
    file:
        path: "{{ item.item }}"
        owner: root
        group: root
        mode: 777
        state: directory
    when: item.stat.isdir
    loop: "{{ file_details.results }}"

Вы действительно выиграете от использования debug: var=file_details (или чего-то еще) в будущем, чтобы посмотреть на форму доступных вам данных.

person mdaniel    schedule 16.12.2020
comment
быстрое исправление - ›когда: item.stat.exists.isdir не работает, поскольку он является логическим и не имеет атрибута isdir. удалив это, и он работает. В интересах сделать код максимально многоразовым - как мне добавить владельца и группу как часть подсписка файлов, то есть [/ Users / Documents / test_folder1, root, root], таким образом я могу иметь разные права доступа к файлам для каждый файл. Я пробовал использовать «item.item.1» и «item.item.2», но это дало мне только «/» и «U». - person fmakawa; 17.12.2020
comment
Да, извините за это - слишком много копировальной пасты из исходного вопроса, недостаточно размышлений :-) Что касается вашего последующего вопроса, это будет сделка типа vars: { folders_to_change: [ { path: /Users/Documents/test_folder1, user: root, group: root } ] }, а затем обновите ссылки на атрибуты соответственно - person mdaniel; 18.12.2020