diff --git a/changelogs/fragments/module-exceptions.yaml b/changelogs/fragments/module-exceptions.yaml new file mode 100644 index 00000000000..f5fc916aa47 --- /dev/null +++ b/changelogs/fragments/module-exceptions.yaml @@ -0,0 +1,2 @@ +bugfixes: + - Module tracebacks are now recognized on stdout and stderr, intead of just on stderr. diff --git a/lib/ansible/plugins/action/__init__.py b/lib/ansible/plugins/action/__init__.py index 752829ddf45..405165a5cc9 100644 --- a/lib/ansible/plugins/action/__init__.py +++ b/lib/ansible/plugins/action/__init__.py @@ -992,6 +992,10 @@ class ActionBase(with_metaclass(ABCMeta, object)): if res['stderr'].startswith(u'Traceback'): data['exception'] = res['stderr'] + # in some cases a traceback will arrive on stdout instead of stderr, such as when using ssh with -tt + if 'exception' not in data and data['module_stdout'].startswith(u'Traceback'): + data['exception'] = data['module_stdout'] + # The default data['msg'] = "MODULE FAILURE" diff --git a/test/integration/targets/module_tracebacks/aliases b/test/integration/targets/module_tracebacks/aliases new file mode 100644 index 00000000000..93fb6f10c18 --- /dev/null +++ b/test/integration/targets/module_tracebacks/aliases @@ -0,0 +1,2 @@ +shippable/posix/group4 +needs/ssh diff --git a/test/integration/targets/module_tracebacks/inventory b/test/integration/targets/module_tracebacks/inventory new file mode 100644 index 00000000000..91565267790 --- /dev/null +++ b/test/integration/targets/module_tracebacks/inventory @@ -0,0 +1,5 @@ +testhost_local ansible_connection=local +testhost_ssh ansible_connection=ssh ansible_host=localhost + +[all:vars] +ansible_python_interpreter="{{ ansible_playbook_python }}" diff --git a/test/integration/targets/module_tracebacks/runme.sh b/test/integration/targets/module_tracebacks/runme.sh new file mode 100755 index 00000000000..b8ac8068b0b --- /dev/null +++ b/test/integration/targets/module_tracebacks/runme.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -eux + +ansible-playbook traceback.yml -i inventory "$@" diff --git a/test/integration/targets/module_tracebacks/traceback.yml b/test/integration/targets/module_tracebacks/traceback.yml new file mode 100644 index 00000000000..b1f0b5164a8 --- /dev/null +++ b/test/integration/targets/module_tracebacks/traceback.yml @@ -0,0 +1,21 @@ +- hosts: all + gather_facts: no + tasks: + - name: intentionally fail module execution + ping: + data: crash + ignore_errors: yes + register: ping + +- hosts: localhost + gather_facts: no + tasks: + - name: verify exceptions were properly captured + assert: + that: + - hostvars.testhost_local.ping is failed + - "'boom' in hostvars.testhost_local.ping.exception" + - "'boom' in hostvars.testhost_local.ping.module_stderr" + - hostvars.testhost_ssh.ping is failed + - "'boom' in hostvars.testhost_ssh.ping.exception" + - "'boom' in hostvars.testhost_ssh.ping.module_stdout"