diff --git a/lib/ansible/executor/play_iterator.py b/lib/ansible/executor/play_iterator.py index f015c28db8d..27b0afd5db3 100644 --- a/lib/ansible/executor/play_iterator.py +++ b/lib/ansible/executor/play_iterator.py @@ -109,7 +109,7 @@ class PlayIterator: FAILED_RESCUE = 4 FAILED_ALWAYS = 8 - def __init__(self, inventory, play, play_context, variable_manager, all_vars): + def __init__(self, inventory, play, play_context, variable_manager, all_vars, start_at_done=False): self._play = play self._blocks = [] @@ -127,12 +127,16 @@ class PlayIterator: host._gathered_facts = True # if we're looking to start at a specific task, iterate through # the tasks for this host until we find the specified task - if play_context.start_at_task is not None: + if play_context.start_at_task is not None and not start_at_done: while True: (s, task) = self.get_next_task_for_host(host, peek=True) if s.run_state == self.ITERATING_COMPLETE: break if task.name == play_context.start_at_task or fnmatch.fnmatch(task.name, play_context.start_at_task): + # we have our match, so clear the start_at_task field on the + # play context to flag that we've started at a task (and future + # plays won't try to advance) + play_context.start_at_task = None break else: self.get_next_task_for_host(host) diff --git a/lib/ansible/executor/task_queue_manager.py b/lib/ansible/executor/task_queue_manager.py index 0b6422218c3..087c2eb972f 100644 --- a/lib/ansible/executor/task_queue_manager.py +++ b/lib/ansible/executor/task_queue_manager.py @@ -62,6 +62,7 @@ class TaskQueueManager: self._callbacks_loaded = False self._callback_plugins = [] + self._start_at_done = False # make sure the module path (if specified) is parsed and # added to the module_loader object @@ -203,8 +204,15 @@ class TaskQueueManager: play_context=play_context, variable_manager=self._variable_manager, all_vars=all_vars, + start_at_done = self._start_at_done, ) + # during initialization, the PlayContext will clear the start_at_task + # field to signal that a matching task was found, so check that here + # and remember it so we don't try to skip tasks on future plays + if self._options.start_at_task is not None and play_context.start_at_task is None: + self._start_at_done = True + # and run the play using the strategy return strategy.run(iterator, play_context)