Как написать обработчик Ansible с несколькими задачами?

81

В ответ на изменение у меня есть несколько связанных задач, которые нужно выполнить. Как написать обработчик Ansible с несколькими задачами?

Например, мне нужен обработчик, который перезапускает службу, только если она уже запущена:

- name: Restart conditionally
  shell: check_is_started.sh
  register: result

- name: Restart conditionally step 2
  service: name=service state=restarted
  when: result
Timdiels
источник

Ответы:

95

Правильное решение этой проблемы есть в версии Ansible 2.2.

обработчики также могут «слушать» общие темы, а задачи могут уведомлять эти темы следующим образом:

handlers:
    - name: restart memcached
      service: name=memcached state=restarted
      listen: "restart web services"
    - name: restart apache
      service: name=apache state=restarted
      listen: "restart web services"

tasks:
    - name: restart everything
      command: echo "this task will restart the web services"
      notify: "restart web services"

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

В частности, на вопрос, это должно работать:

- name: Check if restarted
  shell: check_is_started.sh
  register: result
  listen: Restart processes

- name: Restart conditionally step 2
  service: name=service state=restarted
  when: result
  listen: Restart processes

и в задаче уведомить обработчиков через «Перезапустить процессы»

http://docs.ansible.com/ansible/playbooks_intro.html#handlers-running-operations-on-change

Мкадан
источник
1
Разрешит ли это решение использовать block: и rescue: для обработки ошибок путем запуска команд?
user1767316 01
3
Выполняются ли несколько задач в указанном порядке? Если одна задача зависит от другой задачи, следует ли мне использовать notify-listen внутри обработчика?
user26767
@ user26767 из связанной документации:Notify handlers are always run in the same order they are defined, not in the order listed in the notify-statement. This is also the case for handlers using listen.
swenzel
55

В файле обработчика объедините различные шаги вместе с помощью notify.

- name: Restart conditionally
  debug: msg=Step1
  changed_when: True
  notify: Restart conditionally step 2

- name: Restart conditionally step 2
  debug: msg=Step2
  changed_when: True
  notify: Restart conditionally step 3

- name: Restart conditionally step 3
  debug: msg=Step3

Затем обратитесь к нему из задачи с помощью notify: Restart conditionally.

Обратите внимание, что вы можете уведомлять только обработчики ниже текущего. Так, например, Restart conditionally step 2не могу уведомить Restart conditionally.

Источник: #ansible на irc.freenode.net. Я не уверен, будет ли это работать в будущем, поскольку это не упоминается как функция в официальной документации.

Timdiels
источник
Этот метод помогает с фактом, по которому, кажется, мало литературы: обработчики после уведомления будут выполняться, даже если один из этих обработчиков выйдет из строя. Использование разных notifyметок для тех, которые вы, возможно, не захотите запускать в случае сбоя предыдущего обработчика, - хороший способ «исправить» это, если вы этого не хотите.
fbicknel
27

Изменить: если у вас есть Ansible 2.2 или выше, используйте ответ mkadan. Приведенный ниже ответ не работает с более новыми версиями Ansible. Также обратите внимание, что, согласно приведенному ниже комментарию Эниса Афган, из-за ошибки этот ответ не работает с версиями Ansible между 2.0.2 и 2.1.2.


Начиная с Ansible 2.0, вы можете использовать действие include в своем обработчике для выполнения нескольких задач.

Например, поместите свои задачи в отдельный файл restart_tasks.yml(если вы используете роли, они будут идти в подкаталог задач, а не в подкаталоге обработчиков):

- name: Restart conditionally step 1
  shell: check_is_started.sh
  register: result

- name: Restart conditionally step 2
  service: name=service state=restarted
  when: result

Тогда ваш обработчик будет просто:

- name: Restart conditionally
  include: restart_tasks.yml

Источник: тема выпуска на github: https://github.com/ansible/ansible/issues/14270

Александр Клауэр
источник
5
Обратите внимание, что в версиях Ansible между 2.0.2 и 2.1.2 есть ошибка, из-за которой это не работает: github.com/ansible/ansible/issues/15915
Энис Афган,
1
Для будущих читателей - у меня это не сработало на Ansible 2.9.2. Исправление заменялось includeна include_tasks.
Мартин Мелка
@MartinMelka, спасибо, я добавил предупреждение вверху своего ответа, что оно не предназначено для версий Ansible> = 2.2.
Александр Клауэр
Отлично, спасибо :) При разработке новых обработчиков лучше использовать другой ответ. Но когда инвентарный код Ansible устарел и нужно внести только небольшие изменения (как я), ваш код все еще может быть полезен с этим небольшим дополнением.
Мартин Мелка