Ansible: Handlers

Handlers in Ansible provide another type of conditional execution. They define a task or tasks whose execution is dependent upon the completion status of the play.

For instance, it is a good practice to define an idle timeout limit on ssh sessions. Configuring idle timeout for the ssh daemon requires setting a limit in seconds in its configuration file. Ansible’s lineinfile module is capable of making this change to the configuration file but the daemon still must be restarted before the setting will take effect. This provides an perfect use case for a handler.

The following playbook uses a handler to signal to Ansible engine that a task which restarts the ssh daemon should be executed after the daemon’s configuration file is altered.

- name: Set SSHD idle session timeout limit
  hosts: all
  - name: Set client alive interval to 10 minutes (600s)
      path: /etc/ssh/sshd_config
      state: present
      insertafter: '^#ClientAliveInterval'
      line: ClientAliveInterval 600
      backup: True
    notify: restart_sshd
  - name: restart_sshd
      name: sshd
      state: restarted

Notice that the notify keyword is used at the task level to trigger tasks defined in the handlers section. Also note that the handler task name must exactly match the argument provided with the notify keyword.

An ansible play typically returns one of three completion statuses to the management node. These are ok, changed, and failed. As you might guess, a return value of changed indicates that a play ran and succeeded at making some changes to the target managed host, while failed indicates a change was attempted but unsuccessful. Because Ansible always attempts to maintain idempotency a third completion status is necessary. For this reason the ok status exists to indicate that a play ran but did not need to change anything. It is important to make this distinction here because handlers will not be triggered for plays returning ok or failed statuses. Handlers will only be triggered to run when the play returns a changed status.

When considering these three play completion statuses it is possible to imagine a case in which one of several tasks defined in a play encounters a failure condition. By default this would mean that the related handlers would not be triggered. When defining a play whose handlers are required to run even in the event of a task causing the play’s completion status to return failed it is possible to use the more general ignore_errors: true, and/or the more specific force_handlers: true construction to guarantee that handlers will be triggered upon the play’s completion.

- name: Demo force_handlers
  hosts: all
  force_handlers: True
  ignore_errors: True
  - name: Define a task which will fail
      src: /tmp/nothing
      dest: /tmp/nowhere
  - name: Define a task which will succeed
      content: "This task will succeed!"
      dest: /tmp/msg
    notify: print_completion_message
  - name: print_completion_message
      msg: "Task complete! Running handler!"


Happy Independence Day, USA!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.