Ansible включает задачу только в том случае, если файл существует
Я пытаюсь включить файл только в том случае, если он существует. Это позволяет настраивать "задачи/роли" между существующими "задачами/ролями", если это необходимо пользователю моей роли. Я нашел это:
- include: ...
when: condition
Но в Ansible docs указано, что:
"Все задачи оцениваются, но условное применяется к каждой задаче" - http://docs.ansible.com/playbooks_conditionals.html#applying-when-to-roles-and-includes
Итак,
- stat: path=/home/user/optional/file.yml
register: optional_file
- include: /home/user/optional/file.yml
when: optional_file.stat.exists
Ошибка, если включенный файл не существует. Я предполагаю, что может быть еще один механизм, позволяющий пользователю добавлять задачи к существующему рецепту. Я не могу позволить пользователю добавлять роль после моего, потому что они не будут контролировать порядок: их роль будет выполнена после моего.
Ответы
Ответ 1
Спасибо всем за вашу помощь! Я отвечаю на свой вопрос после того, как, наконец, попытаюсь ответить на все ответы и мой собственный код вопроса сегодня. Ansible: ansible 2.0.1.0
Теперь мой исходный код работает, за исключением того, что дополнительный файл, который я искал, был на моем локальном компьютере, поэтому мне пришлось запустить stat через local_action и установить become: no
для этих конкретных задач, поэтому он не попытался бы сделать это sudo на моей локальной машине и ошибка с: "sudo: требуется пароль \n"
- local_action: stat path=/home/user/optional/file.yml
register: optional_file
become: no
- include: /home/user/optional/file.yml
when: optional_file.stat.exists
Ответ 2
Условие with_first_found
может выполнить это без stat
или local_action
. Это условие будет проходить через список локальных файлов и выполнить задачу с item
, установленной в путь к первому существующему файлу. Включение skip: true
в параметры with_first_round
предотвратит его отказ, если ни один из файлов не существует
Пример:
- hosts: localhost
connection: local
gather_facts: false
tasks:
- include: "{{ item }}"
with_first_found:
- files:
- /home/user/optional/file.yml
skip: true
Ответ 3
Я использую что-то похожее, но для файлового модуля, и для чего трюк для меня - проверить определение переменной, попробуйте что-то вроде:
when: optional_file.stat.exists is defined and optional_file.stat.exists
задача будет выполняться только тогда, когда существует переменная.
Ответ 4
Я мог бы потратить здесь время на bash возможные действия по обработке ошибок, но, короче говоря, вы правы, и вы не можете использовать модуль stat
для этой цели по указанным причинам.
Самое простое решение для большинства проблем - это сделать это вне возможности. Например.
- shell: test -f /home/user/optional/file.yml # or use -r if you're too particular.
register: optional_file
failed_when: False
- include: /home/user/optional/file.yml
when: optional_file.rc == 0
- debug: msg="/home/user/optional/file.yml did not exist and was not included"
when: optional_file.rc != 0
* failed_when
, чтобы избежать исключения хоста из дальнейших задач, когда файл не существует.
Ответ 5
Если я не ошибаюсь, вы хотите продолжить воспроизведение, даже если инструкция false?
Если да, добавьте эту строку после when:
ignore_errors: True
Итак, ваши задачи будут выглядеть так:
- stat: path=/home/user/optional/file.yml
register: optional_file
- include: /home/user/optional/file.yml
when: optional_file.stat.exists
ignore_errors: True
Пожалуйста, дайте мне знать, если я правильно понял ваш вопрос или могу помочь. Благодаря
Ответ 6
Лучший вариант, который я придумал, заключается в следующем:
- include: "{{ hook_variable | default(lookup('pipe', 'pwd') ~ '/hooks/empty.yml') }}"
Это не совсем "if-exists", но дает пользователям вашей роли тот же результат. Создайте несколько переменных внутри вашей роли и пустой файл по умолчанию. Фильтры Jinja "по умолчанию" и "lookup" заботятся о возврате в пустой файл, если переменная не была установлена.
Для удобства пользователь может использовать переменную {{ playbook_dir }}
для установки путей:
hook_variable: "{{ playbook_dir }}/hooks/tasks-file.yml"
Ответ 7
Используя ansible-2.1.0, я могу использовать такие фрагменты в моей книге:
- hosts: all
gather_facts: false
tasks:
- name: Determine if local playbook exists
local_action: stat path=local.yml
register: st
- include: local.yml
when: st.stat.exists
Я не получаю ошибок/сбоев, когда local.yml
не существует, а playbook исполняется (в качестве учебника, то есть начинается с строки hosts:
и т.д.)
Вы можете сделать то же самое на уровне задачи вместо этого с похожим кодом.
Использование stat
будет работать правильно.