diff --git a/changelogs/fragments/82363-multiple-handlers-with-recursive-notification.yml b/changelogs/fragments/82363-multiple-handlers-with-recursive-notification.yml new file mode 100644 index 00000000000..92bd37b486e --- /dev/null +++ b/changelogs/fragments/82363-multiple-handlers-with-recursive-notification.yml @@ -0,0 +1,2 @@ +bugfixes: + - Run all handlers with the same ``listen`` topic, even when notified from another handler (https://github.com/ansible/ansible/issues/82363). diff --git a/lib/ansible/plugins/strategy/__init__.py b/lib/ansible/plugins/strategy/__init__.py index 0d056b92013..4c5e352b17e 100644 --- a/lib/ansible/plugins/strategy/__init__.py +++ b/lib/ansible/plugins/strategy/__init__.py @@ -53,6 +53,7 @@ from ansible.template import Templar from ansible.utils.display import Display from ansible.utils.fqcn import add_internal_fqcns from ansible.utils.unsafe_proxy import wrap_var +from ansible.utils.sentinel import Sentinel from ansible.utils.vars import combine_vars, isidentifier from ansible.vars.clean import strip_internal_keys, module_response_deepcopy @@ -656,6 +657,7 @@ class StrategyBase: # otherwise depending on the setting either error or warn host_state = iterator.get_state_for_host(original_host.name) for notification in result_item['_ansible_notify']: + handler = Sentinel for handler in self.search_handlers_by_notification(notification, iterator): if host_state.run_state == IteratingStates.HANDLERS: # we're currently iterating handlers, so we need to expand this now @@ -666,8 +668,8 @@ class StrategyBase: else: iterator.add_notification(original_host.name, notification) display.vv(f"Notification for handler {notification} has been saved.") - break - else: + break + if handler is Sentinel: msg = ( f"The requested handler '{notification}' was not found in either the main handlers" " list nor in the listening handlers list" diff --git a/test/integration/targets/handlers/runme.sh b/test/integration/targets/handlers/runme.sh index 613fa4a8185..1381878c4e2 100755 --- a/test/integration/targets/handlers/runme.sh +++ b/test/integration/targets/handlers/runme.sh @@ -69,6 +69,9 @@ done # Notify handler listen ansible-playbook test_handlers_listen.yml -i inventory.handlers -v "$@" +# https://github.com/ansible/ansible/issues/82363 +ansible-playbook test_multiple_handlers_with_recursive_notification.yml -i inventory.handlers -v "$@" + # Notify inexistent handlers results in error set +e result="$(ansible-playbook test_handlers_inexistent_notify.yml -i inventory.handlers "$@" 2>&1)" diff --git a/test/integration/targets/handlers/test_multiple_handlers_with_recursive_notification.yml b/test/integration/targets/handlers/test_multiple_handlers_with_recursive_notification.yml new file mode 100644 index 00000000000..c4b698312ba --- /dev/null +++ b/test/integration/targets/handlers/test_multiple_handlers_with_recursive_notification.yml @@ -0,0 +1,36 @@ +--- +- name: test multiple handlers with recursive notification + hosts: localhost + gather_facts: false + + tasks: + - name: notify handler 1 + command: echo + changed_when: true + notify: handler 1 + + - meta: flush_handlers + + - name: verify handlers + assert: + that: + - "ran_handler_1 is defined" + - "ran_handler_2a is defined" + - "ran_handler_2b is defined" + + handlers: + - name: handler 1 + set_fact: + ran_handler_1: True + changed_when: true + notify: handler_2 + + - name: handler 2a + set_fact: + ran_handler_2a: True + listen: handler_2 + + - name: handler 2b + set_fact: + ran_handler_2b: True + listen: handler_2