diff --git a/changelogs/fragments/50897-include_role-any_errors_fatal.yaml b/changelogs/fragments/50897-include_role-any_errors_fatal.yaml new file mode 100644 index 00000000000..ce0c68e7f6a --- /dev/null +++ b/changelogs/fragments/50897-include_role-any_errors_fatal.yaml @@ -0,0 +1,2 @@ +bugfixes: + - Make include_role/include_tasks work with any_errors_fatal (https://github.com/ansible/ansible/issues/50897) diff --git a/lib/ansible/playbook/included_file.py b/lib/ansible/playbook/included_file.py index d0e19925785..c256d70b740 100644 --- a/lib/ansible/playbook/included_file.py +++ b/lib/ansible/playbook/included_file.py @@ -43,6 +43,7 @@ class IncludedFile: self._task = task self._hosts = [] self._is_role = is_role + self._results = [] def add_host(self, host): if host not in self._hosts: @@ -212,6 +213,7 @@ class IncludedFile: try: inc_file.add_host(original_host) + inc_file._results.append(res) except ValueError: # The host already exists for this include, advance forward, this is a new include idx += pos + 1 diff --git a/lib/ansible/plugins/strategy/__init__.py b/lib/ansible/plugins/strategy/__init__.py index faf48e5acc8..ae3d0e7d55e 100644 --- a/lib/ansible/plugins/strategy/__init__.py +++ b/lib/ansible/plugins/strategy/__init__.py @@ -970,6 +970,9 @@ class StrategyBase: else: reason = to_text(e) + for r in included_file._results: + r._result['failed'] = True + # mark all of the hosts including this file as failed, send callbacks, # and increment the stats for this host for host in included_file._hosts: diff --git a/lib/ansible/plugins/strategy/free.py b/lib/ansible/plugins/strategy/free.py index e328bfcc5d0..475b7efcf4a 100644 --- a/lib/ansible/plugins/strategy/free.py +++ b/lib/ansible/plugins/strategy/free.py @@ -260,6 +260,9 @@ class StrategyModule(StrategyBase): except AnsibleParserError: raise except AnsibleError as e: + for r in included_file._results: + r._result['failed'] = True + for host in included_file._hosts: iterator.mark_host_failed(host) display.warning(to_text(e)) diff --git a/lib/ansible/plugins/strategy/linear.py b/lib/ansible/plugins/strategy/linear.py index f9a30a12208..d90d347d3e3 100644 --- a/lib/ansible/plugins/strategy/linear.py +++ b/lib/ansible/plugins/strategy/linear.py @@ -339,7 +339,6 @@ class StrategyModule(StrategyBase): variable_manager=self._variable_manager ) - include_failure = False if len(included_files) > 0: display.debug("we have included files to process") @@ -385,11 +384,13 @@ class StrategyModule(StrategyBase): except AnsibleParserError: raise except AnsibleError as e: + for r in included_file._results: + r._result['failed'] = True + for host in included_file._hosts: self._tqm._failed_hosts[host.name] = True iterator.mark_host_failed(host) display.error(to_text(e), wrap_text=False) - include_failure = True continue # finally go through all of the hosts and append the diff --git a/test/integration/targets/any_errors_fatal/50897.yml b/test/integration/targets/any_errors_fatal/50897.yml new file mode 100644 index 00000000000..1d09eb18f03 --- /dev/null +++ b/test/integration/targets/any_errors_fatal/50897.yml @@ -0,0 +1,19 @@ +- hosts: testhost,testhost2 + gather_facts: no + any_errors_fatal: yes + tasks: + - name: EXPECTED FAILURE include_role that doesn't exist + include_role: + name: 'non-existant-role' + when: + - inventory_hostname == 'testhost2' + - test_name == 'test_include_role' + + - name: EXPECTED FAILURE include_tasks that don't exist + include_tasks: non-existant.yml + when: + - inventory_hostname == 'testhost2' + - test_name == 'test_include_tasks' + + - debug: + msg: 'any_errors_fatal_this_should_never_be_reached' diff --git a/test/integration/targets/any_errors_fatal/runme.sh b/test/integration/targets/any_errors_fatal/runme.sh index 02cd499fd57..c54ea8d5e0b 100755 --- a/test/integration/targets/any_errors_fatal/runme.sh +++ b/test/integration/targets/any_errors_fatal/runme.sh @@ -5,14 +5,14 @@ ansible-playbook -i inventory "$@" play_level.yml| tee out.txt | grep 'any_error res=$? cat out.txt if [ "${res}" -eq 0 ] ; then - exit 1 + exit 1 fi ansible-playbook -i inventory "$@" on_includes.yml | tee out.txt | grep 'any_errors_fatal_this_should_never_be_reached' res=$? cat out.txt if [ "${res}" -eq 0 ] ; then - exit 1 + exit 1 fi set -ux @@ -20,4 +20,18 @@ set -ux ansible-playbook -i inventory "$@" always_block.yml | tee out.txt | grep 'any_errors_fatal_always_block_start' res=$? cat out.txt -exit $res + +if [ "${res}" -ne 0 ] ; then + exit 1 +fi + +set -ux + +for test_name in test_include_role test_include_tasks; do + ansible-playbook -i inventory "$@" -e test_name=$test_name 50897.yml | tee out.txt | grep 'any_errors_fatal_this_should_never_be_reached' + res=$? + cat out.txt + if [ "${res}" -eq 0 ] ; then + exit 1 + fi +done