summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--changelogs/fragments/module-exceptions.yaml2
-rw-r--r--lib/ansible/plugins/action/__init__.py4
-rw-r--r--test/integration/targets/module_tracebacks/aliases2
-rw-r--r--test/integration/targets/module_tracebacks/inventory5
-rwxr-xr-xtest/integration/targets/module_tracebacks/runme.sh5
-rw-r--r--test/integration/targets/module_tracebacks/traceback.yml21
6 files changed, 39 insertions, 0 deletions
diff --git a/changelogs/fragments/module-exceptions.yaml b/changelogs/fragments/module-exceptions.yaml
new file mode 100644
index 0000000000..f5fc916aa4
--- /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 752829ddf4..405165a5cc 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 0000000000..93fb6f10c1
--- /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 0000000000..9156526779
--- /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 0000000000..b8ac8068b0
--- /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 0000000000..b1f0b5164a
--- /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"