handler not executing using when condition in task

445 Views Asked by At

I'm trying to set up an NFS share between two nodes using Ansible. I'm using the role nfs, which is executed by both nodes, and I separated client and server tasks using the when condition.

After templating the NFS /etc/exports on the server node I want to restart the NFS server using a handler, but the notify doesn't seem to work.

This is the task I'm using:

- name: Template NFS /etc/exports
  ansible.builtin.template:
    src: exports
    dest: /etc/exports
  notify:
  - Restart NFS server
  when: inventory_hostname == groups['nfs-servers'][0]

I tried to restart the nfs server using this handler:

- name: Restart NFS server
  ansible.builtin.systemd:
    name: nfs-kernel-server
    state: restarted

However, the handler never executes, even when exports is actually templated. I think that's because the task always results in changed = false for the client node (node2), due to the when condition. This is the output of the task:

TASK [nfs : Template NFS /etc/exports] 

skipping: [node2] => changed=false 
  skip_reason: Conditional result was False

changed: [node1] => changed=true 
  checksum: db864f9235e5afc0272896c4467e244d3b9c4147
  dest: /etc/exports
  gid: 0
  group: root
  md5sum: 447bf4f5557e3a020c40f4e729c90a62
  mode: '0644'
  owner: root
  size: 94
  src: /home/test/.ansible/tmp/ansible-tmp-1673949188.2970977-15410-64672518997352/source
  state: file
  uid: 0

Any suggestions on how to use when and notify together? Is there a way to make the notify ignore the skipping result?

Everything works fine if I use two roles and I remove the when condition.

1

There are 1 best solutions below

0
On BEST ANSWER

This is the expected behaviour, handlers are running operations on change, if there is no change, there will be no handler run.

So, you will have to trigger the handlers in a separate task in order to have the handler react to a change on another host. In this way of doing it, you will have to register the result of the template task in order to inspect its change state with the help of the hostsvar from other hosts.

This can be done with a changed state on any task you like, for example, a debug task.

From the task you are providing I also see some other improvements possible:

  1. Do not use a when in order to limit a task to a single host, prefer delegation and the use of run_once: true, which also offer the advantages that facts collected with run_once: true are propagated to all hosts, and avoid the need to use hostsvar.
  2. Watch out for warning, your actual group name, containing a dash, is raised by Ansible as problematic
    [WARNING]: Invalid characters were found in group names but not replaced, 
    use -vvvv to see details
    
    and in verbose mode:
    Not replacing invalid character(s) "{'-'}" in group name (nfs-servers)
    
    Use underscores instead of dashes.

So, with all this:

- hosts: nfs_servers
  gather_facts: no

  tasks:
    - name: Template NFS /etc/exports
      ansible.builtin.template:
        src: exports
        dest: /etc/exports
      delegate_to: "{{ groups.nfs_servers.0 }}"
      run_once: true
      register: templated_exports

    - name: Propagation of the change to notify handler
      ansible.builtin.debug:
        msg: Notify all handlers on /etc/exports change
      notify:
        - Restart NFS server
      changed_when: true
      when: templated_exports is changed

  handlers:
    - name: Restart NFS server
      ansible.builtin.debug:
        msg: Restarting NFS server now

When run with a file change:

PLAY [nfs_servers] *******************************************************

TASK [Template NFS /etc/exports] *****************************************
changed: [node1]

TASK [Propagation of the change to notify handler] ***********************
changed: [node1] => 
  msg: Notify all handlers on /etc/exports change
changed: [node2] => 
  msg: Notify all handlers on /etc/exports change

RUNNING HANDLER [Restart NFS server] *************************************
ok: [node1] => 
  msg: Restarting NFS server now
ok: [node2] => 
  msg: Restarting NFS server now

When run with no change:

PLAY [nfs_servers] *******************************************************

TASK [Template NFS /etc/exports] *****************************************
ok: [node1]

TASK [Propagation of the change to notify handler] ***********************
skipping: [node1]
skipping: [node2]