Allow handlers to run in between pre_tasks, roles, tasks, and post_tasks.

pull/2730/head
Michael DeHaan 12 years ago
parent 84781bf185
commit 32fb6c807c

@ -496,15 +496,35 @@ class PlayBook(object):
self.inventory.also_restrict_to(on_hosts)
for task in play.tasks():
if task.meta is not None:
# meta tasks are an internalism and are not valid for end-user playbook usage
# here a meta task is a placeholder that signals handlers should be run
if task.meta == 'flush_handlers':
for handler in play.handlers():
if len(handler.notified_by) > 0:
self.inventory.restrict_to(handler.notified_by)
self._run_task(play, handler, True)
self.inventory.lift_restriction()
for host in handler.notified_by:
handler.notified_by.remove(host)
continue
hosts_count = len(self._list_available_hosts(play.hosts))
# only run the task if the requested tags match
should_run = False
for x in self.only_tags:
for y in task.tags:
if (x==y):
should_run = True
break
if should_run:
if not self._run_task(play, task, False):
# whether no hosts matched is fatal or not depends if it was on the initial step.
@ -523,12 +543,13 @@ class PlayBook(object):
return False
# run notify actions
for handler in play.handlers():
if len(handler.notified_by) > 0:
self.inventory.restrict_to(handler.notified_by)
self._run_task(play, handler, True)
self.inventory.lift_restriction()
handler.notified_by = []
#for handler in play.handlers():
# if len(handler.notified_by) > 0:
# self.inventory.restrict_to(handler.notified_by)
# self._run_task(play, handler, True)
# self.inventory.lift_restriction()
# handler.notified_by = []
# handler.notified_by = []
self.inventory.lift_also_restriction()

@ -127,7 +127,7 @@ class Play(object):
# and it auto-extends tasks/handlers/vars_files as appropriate if found
if roles is None:
return ds
roles = []
if type(roles) != list:
raise errors.AnsibleError("value of 'roles:' must be a list")
@ -140,6 +140,7 @@ class Play(object):
pre_tasks = []
for x in pre_tasks:
new_tasks.append(x)
new_tasks.append(dict(meta='flush_handlers'))
# variables if the role was parameterized (i.e. given as a hash)
has_dict = {}
@ -200,8 +201,11 @@ class Play(object):
if type(post_tasks) != list:
post_tasks = []
new_tasks.append(dict(meta='flush_handlers'))
new_tasks.extend(tasks)
new_tasks.append(dict(meta='flush_handlers'))
new_tasks.extend(post_tasks)
new_tasks.append(dict(meta='flush_handlers'))
new_handlers.extend(handlers)
new_vars_files.extend(vars_files)
ds['tasks'] = new_tasks
@ -223,6 +227,12 @@ class Play(object):
for x in tasks:
if not isinstance(x, dict):
raise errors.AnsibleError("expecting dict; got: %s" % x)
if 'meta' in x:
if x['meta'] == 'flush_handlers':
results.append(Task(self,x))
continue
task_vars = self.vars.copy()
task_vars.update(vars)
if original_file:
@ -369,6 +379,7 @@ class Play(object):
# gather all the tags in all the tasks into one list
all_tags = []
for task in self._tasks:
if not task.meta:
all_tags.extend(task.tags)
# compare the lists of tags using sets and return the matched and unmatched

@ -22,7 +22,7 @@ import ansible.utils.template as template
class Task(object):
__slots__ = [
'name', 'action', 'only_if', 'when', 'async_seconds', 'async_poll_interval',
'name', 'meta', 'action', 'only_if', 'when', 'async_seconds', 'async_poll_interval',
'notify', 'module_name', 'module_args', 'module_vars',
'play', 'notified_by', 'tags', 'register',
'delegate_to', 'first_available_file', 'ignore_errors',
@ -33,7 +33,7 @@ class Task(object):
# to prevent typos and such
VALID_KEYS = [
'name', 'action', 'only_if', 'async', 'poll', 'notify',
'name', 'meta', 'action', 'only_if', 'async', 'poll', 'notify',
'first_available_file', 'include', 'tags', 'register', 'ignore_errors',
'delegate_to', 'local_action', 'transport', 'sudo', 'sudo_user',
'sudo_pass', 'when', 'connection', 'environment', 'args',
@ -43,6 +43,15 @@ class Task(object):
def __init__(self, play, ds, module_vars=None, additional_conditions=None):
''' constructor loads from a task or handler datastructure '''
# meta directives are used to tell things like ansible/playbook to run
# operations like handler execution. Meta tasks are not executed
# normally.
if 'meta' in ds:
self.meta = ds['meta']
return
else:
self.meta = None
for x in ds.keys():
# code to allow for saying "modulename: args" versus "action: modulename args"

Loading…
Cancel
Save