diff --git a/lib/ansible/plugins/strategy/__init__.py b/lib/ansible/plugins/strategy/__init__.py index 4c081d1c41..4099d8d963 100644 --- a/lib/ansible/plugins/strategy/__init__.py +++ b/lib/ansible/plugins/strategy/__init__.py @@ -750,6 +750,20 @@ class StrategyBase: return changed + def _copy_included_file(self, included_file): + ''' + A proven safe and performant way to create a copy of an included file + ''' + ti_copy = included_file._task.copy(exclude_parent=True) + ti_copy._parent = included_file._task._parent + + temp_vars = ti_copy.vars.copy() + temp_vars.update(included_file._args) + + ti_copy.vars = temp_vars + + return ti_copy + def _load_included_file(self, included_file, iterator, is_handler=False): ''' Loads an included YAML file of tasks, applying the optional set of variables. @@ -763,10 +777,7 @@ class StrategyBase: elif not isinstance(data, list): raise AnsibleError("included task files must contain a list of tasks") - ti_copy = included_file._task.copy(exclude_parent=True) - ti_copy._parent = included_file._task._parent - temp_vars = ti_copy.vars.copy() - temp_vars.update(included_file._args) + ti_copy = self._copy_included_file(included_file) # pop tags out of the include args, if they were specified there, and assign # them to the include. If the include already had tags specified, we raise an # error so that users know not to specify them both ways @@ -781,8 +792,6 @@ class StrategyBase: display.deprecated("You should not specify tags in the include parameters. All tags should be specified using the task-level option") included_file._task.tags = tags - ti_copy.vars = temp_vars - block_list = load_list_of_blocks( data, play=iterator._play, diff --git a/lib/ansible/plugins/strategy/free.py b/lib/ansible/plugins/strategy/free.py index 07e02cfb83..c0a8a2bcd8 100644 --- a/lib/ansible/plugins/strategy/free.py +++ b/lib/ansible/plugins/strategy/free.py @@ -193,10 +193,9 @@ class StrategyModule(StrategyBase): display.debug("collecting new blocks for %s" % included_file) try: if included_file._is_role: - new_ir = included_file._task.copy() - new_ir.vars.update(included_file._args) + new_ir = self._copy_included_file(included_file) - new_blocks, handler_blocks = included_file._task.get_block_list( + new_blocks, handler_blocks = new_ir.get_block_list( play=iterator._play, variable_manager=self._variable_manager, loader=self._loader, diff --git a/lib/ansible/plugins/strategy/linear.py b/lib/ansible/plugins/strategy/linear.py index 3409888fa0..d9a0c185e8 100644 --- a/lib/ansible/plugins/strategy/linear.py +++ b/lib/ansible/plugins/strategy/linear.py @@ -324,8 +324,7 @@ class StrategyModule(StrategyBase): # list of noop tasks, to make sure that they continue running in lock-step try: if included_file._is_role: - new_ir = included_file._task.copy() - new_ir.vars.update(included_file._args) + new_ir = self._copy_included_file(included_file) new_blocks, handler_blocks = new_ir.get_block_list( play=iterator._play,