diff --git a/changelogs/fragments/37187-catch-cond-tmpl-errors.yml b/changelogs/fragments/37187-catch-cond-tmpl-errors.yml new file mode 100644 index 00000000000..5574894e77b --- /dev/null +++ b/changelogs/fragments/37187-catch-cond-tmpl-errors.yml @@ -0,0 +1,4 @@ +bugfixes: +- >- + ``failed_when``/``changed_when`` - Catch templating errors to prevent masking of module output + (https://github.com/ansible/ansible/issues/37187) diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py index 1c04f235c94..84248ec133c 100644 --- a/lib/ansible/executor/task_executor.py +++ b/lib/ansible/executor/task_executor.py @@ -671,8 +671,14 @@ class TaskExecutor: # if we didn't skip this task, use the helpers to evaluate the changed/ # failed_when properties if 'skipped' not in result: - _evaluate_changed_when_result(result) - _evaluate_failed_when_result(result) + try: + condname = 'changed' + _evaluate_changed_when_result(result) + condname = 'failed' + _evaluate_failed_when_result(result) + except AnsibleError as e: + result['failed'] = True + result['%s_when_result' % condname] = to_text(e) if retries > 1: cond = Conditional(loader=self._loader) diff --git a/test/integration/targets/changed_when/tasks/main.yml b/test/integration/targets/changed_when/tasks/main.yml index 7b997189666..4f0a87479a9 100644 --- a/test/integration/targets/changed_when/tasks/main.yml +++ b/test/integration/targets/changed_when/tasks/main.yml @@ -59,3 +59,15 @@ assert: that: - groupby is not changed + +- name: invalid conditional + command: echo foo + changed_when: boomboomboom + register: invalid_conditional + ignore_errors: true + +- assert: + that: + - invalid_conditional is failed + - invalid_conditional.stdout is defined + - invalid_conditional.changed_when_result is contains('boomboomboom') diff --git a/test/integration/targets/failed_when/tasks/main.yml b/test/integration/targets/failed_when/tasks/main.yml index 3f8ae545f2e..1b10bef14b7 100644 --- a/test/integration/targets/failed_when/tasks/main.yml +++ b/test/integration/targets/failed_when/tasks/main.yml @@ -66,3 +66,15 @@ that: - "'failed' in result and not result.failed" - "'failed_when_result' in result and not result.failed_when_result" + +- name: invalid conditional + command: echo foo + failed_when: boomboomboom + register: invalid_conditional + ignore_errors: true + +- assert: + that: + - invalid_conditional is failed + - invalid_conditional.stdout is defined + - invalid_conditional.failed_when_result is contains('boomboomboom')