===== Как делать 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!" }