|
|
@ -68,7 +68,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|
|
|
|
|
|
|
|
|
|
|
:kwarg tmp: Deprecated parameter. This is no longer used. An action plugin that calls
|
|
|
|
:kwarg tmp: Deprecated parameter. This is no longer used. An action plugin that calls
|
|
|
|
another one and wants to use the same remote tmp for both should set
|
|
|
|
another one and wants to use the same remote tmp for both should set
|
|
|
|
self._connection._shell.tempdir rather than this parameter.
|
|
|
|
self._connection._shell.tmpdir rather than this parameter.
|
|
|
|
:kwarg task_vars: The variables (host vars, group vars, config vars,
|
|
|
|
:kwarg task_vars: The variables (host vars, group vars, config vars,
|
|
|
|
etc) associated with this task.
|
|
|
|
etc) associated with this task.
|
|
|
|
:returns: dictionary of results from the module
|
|
|
|
:returns: dictionary of results from the module
|
|
|
@ -82,8 +82,8 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|
|
|
|
|
|
|
|
|
|
|
if tmp is not None:
|
|
|
|
if tmp is not None:
|
|
|
|
result['warning'] = ['ActionModule.run() no longer honors the tmp parameter. Action'
|
|
|
|
result['warning'] = ['ActionModule.run() no longer honors the tmp parameter. Action'
|
|
|
|
' plugins should set self._connection._shell.tempdir to share'
|
|
|
|
' plugins should set self._connection._shell.tmpdir to share'
|
|
|
|
' the tempdir']
|
|
|
|
' the tmpdir']
|
|
|
|
del tmp
|
|
|
|
del tmp
|
|
|
|
|
|
|
|
|
|
|
|
if self._task.async_val and not self._supports_async:
|
|
|
|
if self._task.async_val and not self._supports_async:
|
|
|
@ -93,7 +93,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|
|
|
elif self._task.async_val and self._play_context.check_mode:
|
|
|
|
elif self._task.async_val and self._play_context.check_mode:
|
|
|
|
raise AnsibleActionFail('check mode and async cannot be used on same task.')
|
|
|
|
raise AnsibleActionFail('check mode and async cannot be used on same task.')
|
|
|
|
|
|
|
|
|
|
|
|
if self._connection._shell.tempdir is None and self._early_needs_tmp_path():
|
|
|
|
if self._connection._shell.tmpdir is None and self._early_needs_tmp_path():
|
|
|
|
self._make_tmp_path()
|
|
|
|
self._make_tmp_path()
|
|
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
return result
|
|
|
@ -201,7 +201,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|
|
|
|
|
|
|
|
|
|
|
def _early_needs_tmp_path(self):
|
|
|
|
def _early_needs_tmp_path(self):
|
|
|
|
'''
|
|
|
|
'''
|
|
|
|
Determines if a temp path should be created before the action is executed.
|
|
|
|
Determines if a tmp path should be created before the action is executed.
|
|
|
|
'''
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
return getattr(self, 'TRANSFERS_FILES', False)
|
|
|
|
return getattr(self, 'TRANSFERS_FILES', False)
|
|
|
@ -239,7 +239,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|
|
|
except KeyError:
|
|
|
|
except KeyError:
|
|
|
|
admin_users = ['root', remote_user] # plugin does not support admin_users
|
|
|
|
admin_users = ['root', remote_user] # plugin does not support admin_users
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
remote_tmp = self._connection._shell.get_option('remote_temp')
|
|
|
|
remote_tmp = self._connection._shell.get_option('remote_tmp')
|
|
|
|
except KeyError:
|
|
|
|
except KeyError:
|
|
|
|
remote_tmp = '~/ansible'
|
|
|
|
remote_tmp = '~/ansible'
|
|
|
|
|
|
|
|
|
|
|
@ -267,7 +267,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
output = ('Authentication or permission failure. '
|
|
|
|
output = ('Authentication or permission failure. '
|
|
|
|
'In some cases, you may have been able to authenticate and did not have permissions on the target directory. '
|
|
|
|
'In some cases, you may have been able to authenticate and did not have permissions on the target directory. '
|
|
|
|
'Consider changing the remote temp path in ansible.cfg to a path rooted in "/tmp". '
|
|
|
|
'Consider changing the remote tmp path in ansible.cfg to a path rooted in "/tmp". '
|
|
|
|
'Failed command was: %s, exited with result %d' % (cmd, result['rc']))
|
|
|
|
'Failed command was: %s, exited with result %d' % (cmd, result['rc']))
|
|
|
|
if 'stdout' in result and result['stdout'] != u'':
|
|
|
|
if 'stdout' in result and result['stdout'] != u'':
|
|
|
|
output = output + u", stdout output: %s" % result['stdout']
|
|
|
|
output = output + u", stdout output: %s" % result['stdout']
|
|
|
@ -289,10 +289,10 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|
|
|
if rc == '/':
|
|
|
|
if rc == '/':
|
|
|
|
raise AnsibleError('failed to resolve remote temporary directory from %s: `%s` returned empty string' % (basefile, cmd))
|
|
|
|
raise AnsibleError('failed to resolve remote temporary directory from %s: `%s` returned empty string' % (basefile, cmd))
|
|
|
|
|
|
|
|
|
|
|
|
self._connection._shell.tempdir = rc
|
|
|
|
self._connection._shell.tmpdir = rc
|
|
|
|
|
|
|
|
|
|
|
|
if not use_system_tmp:
|
|
|
|
if not use_system_tmp:
|
|
|
|
self._connection._shell.env.update({'ANSIBLE_REMOTE_TEMP': self._connection._shell.tempdir})
|
|
|
|
self._connection._shell.env.update({'ANSIBLE_REMOTE_TMP': self._connection._shell.tmpdir})
|
|
|
|
return rc
|
|
|
|
return rc
|
|
|
|
|
|
|
|
|
|
|
|
def _should_remove_tmp_path(self, tmp_path):
|
|
|
|
def _should_remove_tmp_path(self, tmp_path):
|
|
|
@ -302,8 +302,8 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|
|
|
def _remove_tmp_path(self, tmp_path):
|
|
|
|
def _remove_tmp_path(self, tmp_path):
|
|
|
|
'''Remove a temporary path we created. '''
|
|
|
|
'''Remove a temporary path we created. '''
|
|
|
|
|
|
|
|
|
|
|
|
if tmp_path is None and self._connection._shell.tempdir:
|
|
|
|
if tmp_path is None and self._connection._shell.tmpdir:
|
|
|
|
tmp_path = self._connection._shell.tempdir
|
|
|
|
tmp_path = self._connection._shell.tmpdir
|
|
|
|
|
|
|
|
|
|
|
|
if self._should_remove_tmp_path(tmp_path):
|
|
|
|
if self._should_remove_tmp_path(tmp_path):
|
|
|
|
cmd = self._connection._shell.remove(tmp_path, recurse=True)
|
|
|
|
cmd = self._connection._shell.remove(tmp_path, recurse=True)
|
|
|
@ -316,7 +316,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|
|
|
display.warning('Error deleting remote temporary files (rc: %s, stderr: %s})'
|
|
|
|
display.warning('Error deleting remote temporary files (rc: %s, stderr: %s})'
|
|
|
|
% (tmp_rm_res.get('rc'), tmp_rm_res.get('stderr', 'No error string available.')))
|
|
|
|
% (tmp_rm_res.get('rc'), tmp_rm_res.get('stderr', 'No error string available.')))
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
self._connection._shell.tempdir = None
|
|
|
|
self._connection._shell.tmpdir = None
|
|
|
|
|
|
|
|
|
|
|
|
def _transfer_file(self, local_path, remote_path):
|
|
|
|
def _transfer_file(self, local_path, remote_path):
|
|
|
|
self._connection.put_file(local_path, remote_path)
|
|
|
|
self._connection.put_file(local_path, remote_path)
|
|
|
@ -493,8 +493,8 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|
|
|
'''
|
|
|
|
'''
|
|
|
|
if tmp is not None:
|
|
|
|
if tmp is not None:
|
|
|
|
display.warning('_execute_remote_stat no longer honors the tmp parameter. Action'
|
|
|
|
display.warning('_execute_remote_stat no longer honors the tmp parameter. Action'
|
|
|
|
' plugins should set self._connection._shell.tempdir to share'
|
|
|
|
' plugins should set self._connection._shell.tmpdir to share'
|
|
|
|
' the tempdir')
|
|
|
|
' the tmpdir')
|
|
|
|
del tmp # No longer used
|
|
|
|
del tmp # No longer used
|
|
|
|
|
|
|
|
|
|
|
|
module_args = dict(
|
|
|
|
module_args = dict(
|
|
|
@ -647,7 +647,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|
|
|
module_args['_ansible_shell_executable'] = self._play_context.executable
|
|
|
|
module_args['_ansible_shell_executable'] = self._play_context.executable
|
|
|
|
|
|
|
|
|
|
|
|
# make sure all commands use the designated temporary directory
|
|
|
|
# make sure all commands use the designated temporary directory
|
|
|
|
module_args['_ansible_tempdir'] = self._connection._shell.tempdir
|
|
|
|
module_args['_ansible_tmpdir'] = self._connection._shell.tmpdir
|
|
|
|
|
|
|
|
|
|
|
|
def _update_connection_options(self, options, variables=None):
|
|
|
|
def _update_connection_options(self, options, variables=None):
|
|
|
|
''' ensures connections have the appropriate information '''
|
|
|
|
''' ensures connections have the appropriate information '''
|
|
|
@ -670,12 +670,12 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|
|
|
'''
|
|
|
|
'''
|
|
|
|
if tmp is not None:
|
|
|
|
if tmp is not None:
|
|
|
|
display.warning('_execute_module no longer honors the tmp parameter. Action plugins'
|
|
|
|
display.warning('_execute_module no longer honors the tmp parameter. Action plugins'
|
|
|
|
' should set self._connection._shell.tempdir to share the tempdir')
|
|
|
|
' should set self._connection._shell.tmpdir to share the tmpdir')
|
|
|
|
del tmp # No longer used
|
|
|
|
del tmp # No longer used
|
|
|
|
if delete_remote_tmp is not None:
|
|
|
|
if delete_remote_tmp is not None:
|
|
|
|
display.warning('_execute_module no longer honors the delete_remote_tmp parameter.'
|
|
|
|
display.warning('_execute_module no longer honors the delete_remote_tmp parameter.'
|
|
|
|
' Action plugins should check self._connection._shell.tempdir to'
|
|
|
|
' Action plugins should check self._connection._shell.tmpdir to'
|
|
|
|
' see if a tempdir existed before they were called to determine'
|
|
|
|
' see if a tmpdir existed before they were called to determine'
|
|
|
|
' if they are responsible for removing it.')
|
|
|
|
' if they are responsible for removing it.')
|
|
|
|
del delete_remote_tmp # No longer used
|
|
|
|
del delete_remote_tmp # No longer used
|
|
|
|
|
|
|
|
|
|
|
@ -696,22 +696,22 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|
|
|
if not shebang and module_style != 'binary':
|
|
|
|
if not shebang and module_style != 'binary':
|
|
|
|
raise AnsibleError("module (%s) is missing interpreter line" % module_name)
|
|
|
|
raise AnsibleError("module (%s) is missing interpreter line" % module_name)
|
|
|
|
|
|
|
|
|
|
|
|
tempdir = self._connection._shell.tempdir
|
|
|
|
tmpdir = self._connection._shell.tmpdir
|
|
|
|
remote_module_path = None
|
|
|
|
remote_module_path = None
|
|
|
|
|
|
|
|
|
|
|
|
if not self._is_pipelining_enabled(module_style, wrap_async):
|
|
|
|
if not self._is_pipelining_enabled(module_style, wrap_async):
|
|
|
|
# we might need remote temp dir
|
|
|
|
# we might need remote tmp dir
|
|
|
|
if tempdir is None:
|
|
|
|
if tmpdir is None:
|
|
|
|
self._make_tmp_path()
|
|
|
|
self._make_tmp_path()
|
|
|
|
tempdir = self._connection._shell.tempdir
|
|
|
|
tmpdir = self._connection._shell.tmpdir
|
|
|
|
|
|
|
|
|
|
|
|
remote_module_filename = self._connection._shell.get_remote_filename(module_path)
|
|
|
|
remote_module_filename = self._connection._shell.get_remote_filename(module_path)
|
|
|
|
remote_module_path = self._connection._shell.join_path(tempdir, remote_module_filename)
|
|
|
|
remote_module_path = self._connection._shell.join_path(tmpdir, remote_module_filename)
|
|
|
|
|
|
|
|
|
|
|
|
args_file_path = None
|
|
|
|
args_file_path = None
|
|
|
|
if module_style in ('old', 'non_native_want_json', 'binary'):
|
|
|
|
if module_style in ('old', 'non_native_want_json', 'binary'):
|
|
|
|
# we'll also need a temp file to hold our module arguments
|
|
|
|
# we'll also need a tmp file to hold our module arguments
|
|
|
|
args_file_path = self._connection._shell.join_path(tempdir, 'args')
|
|
|
|
args_file_path = self._connection._shell.join_path(tmpdir, 'args')
|
|
|
|
|
|
|
|
|
|
|
|
if remote_module_path or module_style != 'new':
|
|
|
|
if remote_module_path or module_style != 'new':
|
|
|
|
display.debug("transferring module to remote %s" % remote_module_path)
|
|
|
|
display.debug("transferring module to remote %s" % remote_module_path)
|
|
|
@ -733,8 +733,8 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|
|
|
environment_string = self._compute_environment_string()
|
|
|
|
environment_string = self._compute_environment_string()
|
|
|
|
|
|
|
|
|
|
|
|
remote_files = []
|
|
|
|
remote_files = []
|
|
|
|
if tempdir and remote_module_path:
|
|
|
|
if tmpdir and remote_module_path:
|
|
|
|
remote_files = [tempdir, remote_module_path]
|
|
|
|
remote_files = [tmpdir, remote_module_path]
|
|
|
|
|
|
|
|
|
|
|
|
if args_file_path:
|
|
|
|
if args_file_path:
|
|
|
|
remote_files.append(args_file_path)
|
|
|
|
remote_files.append(args_file_path)
|
|
|
@ -748,7 +748,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|
|
|
(async_module_style, shebang, async_module_data, async_module_path) = self._configure_module(module_name='async_wrapper', module_args=dict(),
|
|
|
|
(async_module_style, shebang, async_module_data, async_module_path) = self._configure_module(module_name='async_wrapper', module_args=dict(),
|
|
|
|
task_vars=task_vars)
|
|
|
|
task_vars=task_vars)
|
|
|
|
async_module_remote_filename = self._connection._shell.get_remote_filename(async_module_path)
|
|
|
|
async_module_remote_filename = self._connection._shell.get_remote_filename(async_module_path)
|
|
|
|
remote_async_module_path = self._connection._shell.join_path(tempdir, async_module_remote_filename)
|
|
|
|
remote_async_module_path = self._connection._shell.join_path(tmpdir, async_module_remote_filename)
|
|
|
|
self._transfer_data(remote_async_module_path, async_module_data)
|
|
|
|
self._transfer_data(remote_async_module_path, async_module_data)
|
|
|
|
remote_files.append(remote_async_module_path)
|
|
|
|
remote_files.append(remote_async_module_path)
|
|
|
|
|
|
|
|
|
|
|
@ -770,7 +770,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|
|
|
# maintain a fixed number of positional parameters for async_wrapper
|
|
|
|
# maintain a fixed number of positional parameters for async_wrapper
|
|
|
|
async_cmd.append('_')
|
|
|
|
async_cmd.append('_')
|
|
|
|
|
|
|
|
|
|
|
|
if not self._should_remove_tmp_path(tempdir):
|
|
|
|
if not self._should_remove_tmp_path(tmpdir):
|
|
|
|
async_cmd.append("-preserve_tmp")
|
|
|
|
async_cmd.append("-preserve_tmp")
|
|
|
|
|
|
|
|
|
|
|
|
cmd = " ".join(to_text(x) for x in async_cmd)
|
|
|
|
cmd = " ".join(to_text(x) for x in async_cmd)
|
|
|
@ -784,7 +784,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|
|
|
|
|
|
|
|
|
|
|
cmd = self._connection._shell.build_module_command(environment_string, shebang, cmd, arg_path=args_file_path).strip()
|
|
|
|
cmd = self._connection._shell.build_module_command(environment_string, shebang, cmd, arg_path=args_file_path).strip()
|
|
|
|
|
|
|
|
|
|
|
|
# Fix permissions of the tempdir path and tempdir files. This should be called after all
|
|
|
|
# Fix permissions of the tmpdir path and tmpdir files. This should be called after all
|
|
|
|
# files have been transferred.
|
|
|
|
# files have been transferred.
|
|
|
|
if remote_files:
|
|
|
|
if remote_files:
|
|
|
|
# remove none/empty
|
|
|
|
# remove none/empty
|
|
|
@ -806,9 +806,9 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
|
|
|
remove_internal_keys(data)
|
|
|
|
remove_internal_keys(data)
|
|
|
|
|
|
|
|
|
|
|
|
if wrap_async:
|
|
|
|
if wrap_async:
|
|
|
|
# async_wrapper will clean up its tempdir on its own so we want the controller side to
|
|
|
|
# async_wrapper will clean up its tmpdir on its own so we want the controller side to
|
|
|
|
# forget about it now
|
|
|
|
# forget about it now
|
|
|
|
self._connection._shell.tempdir = None
|
|
|
|
self._connection._shell.tmpdir = None
|
|
|
|
|
|
|
|
|
|
|
|
# FIXME: for backwards compat, figure out if still makes sense
|
|
|
|
# FIXME: for backwards compat, figure out if still makes sense
|
|
|
|
data['changed'] = True
|
|
|
|
data['changed'] = True
|
|
|
|