Fix play stats when rescue block is a child block (#70922)

* check run state of current block only

* Add changelog and test

* Add test for issue 29047

* Fix for both tests

* blerg

* Change test messages

* fix tests

* Add multi-level block in rescue test case

* Add recursive rescue check and multi-level test

* Should probably run the new test

* ci_complete

* Merge new tests

* ci_complete
This commit is contained in:
David Shrewsbury 2020-08-18 05:20:55 -04:00 committed by GitHub
parent 824cd4cbeb
commit f2f6c34632
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 79 additions and 1 deletions

View File

@ -0,0 +1,2 @@
bugfixes:
- Fix statistics reporting when rescue block contains another block (issue https://github.com/ansible/ansible/issues/61253).

View File

@ -514,6 +514,17 @@ class PlayIterator:
return self.get_active_state(state.always_child_state)
return state
def is_any_block_rescuing(self, state):
'''
Given the current HostState state, determines if the current block, or any child blocks,
are in rescue mode.
'''
if state.run_state == self.ITERATING_RESCUE:
return True
if state.tasks_child_state is not None:
return self.is_any_block_rescuing(state.tasks_child_state)
return False
def get_original_task(self, host, task):
# now a noop because we've changed the way we do caching
return (None, None)

View File

@ -565,7 +565,12 @@ class StrategyBase:
if iterator.is_failed(original_host) and state and state.run_state == iterator.ITERATING_COMPLETE:
self._tqm._failed_hosts[original_host.name] = True
if state and iterator.get_active_state(state).run_state == iterator.ITERATING_RESCUE:
# Use of get_active_state() here helps detect proper state if, say, we are in a rescue
# block from an included file (include_tasks). In a non-included rescue case, a rescue
# that starts with a new 'block' will have an active state of ITERATING_TASKS, so we also
# check the current state block tree to see if any blocks are rescuing.
if state and (iterator.get_active_state(state).run_state == iterator.ITERATING_RESCUE or
iterator.is_any_block_rescuing(state)):
self._tqm._stats.increment('rescued', original_host.name)
self._variable_manager.set_nonpersistent_facts(
original_host.name,

View File

@ -0,0 +1,33 @@
- hosts: localhost
gather_facts: no
tasks:
- block:
- name: "EXPECTED FAILURE"
fail:
msg: "fail to test single level block in rescue"
rescue:
- block:
- debug:
msg: Rescued!
- block:
- name: "EXPECTED FAILURE"
fail:
msg: "fail to test multi-level block in rescue"
rescue:
- block:
- block:
- debug:
msg: Rescued!
- name: "Outer block"
block:
- name: "Inner block"
block:
- name: "EXPECTED FAILURE"
fail:
msg: "fail to test multi-level block"
rescue:
- name: "Rescue block"
block:
- debug: msg="Inner block rescue"

View File

@ -0,0 +1,4 @@
- hosts: localhost
gather_facts: no
tasks:
- include_tasks: issue29047_tasks.yml

View File

@ -0,0 +1,13 @@
---
- name: "EXPECTED FAILURE"
block:
- fail:
msg: "EXPECTED FAILURE"
rescue:
- name: Assert that ansible_failed_task is defined
assert:
that: ansible_failed_task is defined
- name: Assert that ansible_failed_result is defined
assert:
that: ansible_failed_result is defined

View File

@ -74,3 +74,13 @@ cat rc_test.out
[ "$(grep -c 'Failure in always' rc_test.out )" -eq 1 ]
[ "$(grep -c 'DID NOT RUN' rc_test.out )" -eq 0 ]
rm -f rc_test.out
# https://github.com/ansible/ansible/issues/29047
ansible-playbook -vv issue29047.yml -i ../../inventory
# https://github.com/ansible/ansible/issues/61253
ansible-playbook -vv block_in_rescue.yml -i ../../inventory > rc_test.out
cat rc_test.out
[ "$(grep -c 'rescued=3' rc_test.out)" -eq 1 ]
[ "$(grep -c 'failed=0' rc_test.out)" -eq 1 ]
rm -f rc_test.out