summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Cammarata <jimi@sngx.net>2016-07-06 14:40:11 -0500
committerJames Cammarata <jimi@sngx.net>2016-07-06 14:40:11 -0500
commit038012aeebc32a9aa1cbe075b081ba736eb98831 (patch)
tree7df907c1d65886ccbf46823405a885db4b0461a8
parent690bc192d5e535eba6174edbe4f98977abd9f271 (diff)
downloadansible-issue_15418.tar.gz
Fix the way handlers are compiled and found/notifiedissue_15418
* Instead of rebuilding the handler list all over the place, we now compile the handlers at the point the play is post-validated so that the view of the play in the PlayIterator contains the definitive list * Assign the dep_chain to the handlers as they're compiling, just as we do for regular tasks * Clean up the logic used to find a given handler, which is greatly simplified by the above changes Fixes #15418
-rw-r--r--lib/ansible/executor/task_queue_manager.py7
-rw-r--r--lib/ansible/playbook/play.py2
-rw-r--r--lib/ansible/playbook/role/__init__.py18
-rw-r--r--lib/ansible/plugins/strategy/__init__.py36
4 files changed, 33 insertions, 30 deletions
diff --git a/lib/ansible/executor/task_queue_manager.py b/lib/ansible/executor/task_queue_manager.py
index 58b1409d1b..8c09151f26 100644
--- a/lib/ansible/executor/task_queue_manager.py
+++ b/lib/ansible/executor/task_queue_manager.py
@@ -122,10 +122,6 @@ class TaskQueueManager:
inventory hostnames for those hosts triggering the handler.
'''
- handlers = play.handlers
- for role in play.roles:
- handlers.extend(role.get_handler_blocks())
-
# Zero the dictionary first by removing any entries there.
# Proxied dicts don't support iteritems, so we have to use keys()
self._notified_handlers.clear()
@@ -141,7 +137,7 @@ class TaskQueueManager:
return temp_list
handler_list = []
- for handler_block in handlers:
+ for handler_block in play.handlers:
handler_list.extend(_process_block(handler_block))
# then initialize it with the given handler list
@@ -220,6 +216,7 @@ class TaskQueueManager:
new_play = play.copy()
new_play.post_validate(templar)
+ new_play.handlers = new_play.compile_roles_handlers() + new_play.handlers
self.hostvars = HostVars(
inventory=self._inventory,
diff --git a/lib/ansible/playbook/play.py b/lib/ansible/playbook/play.py
index a85ab7fe64..2031465eef 100644
--- a/lib/ansible/playbook/play.py
+++ b/lib/ansible/playbook/play.py
@@ -265,7 +265,7 @@ class Play(Base, Taggable, Become):
if len(self.roles) > 0:
for r in self.roles:
- block_list.extend(r.get_handler_blocks())
+ block_list.extend(r.get_handler_blocks(play=self))
return block_list
diff --git a/lib/ansible/playbook/role/__init__.py b/lib/ansible/playbook/role/__init__.py
index 6793feb343..3f1908c754 100644
--- a/lib/ansible/playbook/role/__init__.py
+++ b/lib/ansible/playbook/role/__init__.py
@@ -301,12 +301,24 @@ class Role(Base, Become, Conditional, Taggable):
def get_task_blocks(self):
return self._task_blocks[:]
- def get_handler_blocks(self):
+ def get_handler_blocks(self, play, dep_chain=None):
block_list = []
+
+ # update the dependency chain here
+ if dep_chain is None:
+ dep_chain = []
+ new_dep_chain = dep_chain + [self]
+
for dep in self.get_direct_dependencies():
- dep_blocks = dep.get_handler_blocks()
+ dep_blocks = dep.get_handler_blocks(play=play, dep_chain=new_dep_chain)
block_list.extend(dep_blocks)
- block_list.extend(self._handler_blocks)
+
+ for task_block in self._handler_blocks:
+ new_task_block = task_block.copy()
+ new_task_block._dep_chain = new_dep_chain
+ new_task_block._play = play
+ block_list.append(new_task_block)
+
return block_list
def has_run(self, host):
diff --git a/lib/ansible/plugins/strategy/__init__.py b/lib/ansible/plugins/strategy/__init__.py
index 8864d57736..d7441b0908 100644
--- a/lib/ansible/plugins/strategy/__init__.py
+++ b/lib/ansible/plugins/strategy/__init__.py
@@ -349,33 +349,27 @@ class StrategyBase:
# 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 = None
- if original_task._role:
- target_handler = search_handler_blocks(handler_name, original_task._role.get_handler_blocks())
- if target_handler is None:
- target_handler = search_handler_blocks(handler_name, iterator._play.handlers)
- if target_handler is None:
- if handler_name in self._listening_handlers:
- for listening_handler_name in self._listening_handlers[handler_name]:
- listening_handler = None
- if original_task._role:
- listening_handler = search_handler_blocks(listening_handler_name, original_task._role.get_handler_blocks())
- if listening_handler is None:
- listening_handler = search_handler_blocks(listening_handler_name, iterator._play.handlers)
- if listening_handler is None:
- raise AnsibleError("The requested handler listener '%s' was not found in any of the known handlers" % listening_handler_name)
-
- if original_host not in self._notified_handlers[listening_handler]:
- self._notified_handlers[listening_handler].append(original_host)
- display.vv("NOTIFIED HANDLER %s" % (listening_handler_name,))
- else:
- raise AnsibleError("The requested handler '%s' was found in neither the main handlers list nor the listening handlers list" % handler_name)
+ if handler_name in self._listening_handlers:
+ for listening_handler_name in self._listening_handlers[handler_name]:
+ listening_handler = search_handler_blocks(listening_handler_name, iterator._play.handlers)
+ if listening_handler is None:
+ raise AnsibleError("The requested handler listener '%s' was not found in any of the known handlers" % listening_handler_name)
+
+ if original_host not in self._notified_handlers[listening_handler]:
+ self._notified_handlers[listening_handler].append(original_host)
+ display.vv("NOTIFIED HANDLER %s" % (listening_handler_name,))
else:
+ target_handler = search_handler_blocks(handler_name, 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 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 found in neither the main handlers list nor the listening handlers list" % handler_name)
elif result[0] == 'register_host_var':
# essentially the same as 'set_host_var' below, however we