Ansible Playbook: Execute Specific Tasks Based on Task Status

Ansible Playbook: Execute Specific Tasks Based on Task Status

Using Handlers

First, let’s take an example of using Ansible to modify the SSH service configuration file and restart the service. The following Playbook can achieve this functionality:

- name: set sshd conf
  ansible.builtin.lineinfile:
    path: /etc/ssh/sshd_config
    backrefs: true
    regexp: "^#?\\s*PermitRootLogin"
    line: PermitRootLogin yes
- name: restart ssh
  ansible.builtin.systemd:
    name: sshd
    state: restarted
    enabled: true

In this Playbook, the SSH service is restarted every time it is executed. Although this achieves the desired result, it does not comply with Ansible’s idempotency rules.

To address this issue, Ansible can execute specific tasks when certain tasks are in a <span>changed</span> state. Ansible implements this functionality through the following three fields:

  • <span>notify</span>: Specifies which tasks trigger specific tasks when in a <span>changed</span> state
  • <span>handlers</span>: Specifies tasks that can be triggered by <span>notify</span>
  • <span>listen</span>: Used to listen for <span>notify</span>

Below is an optimized Playbook:

- name: set sshd conf
  ansible.builtin.lineinfile:
    path: /etc/ssh/sshd_config
    backrefs: true
    regexp: "^#?\\s*PermitRootLogin"
    line: PermitRootLogin yes
  notify: restart sshd
handlers:
- name: restart ssh
  ansible.builtin.systemd:
    name: sshd
    state: restarted
    enabled: true
  listen: restart sshd

Here we can see:

  • • The Play that sets the SSH configuration file has a <span>notify</span> entry of <span>restart sshd</span>, indicating that there is a notification for <span>restart sshd</span>
  • • There is a Play under <span>handlers</span> to restart the SSHD service
  • • There is a <span>listen</span> entry of <span>restart sshd</span>, which corresponds to the previous <span>notify</span>

The functionality implemented by these three fields is that when the SSH configuration file is modified, the SSHD service is restarted. If no modification occurs, the Play to restart the SSHD service will not execute.

[root@study ansible]# ansible-playbook /tmp/test.yml

PLAY [test handlers] **********************************************************************************************************************************************

TASK [set sshd conf] **********************************************************************************************************************************************
ok: [servera]

TASK [restart ssh] ************************************************************************************************************************************************
changed: [servera]

PLAY RECAP ********************************************************************************************************************************************************
servera                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
[root@study ansible]# ansible-playbook test.yml

PLAY [test handlers] **********************************************************************************************************************************************

TASK [set sshd conf] **********************************************************************************************************************************************
ok: [servera]

PLAY RECAP ********************************************************************************************************************************************************
servera                    : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

If there is only one Play that <span>notify</span> triggers, then <span>listen</span> can be omitted; it is sufficient for the <span>notify</span> content to correspond with the <span>name</span> of the Play in <span>handlers</span>.

If <span>notify</span> is used in conjunction with <span>loop</span>, when a <span>changed</span> occurs, all triggerable <span>handlers</span> Plays will be executed.

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_handlers.html#notifying-and-loops

When multiple tasks trigger the same <span>handlers</span> Play, the Play will only execute once.

<span>handlers</span> containing static imports or dynamic imports will behave differently; static imports support notifying the imported Play individually, while dynamic imports will execute all tasks when notified.

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_handlers.html#includes-and-imports-in-handlers

Setting Handlers Task Trigger Timing

By default, <span>handlers</span> Plays will execute only after all <span>tasks</span> have completed. By using <span>meta: flush_handlers</span>, you can make the <span>handlers</span> Play execute earlier:

- name: set sshd conf
  ansible.builtin.lineinfile:
    path: /etc/ssh/sshd_config
    backrefs: true
    regexp: "^#?\\s*PermitRootLogin"
    line: PermitRootLogin yes
  notify: restart sshd
- name: Flush handlers
  meta: flush_handlers
- name: debug
  ansible.builtin.debug:
    msg: "Hello World!"
handlers:
- name: restart ssh
  ansible.builtin.systemd:
    name: sshd
    state: restarted
    enabled: true
  listen: restart sshd

In this Playbook, the Play to restart the service will execute before the debug task.

[root@study ansible]# ansible-playbook test.yml

PLAY [test handlers] **********************************************************************************************************************************************

TASK [set sshd conf] **********************************************************************************************************************************************
changed: [servera]

TASK [Flush handlers] *********************************************************************************************************************************************

RUNNING HANDLER [restart ssh] *************************************************************************************************************************************
changed: [servera]

TASK [debug] ******************************************************************************************************************************************************
ok: [servera] =&gt; {
    "msg": "Hello World!"
}

PLAY RECAP ********************************************************************************************************************************************************
servera                    : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Leave a Comment