From bdcde11f9f3c145c3f44edbd4b672ef33fc69175 Mon Sep 17 00:00:00 2001 From: Martin Krizek Date: Fri, 7 Aug 2020 22:30:41 +0200 Subject: [PATCH] 2.9: Detect failure in always block after rescue (#70094) (#70203) * Detect failure in always block after rescue (#70094) * Detect failure in always block after rescue Fixes #70000 ci_complete * Add more tests (cherry picked from commit 0ed5b7737708127899762ba768af93cae11e116a) * add changelog Co-authored-by: Matt Davis --- ...0000-playbook-detect-failure-in-always.yml | 2 ++ lib/ansible/executor/play_iterator.py | 2 +- .../blocks/always_failure_no_rescue_rc.yml | 13 +++++++ .../blocks/always_failure_with_rescue_rc.yml | 16 +++++++++ .../targets/blocks/always_no_rescue_rc.yml | 12 +++++++ test/integration/targets/blocks/runme.sh | 35 +++++++++++++++++++ 6 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/70000-playbook-detect-failure-in-always.yml create mode 100644 test/integration/targets/blocks/always_failure_no_rescue_rc.yml create mode 100644 test/integration/targets/blocks/always_failure_with_rescue_rc.yml create mode 100644 test/integration/targets/blocks/always_no_rescue_rc.yml diff --git a/changelogs/fragments/70000-playbook-detect-failure-in-always.yml b/changelogs/fragments/70000-playbook-detect-failure-in-always.yml new file mode 100644 index 00000000000..1637e47ffb5 --- /dev/null +++ b/changelogs/fragments/70000-playbook-detect-failure-in-always.yml @@ -0,0 +1,2 @@ +bugfixes: + - playbooks - detect and propagate failures in ``always`` blocks after ``rescue`` (https://github.com/ansible/ansible/issues/70000) diff --git a/lib/ansible/executor/play_iterator.py b/lib/ansible/executor/play_iterator.py index 0fdcb2fedcc..781dbee4255 100644 --- a/lib/ansible/executor/play_iterator.py +++ b/lib/ansible/executor/play_iterator.py @@ -489,7 +489,7 @@ class PlayIterator: elif state.run_state == self.ITERATING_ALWAYS and state.fail_state & self.FAILED_ALWAYS == 0: return False else: - return not state.did_rescue + return not (state.did_rescue and state.fail_state & self.FAILED_ALWAYS == 0) elif state.run_state == self.ITERATING_TASKS and self._check_failed_state(state.tasks_child_state): cur_block = self._blocks[state.cur_block] if len(cur_block.rescue) > 0 and state.fail_state & self.FAILED_RESCUE == 0: diff --git a/test/integration/targets/blocks/always_failure_no_rescue_rc.yml b/test/integration/targets/blocks/always_failure_no_rescue_rc.yml new file mode 100644 index 00000000000..924643ce0fe --- /dev/null +++ b/test/integration/targets/blocks/always_failure_no_rescue_rc.yml @@ -0,0 +1,13 @@ +- hosts: localhost + gather_facts: no + tasks: + - block: + - name: EXPECTED FAILURE + fail: + msg: Failure in block + always: + - name: EXPECTED FAILURE + fail: + msg: Failure in always + - debug: + msg: DID NOT RUN diff --git a/test/integration/targets/blocks/always_failure_with_rescue_rc.yml b/test/integration/targets/blocks/always_failure_with_rescue_rc.yml new file mode 100644 index 00000000000..f3029cbcc8a --- /dev/null +++ b/test/integration/targets/blocks/always_failure_with_rescue_rc.yml @@ -0,0 +1,16 @@ +- hosts: localhost + gather_facts: no + tasks: + - block: + - name: EXPECTED FAILURE + fail: + msg: Failure in block + rescue: + - debug: + msg: Rescue + always: + - name: EXPECTED FAILURE + fail: + msg: Failure in always + - debug: + msg: DID NOT RUN diff --git a/test/integration/targets/blocks/always_no_rescue_rc.yml b/test/integration/targets/blocks/always_no_rescue_rc.yml new file mode 100644 index 00000000000..a4e864160ad --- /dev/null +++ b/test/integration/targets/blocks/always_no_rescue_rc.yml @@ -0,0 +1,12 @@ +- hosts: localhost + gather_facts: no + tasks: + - block: + - name: EXPECTED FAILURE + fail: + msg: Failure in block + always: + - debug: + msg: Always + - debug: + msg: DID NOT RUN diff --git a/test/integration/targets/blocks/runme.sh b/test/integration/targets/blocks/runme.sh index f158735611f..69f8d04aa1a 100755 --- a/test/integration/targets/blocks/runme.sh +++ b/test/integration/targets/blocks/runme.sh @@ -39,3 +39,38 @@ env python -c \ [ "$(grep -c 'TEST COMPLETE' block_test.out)" = "$(grep -E '^[0-9]+ plays in' block_test_wo_colors.out | cut -f1 -d' ')" ] ansible-playbook -vv block_rescue_vars.yml + +# https://github.com/ansible/ansible/issues/70000 +set +e +exit_code=0 +ansible-playbook -vv always_failure_with_rescue_rc.yml > rc_test.out || exit_code=$? +set -e +cat rc_test.out +[ $exit_code -eq 2 ] +[ "$(grep -c 'Failure in block' rc_test.out )" -eq 1 ] +[ "$(grep -c 'Rescue' rc_test.out )" -eq 1 ] +[ "$(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 + +set +e +exit_code=0 +ansible-playbook -vv always_no_rescue_rc.yml > rc_test.out || exit_code=$? +set -e +cat rc_test.out +[ $exit_code -eq 2 ] +[ "$(grep -c 'Failure in block' rc_test.out )" -eq 1 ] +[ "$(grep -c 'Always' rc_test.out )" -eq 1 ] +[ "$(grep -c 'DID NOT RUN' rc_test.out )" -eq 0 ] +rm -f rc_test.out + +set +e +exit_code=0 +ansible-playbook -vv always_failure_no_rescue_rc.yml > rc_test.out || exit_code=$? +set -e +cat rc_test.out +[ $exit_code -eq 2 ] +[ "$(grep -c 'Failure in block' rc_test.out )" -eq 1 ] +[ "$(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