11

I would like to notify a handler in my role by doing something like this:

- name: Notify handler
  notify: my_handler
  when: this_thing_is_true|bool

But Ansible just whines:

ERROR! no module/action detected in task.

I have tried various wedges, such as:

- name: Notify handler
  meta: noop
  notify: my_handler
  when: this_thing_is_true|bool

But that similarly whines:

[WARNING]: noop task does not support when conditional

Any suggestions?

fbicknel
  • 1,219
  • 13
  • 21

3 Answers3

13

@β.εηοιτ.βε shows a solution that prefers debug, but I think that the output from assert is cleaner.

debug code:

- name: with debug
  debug: msg=''
  changed_when: true
  when: something is changed
  notify: 'do stuff'

assert code:

- name: with assert
  assert: { that: true, quiet: true }
  changed_when: true
  when: something is changed
  notify: 'do stuff'

debug output:

TASK [mytask : with debug] *****************************************************
changed: [server] => {
    "msg": ""
}

RUNNING HANDLER [mytask : do stuff] ********************************************
changed: [server]

assert output (seems cleaner):

TASK [mytask : with assert] ****************************************************
changed: [server]

RUNNING HANDLER [myhandlers : do stuff] ****************************************
changed: [server]
lonix
  • 14,255
  • 23
  • 85
  • 176
9

Please mind that running a task is not enough for an handler to be notified, you also need a task that creates a changed result.

You can achieve a change result on any task with the help of the changed_when option in Ansible.
Then, doing a simple debug could be an option.

The other ideas I had, but that did not really made sense in the end:

  • pause: but you cannot pause for less than a second
  • assert: but it feels silly to assert the same condition that you also need to put in the changed_that to notify the handler. You can still assert: that=true but it feels equally silly.
  • Maybe the most silliest of the ideas I could came with was a fail task with a failed_when: false.
  • command: 'true' is maybe less silly, compared to the above, but I am not totally convinced, still

Given the playbook:

- hosts: localhost
  gather_facts: no
  vars:
    this_thing_is_true: true

  tasks:
    - debug:
        msg: 'Notifying handlers'
        # var: this_thing_is_true 
        # ^-- might be an alternative option to msg:
      changed_when: this_thing_is_true  
      notify: 
        - me 

  handlers:
    - name: me
      debug:
        msg: 'I have been notified'

Gives the recap:

PLAY [localhost] **************************************************

TASK [debug] ******************************************************
changed: [localhost] => 
  msg: Notifying handlers

RUNNING HANDLER [me] **********************************************
ok: [localhost] => 
  msg: I have been notified 
β.εηοιτ.βε
  • 33,893
  • 13
  • 69
  • 83
  • 1
    Thanks for the edit and the solution. Meta: Did not know I could add `yaml` after the ``` and get syntax highlighting. Topic: Yeah, now that you mention it, the root cause must have been there was no way the task could determine if it produced a changed condition or not. – fbicknel Jun 04 '20 at 13:14
  • Agreed `assert` doesn't "feel right", but on the other hand the output is cleaner, see my answer below. – lonix Mar 19 '21 at 13:20
1

I learnt from both the given answers here. On top of that I was curious about why can't you always trigger a change for the sake of notify, then use a statement with it. After some testing it turns out you can! \o/

- debug:
    msg: Deciding what to do
  changed_when: true
  notify: "{{ ( res.json == [] ) | ternary( 'on empty object', 'on object exist'  ) }}"

Calls handler "on empty object" if true, otherwise "on object exist"

MetalGodwin
  • 3,784
  • 2
  • 17
  • 14