Уведомлять обработчик или регистрировать доступную переменную при обнаружении изменений в include_role?

После долгих поисков я пришел к выводу, что 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, я бы хотел придерживаться исходных версий (рассматривать роли как внешние библиотеки), а это означает, что в идеале я не хотел бы изменять код роль, поскольку это не очень интуитивно чтобы поддерживать форки всех ролей, которые нужно использовать (иначе внешние роли / библиотеки в значительной степени потеряет свое значение).

Итак, каково предлагаемое решение такой проблемы, когда кто-то хочет повторно использовать код из внешних ролей, и в зависимости от того, произошло ли какое-либо изменение вызываемой роли, что-то сделать? Я совершенно неправильно думаю о том, как я реализовал свою логику доступного playbook?

Взгляните на следующий конкретный пример того, что я пытаюсь сделать:

У меня есть разделенные задачи, которые я хочу повторно использовать в меньших ролях. В моей роли 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 как на внешнюю / восходящую роль в этом случае.

Привет, хороший вопрос. Я могу рассматривать Ansible как серию или пьесу, вызывающую роли (для меня роль - это многократно используемый и стандартный способ распространения кода Ansible). Импорт или включение ролей в другую роль - это не способ использования Ansible, IMHO. У нас есть мета для определения зависимостей ролей и сценарии для их оркестровки. По моему опыту работы с Ansible, я обнаружил, что эти роли с определенными переменными и вызовами других внешних ролей, игр, задач и т. д. Неуправляемы. Почему бы не делать из основного сценария?

imjoseangel 27.05.2018 22:45

Извините, но ответ, который вы уже прочитали, действителен, независимо от того, насколько он вам не нравится. Также вопросы о передовой практике считаются слишком общими / требуют мнений многими пользователями SO, поэтому постарайтесь задавать четко определенные вопросы по программированию.

techraf 28.05.2018 05:53

@techraf Я думаю, что ОП поднял веский вопрос. Кроме того, процитированному вопросу более двух лет, что само по себе дает основание искать альтернативы. Я не вижу необходимости торопиться с вашим комментарием.

jan groth 28.05.2018 06:46

@jangroth ① SO не для того, чтобы поднимать действительные баллы, а для того, чтобы задавать вопросы, как определено в Справочном центре и решено сообществом. ② На вопросы нет ограничения по времени, можно добавить ответ под 2-х лет. вопрос, если он у вас есть. ③ Я закрыл вопрос как дубликат и объяснил OP причину. Я не знаю, что в этом «резкого», почему вы почувствовали необходимость называть это так и чего вы хотели этим достичь.

techraf 28.05.2018 06:58

@techraf Существующий вопрос, который я уже включил в свой вопрос, очень ограничен, и это не значит, что мне просто не нравится ответ; Существующий ответ просто не является решением того, что я спрашиваю и подробно описал в этом вопросе. Во всяком случае, я немного обновил вопрос и больше не прошу best practices. Теперь более конкретно. Надеюсь, вы передумаете и снова откроете этот вопрос. Спасибо.

Vangelis Tasoulas 28.05.2018 19:00

Ответ (который хорошо написан и ни в коем случае не является «очень ограничен») для dup-target содержит простой и действительный ответ на ваш вопрос: Короткий ответ: это невозможно.. С вашими последующими правками («Не надо трогать код роли.») вам даже не нужно читать дальше.

techraf 28.05.2018 19:40

Что касается не следует трогать код роли, ответьте мне, пожалуйста, на один вопрос. Когда вы используете роли из ansible-galaxy, вы детализируете детали, вносите ли они изменения и пытаетесь сохранить свои собственные вилки ролей, которые вы используете? Звучит не очень интуитивно. Если кому-то приходится это делать, значит, что-то идет не так, и роли теряют свое значение. Это похоже на попытку использовать библиотеку, но перед ее использованием вам предлагается изменить код библиотеки. Дело не в том, что вы не можете этого сделать, но должен быть какой-то способ достичь того, чего вы хотите, изменив свой собственный код, а не код библиотеки.

Vangelis Tasoulas 28.05.2018 21:44

@VangelisTasoulas Это именно та проблема, с которой я столкнулся сейчас ... Есть обновления по этому поводу? По-прежнему невозможно запустить собственный обработчик при изменении задачи, произошедшей в рамках чьей-либо роли, используемой в игре?

Drew 31.10.2020 11:17

@Drew Я уже некоторое время серьезно не работаю с ansible, и у меня до сих пор нет решения этой проблемы :(

Vangelis Tasoulas 11.11.2020 00:09
Переменные, типы данных и операторы в Python
Переменные, типы данных и операторы в Python
В Python переменные используются как место для хранения значений. Пример переменной формы:
7
9
1 713
1

Ответы 1

Ты не сможешь это сделать. Вы должны понимать, что роли подобны функциям в других языках. Вы не можете полагаться на то, что происходит внутри.

Вот почему обработчики можно использовать только в текущем контексте, роли или сценарии, и вы не можете их перекрестно вызывать.

Другие вопросы по теме