diff --git a/lib/ansible/executor/play_iterator.py b/lib/ansible/executor/play_iterator.py index 584cfb0fe6..09caeec2d9 100644 --- a/lib/ansible/executor/play_iterator.py +++ b/lib/ansible/executor/play_iterator.py @@ -49,6 +49,7 @@ class HostState: self.cur_rescue_task = 0 self.cur_always_task = 0 self.cur_role = None + self.cur_dep_chain = None self.run_state = PlayIterator.ITERATING_SETUP self.fail_state = PlayIterator.FAILED_NONE self.pending_setup = False @@ -102,6 +103,8 @@ class HostState: new_state.run_state = self.run_state new_state.fail_state = self.fail_state new_state.pending_setup = self.pending_setup + if self.cur_dep_chain is not None: + new_state.cur_dep_chain = self.cur_dep_chain[:] if self.tasks_child_state is not None: new_state.tasks_child_state = self.tasks_child_state.copy() if self.rescue_child_state is not None: @@ -212,13 +215,21 @@ class PlayIterator: s.pending_setup = False if not task: + old_s = s (s, task) = self._get_next_task_from_state(s, peek=peek) + def _roles_are_different(ra, rb): + if ra != rb: + return True + else: + return old_s.cur_dep_chain != task._block._dep_chain + if task and task._role: # if we had a current role, mark that role as completed - if s.cur_role and task._role != s.cur_role and host.name in s.cur_role._had_task_run and not peek: + if s.cur_role and _roles_are_different(task._role, s.cur_role) and host.name in s.cur_role._had_task_run and not peek: s.cur_role._completed[host.name] = True s.cur_role = task._role + s.cur_dep_chain = task._block._dep_chain if not peek: self._host_states[host.name] = s diff --git a/lib/ansible/playbook/role/__init__.py b/lib/ansible/playbook/role/__init__.py index 10e14b4ac3..f192ea6c94 100644 --- a/lib/ansible/playbook/role/__init__.py +++ b/lib/ansible/playbook/role/__init__.py @@ -323,7 +323,7 @@ class Role(Base, Become, Conditional, Taggable): return host.name in self._completed and not self._metadata.allow_duplicates - def compile(self, play, dep_chain=[]): + def compile(self, play, dep_chain=None): ''' Returns the task list for this role, which is created by first recursively compiling the tasks for all direct dependencies, and @@ -337,18 +337,20 @@ class Role(Base, Become, Conditional, Taggable): block_list = [] # update the dependency chain here + if dep_chain is None: + dep_chain = [] new_dep_chain = dep_chain + [self] deps = self.get_direct_dependencies() for dep in deps: dep_blocks = dep.compile(play=play, dep_chain=new_dep_chain) - for dep_block in dep_blocks: - new_dep_block = dep_block.copy() - new_dep_block._dep_chain = new_dep_chain - new_dep_block._play = play - block_list.append(new_dep_block) + block_list.extend(dep_blocks) - block_list.extend(self._task_blocks) + for task_block in self._task_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 diff --git a/test/integration/roles/test_var_precedence_dep/tasks/main.yml b/test/integration/roles/test_var_precedence_dep/tasks/main.yml index b50f9dfc27..2f8e17096b 100644 --- a/test/integration/roles/test_var_precedence_dep/tasks/main.yml +++ b/test/integration/roles/test_var_precedence_dep/tasks/main.yml @@ -7,7 +7,7 @@ - assert: that: - 'extra_var == "extra_var"' - - 'param_var == "param_var"' + - 'param_var == "param_var_role1"' - 'vars_var == "vars_var"' - 'vars_files_var == "vars_files_var"' - 'vars_files_var_role == "vars_files_var_dep"'