Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

correctly use configured ansible_shell_executable #31361

Merged
merged 1 commit into from
Oct 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 26 additions & 22 deletions lib/ansible/module_utils/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,7 @@ def __init__(self, argument_spec, bypass_checks=False, no_log=False,
self._debug = False
self._diff = False
self._socket_path = None
self._shell = None
self._verbosity = 0
# May be used to set modifications to the environment for any
# run_command invocation
Expand All @@ -810,7 +811,7 @@ def __init__(self, argument_spec, bypass_checks=False, no_log=False,
self.aliases = {}
self._legal_inputs = ['_ansible_check_mode', '_ansible_no_log', '_ansible_debug', '_ansible_diff', '_ansible_verbosity',
'_ansible_selinux_special_fs', '_ansible_module_name', '_ansible_version', '_ansible_syslog_facility',
'_ansible_socket']
'_ansible_socket', '_ansible_shell_executable']
self._options_context = list()

if add_file_common_args:
Expand Down Expand Up @@ -1612,6 +1613,9 @@ def _check_arguments(self, check_invalid_arguments, spec=None, param=None, legal
elif k == '_ansible_socket':
self._socket_path = v

elif k == '_ansible_shell_executable' and v:
self._shell = v

elif check_invalid_arguments and k not in legal_inputs:
unsupported_parameters.add(k)

Expand Down Expand Up @@ -2602,33 +2606,37 @@ def run_command(self, args, check_rc=False, close_fds=True, executable=None, dat
strings on python3, use encoding=None to turn decoding to text off.
'''

if isinstance(args, list):
if use_unsafe_shell:
if not isinstance(args, (list, binary_type, text_type)):
msg = "Argument 'args' to run_command must be list or string"
self.fail_json(rc=257, cmd=args, msg=msg)

shell = False
if use_unsafe_shell:

# stringify args for unsafe/direct shell usage
if isinstance(args, list):
args = " ".join([shlex_quote(x) for x in args])
shell = True
elif isinstance(args, (binary_type, text_type)):
if use_unsafe_shell:
shell = True

# not set explicitly, check if set by controller
if executable:
args = [executable, '-c', args]
elif self._shell not in (None, '/bin/sh'):
args = [self._shell, '-c', args]
else:
shell = True
else:
# ensure args are a list
if isinstance(args, (binary_type, text_type)):
# On python2.6 and below, shlex has problems with text type
# On python3, shlex needs a text type.
if PY2:
args = to_bytes(args, errors='surrogate_or_strict')
elif PY3:
args = to_text(args, errors='surrogateescape')
args = shlex.split(args)
else:
msg = "Argument 'args' to run_command must be list or string"
self.fail_json(rc=257, cmd=args, msg=msg)

shell = False
if use_unsafe_shell:
if executable is None:
executable = os.environ.get('SHELL')
if executable:
args = [executable, '-c', args]
else:
shell = True
# expand shellisms
args = [os.path.expanduser(os.path.expandvars(x)) for x in args if x is not None]

prompt_re = None
if prompt_regex:
Expand All @@ -2642,10 +2650,6 @@ def run_command(self, args, check_rc=False, close_fds=True, executable=None, dat
except re.error:
self.fail_json(msg="invalid prompt regular expression given to run_command")

# expand things like $HOME and ~
if not shell:
args = [os.path.expanduser(os.path.expandvars(x)) for x in args if x is not None]

rc = 0
msg = None
st_in = None
Expand Down
3 changes: 3 additions & 0 deletions lib/ansible/plugins/action/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,9 @@ def _update_module_args(self, module_name, module_args, task_vars):
# give the module the socket for persistent connections
module_args['_ansible_socket'] = task_vars.get('ansible_socket')

# make sure all commands use the designated shell executable
module_args['_ansible_shell_executable'] = self._play_context.executable

def _execute_module(self, module_name=None, module_args=None, tmp=None, task_vars=None, persist_files=False, delete_remote_tmp=True, wrap_async=False):
'''
Transfer and run a module along with its arguments.
Expand Down