Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I write an Ansible handler with multiple tasks?

In response to a change, I have multiple related tasks that should run. How do I write an Ansible handler with multiple tasks?

For example, I would like a handler that restarts a service only if already started:

- name: Restart conditionally   shell: check_is_started.sh   register: result  - name: Restart conditionally step 2   service: name=service state=restarted   when: result 
like image 355
Tim Diels Avatar asked Jul 24 '15 20:07

Tim Diels


People also ask

How do I run multiple tasks in Ansible?

If you want to run multiple tasks in a playbook concurrently, use async with poll set to 0. When you set poll: 0 , Ansible starts the task and immediately moves on to the next task without waiting for a result. Each async task runs until it either completes, fails or times out (runs longer than its async value).

What are handlers used for in Ansible and how is it different from tasks?

In a nutshell, handlers are special tasks that only get executed when triggered via the notify directive. Handlers are executed at the end of the play, once all tasks are finished. In Ansible, handlers are typically used to start, reload, restart, and stop services.

Can an Ansible handler notify another handler?

Notifying the same handler multiple times will result in executing the handler only once regardless of how many tasks notify it. For example, if multiple tasks update a configuration file and notify a handler to restart Apache, Ansible only bounces Apache once to avoid unnecessary restarts.


2 Answers

There is proper solution to this problem as of Ansible 2.2.

handlers can also “listen” to generic topics, and tasks can notify those topics as follows:

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" 

This use makes it much easier to trigger multiple handlers. It also decouples handlers from their names, making it easier to share handlers among playbooks and roles

Specifically to the question, this should work:

- 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 

and in the task, notify handlers via 'Restart processes'

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

like image 171
mkadan Avatar answered Sep 28 '22 04:09

mkadan


In your handler file, chain the different steps together using 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 

Then refer to it from a task with notify: Restart conditionally.

Note that you can only notify to handlers below the current one. So for example, Restart conditionally step 2 can't notify Restart conditionally.

Source: #ansible at irc.freenode.net. I'm unsure whether this will continue to work in the future as it's not mentioned as a feature in the official documentation.

like image 29
Tim Diels Avatar answered Sep 28 '22 05:09

Tim Diels