![Ansible: фатальная ошибка, выдаваемая include_tasks, даже если используется блок восстановления блока](https://rvso.com/image/717732/Ansible%3A%20%D1%84%D0%B0%D1%82%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F%20%D0%BE%D1%88%D0%B8%D0%B1%D0%BA%D0%B0%2C%20%D0%B2%D1%8B%D0%B4%D0%B0%D0%B2%D0%B0%D0%B5%D0%BC%D0%B0%D1%8F%20include_tasks%2C%20%D0%B4%D0%B0%D0%B6%D0%B5%20%D0%B5%D1%81%D0%BB%D0%B8%20%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D1%83%D0%B5%D1%82%D1%81%D1%8F%20%D0%B1%D0%BB%D0%BE%D0%BA%20%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%B1%D0%BB%D0%BE%D0%BA%D0%B0.png)
Я пытаюсь включить несколько задач на основе некоторых значений, определенных в одной hostvar, но некоторые фатальные ошибки выдаются даже если я использую блок block-rescue. У меня есть переменнаяпрофилиопределено вhost_vars/имя_хоста.yml:
profiles: '["profile1","trap1"]'
и рольтестовые_профилив/etc/ansible/роли. Здесь, в каталоге задач у меня есть следующие файлы .yml:профиль1.yml, профиль2.yml, основной.yml.
Содержимое файла main.yml:
- name: import profiles
block:
- include_tasks: "{{ item }}.yml"
with_items: "{{ profiles|default([]) }}"
rescue:
- debug: msg='Error encountered while trying to include a .yml file corresponding to a defined profile from profiles variable. Profiles - "{{ profiles }}"'
when: profiles is defined
Содержание книги:
- name: Test profiles config
hosts: myhost
roles:
- test_profiles
Вывод примерно такой:
TASK [test_profiles : include_tasks] ***********************************************************************************************************************************************************************
included: /etc/ansible/roles/test_profiles/tasks/profile.yml for <my_host>
fatal: [<my_host>]: FAILED! => {"reason": "Unable to retrieve file contents\nCould not find or access '/etc/ansible/trap1.yml'"}
TASK [test_profiles : Ensure that profile directory exists into the D:\profiles directory] ************************************************************************************************
ok: [<my_host>]
TASK [test_profiles : Update profile.properties file] ***************************************************************************************************************************************************
ok: [<my_host>]
TASK [test_profiles : debug] *******************************************************************************************************************************************************************************
ok: [<my_host>] => {
"msg": "Error encountered while trying to include a .yml file corresponding to a defined profile from profiles variable. Profiles - \"[\"profile1\",\"trap1\"]\""
}
to retry, use: --limit @/etc/ansible/playbook_test_profiles.retry
PLAY RECAP ********************************************************************************************************************************************************************************************************
<my_host> : ok=5 changed=0 unreachable=0 failed=1
С моей точки зрения, эта фатальная ошибка не должна появляться. Что я делаю не так и как мне избавиться от этого? Я также пробовал скогдаусловный, но безуспешно.
я используюАнсибль 2.4.2.0и задачи выполняются для некоторых хостов Windows.
решение1
block
/ rescue
не предотвращает возникновение ошибки. Он обнаруживает неудавшуюся задачу и выполняет rescue
блок для восстановления после ошибки. Но неудавшаяся задача все еще существует и будет видна в обзоре игры.
Я бы рекомендовал использовать подход fail fast при проектировании плейбуков. В вашем случае вы можете просканировать локальные файлы, чтобы проверить, является ли пользовательский ввод (предоставленная конфигурация) допустимым: находятся ли файлы профилей на месте. Пользователь assert
/ fail
модули.
решение2
В конце концов я удалил блок block-rescue. Я нашел способ проверить, существует ли мой .yml-файл. Это делается с помощьюпуть_ролипеременная (которая вернет путь к текущей роли — доступно с Ansible 1.8 — работает только внутри роли) и тестis_file.
Мой main.yml для описанной выше роли выглядит так:
- name: Import profiles
include_tasks: "{{ item }}.yml"
with_items: "{{ profiles|default([]) }}"
when: (role_path + '/tasks/' + item + '.yml') | is_file
Благодаря этой проверке фатальное исключение больше не будет выдаваться — файл trap1.yml будет пропущен.
Вывод будет примерно таким:
TASK [test_profiles : Import profiles] ***********************************************************
skipping: [<my_host>] => (item=trap1)
included: /etc/ansible/roles/test_profiles/tasks/profile1.yml for <my_host>
TASK [test_profiles : Ensure that profile directory exists into the D:\profiles directory] *******
ok: [<my_host>]
TASK [test_profiles : Update profile.properties file] ********************************************
changed: [<my_host>]
to retry, use: --limit @/etc/ansible/playbook_test_profiles.retry
PLAY RECAP ***************************************************************************************
<my_host> : ok=4 changed=1 unreachable=0 failed=0
Меня устраивает это решение, но я открыт и для других предложений.