===== Как делать include задач в Ansible=====
Вы можете использовать модуль include_tasks Ansible для импорта задач из других файлов. Существует ряд причин, по которым вам может потребоваться переместить задачи в отдельные файлы при использовании Ansible:
- **Рефакторинг** – разбивайте невероятно большие сборники пьес на файлы меньшего размера, чтобы их было легче понять.
- **Условное включение задач** — вы можете запускать группы задач условно на основе некоторых свойств хоста (например, ОС).
- **Циклическое выполнение списка задач для каждого элемента**
Я часто использую модуль include_tasks и включил наиболее распространенные варианты использования в разделы ниже..
===== Распространенные варианты использования =====
Моими наиболее распространенными вариантами использования 'include_tasks' являются:
- Выполнение различных задач в зависимости от операционной системы хоста (например, операционные системы на основе Debian или RHEL)
- Разделение роли 'main.yml' на файлы меньшего размера, более управляемые
===== Как include задачи из файла =====
Самой простой функцией модуля 'include_tasks' является импорт задач из файла в другой список задач. Это может быть в файлах задач playbook или rolenïSs. Наиболее распространенное использование этого метода - разбивать большие списки задач на более мелкие, более управляемые файлы.
Например, представьте, что у вас есть список задач, подобных следующему:
---
# ./roles/my_role/tasks/main.yml
- name: install dependencies
apt:
name: "{{ item }}"
state: present
become: true
loop:
- nginx
- php7.2
- name: configure the application
copy:
src: my_app.conf
dest: /etc/my_app.conf
become: true
Это всего лишь 2 задачи, но ради примера вы можете разбить эти задачи на их собственные файлы:
---
# ./roles/my_role/tasks/install.yml
- name: install dependencies
apt:
name: "{{ item }}"
state: present
become: true
loop:
- nginx
- php7.2
---
# ./roles/my_role/tasks/configure.yml
- name: configure the application
copy:
src: my_app.conf
dest: /etc/my_app.conf
become: true
Теперь вы можете переписать исходный список задач следующим образом:
---
# ./roles/my_role/tasks/main.yml
- include_tasks: install.yml
- include_tasks: configure.yml
Если вам когда-нибудь понадобится добавить дополнительные задачи для настройки роли, вы можете добавить их непосредственно в 'setup.yml' или 'configure.yml' вместо 'main.yml'.
Использование этого метода также является хорошим способом реорганизовать большие списки задач в более мелкие логические группы (т. Е. Эта группа задач устанавливает объекты, а эта группа задач настраивает объекты)..
===== Как включать задачи по условию =====
Другой очень распространенный вариант использования 'include_tasks' - это импорт по условию некоторых задач на основе некоторой переменной в роли.
Распространенным примером может быть предоставление пользователю возможности выбирать, устанавливать ли часть программного обеспечения с помощью менеджера пакетов, такого как 'apt' или 'yum', или путем компиляции его из исходного кода.
Используйте ключевое слово 'when' для условного включения задач:
# ./roles/my_role/tasks/main.yml
- include_tasks: install_with_apt.yml
when: not install_from_source
- include_tasks: compile_and_install_from_source.yml
when: install_from_source
В приведенном выше примере пользователь мог установить 'install_from_source: true' или 'install_from_source: false', чтобы управлять способом установки пакета.
===== Как включить задачи с динамическим именем файла =====
По моему опыту, включение задач с динамическим именем файла чаще всего используется для изменения задач в зависимости от операционной системы удаленного хоста.
Рассмотрим этот пример:
# ./roles/redis/tasks/main.yml
- name: install redis on Debian based distros
apt:
name: redis-server
state: present
update_cache: true
become: true
when: ansible_os_family == 'Debian'
- name: ensure epel-release repo is installed on RHEL based distros
yum:
name: epel-release
state: present
update_cache: true
become: true
when: ansible_os_family == 'RedHat'
- name: install redis on RHEL based distros
yum:
name: redis
state: present
update_cache: true
become: true
when: ansible_os_family == 'RedHat'
Вы могли бы преобразовать эти задачи в отдельные файлы, а затем использовать условную логику для их включения:
---
# ./roles/redis/tasks/setup-Debian.yml
- name: install redis on Debian based distros
apt:
name: redis-server
state: present
update_cache: true
become: true
---
# ./roles/redis/tasks/setup-RedHat.yml
- name: ensure epel-release repo is installed on RHEL based distros
yum:
name: epel-release
state: present
update_cache: true
become: true
- name: install redis on RHEL based distros
yum:
name: redis
state: present
update_cache: true
become: true
После создания отдельных файлов вы можете изменить файл основных задач, чтобы он выглядел следующим образом:
# ./roles/redis/tasks/main.yml
- include_tasks: setup-Debian.yml
when: ansible_os_family == 'Debian'
- include_tasks: setup-RedHat.yml
when: ansible_os_family == 'RedHat'
Намного лучше, но вы могли бы сделать его еще более кратким, просто используя переменную 'ansible_os_family' для включения файла в одну строку:
- include_tasks: "setup-{{ ansible_os_family }}.yml"
Это приведет к тем же результатам, что и исходный список задач. Это обычный шаблон, используемый во многих сторонних ролях, которые вы найдете в Ansible Galaxy.
===== Как включать задачи для каждого элемента в цикле =====
Вероятно, это наименее распространенный вариант использования 'include_tasks', но я использовал его несколько раз. Этот метод полезен всякий раз, когда вам нужно запустить ** несколько задач ** для каждого элемента в цикле.
Вот надуманный пример, чтобы показать вам, как вы могли бы это использовать: список задач 'greet_tasks.yml', который создаст факт приветствия, а затем распечатает его с надписью 'debug'.:
---
# ./greet_tasks.yml
- name: set greeting fact
set_fact:
greeting: "Greeting {{ index }}: Hello, {{ name }}!"
- name: print greeting fact
debug: var=greeting
Вы можете запускать эти задачи в цикле в сборнике задач, подобном этому:
# ./greet.yml
- name: greet people
hosts: "*"
tasks:
- include_tasks: greet.yml
loop:
- World
- Percy
loop_control:
loop_var: name
index_var: index
Запуск playbook приведет к следующему результату:
TASK [set greeting fact]
ok: [123.123.123.123]
TASK [print greeting fact]
ok: [123.123.123.123] => {
"greeting": "Greeting 0: Hello, World!"
}
TASK [set greeting fact]
ok: [123.123.123.123]
TASK [print greeting fact]
ok: [123.123.123.123] => {
"greeting": "Greeting 1: Hello, Percy!"
}