From 39c9c6b9423877f7e153cb40b5ce17862b5553e7 Mon Sep 17 00:00:00 2001 From: Dag Wieers Date: Wed, 7 Dec 2016 17:00:11 +0100 Subject: [PATCH] Ensure that command/shell errors are displayed This fix ensures that if there are specific module errors (in our case the python interpreter was not found) then command and shell returns a proper error. It also fixes a few other imperfections that we noticed during troubleshooting: - Return the real RC if it were available - Improve a dictionary evaluation using .get() - Return an RC of -1 if it is unknown (instead of returning 0) This fixes #18846 --- lib/ansible/plugins/action/__init__.py | 4 +++- lib/ansible/plugins/callback/minimal.py | 4 ++-- lib/ansible/plugins/callback/oneline.py | 6 +++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/ansible/plugins/action/__init__.py b/lib/ansible/plugins/action/__init__.py index 179ed03c6ed..d28adf25b1d 100644 --- a/lib/ansible/plugins/action/__init__.py +++ b/lib/ansible/plugins/action/__init__.py @@ -720,6 +720,8 @@ class ActionBase(with_metaclass(ABCMeta, object)): data['module_stderr'] = res['stderr'] if res['stderr'].startswith(u'Traceback'): data['exception'] = res['stderr'] + if 'rc' in res: + data['rc'] = res['rc'] return data def _low_level_execute_command(self, cmd, sudoable=True, in_data=None, executable=None, encoding_errors='surrogate_or_replace'): @@ -801,7 +803,7 @@ class ActionBase(with_metaclass(ABCMeta, object)): display.debug("Going to peek to see if file has changed permissions") peek_result = self._execute_module(module_name='file', module_args=dict(path=destination, diff_peek=True), task_vars=task_vars, persist_files=True) - if not('failed' in peek_result and peek_result['failed']) or peek_result.get('rc', 0) == 0: + if not peek_result.get('failed', False) or peek_result.get('rc', 0) == 0: if peek_result['state'] == 'absent': diff['before'] = '' diff --git a/lib/ansible/plugins/callback/minimal.py b/lib/ansible/plugins/callback/minimal.py index 33ddb16641f..9d7ec1d4523 100644 --- a/lib/ansible/plugins/callback/minimal.py +++ b/lib/ansible/plugins/callback/minimal.py @@ -37,7 +37,7 @@ class CallbackModule(CallbackBase): def _command_generic_msg(self, host, result, caption): ''' output the result of a command run ''' - buf = "%s | %s | rc=%s >>\n" % (host, caption, result.get('rc',0)) + buf = "%s | %s | rc=%s >>\n" % (host, caption, result.get('rc', -1)) buf += result.get('stdout','') buf += result.get('stderr','') buf += result.get('msg','') @@ -55,7 +55,7 @@ class CallbackModule(CallbackBase): self._display.display(msg, color=C.COLOR_ERROR) - if result._task.action in C.MODULE_NO_JSON: + if result._task.action in C.MODULE_NO_JSON and 'module_stderr' not in result._result: self._display.display(self._command_generic_msg(result._host.get_name(), result._result, "FAILED"), color=C.COLOR_ERROR) else: self._display.display("%s | FAILED! => %s" % (result._host.get_name(), self._dump_results(result._result, indent=4)), color=C.COLOR_ERROR) diff --git a/lib/ansible/plugins/callback/oneline.py b/lib/ansible/plugins/callback/oneline.py index 743551fe735..12ff2aeb650 100644 --- a/lib/ansible/plugins/callback/oneline.py +++ b/lib/ansible/plugins/callback/oneline.py @@ -38,9 +38,9 @@ class CallbackModule(CallbackBase): stdout = result.get('stdout','').replace('\n', '\\n') if 'stderr' in result and result['stderr']: stderr = result.get('stderr','').replace('\n', '\\n') - return "%s | %s | rc=%s | (stdout) %s (stderr) %s" % (hostname, caption, result.get('rc',0), stdout, stderr) + return "%s | %s | rc=%s | (stdout) %s (stderr) %s" % (hostname, caption, result.get('rc', -1), stdout, stderr) else: - return "%s | %s | rc=%s | (stdout) %s" % (hostname, caption, result.get('rc',0), stdout) + return "%s | %s | rc=%s | (stdout) %s" % (hostname, caption, result.get('rc', -1), stdout) def v2_runner_on_failed(self, result, ignore_errors=False): if 'exception' in result._result: @@ -51,7 +51,7 @@ class CallbackModule(CallbackBase): else: msg = "An exception occurred during task execution. The full traceback is:\n" + result._result['exception'].replace('\n','') - if result._task.action in C.MODULE_NO_JSON: + if result._task.action in C.MODULE_NO_JSON and 'module_stderr' not in result._result: self._display.display(self._command_generic_msg(result._host.get_name(), result._result,'FAILED'), color=C.COLOR_ERROR) else: self._display.display(msg, color=C.COLOR_ERROR)