use configured ansible_shell_executable

refine args/shell/executable hanlding
pull/31340/merge
Brian Coca 7 years ago committed by Brian Coca
parent 48f4643a66
commit f2ade09dce

@ -800,6 +800,7 @@ class AnsibleModule(object):
self._debug = False self._debug = False
self._diff = False self._diff = False
self._socket_path = None self._socket_path = None
self._shell = None
self._verbosity = 0 self._verbosity = 0
# May be used to set modifications to the environment for any # May be used to set modifications to the environment for any
# run_command invocation # run_command invocation
@ -810,7 +811,7 @@ class AnsibleModule(object):
self.aliases = {} self.aliases = {}
self._legal_inputs = ['_ansible_check_mode', '_ansible_no_log', '_ansible_debug', '_ansible_diff', '_ansible_verbosity', 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_selinux_special_fs', '_ansible_module_name', '_ansible_version', '_ansible_syslog_facility',
'_ansible_socket'] '_ansible_socket', '_ansible_shell_executable']
self._options_context = list() self._options_context = list()
if add_file_common_args: if add_file_common_args:
@ -1612,6 +1613,9 @@ class AnsibleModule(object):
elif k == '_ansible_socket': elif k == '_ansible_socket':
self._socket_path = v self._socket_path = v
elif k == '_ansible_shell_executable' and v:
self._shell = v
elif check_invalid_arguments and k not in legal_inputs: elif check_invalid_arguments and k not in legal_inputs:
unsupported_parameters.add(k) unsupported_parameters.add(k)
@ -2602,14 +2606,27 @@ class AnsibleModule(object):
strings on python3, use encoding=None to turn decoding to text off. strings on python3, use encoding=None to turn decoding to text off.
''' '''
if isinstance(args, list): if not isinstance(args, (list, binary_type, text_type)):
if use_unsafe_shell: 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]) args = " ".join([shlex_quote(x) for x in args])
shell = True
elif isinstance(args, (binary_type, text_type)): # not set explicitly, check if set by controller
if use_unsafe_shell: if executable:
shell = True args = [executable, '-c', args]
elif self._shell not in (None, '/bin/sh'):
args = [self._shell, '-c', args]
else: 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 python2.6 and below, shlex has problems with text type
# On python3, shlex needs a text type. # On python3, shlex needs a text type.
if PY2: if PY2:
@ -2617,18 +2634,9 @@ class AnsibleModule(object):
elif PY3: elif PY3:
args = to_text(args, errors='surrogateescape') args = to_text(args, errors='surrogateescape')
args = shlex.split(args) 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 # expand shellisms
if use_unsafe_shell: args = [os.path.expanduser(os.path.expandvars(x)) for x in args if x is not None]
if executable is None:
executable = os.environ.get('SHELL')
if executable:
args = [executable, '-c', args]
else:
shell = True
prompt_re = None prompt_re = None
if prompt_regex: if prompt_regex:
@ -2642,10 +2650,6 @@ class AnsibleModule(object):
except re.error: except re.error:
self.fail_json(msg="invalid prompt regular expression given to run_command") 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 rc = 0
msg = None msg = None
st_in = None st_in = None

@ -607,6 +607,9 @@ class ActionBase(with_metaclass(ABCMeta, object)):
# give the module the socket for persistent connections # give the module the socket for persistent connections
module_args['_ansible_socket'] = task_vars.get('ansible_socket') 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): 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. Transfer and run a module along with its arguments.

Loading…
Cancel
Save