|
|
|
@ -29,12 +29,32 @@ import traceback
|
|
|
|
|
|
|
|
|
|
from ansible import constants as C
|
|
|
|
|
from ansible.errors import AnsibleError, AnsibleFileNotFound
|
|
|
|
|
from ansible.module_utils.basic import FILE_COMMON_ARGUMENTS
|
|
|
|
|
from ansible.module_utils._text import to_bytes, to_native, to_text
|
|
|
|
|
from ansible.module_utils.parsing.convert_bool import boolean
|
|
|
|
|
from ansible.plugins.action import ActionBase
|
|
|
|
|
from ansible.utils.hashing import checksum
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Supplement the FILE_COMMON_ARGUMENTS with arguments that are specific to file
|
|
|
|
|
# FILE_COMMON_ARGUMENTS contains things that are not arguments of file so remove those as well
|
|
|
|
|
REAL_FILE_ARGS = frozenset(FILE_COMMON_ARGUMENTS.keys()).union(
|
|
|
|
|
('state', 'path', 'original_basename', 'recurse', 'force',
|
|
|
|
|
'_diff_peek', 'src')).difference(
|
|
|
|
|
('content', 'decrypt', 'backup', 'remote_src', 'regexp', 'delimiter',
|
|
|
|
|
'directory_mode', 'unsafe_writes'))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _create_remote_file_args(module_args):
|
|
|
|
|
"""remove keys that are not relevant to file"""
|
|
|
|
|
return dict((k, v) for k, v in module_args.items() if k in REAL_FILE_ARGS)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _create_remote_copy_args(module_args):
|
|
|
|
|
"""remove action plugin only keys"""
|
|
|
|
|
return dict((k, v) for k, v in module_args.items() if k not in ('content', 'decrypt'))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _walk_dirs(topdir, base_path=None, local_follow=False, trailing_slash_detector=None):
|
|
|
|
|
"""
|
|
|
|
|
Walk a filesystem tree returning enough information to copy the files
|
|
|
|
@ -188,10 +208,6 @@ class ActionModule(ActionBase):
|
|
|
|
|
|
|
|
|
|
TRANSFERS_FILES = True
|
|
|
|
|
|
|
|
|
|
def _create_remote_file_args(self, module_args):
|
|
|
|
|
# remove action plugin only keys
|
|
|
|
|
return dict((k, v) for k, v in module_args.items() if k not in ('content', 'decrypt'))
|
|
|
|
|
|
|
|
|
|
def _copy_file(self, source_full, source_rel, content, content_tempfile,
|
|
|
|
|
dest, task_vars, follow):
|
|
|
|
|
decrypt = boolean(self._task.args.get('decrypt', True), strict=False)
|
|
|
|
@ -283,7 +299,7 @@ class ActionModule(ActionBase):
|
|
|
|
|
|
|
|
|
|
# src and dest here come after original and override them
|
|
|
|
|
# we pass dest only to make sure it includes trailing slash in case of recursive copy
|
|
|
|
|
new_module_args = self._create_remote_file_args(self._task.args)
|
|
|
|
|
new_module_args = _create_remote_copy_args(self._task.args)
|
|
|
|
|
new_module_args.update(
|
|
|
|
|
dict(
|
|
|
|
|
src=tmp_src,
|
|
|
|
@ -318,12 +334,13 @@ class ActionModule(ActionBase):
|
|
|
|
|
dest = dest_status_nofollow['lnk_source']
|
|
|
|
|
|
|
|
|
|
# Build temporary module_args.
|
|
|
|
|
new_module_args = self._create_remote_file_args(self._task.args)
|
|
|
|
|
new_module_args = _create_remote_file_args(self._task.args)
|
|
|
|
|
new_module_args.update(
|
|
|
|
|
dict(
|
|
|
|
|
src=source_rel,
|
|
|
|
|
dest=dest,
|
|
|
|
|
original_basename=source_rel,
|
|
|
|
|
recurse=False,
|
|
|
|
|
state='file',
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
@ -340,34 +357,6 @@ class ActionModule(ActionBase):
|
|
|
|
|
result.update(module_return)
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
def _get_file_args(self):
|
|
|
|
|
new_module_args = {'recurse': False}
|
|
|
|
|
|
|
|
|
|
if 'attributes' in self._task.args:
|
|
|
|
|
new_module_args['attributes'] = self._task.args['attributes']
|
|
|
|
|
if 'follow' in self._task.args:
|
|
|
|
|
new_module_args['follow'] = self._task.args['follow']
|
|
|
|
|
if 'force' in self._task.args:
|
|
|
|
|
new_module_args['force'] = self._task.args['force']
|
|
|
|
|
if 'group' in self._task.args:
|
|
|
|
|
new_module_args['group'] = self._task.args['group']
|
|
|
|
|
if 'mode' in self._task.args:
|
|
|
|
|
new_module_args['mode'] = self._task.args['mode']
|
|
|
|
|
if 'owner' in self._task.args:
|
|
|
|
|
new_module_args['owner'] = self._task.args['owner']
|
|
|
|
|
if 'selevel' in self._task.args:
|
|
|
|
|
new_module_args['selevel'] = self._task.args['selevel']
|
|
|
|
|
if 'serole' in self._task.args:
|
|
|
|
|
new_module_args['serole'] = self._task.args['serole']
|
|
|
|
|
if 'setype' in self._task.args:
|
|
|
|
|
new_module_args['setype'] = self._task.args['setype']
|
|
|
|
|
if 'seuser' in self._task.args:
|
|
|
|
|
new_module_args['seuser'] = self._task.args['seuser']
|
|
|
|
|
if 'unsafe_writes' in self._task.args:
|
|
|
|
|
new_module_args['unsafe_writes'] = self._task.args['unsafe_writes']
|
|
|
|
|
|
|
|
|
|
return new_module_args
|
|
|
|
|
|
|
|
|
|
def _create_content_tempfile(self, content):
|
|
|
|
|
''' Create a tempfile containing defined content '''
|
|
|
|
|
fd, content_tempfile = tempfile.mkstemp(dir=C.DEFAULT_LOCAL_TMP)
|
|
|
|
@ -520,10 +509,12 @@ class ActionModule(ActionBase):
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
# Use file module to create these
|
|
|
|
|
new_module_args = self._get_file_args()
|
|
|
|
|
new_module_args = _create_remote_file_args(self._task.args)
|
|
|
|
|
new_module_args['path'] = os.path.join(dest, dest_path)
|
|
|
|
|
new_module_args['state'] = 'directory'
|
|
|
|
|
new_module_args['mode'] = self._task.args.get('directory_mode', None)
|
|
|
|
|
new_module_args['recurse'] = False
|
|
|
|
|
del new_module_args['src']
|
|
|
|
|
|
|
|
|
|
module_return = self._execute_module(module_name='file', module_args=new_module_args, task_vars=task_vars)
|
|
|
|
|
module_executed = True
|
|
|
|
@ -531,11 +522,12 @@ class ActionModule(ActionBase):
|
|
|
|
|
|
|
|
|
|
for target_path, dest_path in source_files['symlinks']:
|
|
|
|
|
# Copy symlinks over
|
|
|
|
|
new_module_args = self._get_file_args()
|
|
|
|
|
new_module_args = _create_remote_file_args(self._task.args)
|
|
|
|
|
new_module_args['path'] = os.path.join(dest, dest_path)
|
|
|
|
|
new_module_args['src'] = target_path
|
|
|
|
|
new_module_args['state'] = 'link'
|
|
|
|
|
new_module_args['force'] = True
|
|
|
|
|
|
|
|
|
|
# Only follow remote symlinks in the non-recursive case
|
|
|
|
|
if source_files['directories']:
|
|
|
|
|
new_module_args['follow'] = False
|
|
|
|
|