Backport/2.10/72390 (#72690)
* Return error if cwd directory does not exist (#72390)
* Return warning or error if cwd directory does not exist, in AnsibleModule.run_command()
(cherry picked from commit 5654de6fce
)
* added flag in run_command signature to control behaviour when cwd does not exist
This commit is contained in:
parent
7f1ee07634
commit
71ef981191
4 changed files with 27 additions and 9 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
bugfixes:
|
||||||
|
- basic.AnsibleModule - AnsibleModule.run_command silently ignores a non-existent directory in the ``cwd`` argument (https://github.com/ansible/ansible/pull/72390).
|
2
changelogs/fragments/run-command-cwd.yml
Normal file
2
changelogs/fragments/run-command-cwd.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
bugfixes:
|
||||||
|
- AnsibleModule - added arg ``ignore_invalid_cwd`` to ``AnsibleModule.run_command()``, to control its behaviour when ``cwd`` is invalid. (https://github.com/ansible/ansible/pull/72390)
|
|
@ -2531,7 +2531,7 @@ class AnsibleModule(object):
|
||||||
|
|
||||||
def run_command(self, args, check_rc=False, close_fds=True, executable=None, data=None, binary_data=False, path_prefix=None, cwd=None,
|
def run_command(self, args, check_rc=False, close_fds=True, executable=None, data=None, binary_data=False, path_prefix=None, cwd=None,
|
||||||
use_unsafe_shell=False, prompt_regex=None, environ_update=None, umask=None, encoding='utf-8', errors='surrogate_or_strict',
|
use_unsafe_shell=False, prompt_regex=None, environ_update=None, umask=None, encoding='utf-8', errors='surrogate_or_strict',
|
||||||
expand_user_and_vars=True, pass_fds=None, before_communicate_callback=None):
|
expand_user_and_vars=True, pass_fds=None, before_communicate_callback=None, ignore_invalid_cwd=True):
|
||||||
'''
|
'''
|
||||||
Execute a command, returns rc, stdout, and stderr.
|
Execute a command, returns rc, stdout, and stderr.
|
||||||
|
|
||||||
|
@ -2582,6 +2582,9 @@ class AnsibleModule(object):
|
||||||
after ``Popen`` object will be created
|
after ``Popen`` object will be created
|
||||||
but before communicating to the process.
|
but before communicating to the process.
|
||||||
(``Popen`` object will be passed to callback as a first argument)
|
(``Popen`` object will be passed to callback as a first argument)
|
||||||
|
:kw ignore_invalid_cwd: This flag indicates whether an invalid ``cwd``
|
||||||
|
(non-existent or not a directory) should be ignored or should raise
|
||||||
|
an exception.
|
||||||
:returns: A 3-tuple of return code (integer), stdout (native string),
|
:returns: A 3-tuple of return code (integer), stdout (native string),
|
||||||
and stderr (native string). On python2, stdout and stderr are both
|
and stderr (native string). On python2, stdout and stderr are both
|
||||||
byte strings. On python3, stdout and stderr are text strings converted
|
byte strings. On python3, stdout and stderr are text strings converted
|
||||||
|
@ -2695,14 +2698,17 @@ class AnsibleModule(object):
|
||||||
prev_dir = os.getcwd()
|
prev_dir = os.getcwd()
|
||||||
|
|
||||||
# make sure we're in the right working directory
|
# make sure we're in the right working directory
|
||||||
if cwd and os.path.isdir(cwd):
|
if cwd:
|
||||||
|
if os.path.isdir(cwd):
|
||||||
cwd = to_bytes(os.path.abspath(os.path.expanduser(cwd)), errors='surrogate_or_strict')
|
cwd = to_bytes(os.path.abspath(os.path.expanduser(cwd)), errors='surrogate_or_strict')
|
||||||
kwargs['cwd'] = cwd
|
kwargs['cwd'] = cwd
|
||||||
try:
|
try:
|
||||||
os.chdir(cwd)
|
os.chdir(cwd)
|
||||||
except (OSError, IOError) as e:
|
except (OSError, IOError) as e:
|
||||||
self.fail_json(rc=e.errno, msg="Could not open %s, %s" % (cwd, to_native(e)),
|
self.fail_json(rc=e.errno, msg="Could not chdir to %s, %s" % (cwd, to_native(e)),
|
||||||
exception=traceback.format_exc())
|
exception=traceback.format_exc())
|
||||||
|
elif not ignore_invalid_cwd:
|
||||||
|
self.fail_json(msg="Provided cwd is not a valid directory: %s" % cwd)
|
||||||
|
|
||||||
old_umask = None
|
old_umask = None
|
||||||
if umask:
|
if umask:
|
||||||
|
|
|
@ -180,6 +180,14 @@ class TestRunCommandCwd:
|
||||||
rc_am.run_command('/bin/ls', cwd='/not-a-dir')
|
rc_am.run_command('/bin/ls', cwd='/not-a-dir')
|
||||||
assert rc_am._os.chdir.mock_calls == [mocker.call('/old'), ]
|
assert rc_am._os.chdir.mock_calls == [mocker.call('/old'), ]
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('stdin', [{}], indirect=['stdin'])
|
||||||
|
def test_cwd_not_a_dir_noignore(self, rc_am):
|
||||||
|
rc_am._os.getcwd.return_value = '/old'
|
||||||
|
rc_am._os.path.isdir.side_effect = lambda d: d != '/not-a-dir'
|
||||||
|
with pytest.raises(SystemExit):
|
||||||
|
rc_am.run_command('/bin/ls', cwd='/not-a-dir', ignore_invalid_cwd=False)
|
||||||
|
assert rc_am.fail_json.called
|
||||||
|
|
||||||
|
|
||||||
class TestRunCommandPrompt:
|
class TestRunCommandPrompt:
|
||||||
@pytest.mark.parametrize('stdin', [{}], indirect=['stdin'])
|
@pytest.mark.parametrize('stdin', [{}], indirect=['stdin'])
|
||||||
|
|
Loading…
Reference in a new issue