Як написати обробник 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

Відповіді:


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: and rescue: для обробки помилок, запускаючи команди?
user1767316

3
Чи виконуються численні завдання в перерахованому порядку? Якщо одне завдання залежить від іншого, чи слід використовувати сповіщення-прослуховування всередині обробника?
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

У своєму файлі обробника об’єднайте різні кроки за допомогою функції сповіщення.

- 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. Я не впевнений, чи буде це працювати і надалі, оскільки це не згадується як особливість в офіційній документації.


Цей метод допомагає з фактом, про який, здається, мало літератури: обробники, отримавши повідомлення, будуть виконуватися, навіть якщо один із цих обробників не вдасться. Використання різних notifyміток для тих, кого ви, можливо, не захочете запускати, якщо попередній обробник не вдається, є хорошим способом «виправити» це, якщо ви не хочете, щоб це було так.
fbicknel

27

Редагувати: якщо у вас Ansible 2.2 або вище, використовуйте відповідь mkadan. Відповідь нижче не працює з новішими версіями Ansible. Також зверніть увагу, що згідно з коментарем Еніса Афгана нижче, через помилку ця відповідь не працює з версіями Ansible між 2.0.2 і 2.1.2.


Починаючи з Ansible 2.0, ви можете використовувати дію включення у своєму обробнику для запуску декількох завдань.

Наприклад, розмістіть свої завдання в окремому файлі 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.
Martin Melka

@MartinMelka дякую, я додав попередження у верхній частині моєї відповіді, що воно не призначене для версій Ansible> = 2.2.
Alexander Klauer

Чудово, дякую :) При розробці нових обробників, інша відповідь буде кращою. Але коли інвентарний код Ansible застарів і потрібно вносити лише невеликі зміни (як це робив я), ваш все одно може бути корисним завдяки цьому невеликому доповненню.
Martin Melka
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.