Handle notifications when coupled with a loop

Fixes #11606
pull/11606/merge
James Cammarata 9 years ago
parent 319812542f
commit 5abdd3b821

@ -122,18 +122,6 @@ class ResultProcess(multiprocessing.Process):
elif result.is_skipped(): elif result.is_skipped():
self._send_result(('host_task_skipped', result)) self._send_result(('host_task_skipped', result))
else: else:
# if this task is notifying a handler, do it now
if result._task.notify and result._result.get('changed', False):
# The shared dictionary for notified handlers is a proxy, which
# does not detect when sub-objects within the proxy are modified.
# So, per the docs, we reassign the list so the proxy picks up and
# notifies all other threads
for notify in result._task.notify:
if result._task._role:
role_name = result._task._role.get_name()
notify = "%s : %s" %(role_name, notify)
self._send_result(('notify_handler', result._host, notify))
if result._task.loop: if result._task.loop:
# this task had a loop, and has more than one result, so # this task had a loop, and has more than one result, so
# loop over all of them instead of a single result # loop over all of them instead of a single result
@ -142,6 +130,20 @@ class ResultProcess(multiprocessing.Process):
result_items = [ result._result ] result_items = [ result._result ]
for result_item in result_items: for result_item in result_items:
# if this task is notifying a handler, do it now
if 'ansible_notify' in result_item and result.is_changed():
# The shared dictionary for notified handlers is a proxy, which
# does not detect when sub-objects within the proxy are modified.
# So, per the docs, we reassign the list so the proxy picks up and
# notifies all other threads
for notify in result_item['ansible_notify']:
if result._task._role:
role_name = result._task._role.get_name()
notify = "%s : %s" % (role_name, notify)
self._send_result(('notify_handler', result._host, notify))
# now remove the notify field from the results, as its no longer needed
result_item.pop('ansible_notify')
if 'add_host' in result_item: if 'add_host' in result_item:
# this task added a new host (add_host module) # this task added a new host (add_host module)
self._send_result(('add_host', result_item)) self._send_result(('add_host', result_item))

@ -330,6 +330,12 @@ class TaskExecutor:
if 'ansible_facts' in result: if 'ansible_facts' in result:
variables.update(result['ansible_facts']) variables.update(result['ansible_facts'])
# save the notification target in the result, if it was specified, as
# this task may be running in a loop in which case the notification
# may be item-specific, ie. "notify: service {{item}}"
if self._task.notify:
result['ansible_notify'] = self._task.notify
# and return # and return
debug("attempt loop complete, returning result") debug("attempt loop complete, returning result")
return result return result

@ -23,7 +23,13 @@ class ActionModule(ActionBase):
def run(self, tmp=None, task_vars=dict()): def run(self, tmp=None, task_vars=dict()):
#vv("REMOTE_MODULE %s %s" % (module_name, module_args), host=conn.host) results = self._execute_module(tmp, task_vars=task_vars)
return self._execute_module(tmp, task_vars=task_vars)
# Remove special fields from the result, which can only be set
# internally by the executor engine. We do this only here in
# the 'normal' action, as other action plugins may set this.
for field in ('ansible_facts', 'ansible_notify'):
if field in results:
results.pop(field)
return results

Loading…
Cancel
Save