script: Add support for chdir argument

pull/26542/merge
Karim BEN YOUSSEF 7 years ago committed by Toshio Kuratomi
parent 3c4db1e8dd
commit 804f40f7a5

@ -50,6 +50,12 @@ options:
required: no required: no
default: null default: null
version_added: "1.5" version_added: "1.5"
chdir:
description:
- cd into this directory on the remote node before running the script
version_added: "2.4"
required: false
default: null
notes: notes:
- It is usually preferable to write Ansible modules than pushing scripts. Convert your script to an Ansible module for bonus points! - It is usually preferable to write Ansible modules than pushing scripts. Convert your script to an Ansible module for bonus points!
- The ssh connection plugin will force pseudo-tty allocation via -tt when scripts are executed. pseudo-ttys do not have a stderr channel and all - The ssh connection plugin will force pseudo-tty allocation via -tt when scripts are executed. pseudo-ttys do not have a stderr channel and all

@ -842,7 +842,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
data['rc'] = res['rc'] data['rc'] = res['rc']
return data return data
def _low_level_execute_command(self, cmd, sudoable=True, in_data=None, executable=None, encoding_errors='surrogate_then_replace'): def _low_level_execute_command(self, cmd, sudoable=True, in_data=None, executable=None, encoding_errors='surrogate_then_replace', chdir=None):
''' '''
This is the function which executes the low level shell command, which This is the function which executes the low level shell command, which
may be commands to create/remove directories for temporary files, or to may be commands to create/remove directories for temporary files, or to
@ -855,6 +855,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
used as a key or is going to be written back out to a file used as a key or is going to be written back out to a file
verbatim, then this won't work. May have to use some sort of verbatim, then this won't work. May have to use some sort of
replacement strategy (python3 could use surrogateescape) replacement strategy (python3 could use surrogateescape)
:kwarg chdir: cd into this directory before executing the command.
''' '''
display.debug("_low_level_execute_command(): starting") display.debug("_low_level_execute_command(): starting")
@ -863,6 +864,10 @@ class ActionBase(with_metaclass(ABCMeta, object)):
# display.debug("_low_level_execute_command(): no command, exiting") # display.debug("_low_level_execute_command(): no command, exiting")
# return dict(stdout='', stderr='', rc=254) # return dict(stdout='', stderr='', rc=254)
if chdir:
display.debug("_low_level_execute_command(): changing cwd to %s for this command" % chdir)
cmd = self._connection._shell.append_command('cd %s' % chdir, cmd)
allow_same_user = C.BECOME_ALLOW_SAME_USER allow_same_user = C.BECOME_ALLOW_SAME_USER
same_user = self._play_context.become_user == self._play_context.remote_user same_user = self._play_context.become_user == self._play_context.remote_user
if sudoable and self._play_context.become and (allow_same_user or not same_user): if sudoable and self._play_context.become and (allow_same_user or not same_user):

@ -18,6 +18,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type __metaclass__ = type
import os import os
import re
from ansible.errors import AnsibleError from ansible.errors import AnsibleError
from ansible.module_utils._text import to_native from ansible.module_utils._text import to_native
@ -27,6 +28,10 @@ from ansible.plugins.action import ActionBase
class ActionModule(ActionBase): class ActionModule(ActionBase):
TRANSFERS_FILES = True TRANSFERS_FILES = True
# On Windows platform, absolute paths begin with a (back)slash
# after chopping off a potential drive letter.
windows_absolute_path_detection = re.compile(r'^(?:[a-zA-Z]\:)?(\\|\/)')
def run(self, tmp=None, task_vars=None): def run(self, tmp=None, task_vars=None):
''' handler for file transfer operations ''' ''' handler for file transfer operations '''
if task_vars is None: if task_vars is None:
@ -55,6 +60,18 @@ class ActionModule(ActionBase):
self._remove_tmp_path(tmp) self._remove_tmp_path(tmp)
return dict(skipped=True, msg=("skipped, since %s does not exist" % removes)) return dict(skipped=True, msg=("skipped, since %s does not exist" % removes))
# The chdir must be absolute, because a relative path would rely on
# remote node behaviour & user config.
chdir = self._task.args.get('chdir')
if chdir:
# Powershell is the only Windows-path aware shell
if self._connection._shell.SHELL_FAMILY == 'powershell' and \
not self.windows_absolute_path_detection.matches(chdir):
return dict(failed=True, msg='chdir %s must be an absolute path for a Windows remote node' % chdir)
# Every other shell is unix-path-aware.
if self._connection._shell.SHELL_FAMILY != 'powershell' and not chdir.startswith('/'):
return dict(failed=True, msg='chdir %s must be an absolute path for a Unix-aware remote node' % chdir)
# the script name is the first item in the raw params, so we split it # the script name is the first item in the raw params, so we split it
# out now so we know the file name we need to transfer to the remote, # out now so we know the file name we need to transfer to the remote,
# and everything else is an argument to the script which we need later # and everything else is an argument to the script which we need later
@ -86,7 +103,7 @@ class ActionModule(ActionBase):
if self._connection.transport == "winrm": if self._connection.transport == "winrm":
exec_data = self._connection._create_raw_wrapper_payload(script_cmd, env_dict) exec_data = self._connection._create_raw_wrapper_payload(script_cmd, env_dict)
result.update(self._low_level_execute_command(cmd=script_cmd, in_data=exec_data, sudoable=True)) result.update(self._low_level_execute_command(cmd=script_cmd, in_data=exec_data, sudoable=True, chdir=chdir))
# clean up after # clean up after
self._remove_tmp_path(tmp) self._remove_tmp_path(tmp)

Loading…
Cancel
Save