Giter Club home page Giter Club logo

Comments (10)

s-hertel avatar s-hertel commented on July 20, 2024 1

This looks like a duplicate of #81013 (comment) / #80925 (which has a porting guide entry, though it focuses on include_role). If the handler didn't have the listen keyword, it should have always behaved as it does now, but there was a bug where the search order was backwards for listen, which was fixed in #81358.

from ansible.

ansibot avatar ansibot commented on July 20, 2024

Files identified in the description:

None

If these files are incorrect, please update the component name section of the description or use the component bot command.

from ansible.

mkrizek avatar mkrizek commented on July 20, 2024

This is the documented behavior. Handlers are play scoped, last one with the same name wins; in this case the last one inserted into the play inherits when: inventory_hostname == "server-01" which is why it is only run on server-01.

from ansible.

MorphBonehunter avatar MorphBonehunter commented on July 20, 2024

Ok, maybe i didn't understand the docs right, but i can not see the fact that the handlers played scoped besides that all handlers are in global scope and handler definitions included later in the play with identical names overwrites one defined before.
The docs doesn't mention that conditional includes of roles defacto disable handler execution for all hosts which not match the condition as i mention in #83112 and which is also the reason for this issue.

As i also mentioned in the linked bug, this behavior changes over time as we do have an Debian 11 with ansible core 2.12.10 and there it works so this is some kind of regression, maybe with #77955.

We can workaround this with defining handlers per role which in fact do the same but with different names.

from ansible.

mkrizek avatar mkrizek commented on July 20, 2024

Ok, maybe i didn't understand the docs right, but i can not see the fact that the handlers played scoped besides that all handlers are in global scope and handler definitions included later in the play with identical names overwrites one defined before.

I feel like this is covered in https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_handlers.html#naming-handlers. But any suggestions on how to improve the docs are always welcome.

The docs doesn't mention that conditional includes of roles defacto disable handler execution for all hosts which not match the condition as i mention in #83112 and which is also the reason for this issue.

That is indeed not mentioned there but it is a general functionality in Ansible and not specific to handlers. Every task and handler within a role imported statically (either via roles: section or import_role) inherit the when conditional (and other keywords).

As i also mentioned in the linked bug, this behavior changes over time as we do have an Debian 11 with ansible core 2.12.10 and there it works so this is some kind of regression, maybe with #77955.

Please see the comment from @s-hertel above. It is not a regression but a fix for unintended behavior with an entry in the porting guide. Sorry this has caused your playbook to be incompatible a with newer ansible-core version, we try and list changes like this in a changelog and porting guide at least.

We can workaround this with defining handlers per role which in fact do the same but with different names.

You can target a handler from a specific role by using a special form of the handler name in notify, see Handler in roles in https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_handlers.html#handlers-in-roles.

Hope this helps.

from ansible.

MorphBonehunter avatar MorphBonehunter commented on July 20, 2024

Ok, maybe i didn't understand the docs right, but i can not see the fact that the handlers played scoped besides that all handlers are in global scope and handler definitions included later in the play with identical names overwrites one defined before.

I feel like this is covered in https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_handlers.html#naming-handlers. But any suggestions on how to improve the docs are always welcome.

Ok, i see what you mean, the docs are good on this point, but my problem is, that this was not my point 😄

The docs doesn't mention that conditional includes of roles defacto disable handler execution for all hosts which not match the condition as i mention in #83112 and which is also the reason for this issue.

That is indeed not mentioned there but it is a general functionality in Ansible and not specific to handlers. Every task and handler within a role imported statically (either via roles: section or import_role) inherit the when conditional (and other keywords).

Yes, that true, i was just convinced that this does not apply to handlers.

As i also mentioned in the linked bug, this behavior changes over time as we do have an Debian 11 with ansible core 2.12.10 and there it works so this is some kind of regression, maybe with #77955.

