diff --git a/lib/ansible/plugins/strategy/__init__.py b/lib/ansible/plugins/strategy/__init__.py index 785c045240f..edb17ff8bd4 100644 --- a/lib/ansible/plugins/strategy/__init__.py +++ b/lib/ansible/plugins/strategy/__init__.py @@ -39,6 +39,7 @@ from ansible.inventory.group import Group from ansible.module_utils.facts import Facts from ansible.playbook.helpers import load_list_of_blocks from ansible.playbook.included_file import IncludedFile +from ansible.playbook.task_include import TaskInclude from ansible.plugins import action_loader, connection_loader, filter_loader, lookup_loader, module_loader, test_loader from ansible.template import Templar from ansible.utils.unicode import to_unicode @@ -344,21 +345,48 @@ class StrategyBase: continue return None + def parent_handler_match(target_handler, handler_name): + if target_handler: + if isinstance(target_handler, TaskInclude): + try: + handler_vars = self._variable_manager.get_vars(loader=self._loader, play=iterator._play, task=target_handler) + templar = Templar(loader=self._loader, variables=handler_vars) + target_handler_name = templar.template(target_handler.name) + if target_handler_name == handler_name: + return True + else: + target_handler_name = templar.template(target_handler.get_name()) + if target_handler_name == handler_name: + return True + except (UndefinedError, AnsibleUndefinedVariable) as e: + pass + return parent_handler_match(target_handler._task_include, handler_name) + else: + return False + # Find the handler using the above helper. First we look up the # dependency chain of the current task (if it's from a role), otherwise # we just look through the list of handlers in the current play/all # roles and use the first one that matches the notify name target_handler = search_handler_blocks(iterator._play.handlers) - if target_handler is None: - raise AnsibleError("The requested handler '%s' was not found in any of the known handlers" % handler_name) - - if target_handler in self._notified_handlers: + if target_handler is not None: if original_host not in self._notified_handlers[target_handler]: self._notified_handlers[target_handler].append(original_host) # FIXME: should this be a callback? display.vv("NOTIFIED HANDLER %s" % (handler_name,)) else: - raise AnsibleError("The requested handler '%s' was not found in the main handlers list" % handler_name) + # As there may be more than one handler with the notified name as the + # parent, so we just keep track of whether or not we found one at all + found = False + for target_handler in self._notified_handlers: + if parent_handler_match(target_handler, handler_name): + self._notified_handlers[target_handler].append(original_host) + display.vv("NOTIFIED HANDLER %s" % (target_handler.get_name(),)) + found = True + + # and if none were found, then we raise an error + if not found: + raise AnsibleError("The requested handler '%s' was not found in the main handlers list" % handler_name) elif result[0] == 'register_host_var': # essentially the same as 'set_host_var' below, however we diff --git a/lib/ansible/vars/__init__.py b/lib/ansible/vars/__init__.py index c88b41aefcf..5ecc35339e2 100644 --- a/lib/ansible/vars/__init__.py +++ b/lib/ansible/vars/__init__.py @@ -236,7 +236,10 @@ class VariableManager: # sure it sees its defaults above any other roles, as we previously # (v1) made sure each task had a copy of its roles default vars if task and task._role is not None: - all_vars = combine_vars(all_vars, task._role.get_default_vars(dep_chain=task._block.get_dep_chain())) + dep_chain = [] + if task._block: + dep_chain = task._block.get_dep_chain() + all_vars = combine_vars(all_vars, task._role.get_default_vars(dep_chain=dep_chain)) if host: # next, if a host is specified, we load any vars from group_vars @@ -333,7 +336,10 @@ class VariableManager: # vars (which will look at parent blocks/task includes) if task: if task._role: - all_vars = combine_vars(all_vars, task._role.get_vars(task._block._dep_chain, include_params=False)) + dep_chain = [] + if task._block: + dep_chain = task._block.get_dep_chain() + all_vars = combine_vars(all_vars, task._role.get_vars(dep_chain=dep_chain, include_params=False)) all_vars = combine_vars(all_vars, task.get_vars()) # next, we merge in the vars cache (include vars) and nonpersistent @@ -345,7 +351,10 @@ class VariableManager: # next, we merge in role params and task include params if task: if task._role: - all_vars = combine_vars(all_vars, task._role.get_role_params(task._block.get_dep_chain())) + dep_chain = [] + if task._block: + dep_chain = task._block.get_dep_chain() + all_vars = combine_vars(all_vars, task._role.get_role_params(dep_chain=dep_chain)) # special case for include tasks, where the include params # may be specified in the vars field for the task, which should