summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Cammarata <jimi@sngx.net>2017-01-19 09:25:30 -0600
committerJames Cammarata <jimi@sngx.net>2017-01-19 10:11:52 -0600
commitf4ecbc4c3ff8ce5269b59fdfe5e14abd9f163909 (patch)
treee02b103281aca7a4f7f842d604b2abf0409a5b31
parentb12256acf27e1c4bee60dd7e79f4384b2cfef67f (diff)
downloadansible-f4ecbc4c3ff8ce5269b59fdfe5e14abd9f163909.tar.gz
Fixing iterator bug related to reworking of end-of-role detection
Bug was introduced in cae682607 (cherry picked from commit 9d549c34981694e9fb62d3aa37392a439b5ae487)
-rw-r--r--lib/ansible/executor/play_iterator.py10
-rw-r--r--test/units/executor/test_play_iterator.py67
2 files changed, 69 insertions, 8 deletions
diff --git a/lib/ansible/executor/play_iterator.py b/lib/ansible/executor/play_iterator.py
index dac3e93fa4..9609f7e152 100644
--- a/lib/ansible/executor/play_iterator.py
+++ b/lib/ansible/executor/play_iterator.py
@@ -270,7 +270,7 @@ class PlayIterator:
return (s, task)
- def _get_next_task_from_state(self, state, host, peek):
+ def _get_next_task_from_state(self, state, host, peek, in_child=False):
task = None
@@ -336,7 +336,7 @@ class PlayIterator:
# have one recurse into it for the next task. If we're done with the child
# state, we clear it and drop back to geting the next task from the list.
if state.tasks_child_state:
- (state.tasks_child_state, task) = self._get_next_task_from_state(state.tasks_child_state, host=host, peek=peek)
+ (state.tasks_child_state, task) = self._get_next_task_from_state(state.tasks_child_state, host=host, peek=peek, in_child=True)
if self._check_failed_state(state.tasks_child_state):
# failed child state, so clear it and move into the rescue portion
state.tasks_child_state = None
@@ -374,7 +374,7 @@ class PlayIterator:
# The process here is identical to ITERATING_TASKS, except instead
# we move into the always portion of the block.
if state.rescue_child_state:
- (state.rescue_child_state, task) = self._get_next_task_from_state(state.rescue_child_state, host=host, peek=peek)
+ (state.rescue_child_state, task) = self._get_next_task_from_state(state.rescue_child_state, host=host, peek=peek, in_child=True)
if self._check_failed_state(state.rescue_child_state):
state.rescue_child_state = None
self._set_failed_state(state)
@@ -404,7 +404,7 @@ class PlayIterator:
# run state to ITERATING_COMPLETE in the event of any errors, or when we
# have hit the end of the list of blocks.
if state.always_child_state:
- (state.always_child_state, task) = self._get_next_task_from_state(state.always_child_state, host=host, peek=peek)
+ (state.always_child_state, task) = self._get_next_task_from_state(state.always_child_state, host=host, peek=peek, in_child=True)
if self._check_failed_state(state.always_child_state):
state.always_child_state = None
self._set_failed_state(state)
@@ -429,7 +429,7 @@ class PlayIterator:
# we're advancing blocks, so if this was an end-of-role block we
# mark the current role complete
- if block._eor and host.name in block._role._had_task_run:
+ if block._eor and host.name in block._role._had_task_run and not in_child:
block._role._completed[host.name] = True
else:
task = block.always[state.cur_always_task]
diff --git a/test/units/executor/test_play_iterator.py b/test/units/executor/test_play_iterator.py
index e11772031f..337342a349 100644
--- a/test/units/executor/test_play_iterator.py
+++ b/test/units/executor/test_play_iterator.py
@@ -98,6 +98,29 @@ class TestPlayIterator(unittest.TestCase):
- include: foo.yml
- name: role task after include
debug: msg="after include in role"
+ - block:
+ - name: starting role nested block 1
+ debug:
+ - block:
+ - name: role nested block 1 task 1
+ debug:
+ - name: role nested block 1 task 2
+ debug:
+ - name: role nested block 1 task 3
+ debug:
+ - name: end of role nested block 1
+ debug:
+ - name: starting role nested block 2
+ debug:
+ - block:
+ - name: role nested block 2 task 1
+ debug:
+ - name: role nested block 2 task 2
+ debug:
+ - name: role nested block 2 task 3
+ debug:
+ - name: end of role nested block 2
+ debug:
""",
'/etc/ansible/roles/test_role/tasks/foo.yml': """
- name: role included task
@@ -160,13 +183,11 @@ class TestPlayIterator(unittest.TestCase):
# role block task
(host_state, task) = itr.get_next_task_for_host(hosts[0])
self.assertIsNotNone(task)
- self.assertEqual(task.action, 'debug')
self.assertEqual(task.name, "role block task")
self.assertIsNotNone(task._role)
# role block always task
(host_state, task) = itr.get_next_task_for_host(hosts[0])
self.assertIsNotNone(task)
- self.assertEqual(task.action, 'debug')
self.assertEqual(task.name, "role always task")
self.assertIsNotNone(task._role)
# role include task
@@ -178,9 +199,49 @@ class TestPlayIterator(unittest.TestCase):
# role task after include
(host_state, task) = itr.get_next_task_for_host(hosts[0])
self.assertIsNotNone(task)
- self.assertEqual(task.action, 'debug')
self.assertEqual(task.name, "role task after include")
self.assertIsNotNone(task._role)
+ # role nested block tasks
+ (host_state, task) = itr.get_next_task_for_host(hosts[0])
+ self.assertIsNotNone(task)
+ self.assertEqual(task.name, "starting role nested block 1")
+ self.assertIsNotNone(task._role)
+ (host_state, task) = itr.get_next_task_for_host(hosts[0])
+ self.assertIsNotNone(task)
+ self.assertEqual(task.name, "role nested block 1 task 1")
+ self.assertIsNotNone(task._role)
+ (host_state, task) = itr.get_next_task_for_host(hosts[0])
+ self.assertIsNotNone(task)
+ self.assertEqual(task.name, "role nested block 1 task 2")
+ self.assertIsNotNone(task._role)
+ (host_state, task) = itr.get_next_task_for_host(hosts[0])
+ self.assertIsNotNone(task)
+ self.assertEqual(task.name, "role nested block 1 task 3")
+ self.assertIsNotNone(task._role)
+ (host_state, task) = itr.get_next_task_for_host(hosts[0])
+ self.assertIsNotNone(task)
+ self.assertEqual(task.name, "end of role nested block 1")
+ self.assertIsNotNone(task._role)
+ (host_state, task) = itr.get_next_task_for_host(hosts[0])
+ self.assertIsNotNone(task)
+ self.assertEqual(task.name, "starting role nested block 2")
+ self.assertIsNotNone(task._role)
+ (host_state, task) = itr.get_next_task_for_host(hosts[0])
+ self.assertIsNotNone(task)
+ self.assertEqual(task.name, "role nested block 2 task 1")
+ self.assertIsNotNone(task._role)
+ (host_state, task) = itr.get_next_task_for_host(hosts[0])
+ self.assertIsNotNone(task)
+ self.assertEqual(task.name, "role nested block 2 task 2")
+ self.assertIsNotNone(task._role)
+ (host_state, task) = itr.get_next_task_for_host(hosts[0])
+ self.assertIsNotNone(task)
+ self.assertEqual(task.name, "role nested block 2 task 3")
+ self.assertIsNotNone(task._role)
+ (host_state, task) = itr.get_next_task_for_host(hosts[0])
+ self.assertIsNotNone(task)
+ self.assertEqual(task.name, "end of role nested block 2")
+ self.assertIsNotNone(task._role)
# regular play task
(host_state, task) = itr.get_next_task_for_host(hosts[0])
self.assertIsNotNone(task)