После долгих поисков я пришел к выводу, что ansible (я использую последнюю стабильную на данный момент версию v2.5.3), скорее всего, не поддерживает регистрацию переменных или уведомлений из операторов include_role
и import_role
.
Есть похожий вопрос здесь , и предложение в одном из ответов: Each individual task within your include file can register variables, and you can reference those variables elsewhere
.
Однако, если я последую этому предложению, мне нужно будет добавить дополнительныененужный код во всех моих включенных ролях, просто потому, что мне может понадобиться обходной путь на специальном сервере.Вещи могут быстро выйти из-под контроля и стать беспорядочными, особенно в случае вложенных включений ролей (т. Е. Когда включенная роль содержит больше включенных ролей).Более того, если я использую роли из ansible-galaxy, я хотел бы придерживаться исходных версий (обрабатывать роли как внешние библиотеки), что означает, что в идеале я бы не хотел менять код роли какне очень интуитивно понятно, что нужно поддерживать вилки всех ролей, которые нужно использовать (в противном случае внешние роли / библиотеки в значительной степени теряют свое значение).
Так что же предлагаетсярешение для такой проблемы, когда кто-то хочет повторно использовать код из внешних ролей и на основе каких-либо изменений в вызываемой роли что-то делать?Неужели я думаю, что здесь неправильно с точки зрения того, как я реализовал свою логику в игровой форме?
Взгляните на следующий конкретный пример того, что я пытаюсь сделать :
У меня есть разделенные задачи, которые я хочу использовать в небольших ролях.В моей роли common
у меня есть add-file.yml
набор задач, который выглядит следующим образом (roles/common/tasks/add-file.yml
):
- name: Copying file "{{ file.src }}" to "{{ file.dest }}"
copy:
src: "{{ file.src }}"
dest: "{{ file.dest }}"
owner: "{{ file.owner | default(ansible_user_id) }}"
group: "{{ file.group | default(ansible_user_id) }}"
mode: "{{ file.mode | default('preserve') }}"
when:
file.state is not defined or file.state != 'absent'
- name : Ensuring file "{{ file.dest }}" is absent
file:
path: "{{ file.dest }}"
state: "{{ file.state }}"
when:
- file.state is defined
- file.state == 'absent'
Это в основном универсальная настраиваемая задача для поддержки state: absent
для копирования файлов до эта ошибка исправлена.
Затем в другой роли (назовем это setup-XY
) я делаю это в файле roles/setup-XY/tasks/main.yml
:
- name: Copying X-file
import_role:
name: common
tasks_from: add-file.yml
vars:
file:
state: present
src: X-file
dest: /home/user/X-file
mode: '0640'
- name: Ensuring Yline in Z-file
lineinfile:
dest: /etc/default/Z-file
regexp: '^Yline'
line: 'Yline=123'
Затем втретья роль (назовем ее z-script
). Я хочу что-то вроде этого в файле roles/z-script/tasks/main.yml
:
- name: Setup-XY
include_role:
name: setup-XY
register: setupxy
- name: Run Z script if setupXY changed
shell: /bin/z-script
when: setupxy.changed
К сожалению, вышеприведенное не работает, поскольку строка register: setupxy
регистрирует setupxy
переменная, которая всегда возвращает "changed": false
.Если я использую import_role
вместо include_role
, переменная вообще не регистрируется (остается неопределенной).
Обратите внимание, что в роли z-script
я хочу запускать команду оболочки /bin/z-script
всякий раз, когдав роли setup-XY
обнаружено любое изменение, т. е. в случае изменения X-file
или Z-file
, и в действительности у меня может быть гораздо больше задач в роли setup-XY
.
Более того, обратите вниманиечто z-script
не связан с ролью setup-XY
(например, z-script
должен запускаться только на конкретном проблемном сервере), поэтому код для выполнения z-script
в идеале не следует отправлять вместес (и загрязняют) ролью setup-XY
.Посмотрите на setup-XY
как внешнюю / восходящую роль в этом случае.