copy - support recursive copying with remote_src (#43998)

* Allow copy module to work with recursive and remote_src #14131
pull/51879/head
Shuang Wang 6 years ago committed by Toshio Kuratomi
parent fb6e91bf98
commit cd1faca6e0

@ -0,0 +1,3 @@
---
minor_changes:
- copy - support recursive copying with remote_src

@ -78,7 +78,7 @@ options:
description: description:
- If C(no), it will search for I(src) at originating/master machine. - If C(no), it will search for I(src) at originating/master machine.
- If C(yes) it will go to the remote/target machine for the I(src). Default is C(no). - If C(yes) it will go to the remote/target machine for the I(src). Default is C(no).
- Currently I(remote_src) does not support recursive copying. - I(remote_src) supports recursive copying as of version 2.8.
- I(remote_src) only works with C(mode=preserve) as of version 2.6. - I(remote_src) only works with C(mode=preserve) as of version 2.6.
type: bool type: bool
default: 'no' default: 'no'
@ -232,6 +232,9 @@ state:
import os import os
import os.path import os.path
import shutil import shutil
import filecmp
import pwd
import grp
import stat import stat
import errno import errno
import tempfile import tempfile
@ -277,6 +280,163 @@ def adjust_recursive_directory_permissions(pre_existing_dir, new_directory_list,
return changed return changed
def chown_recursive(path, module):
changed = False
owner = module.params['owner']
group = module.params['group']
if owner is not None:
if not module.check_mode:
for dirpath, dirnames, filenames in os.walk(path):
owner_changed = module.set_owner_if_different(dirpath, owner, False)
if owner_changed is True:
changed = owner_changed
for dir in [os.path.join(dirpath, d) for d in dirnames]:
owner_changed = module.set_owner_if_different(dir, owner, False)
if owner_changed is True:
changed = owner_changed
for file in [os.path.join(dirpath, f) for f in filenames]:
owner_changed = module.set_owner_if_different(file, owner, False)
if owner_changed is True:
changed = owner_changed
else:
uid = pwd.getpwnam(owner).pw_uid
for dirpath, dirnames, filenames in os.walk(path):
owner_changed = (os.stat(dirpath).st_uid != uid)
if owner_changed is True:
changed = owner_changed
for dir in [os.path.join(dirpath, d) for d in dirnames]:
owner_changed = (os.stat(dir).st_uid != uid)
if owner_changed is True:
changed = owner_changed
for file in [os.path.join(dirpath, f) for f in filenames]:
owner_changed = (os.stat(file).st_uid != uid)
if owner_changed is True:
changed = owner_changed
if group is not None:
if not module.check_mode:
for dirpath, dirnames, filenames in os.walk(path):
group_changed = module.set_group_if_different(dirpath, group, False)
if group_changed is True:
changed = group_changed
for dir in [os.path.join(dirpath, d) for d in dirnames]:
group_changed = module.set_group_if_different(dir, group, False)
if group_changed is True:
changed = group_changed
for file in [os.path.join(dirpath, f) for f in filenames]:
group_changed = module.set_group_if_different(file, group, False)
if group_changed is True:
changed = group_changed
else:
gid = grp.getgrnam(group).gr_gid
for dirpath, dirnames, filenames in os.walk(path):
group_changed = (os.stat(dirpath).st_gid != gid)
if group_changed is True:
changed = group_changed
for dir in [os.path.join(dirpath, d) for d in dirnames]:
group_changed = (os.stat(dir).st_gid != gid)
if group_changed is True:
changed = group_changed
for file in [os.path.join(dirpath, f) for f in filenames]:
group_changed = (os.stat(file).st_gid != gid)
if group_changed is True:
changed = group_changed
return changed
def copy_diff_files(src, dest, module):
changed = False
owner = module.params['owner']
group = module.params['group']
local_follow = module.params['local_follow']
diff_files = filecmp.dircmp(src, dest).diff_files
if len(diff_files):
changed = True
if not module.check_mode:
for item in diff_files:
src_item_path = os.path.join(src, item)
dest_item_path = os.path.join(dest, item)
b_src_item_path = to_bytes(src_item_path, errors='surrogate_or_strict')
b_dest_item_path = to_bytes(dest_item_path, errors='surrogate_or_strict')
if os.path.islink(b_src_item_path) and local_follow is False:
linkto = os.readlink(b_src_item_path)
os.symlink(linkto, b_dest_item_path)
else:
shutil.copyfile(b_src_item_path, b_dest_item_path)
if owner is not None:
module.set_owner_if_different(b_dest_item_path, owner, False)
if group is not None:
module.set_group_if_different(b_dest_item_path, group, False)
changed = True
return changed
def copy_left_only(src, dest, module):
changed = False
owner = module.params['owner']
group = module.params['group']
local_follow = module.params['local_follow']
left_only = filecmp.dircmp(src, dest).left_only
if len(left_only):
changed = True
if not module.check_mode:
for item in left_only:
src_item_path = os.path.join(src, item)
dest_item_path = os.path.join(dest, item)
b_src_item_path = to_bytes(src_item_path, errors='surrogate_or_strict')
b_dest_item_path = to_bytes(dest_item_path, errors='surrogate_or_strict')
if os.path.islink(b_src_item_path) and os.path.isdir(b_src_item_path) and local_follow is True:
shutil.copytree(b_src_item_path, b_dest_item_path, symlinks=not(local_follow))
chown_recursive(b_dest_item_path, module)
if os.path.islink(b_src_item_path) and os.path.isdir(b_src_item_path) and local_follow is False:
linkto = os.readlink(b_src_item_path)
os.symlink(linkto, b_dest_item_path)
if os.path.islink(b_src_item_path) and os.path.isfile(b_src_item_path) and local_follow is True:
shutil.copyfile(b_src_item_path, b_dest_item_path)
if owner is not None:
module.set_owner_if_different(b_dest_item_path, owner, False)
if group is not None:
module.set_group_if_different(b_dest_item_path, group, False)
if os.path.islink(b_src_item_path) and os.path.isfile(b_src_item_path) and local_follow is False:
linkto = os.readlink(b_src_item_path)
os.symlink(linkto, b_dest_item_path)
if not os.path.islink(b_src_item_path) and os.path.isfile(b_src_item_path):
shutil.copyfile(b_src_item_path, b_dest_item_path)
if owner is not None:
module.set_owner_if_different(b_dest_item_path, owner, False)
if group is not None:
module.set_group_if_different(b_dest_item_path, group, False)
if not os.path.islink(b_src_item_path) and os.path.isdir(b_src_item_path):
shutil.copytree(b_src_item_path, b_dest_item_path, symlinks=not(local_follow))
chown_recursive(b_dest_item_path, module)
changed = True
return changed
def copy_common_dirs(src, dest, module):
changed = False
common_dirs = filecmp.dircmp(src, dest).common_dirs
for item in common_dirs:
src_item_path = os.path.join(src, item)
dest_item_path = os.path.join(dest, item)
b_src_item_path = to_bytes(src_item_path, errors='surrogate_or_strict')
b_dest_item_path = to_bytes(dest_item_path, errors='surrogate_or_strict')
diff_files_changed = copy_diff_files(b_src_item_path, b_dest_item_path, module)
left_only_changed = copy_left_only(b_src_item_path, b_dest_item_path, module)
if diff_files_changed or left_only_changed:
changed = True
return changed
def main(): def main():
module = AnsibleModule( module = AnsibleModule(
@ -310,6 +470,7 @@ def main():
_original_basename = module.params.get('_original_basename', None) _original_basename = module.params.get('_original_basename', None)
validate = module.params.get('validate', None) validate = module.params.get('validate', None)
follow = module.params['follow'] follow = module.params['follow']
local_follow = module.params['local_follow']
mode = module.params['mode'] mode = module.params['mode']
owner = module.params['owner'] owner = module.params['owner']
group = module.params['group'] group = module.params['group']
@ -320,8 +481,6 @@ def main():
module.fail_json(msg="Source %s not found" % (src)) module.fail_json(msg="Source %s not found" % (src))
if not os.access(b_src, os.R_OK): if not os.access(b_src, os.R_OK):
module.fail_json(msg="Source %s not readable" % (src)) module.fail_json(msg="Source %s not readable" % (src))
if os.path.isdir(b_src):
module.fail_json(msg="Remote copy does not support recursive copy of directory: %s" % (src))
# Preserve is usually handled in the action plugin but mode + remote_src has to be done on the # Preserve is usually handled in the action plugin but mode + remote_src has to be done on the
# remote host # remote host
@ -329,11 +488,19 @@ def main():
module.params['mode'] = '0%03o' % stat.S_IMODE(os.stat(b_src).st_mode) module.params['mode'] = '0%03o' % stat.S_IMODE(os.stat(b_src).st_mode)
mode = module.params['mode'] mode = module.params['mode']
checksum_src = module.sha1(src)
checksum_dest = None checksum_dest = None
if os.path.isfile(src):
checksum_src = module.sha1(src)
else:
checksum_src = None
# Backwards compat only. This will be None in FIPS mode # Backwards compat only. This will be None in FIPS mode
try: try:
md5sum_src = module.md5(src) if os.path.isfile(src):
md5sum_src = module.md5(src)
else:
md5sum_src = None
except ValueError: except ValueError:
md5sum_src = None md5sum_src = None
@ -381,7 +548,7 @@ def main():
dest = to_native(b_dest, errors='surrogate_or_strict') dest = to_native(b_dest, errors='surrogate_or_strict')
if not force: if not force:
module.exit_json(msg="file already exists", src=src, dest=dest, changed=False) module.exit_json(msg="file already exists", src=src, dest=dest, changed=False)
if os.access(b_dest, os.R_OK): if os.access(b_dest, os.R_OK) and os.path.isfile(dest):
checksum_dest = module.sha1(dest) checksum_dest = module.sha1(dest)
else: else:
if not os.path.exists(os.path.dirname(b_dest)): if not os.path.exists(os.path.dirname(b_dest)):
@ -425,7 +592,7 @@ def main():
if rc != 0: if rc != 0:
module.fail_json(msg="failed to validate", exit_status=rc, stdout=out, stderr=err) module.fail_json(msg="failed to validate", exit_status=rc, stdout=out, stderr=err)
b_mysrc = b_src b_mysrc = b_src
if remote_src: if remote_src and os.path.isfile(b_src):
_, b_mysrc = tempfile.mkstemp(dir=os.path.dirname(b_dest)) _, b_mysrc = tempfile.mkstemp(dir=os.path.dirname(b_dest))
shutil.copyfile(b_src, b_mysrc) shutil.copyfile(b_src, b_mysrc)
@ -443,6 +610,61 @@ def main():
else: else:
changed = False changed = False
if checksum_src is None and checksum_dest is None:
if remote_src and os.path.isdir(module.params['src']):
b_src = to_bytes(module.params['src'], errors='surrogate_or_strict')
b_dest = to_bytes(module.params['dest'], errors='surrogate_or_strict')
if src.endswith(os.path.sep) and os.path.isdir(module.params['dest']):
diff_files_changed = copy_diff_files(b_src, b_dest, module)
left_only_changed = copy_left_only(b_src, b_dest, module)
common_dirs_changed = copy_common_dirs(b_src, b_dest, module)
owner_group_changed = chown_recursive(b_dest, module)
if diff_files_changed or left_only_changed or common_dirs_changed or owner_group_changed:
changed = True
if src.endswith(os.path.sep) and not os.path.exists(module.params['dest']):
b_basename = to_bytes(os.path.basename(src), errors='surrogate_or_strict')
b_dest = to_bytes(os.path.join(b_dest, b_basename), errors='surrogate_or_strict')
b_src = to_bytes(os.path.join(module.params['src'], ""), errors='surrogate_or_strict')
if not module.check_mode:
shutil.copytree(b_src, b_dest, symlinks=not(local_follow))
chown_recursive(dest, module)
changed = True
if not src.endswith(os.path.sep) and os.path.isdir(module.params['dest']):
b_basename = to_bytes(os.path.basename(src), errors='surrogate_or_strict')
b_dest = to_bytes(os.path.join(b_dest, b_basename), errors='surrogate_or_strict')
b_src = to_bytes(os.path.join(module.params['src'], ""), errors='surrogate_or_strict')
if not module.check_mode and not os.path.exists(b_dest):
shutil.copytree(b_src, b_dest, symlinks=not(local_follow))
changed = True
chown_recursive(dest, module)
if module.check_mode and not os.path.exists(b_dest):
changed = True
if os.path.exists(b_dest):
diff_files_changed = copy_diff_files(b_src, b_dest, module)
left_only_changed = copy_left_only(b_src, b_dest, module)
common_dirs_changed = copy_common_dirs(b_src, b_dest, module)
owner_group_changed = chown_recursive(b_dest, module)
if diff_files_changed or left_only_changed or common_dirs_changed or owner_group_changed:
changed = True
if not src.endswith(os.path.sep) and not os.path.exists(module.params['dest']):
b_basename = to_bytes(os.path.basename(module.params['src']), errors='surrogate_or_strict')
b_dest = to_bytes(os.path.join(b_dest, b_basename), errors='surrogate_or_strict')
if not module.check_mode and not os.path.exists(b_dest):
os.makedirs(b_dest)
b_src = to_bytes(os.path.join(module.params['src'], ""), errors='surrogate_or_strict')
diff_files_changed = copy_diff_files(b_src, b_dest, module)
left_only_changed = copy_left_only(b_src, b_dest, module)
common_dirs_changed = copy_common_dirs(b_src, b_dest, module)
owner_group_changed = chown_recursive(b_dest, module)
if diff_files_changed or left_only_changed or common_dirs_changed or owner_group_changed:
changed = True
if module.check_mode and not os.path.exists(b_dest):
changed = True
res_args = dict( res_args = dict(
dest=dest, src=src, md5sum=md5sum_src, checksum=checksum_src, changed=changed dest=dest, src=src, md5sum=md5sum_src, checksum=checksum_src, changed=changed
) )

@ -1488,3 +1488,612 @@
- 'new_sub_dir1/foo.txt' - 'new_sub_dir1/foo.txt'
loop_control: loop_control:
loop_var: 'dest' loop_var: 'dest'
#
# Recursive copying on remote host
#
## prepare for test
- block:
- name: execute - Create a test src dir
file:
path: '{{ remote_dir }}/remote_dir_src'
state: directory
- name: gather - Stat the remote_dir_src
stat:
path: '{{ remote_dir }}/remote_dir_src'
register: stat_remote_dir_src_before
- name: execute - Create a subdir
file:
path: '{{ remote_dir }}/remote_dir_src/subdir'
state: directory
- name: gather - Stat the remote_dir_src/subdir
stat:
path: '{{ remote_dir }}/remote_dir_src/subdir'
register: stat_remote_dir_src_subdir_before
- name: execute - Create a file in the top of src
copy:
dest: '{{ remote_dir }}/remote_dir_src/file1'
content: 'hello world 1'
- name: gather - Stat the remote_dir_src/file1
stat:
path: '{{ remote_dir }}/remote_dir_src/file1'
register: stat_remote_dir_src_file1_before
- name: execute - Create a file in the subdir
copy:
dest: '{{ remote_dir }}/remote_dir_src/subdir/file12'
content: 'hello world 12'
- name: gather - Stat the remote_dir_src/subdir/file12
stat:
path: '{{ remote_dir }}/remote_dir_src/subdir/file12'
register: stat_remote_dir_src_subdir_file12_before
- name: execute - Create a link to the file12
file:
path: '{{ remote_dir }}/remote_dir_src/link_file12'
src: '{{ remote_dir }}/remote_dir_src/subdir/file12'
state: link
- name: gather - Stat the remote_dir_src/link_file12
stat:
path: '{{ remote_dir }}/remote_dir_src/link_file12'
register: stat_remote_dir_src_link_file12_before
### test when src endswith os.sep and dest isdir
- block:
### local_follow: True
- name: execute - Create a test dest dir
file:
path: '{{ remote_dir }}/testcase1_local_follow_true'
state: directory
- name: execute - Copy the directory on remote with local_follow True
copy:
remote_src: True
src: '{{ remote_dir }}/remote_dir_src/'
dest: '{{ remote_dir }}/testcase1_local_follow_true'
local_follow: True
register: testcase1
- name: gather - Stat the testcase1_local_follow_true
stat:
path: '{{ remote_dir }}/testcase1_local_follow_true'
register: stat_testcase1_local_follow_true
- name: gather - Stat the testcase1_local_follow_true/subdir
stat:
path: '{{ remote_dir }}/testcase1_local_follow_true/subdir'
register: stat_testcase1_local_follow_true_subdir
- name: gather - Stat the testcase1_local_follow_true/file1
stat:
path: '{{ remote_dir }}/testcase1_local_follow_true/file1'
register: stat_testcase1_local_follow_true_file1
- name: gather - Stat the testcase1_local_follow_true/subdir/file12
stat:
path: '{{ remote_dir }}/testcase1_local_follow_true/subdir/file12'
register: stat_testcase1_local_follow_true_subdir_file12
- name: gather - Stat the testcase1_local_follow_true/link_file12
stat:
path: '{{ remote_dir }}/testcase1_local_follow_true/link_file12'
register: stat_testcase1_local_follow_true_link_file12
- name: assert - remote_dir_src has copied with local_follow True.
assert:
that:
- testcase1 is changed
- "stat_testcase1_local_follow_true.stat.isdir"
- "stat_testcase1_local_follow_true_subdir.stat.isdir"
- "stat_testcase1_local_follow_true_file1.stat.exists"
- "stat_remote_dir_src_file1_before.stat.checksum == stat_testcase1_local_follow_true_file1.stat.checksum"
- "stat_testcase1_local_follow_true_subdir_file12.stat.exists"
- "stat_remote_dir_src_subdir_file12_before.stat.checksum == stat_testcase1_local_follow_true_subdir_file12.stat.checksum"
- "stat_testcase1_local_follow_true_link_file12.stat.exists"
- "not stat_testcase1_local_follow_true_link_file12.stat.islnk"
- "stat_remote_dir_src_subdir_file12_before.stat.checksum == stat_testcase1_local_follow_true_link_file12.stat.checksum"
### local_follow: False
- name: execute - Create a test dest dir
file:
path: '{{ remote_dir }}/testcase1_local_follow_false'
state: directory
- name: execute - Copy the directory on remote with local_follow False
copy:
remote_src: True
src: '{{ remote_dir }}/remote_dir_src/'
dest: '{{ remote_dir }}/testcase1_local_follow_false'
local_follow: False
register: testcase1
- name: gather - Stat the testcase1_local_follow_false
stat:
path: '{{ remote_dir }}/testcase1_local_follow_false'
register: stat_testcase1_local_follow_false
- name: gather - Stat the testcase1_local_follow_false/subdir
stat:
path: '{{ remote_dir }}/testcase1_local_follow_false/subdir'
register: stat_testcase1_local_follow_false_subdir
- name: gather - Stat the testcase1_local_follow_false/file1
stat:
path: '{{ remote_dir }}/testcase1_local_follow_false/file1'
register: stat_testcase1_local_follow_false_file1
- name: gather - Stat the testcase1_local_follow_false/subdir/file12
stat:
path: '{{ remote_dir }}/testcase1_local_follow_false/subdir/file12'
register: stat_testcase1_local_follow_false_subdir_file12
- name: gather - Stat the testcase1_local_follow_false/link_file12
stat:
path: '{{ remote_dir }}/testcase1_local_follow_false/link_file12'
register: stat_testcase1_local_follow_false_link_file12
- name: assert - remote_dir_src has copied with local_follow True.
assert:
that:
- testcase1 is changed
- "stat_testcase1_local_follow_false.stat.isdir"
- "stat_testcase1_local_follow_false_subdir.stat.isdir"
- "stat_testcase1_local_follow_false_file1.stat.exists"
- "stat_remote_dir_src_file1_before.stat.checksum == stat_testcase1_local_follow_false_file1.stat.checksum"
- "stat_testcase1_local_follow_false_subdir_file12.stat.exists"
- "stat_remote_dir_src_subdir_file12_before.stat.checksum == stat_testcase1_local_follow_false_subdir_file12.stat.checksum"
- "stat_testcase1_local_follow_false_link_file12.stat.exists"
- "stat_testcase1_local_follow_false_link_file12.stat.islnk"
## test when src endswith os.sep and dest not exists
- block:
- name: execute - Copy the directory on remote with local_follow True
copy:
remote_src: True
src: '{{ remote_dir }}/remote_dir_src/'
dest: '{{ remote_dir }}/testcase2_local_follow_true'
local_follow: True
register: testcase2
- name: gather - Stat the testcase2_local_follow_true
stat:
path: '{{ remote_dir }}/testcase2_local_follow_true'
register: stat_testcase2_local_follow_true
- name: gather - Stat the testcase2_local_follow_true/subdir
stat:
path: '{{ remote_dir }}/testcase2_local_follow_true/subdir'
register: stat_testcase2_local_follow_true_subdir
- name: gather - Stat the testcase2_local_follow_true/file1
stat:
path: '{{ remote_dir }}/testcase2_local_follow_true/file1'
register: stat_testcase2_local_follow_true_file1
- name: gather - Stat the testcase2_local_follow_true/subdir/file12
stat:
path: '{{ remote_dir }}/testcase2_local_follow_true/subdir/file12'
register: stat_testcase2_local_follow_true_subdir_file12
- name: gather - Stat the testcase2_local_follow_true/link_file12
stat:
path: '{{ remote_dir }}/testcase2_local_follow_true/link_file12'
register: stat_testcase2_local_follow_true_link_file12
- name: assert - remote_dir_src has copied with local_follow True.
assert:
that:
- testcase2 is changed
- "stat_testcase2_local_follow_true.stat.isdir"
- "stat_testcase2_local_follow_true_subdir.stat.isdir"
- "stat_testcase2_local_follow_true_file1.stat.exists"
- "stat_remote_dir_src_file1_before.stat.checksum == stat_testcase2_local_follow_true_file1.stat.checksum"
- "stat_testcase2_local_follow_true_subdir_file12.stat.exists"
- "stat_remote_dir_src_subdir_file12_before.stat.checksum == stat_testcase2_local_follow_true_subdir_file12.stat.checksum"
- "stat_testcase2_local_follow_true_link_file12.stat.exists"
- "not stat_testcase2_local_follow_true_link_file12.stat.islnk"
- "stat_remote_dir_src_subdir_file12_before.stat.checksum == stat_testcase2_local_follow_true_link_file12.stat.checksum"
### local_follow: False
- name: execute - Copy the directory on remote with local_follow False
copy:
remote_src: True
src: '{{ remote_dir }}/remote_dir_src/'
dest: '{{ remote_dir }}/testcase2_local_follow_false'
local_follow: False
register: testcase2
- name: execute - Copy the directory on remote with local_follow False
copy:
remote_src: True
src: '{{ remote_dir }}/remote_dir_src/'
dest: '{{ remote_dir }}/testcase2_local_follow_false'
local_follow: False
register: testcase1
- name: gather - Stat the testcase2_local_follow_false
stat:
path: '{{ remote_dir }}/testcase2_local_follow_false'
register: stat_testcase2_local_follow_false
- name: gather - Stat the testcase2_local_follow_false/subdir
stat:
path: '{{ remote_dir }}/testcase2_local_follow_false/subdir'
register: stat_testcase2_local_follow_false_subdir
- name: gather - Stat the testcase2_local_follow_false/file1
stat:
path: '{{ remote_dir }}/testcase2_local_follow_false/file1'
register: stat_testcase2_local_follow_false_file1
- name: gather - Stat the testcase2_local_follow_false/subdir/file12
stat:
path: '{{ remote_dir }}/testcase2_local_follow_false/subdir/file12'
register: stat_testcase2_local_follow_false_subdir_file12
- name: gather - Stat the testcase2_local_follow_false/link_file12
stat:
path: '{{ remote_dir }}/testcase2_local_follow_false/link_file12'
register: stat_testcase2_local_follow_false_link_file12
- name: assert - remote_dir_src has copied with local_follow True.
assert:
that:
- testcase2 is changed
- "stat_testcase2_local_follow_false.stat.isdir"
- "stat_testcase2_local_follow_false_subdir.stat.isdir"
- "stat_testcase2_local_follow_false_file1.stat.exists"
- "stat_remote_dir_src_file1_before.stat.checksum == stat_testcase2_local_follow_false_file1.stat.checksum"
- "stat_testcase2_local_follow_false_subdir_file12.stat.exists"
- "stat_remote_dir_src_subdir_file12_before.stat.checksum == stat_testcase2_local_follow_false_subdir_file12.stat.checksum"
- "stat_testcase2_local_follow_false_link_file12.stat.exists"
- "stat_testcase2_local_follow_false_link_file12.stat.islnk"
## test when src not endswith os.sep and dest isdir
- block:
### local_follow: True
- name: execute - Create a test dest dir
file:
path: '{{ remote_dir }}/testcase3_local_follow_true'
state: directory
- name: execute - Copy the directory on remote with local_follow True
copy:
remote_src: True
src: '{{ remote_dir }}/remote_dir_src'
dest: '{{ remote_dir }}/testcase3_local_follow_true'
local_follow: True
register: testcase3
- name: gather - Stat the testcase3_local_follow_true
stat:
path: '{{ remote_dir }}/testcase3_local_follow_true/remote_dir_src'
register: stat_testcase3_local_follow_true_remote_dir_src
- name: gather - Stat the testcase3_local_follow_true/remote_dir_src/subdir
stat:
path: '{{ remote_dir }}/testcase3_local_follow_true/remote_dir_src/subdir'
register: stat_testcase3_local_follow_true_remote_dir_src_subdir
- name: gather - Stat the testcase3_local_follow_true/remote_dir_src/file1
stat:
path: '{{ remote_dir }}/testcase3_local_follow_true/remote_dir_src/file1'
register: stat_testcase3_local_follow_true_remote_dir_src_file1
- name: gather - Stat the testcase3_local_follow_true/remote_dir_src/subdir/file12
stat:
path: '{{ remote_dir }}/testcase3_local_follow_true/remote_dir_src/subdir/file12'
register: stat_testcase3_local_follow_true_remote_dir_src_subdir_file12
- name: gather - Stat the testcase3_local_follow_true/remote_dir_src/link_file12
stat:
path: '{{ remote_dir }}/testcase3_local_follow_true/remote_dir_src/link_file12'
register: stat_testcase3_local_follow_true_remote_dir_src_link_file12
- name: assert - remote_dir_src has copied with local_follow True.
assert:
that:
- testcase3 is changed
- "stat_testcase3_local_follow_true_remote_dir_src.stat.isdir"
- "stat_testcase3_local_follow_true_remote_dir_src_subdir.stat.isdir"
- "stat_testcase3_local_follow_true_remote_dir_src_file1.stat.exists"
- "stat_remote_dir_src_file1_before.stat.checksum == stat_testcase3_local_follow_true_remote_dir_src_file1.stat.checksum"
- "stat_testcase3_local_follow_true_remote_dir_src_subdir_file12.stat.exists"
- "stat_remote_dir_src_subdir_file12_before.stat.checksum == stat_testcase3_local_follow_true_remote_dir_src_subdir_file12.stat.checksum"
- "stat_testcase3_local_follow_true_remote_dir_src_link_file12.stat.exists"
- "not stat_testcase3_local_follow_true_remote_dir_src_link_file12.stat.islnk"
- "stat_remote_dir_src_subdir_file12_before.stat.checksum == stat_testcase3_local_follow_true_remote_dir_src_link_file12.stat.checksum"
### local_follow: False
- name: execute - Create a test dest dir
file:
path: '{{ remote_dir }}/testcase3_local_follow_false'
state: directory
- name: execute - Copy the directory on remote with local_follow False
copy:
remote_src: True
src: '{{ remote_dir }}/remote_dir_src'
dest: '{{ remote_dir }}/testcase3_local_follow_false'
local_follow: False
register: testcase3
- name: gather - Stat the testcase3_local_follow_false
stat:
path: '{{ remote_dir }}/testcase3_local_follow_false/remote_dir_src'
register: stat_testcase3_local_follow_false_remote_dir_src
- name: gather - Stat the testcase3_local_follow_false/remote_dir_src/subdir
stat:
path: '{{ remote_dir }}/testcase3_local_follow_false/remote_dir_src/subdir'
register: stat_testcase3_local_follow_false_remote_dir_src_subdir
- name: gather - Stat the testcase3_local_follow_false/remote_dir_src/file1
stat:
path: '{{ remote_dir }}/testcase3_local_follow_false/remote_dir_src/file1'
register: stat_testcase3_local_follow_false_remote_dir_src_file1
- name: gather - Stat the testcase3_local_follow_false/remote_dir_src/subdir/file12
stat:
path: '{{ remote_dir }}/testcase3_local_follow_false/remote_dir_src/subdir/file12'
register: stat_testcase3_local_follow_false_remote_dir_src_subdir_file12
- name: gather - Stat the testcase3_local_follow_false/remote_dir_src/link_file12
stat:
path: '{{ remote_dir }}/testcase3_local_follow_false/remote_dir_src/link_file12'
register: stat_testcase3_local_follow_false_remote_dir_src_link_file12
- name: assert - remote_dir_src has copied with local_follow False.
assert:
that:
- testcase3 is changed
- "stat_testcase3_local_follow_false_remote_dir_src.stat.isdir"
- "stat_testcase3_local_follow_false_remote_dir_src_subdir.stat.isdir"
- "stat_testcase3_local_follow_false_remote_dir_src_file1.stat.exists"
- "stat_remote_dir_src_file1_before.stat.checksum == stat_testcase3_local_follow_false_remote_dir_src_file1.stat.checksum"
- "stat_testcase3_local_follow_false_remote_dir_src_subdir_file12.stat.exists"
- "stat_remote_dir_src_subdir_file12_before.stat.checksum == stat_testcase3_local_follow_false_remote_dir_src_subdir_file12.stat.checksum"
- "stat_testcase3_local_follow_false_remote_dir_src_link_file12.stat.exists"
- "stat_testcase3_local_follow_false_remote_dir_src_link_file12.stat.islnk"
## test when src not endswith os.sep and dest not exists
- block:
### local_follow: True
- name: execute - Copy the directory on remote with local_follow True
copy:
remote_src: True
src: '{{ remote_dir }}/remote_dir_src'
dest: '{{ remote_dir }}/testcase4_local_follow_true'
local_follow: True
register: testcase4
- name: gather - Stat the testcase4_local_follow_true
stat:
path: '{{ remote_dir }}/testcase4_local_follow_true/remote_dir_src'
register: stat_testcase4_local_follow_true_remote_dir_src
- name: gather - Stat the testcase4_local_follow_true/remote_dir_src/subdir
stat:
path: '{{ remote_dir }}/testcase4_local_follow_true/remote_dir_src/subdir'
register: stat_testcase4_local_follow_true_remote_dir_src_subdir
- name: gather - Stat the testcase4_local_follow_true/remote_dir_src/file1
stat:
path: '{{ remote_dir }}/testcase4_local_follow_true/remote_dir_src/file1'
register: stat_testcase4_local_follow_true_remote_dir_src_file1
- name: gather - Stat the testcase4_local_follow_true/remote_dir_src/subdir/file12
stat:
path: '{{ remote_dir }}/testcase4_local_follow_true/remote_dir_src/subdir/file12'
register: stat_testcase4_local_follow_true_remote_dir_src_subdir_file12
- name: gather - Stat the testcase4_local_follow_true/remote_dir_src/link_file12
stat:
path: '{{ remote_dir }}/testcase4_local_follow_true/remote_dir_src/link_file12'
register: stat_testcase4_local_follow_true_remote_dir_src_link_file12
- name: assert - remote_dir_src has copied with local_follow True.
assert:
that:
- testcase4 is changed
- "stat_testcase4_local_follow_true_remote_dir_src.stat.isdir"
- "stat_testcase4_local_follow_true_remote_dir_src_subdir.stat.isdir"
- "stat_testcase4_local_follow_true_remote_dir_src_file1.stat.exists"
- "stat_remote_dir_src_file1_before.stat.checksum == stat_testcase4_local_follow_true_remote_dir_src_file1.stat.checksum"
- "stat_testcase4_local_follow_true_remote_dir_src_subdir_file12.stat.exists"
- "stat_remote_dir_src_subdir_file12_before.stat.checksum == stat_testcase4_local_follow_true_remote_dir_src_subdir_file12.stat.checksum"
- "stat_testcase4_local_follow_true_remote_dir_src_link_file12.stat.exists"
- "not stat_testcase4_local_follow_true_remote_dir_src_link_file12.stat.islnk"
- "stat_remote_dir_src_subdir_file12_before.stat.checksum == stat_testcase4_local_follow_true_remote_dir_src_link_file12.stat.checksum"
### local_follow: False
- name: execute - Copy the directory on remote with local_follow False
copy:
remote_src: True
src: '{{ remote_dir }}/remote_dir_src'
dest: '{{ remote_dir }}/testcase4_local_follow_false'
local_follow: False
register: testcase4
- name: gather - Stat the testcase4_local_follow_false
stat:
path: '{{ remote_dir }}/testcase4_local_follow_false/remote_dir_src'
register: stat_testcase4_local_follow_false_remote_dir_src
- name: gather - Stat the testcase4_local_follow_false/remote_dir_src/subdir
stat:
path: '{{ remote_dir }}/testcase4_local_follow_false/remote_dir_src/subdir'
register: stat_testcase4_local_follow_false_remote_dir_src_subdir
- name: gather - Stat the testcase4_local_follow_false/remote_dir_src/file1
stat:
path: '{{ remote_dir }}/testcase4_local_follow_false/remote_dir_src/file1'
register: stat_testcase4_local_follow_false_remote_dir_src_file1
- name: gather - Stat the testcase4_local_follow_false/remote_dir_src/subdir/file12
stat:
path: '{{ remote_dir }}/testcase4_local_follow_false/remote_dir_src/subdir/file12'
register: stat_testcase4_local_follow_false_remote_dir_src_subdir_file12
- name: gather - Stat the testcase4_local_follow_false/remote_dir_src/link_file12
stat:
path: '{{ remote_dir }}/testcase4_local_follow_false/remote_dir_src/link_file12'
register: stat_testcase4_local_follow_false_remote_dir_src_link_file12
- name: assert - remote_dir_src has copied with local_follow False.
assert:
that:
- testcase4 is changed
- "stat_testcase4_local_follow_false_remote_dir_src.stat.isdir"
- "stat_testcase4_local_follow_false_remote_dir_src_subdir.stat.isdir"
- "stat_testcase4_local_follow_false_remote_dir_src_file1.stat.exists"
- "stat_remote_dir_src_file1_before.stat.checksum == stat_testcase4_local_follow_false_remote_dir_src_file1.stat.checksum"
- "stat_testcase4_local_follow_false_remote_dir_src_subdir_file12.stat.exists"
- "stat_remote_dir_src_subdir_file12_before.stat.checksum == stat_testcase4_local_follow_false_remote_dir_src_subdir_file12.stat.checksum"
- "stat_testcase4_local_follow_false_remote_dir_src_link_file12.stat.exists"
- "stat_testcase4_local_follow_false_remote_dir_src_link_file12.stat.islnk"
## test copying the directory on remote with chown
- block:
- set_fact:
ansible_copy_test_user_name: 'ansible_copy_test_{{ 100000 | random }}'
- name: execute - create a user for test
user:
name: '{{ ansible_copy_test_user_name }}'
state: present
register: ansible_copy_test_user
- name: execute - create a group for test
group:
name: '{{ ansible_copy_test_user_name }}'
state: present
register: ansible_copy_test_group
- name: execute - Copy the directory on remote with chown
copy:
remote_src: True
src: '{{ remote_dir }}/remote_dir_src/'
dest: '{{ remote_dir }}/new_dir_with_chown'
owner: '{{ ansible_copy_test_user_name }}'
group: '{{ ansible_copy_test_user_name }}'
register: testcase5
- name: gather - Stat the new_dir_with_chown
stat:
path: '{{ remote_dir }}/new_dir_with_chown'
register: stat_new_dir_with_chown
- name: gather - Stat the new_dir_with_chown/file1
stat:
path: '{{ remote_dir }}/new_dir_with_chown/file1'
register: stat_new_dir_with_chown_file1
- name: gather - Stat the new_dir_with_chown/subdir
stat:
path: '{{ remote_dir }}/new_dir_with_chown/subdir'
register: stat_new_dir_with_chown_subdir
- name: gather - Stat the new_dir_with_chown/subdir/file12
stat:
path: '{{ remote_dir }}/new_dir_with_chown/subdir/file12'
register: stat_new_dir_with_chown_subdir_file12
- name: gather - Stat the new_dir_with_chown/link_file12
stat:
path: '{{ remote_dir }}/new_dir_with_chown/link_file12'
register: stat_new_dir_with_chown_link_file12
- name: assert - owner and group have changed
assert:
that:
- testcase5 is changed
- "stat_new_dir_with_chown.stat.uid == {{ ansible_copy_test_user.uid }}"
- "stat_new_dir_with_chown.stat.gid == {{ ansible_copy_test_group.gid }}"
- "stat_new_dir_with_chown.stat.pw_name == '{{ ansible_copy_test_user_name }}'"
- "stat_new_dir_with_chown.stat.gr_name == '{{ ansible_copy_test_user_name }}'"
- "stat_new_dir_with_chown_file1.stat.uid == {{ ansible_copy_test_user.uid }}"
- "stat_new_dir_with_chown_file1.stat.gid == {{ ansible_copy_test_group.gid }}"
- "stat_new_dir_with_chown_file1.stat.pw_name == '{{ ansible_copy_test_user_name }}'"
- "stat_new_dir_with_chown_file1.stat.gr_name == '{{ ansible_copy_test_user_name }}'"
- "stat_new_dir_with_chown_subdir.stat.uid == {{ ansible_copy_test_user.uid }}"
- "stat_new_dir_with_chown_subdir.stat.gid == {{ ansible_copy_test_group.gid }}"
- "stat_new_dir_with_chown_subdir.stat.pw_name == '{{ ansible_copy_test_user_name }}'"
- "stat_new_dir_with_chown_subdir.stat.gr_name == '{{ ansible_copy_test_user_name }}'"
- "stat_new_dir_with_chown_subdir_file12.stat.uid == {{ ansible_copy_test_user.uid }}"
- "stat_new_dir_with_chown_subdir_file12.stat.gid == {{ ansible_copy_test_group.gid }}"
- "stat_new_dir_with_chown_subdir_file12.stat.pw_name == '{{ ansible_copy_test_user_name }}'"
- "stat_new_dir_with_chown_subdir_file12.stat.gr_name == '{{ ansible_copy_test_user_name }}'"
- "stat_new_dir_with_chown_link_file12.stat.uid == {{ ansible_copy_test_user.uid }}"
- "stat_new_dir_with_chown_link_file12.stat.gid == {{ ansible_copy_test_group.gid }}"
- "stat_new_dir_with_chown_link_file12.stat.pw_name == '{{ ansible_copy_test_user_name }}'"
- "stat_new_dir_with_chown_link_file12.stat.gr_name == '{{ ansible_copy_test_user_name }}'"
always:
- name: execute - remove the user for test
user:
name: '{{ ansible_copy_test_user_name }}'
state: absent
remove: yes
- name: execute - remove the group for test
group:
name: '{{ ansible_copy_test_user_name }}'
state: absent
## testcase last - make sure remote_dir_src not change
- block:
- name: Stat the remote_dir_src
stat:
path: '{{ remote_dir }}/remote_dir_src'
register: stat_remote_dir_src_after
- name: Stat the remote_dir_src/subdir
stat:
path: '{{ remote_dir }}/remote_dir_src/subdir'
register: stat_remote_dir_src_subdir_after
- name: Stat the remote_dir_src/file1
stat:
path: '{{ remote_dir }}/remote_dir_src/file1'
register: stat_remote_dir_src_file1_after
- name: Stat the remote_dir_src/subdir/file12
stat:
path: '{{ remote_dir }}/remote_dir_src/subdir/file12'
register: stat_remote_dir_src_subdir_file12_after
- name: Stat the remote_dir_src/link_file12
stat:
path: '{{ remote_dir }}/remote_dir_src/link_file12'
register: stat_remote_dir_src_link_file12_after
- name: Assert that remote_dir_src not change.
assert:
that:
- "stat_remote_dir_src_after.stat.exists"
- "stat_remote_dir_src_after.stat.isdir"
- "stat_remote_dir_src_before.stat.uid == stat_remote_dir_src_after.stat.uid"
- "stat_remote_dir_src_before.stat.gid == stat_remote_dir_src_after.stat.gid"
- "stat_remote_dir_src_before.stat.pw_name == stat_remote_dir_src_after.stat.pw_name"
- "stat_remote_dir_src_before.stat.gr_name == stat_remote_dir_src_after.stat.gr_name"
- "stat_remote_dir_src_before.stat.path == stat_remote_dir_src_after.stat.path"
- "stat_remote_dir_src_before.stat.mode == stat_remote_dir_src_after.stat.mode"
- "stat_remote_dir_src_subdir_after.stat.exists"
- "stat_remote_dir_src_subdir_after.stat.isdir"
- "stat_remote_dir_src_subdir_before.stat.uid == stat_remote_dir_src_subdir_after.stat.uid"
- "stat_remote_dir_src_subdir_before.stat.gid == stat_remote_dir_src_subdir_after.stat.gid"
- "stat_remote_dir_src_subdir_before.stat.pw_name == stat_remote_dir_src_subdir_after.stat.pw_name"
- "stat_remote_dir_src_subdir_before.stat.gr_name == stat_remote_dir_src_subdir_after.stat.gr_name"
- "stat_remote_dir_src_subdir_before.stat.path == stat_remote_dir_src_subdir_after.stat.path"
- "stat_remote_dir_src_subdir_before.stat.mode == stat_remote_dir_src_subdir_after.stat.mode"
- "stat_remote_dir_src_file1_after.stat.exists"
- "stat_remote_dir_src_file1_before.stat.uid == stat_remote_dir_src_file1_after.stat.uid"
- "stat_remote_dir_src_file1_before.stat.gid == stat_remote_dir_src_file1_after.stat.gid"
- "stat_remote_dir_src_file1_before.stat.pw_name == stat_remote_dir_src_file1_after.stat.pw_name"
- "stat_remote_dir_src_file1_before.stat.gr_name == stat_remote_dir_src_file1_after.stat.gr_name"
- "stat_remote_dir_src_file1_before.stat.path == stat_remote_dir_src_file1_after.stat.path"
- "stat_remote_dir_src_file1_before.stat.mode == stat_remote_dir_src_file1_after.stat.mode"
- "stat_remote_dir_src_file1_before.stat.checksum == stat_remote_dir_src_file1_after.stat.checksum"
- "stat_remote_dir_src_subdir_file12_after.stat.exists"
- "stat_remote_dir_src_subdir_file12_before.stat.uid == stat_remote_dir_src_subdir_file12_after.stat.uid"
- "stat_remote_dir_src_subdir_file12_before.stat.gid == stat_remote_dir_src_subdir_file12_after.stat.gid"
- "stat_remote_dir_src_subdir_file12_before.stat.pw_name == stat_remote_dir_src_subdir_file12_after.stat.pw_name"
- "stat_remote_dir_src_subdir_file12_before.stat.gr_name == stat_remote_dir_src_subdir_file12_after.stat.gr_name"
- "stat_remote_dir_src_subdir_file12_before.stat.path == stat_remote_dir_src_subdir_file12_after.stat.path"
- "stat_remote_dir_src_subdir_file12_before.stat.mode == stat_remote_dir_src_subdir_file12_after.stat.mode"
- "stat_remote_dir_src_subdir_file12_before.stat.checksum == stat_remote_dir_src_subdir_file12_after.stat.checksum"
- "stat_remote_dir_src_link_file12_after.stat.exists"
- "stat_remote_dir_src_link_file12_after.stat.islnk"
- "stat_remote_dir_src_link_file12_before.stat.uid == stat_remote_dir_src_link_file12_after.stat.uid"
- "stat_remote_dir_src_link_file12_before.stat.gid == stat_remote_dir_src_link_file12_after.stat.gid"
- "stat_remote_dir_src_link_file12_before.stat.pw_name == stat_remote_dir_src_link_file12_after.stat.pw_name"
- "stat_remote_dir_src_link_file12_before.stat.gr_name == stat_remote_dir_src_link_file12_after.stat.gr_name"
- "stat_remote_dir_src_link_file12_before.stat.path == stat_remote_dir_src_link_file12_after.stat.path"
- "stat_remote_dir_src_link_file12_before.stat.mode == stat_remote_dir_src_link_file12_after.stat.mode"
Loading…
Cancel
Save