summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/ansible/compat/six/_six.py2
-rw-r--r--lib/ansible/executor/play_iterator.py51
-rw-r--r--lib/ansible/module_utils/six.py2
3 files changed, 52 insertions, 3 deletions
diff --git a/lib/ansible/compat/six/_six.py b/lib/ansible/compat/six/_six.py
index 190c0239cd..8caf2ad85c 100644
--- a/lib/ansible/compat/six/_six.py
+++ b/lib/ansible/compat/six/_six.py
@@ -43,6 +43,7 @@ if PY3:
class_types = type,
text_type = str
binary_type = bytes
+ cmp = lambda a, b: (a > b) - (a < b)
MAXSIZE = sys.maxsize
else:
@@ -51,6 +52,7 @@ else:
class_types = (type, types.ClassType)
text_type = unicode
binary_type = str
+ cmp = cmp
if sys.platform.startswith("java"):
# Jython always uses 32 bits.
diff --git a/lib/ansible/executor/play_iterator.py b/lib/ansible/executor/play_iterator.py
index ad8facac65..2408226d6f 100644
--- a/lib/ansible/executor/play_iterator.py
+++ b/lib/ansible/executor/play_iterator.py
@@ -24,6 +24,7 @@ import fnmatch
from ansible.compat.six import iteritems
from ansible import constants as C
from ansible.errors import AnsibleError
+from ansible.module_utils.six import cmp
from ansible.playbook.block import Block
from ansible.playbook.task import Task
from ansible.playbook.role_include import IncludeRole
@@ -48,6 +49,7 @@ class HostState:
self.cur_rescue_task = 0
self.cur_always_task = 0
self.cur_role = None
+ self.cur_role_task = None
self.cur_dep_chain = None
self.run_state = PlayIterator.ITERATING_SETUP
self.fail_state = PlayIterator.FAILED_NONE
@@ -120,6 +122,8 @@ class HostState:
new_state.cur_rescue_task = self.cur_rescue_task
new_state.cur_always_task = self.cur_always_task
new_state.cur_role = self.cur_role
+ if self.cur_role_task:
+ new_state.cur_role_task = self.cur_role_task[:]
new_state.run_state = self.run_state
new_state.fail_state = self.fail_state
new_state.pending_setup = self.pending_setup
@@ -276,12 +280,53 @@ class PlayIterator:
parent = parent._parent
return False
+ def _get_cur_task(s, depth=0):
+ res = [s.run_state, depth, s.cur_block, -1]
+ if s.run_state == self.ITERATING_TASKS:
+ if s.tasks_child_state:
+ res = _get_cur_task(s.tasks_child_state, depth=depth+1)
+ else:
+ res[-1] = s.cur_regular_task
+ elif s.run_state == self.ITERATING_RESCUE:
+ if s.rescue_child_state:
+ res = _get_cur_task(s.rescue_child_state, depth=depth+1)
+ else:
+ res[-1] = s.cur_rescue_task
+ elif s.run_state == self.ITERATING_ALWAYS:
+ if s.always_child_state:
+ res = _get_cur_task(s.always_child_state, depth=depth+1)
+ else:
+ res[-1] = s.cur_always_task
+ return res
+
+ def _role_task_cmp(s):
+ '''
+ tt is a tuple made of the regular/rescue/always task number
+ from the current state of the host.
+ '''
+ if not s.cur_role_task:
+ return 1
+ cur_task = _get_cur_task(s)
+ res = cmp(cur_task[0], s.cur_role_task[0])
+ if res == 0:
+ res = cmp(cur_task[1], s.cur_role_task[1])
+ if res == 0:
+ res = cmp(cur_task[2], s.cur_role_task[2])
+ if res == 0:
+ res = cmp(cur_task[3], s.cur_role_task[3])
+ return res
+
if task and task._role:
# if we had a current role, mark that role as completed
- 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 _role_is_child(s.cur_role) and not peek:
- s.cur_role._completed[host.name] = True
+ if s.cur_role:
+ role_diff = _roles_are_different(task._role, s.cur_role)
+ role_child = _role_is_child(s.cur_role)
+ tasks_cmp = _role_task_cmp(s)
+ host_done = host.name in s.cur_role._had_task_run
+ if (role_diff or (not role_diff and tasks_cmp <= 0)) and host_done and not role_child and not peek:
+ s.cur_role._completed[host.name] = True
s.cur_role = task._role
+ s.cur_role_task = _get_cur_task(s)
s.cur_dep_chain = task.get_dep_chain()
if not peek:
diff --git a/lib/ansible/module_utils/six.py b/lib/ansible/module_utils/six.py
index 85898ec712..b93d4bf8bb 100644
--- a/lib/ansible/module_utils/six.py
+++ b/lib/ansible/module_utils/six.py
@@ -38,6 +38,7 @@ if PY3:
class_types = type,
text_type = str
binary_type = bytes
+ cmp = lambda a, b: (a > b) - (a < b)
MAXSIZE = sys.maxsize
else:
@@ -46,6 +47,7 @@ else:
class_types = (type, types.ClassType)
text_type = unicode
binary_type = str
+ cmp = cmp
if sys.platform.startswith("java"):
# Jython always uses 32 bits.