Please see the comment from @s-hertel above. It is not a regression but a fix for unintended behavior with an entry in the porting guide. Sorry this has caused your playbook to be incompatible a with newer ansible-core version, we try and list changes like this in a changelog and porting guide at least.

I've seen the porting guide but honestly i did not think about it which impact this has.
Maybe a good Idea to link to this from the handler documentation, could be helpful.

We can workaround this with defining handlers per role which in fact do the same but with different names.

You can target a handler from a specific role by using a special form of the handler name in notify, see Handler in roles in https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_handlers.html#handlers-in-roles.

This doesn't work for our case, because of the single source of handler definition.

Hope this helps.

The hint for the porting guide was a good one, a reminder to read this more carefully, so yes i think this helps.
So maybe it's time to rethink some of our "old" role concepts.

from ansible.

s-hertel avatar s-hertel commented on July 20, 2024

This doesn't work for our case, because of the single source of handler definition.

You said you work around this by defining handlers per role which do the same but have different names, but could name them the same and notify them as rolename : handlername.

Another fix is to use a - meta: flush_handlers task to flush the notifications before importing the handler again. The implicit flush doesn't happen per role.

Another option is to use dynamic roles (include_role) instead of static (roles:/import_role), since you can make the role inclusion itself conditional, rather than the imported tasks.

- name: Test playbook
  hosts: server-01,server-02
  tasks:
    - include_role:
        name: test_role_2
    - include_role:
        name: test_role_1
      when: 'inventory_hostname == "server-01"'

If using include_role/import_role, the handlers_from option would allow you to import handlers from an alternate file location just once, which would avoid the issue of having future role invocations re-include the handler.

from ansible.

MorphBonehunter avatar MorphBonehunter commented on July 20, 2024

This doesn't work for our case, because of the single source of handler definition.

You said you work around this by defining handlers per role which do the same but have different names, but could name them the same and notify them as rolename : handlername.

Yes, this also works.

Another fix is to use a - meta: flush_handlers task to flush the notifications before importing the handler again. The implicit flush doesn't happen per role.

Unfortunately this doesn't work.
I tried this in my minimal example in #83112 and as you can see the flush handler in role one isn't executed because of the condition of role two even bevor role two is executed.

Another option is to use dynamic roles (include_role) instead of static (roles:/import_role), since you can make the role inclusion itself conditional, rather than the imported tasks.

- name: Test playbook
  hosts: server-01,server-02
  tasks:
    - include_role:
        name: test_role_2
    - include_role:
        name: test_role_1
      when: 'inventory_hostname == "server-01"'

If using include_role/import_role, the handlers_from option would allow you to import handlers from an alternate file location just once, which would avoid the issue of having future role invocations re-include the handler.

I think we should generaly consider this as this could also speed up things.

from ansible.

s-hertel avatar s-hertel commented on July 20, 2024

@MorphBonehunter Ah, sorry, I didn't look closely at #83112, these options could work for OPs reproducer. It looks like #83112 is due to #78661 (the underlying cause of this one too).

One more option could be using a variable in the handler name. The tricky part is not all variable sources are available during task-preprocessing, so you'd need to use a variable type with high enough precedence, like role parameters (#20 on https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html#understanding-variable-precedence).

# roles/dep/handlers/main.yml 
- name: Debug output dep {{ handler_id }}
  ansible.builtin.debug:
    msg: "Debug output dep"
  listen: Debug output dep

Role parameters can be set in the playbook or a role's meta/main.yml for dependencies like this:

# debug.yml
- name: Testcase
  gather_facts: false
  hosts: localhost
  vars:
    r_enable: false
  roles:
    - role: one
      handler_id: 1  # this is a role param
    - role: two
      when: r_enable
# roles/two/meta/main.yml
dependencies:
  - role: dep
    handler_id: 2  # this is also a role param

from ansible.

mkrizek avatar mkrizek commented on July 20, 2024

Closing as a duplicate of #80925.

If you have further questions please stop by IRC or the mailing list:

See this page for a complete and up to date list of communication channels and their purposes:

from ansible.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.