Let command always return stdout & stderr (#73004)

The `command` module does not return stdout & sterr when calling
a non existing executable or an unknown exception arises. This fix
lets the module return empty byte strings in those cases.
This commit is contained in:
Alexander Sowitzki 2021-01-21 17:40:44 +01:00 committed by Alexander Sowitzki
parent 1934ca9a55
commit e6da544310
5 changed files with 40 additions and 2 deletions

View file

@ -0,0 +1,2 @@
bugfixes:
- Command module now returns stdout & stderr if executable is missing or an unknown error occurs

View file

@ -2772,10 +2772,10 @@ class AnsibleModule(object):
rc = cmd.returncode
except (OSError, IOError) as e:
self.log("Error Executing CMD:%s Exception:%s" % (self._clean_args(args), to_native(e)))
self.fail_json(rc=e.errno, msg=to_native(e), cmd=self._clean_args(args))
self.fail_json(rc=e.errno, stdout=b'', stderr=b'', msg=to_native(e), cmd=self._clean_args(args))
except Exception as e:
self.log("Error Executing CMD:%s Exception:%s" % (self._clean_args(args), to_native(traceback.format_exc())))
self.fail_json(rc=257, msg=to_native(e), exception=traceback.format_exc(), cmd=self._clean_args(args))
self.fail_json(rc=257, stdout=b'', stderr=b'', msg=to_native(e), exception=traceback.format_exc(), cmd=self._clean_args(args))
# Restore env settings
for key, val in old_env_vals.items():

View file

@ -0,0 +1 @@
shippable/posix/group2

View file

@ -0,0 +1,4 @@
- command: commandthatdoesnotexist --would-be-awkward
register: res
changed_when: "'changed' in res.stdout"
failed_when: "res.stdout != '' or res.stderr != ''"

View file

@ -0,0 +1,31 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import sys
import pytest
import json
import sys
import pytest
import subprocess
import ansible.module_utils.basic
from ansible.module_utils._text import to_bytes
from ansible.module_utils import basic
def test_run_non_existent_command(monkeypatch):
""" Test that `command` returns std{out,err} even if the executable is not found """
def fail_json(msg, **kwargs):
assert kwargs["stderr"] == b''
assert kwargs["stdout"] == b''
sys.exit(1)
def popen(*args, **kwargs):
raise OSError()
monkeypatch.setattr(basic, '_ANSIBLE_ARGS', to_bytes(json.dumps({'ANSIBLE_MODULE_ARGS': {}})))
monkeypatch.setattr(subprocess, 'Popen', popen)
am = basic.AnsibleModule(argument_spec={})
monkeypatch.setattr(am, 'fail_json', fail_json)
with pytest.raises(SystemExit):
am.run_command("lecho", "whatever")