summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSloane Hertel <19572925+s-hertel@users.noreply.github.com>2024-12-10 15:09:15 +0100
committerGitHub <noreply@github.com>2024-12-10 15:09:15 +0100
commitf0f5d7f88b1dd809c6de373bb275cd8cabb20006 (patch)
tree429f75ddbe317900aa4102476eab271af0058c2c
parentcsvfile - let the config system do the typecasting (#82263) (diff)
downloadansible-f0f5d7f88b1dd809c6de373bb275cd8cabb20006.tar.xz
ansible-f0f5d7f88b1dd809c6de373bb275cd8cabb20006.zip
simplify copy module (#84313)
* simplify redundancy with AnsibleModule set_*_if_different methods * simplify copying a source directory to a dest directory without modifying behavior
-rw-r--r--changelogs/fragments/simplify-copy-module.yml2
-rw-r--r--lib/ansible/modules/copy.py175
2 files changed, 47 insertions, 130 deletions
diff --git a/changelogs/fragments/simplify-copy-module.yml b/changelogs/fragments/simplify-copy-module.yml
new file mode 100644
index 0000000000..02f33da8d0
--- /dev/null
+++ b/changelogs/fragments/simplify-copy-module.yml
@@ -0,0 +1,2 @@
+bugfixes:
+ - copy - refactor copy module for simplicity.
diff --git a/lib/ansible/modules/copy.py b/lib/ansible/modules/copy.py
index 8a5297466f..fc904ae276 100644
--- a/lib/ansible/modules/copy.py
+++ b/lib/ansible/modules/copy.py
@@ -286,10 +286,8 @@ state:
import errno
import filecmp
-import grp
import os
import os.path
-import pwd
import shutil
import stat
import tempfile
@@ -335,67 +333,24 @@ def adjust_recursive_directory_permissions(pre_existing_dir, new_directory_list,
return changed
+def chown_path(module, path, owner, group):
+ """Update the owner/group if specified and different from the current owner/group."""
+ changed = module.set_owner_if_different(path, owner, False)
+ return module.set_group_if_different(path, group, 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
+ # TODO: Consolidate with the other methods calling set_*_if_different method, this is inefficient.
+ for dirpath, dirnames, filenames in os.walk(path):
+ changed |= chown_path(module, dirpath, owner, group)
+ for subdir in [os.path.join(dirpath, d) for d in dirnames]:
+ changed |= chown_path(module, subdir, owner, group)
+ for filepath in [os.path.join(dirpath, f) for f in filenames]:
+ changed |= chown_path(module, filepath, owner, group)
return changed
@@ -423,10 +378,7 @@ def copy_diff_files(src, dest, module):
shutil.copyfile(b_src_item_path, b_dest_item_path)
shutil.copymode(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)
+ chown_path(module, b_dest_item_path, owner, group)
changed = True
return changed
@@ -458,10 +410,7 @@ def copy_left_only(src, dest, module):
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)
+ chown_path(module, b_dest_item_path, owner, group)
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)
@@ -470,11 +419,7 @@ def copy_left_only(src, dest, module):
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)
shutil.copymode(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)
+ chown_path(module, b_dest_item_path, owner, group)
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)
@@ -502,6 +447,21 @@ def copy_common_dirs(src, dest, module):
return changed
+def copy_directory(src, dest, module):
+ if not os.path.exists(dest):
+ if not module.check_mode:
+ shutil.copytree(src, dest, symlinks=not module.params['local_follow'])
+ chown_recursive(dest, module)
+ changed = True
+ else:
+ diff_files_changed = copy_diff_files(src, dest, module)
+ left_only_changed = copy_left_only(src, dest, module)
+ common_dirs_changed = copy_common_dirs(src, dest, module)
+ owner_group_changed = chown_recursive(dest, module)
+ changed = any([diff_files_changed, left_only_changed, common_dirs_changed, owner_group_changed])
+ return changed
+
+
def main():
module = AnsibleModule(
@@ -652,12 +612,8 @@ def main():
if validate:
# if we have a mode, make sure we set it on the temporary
# file source as some validations may require it
- if mode is not None:
- module.set_mode_if_different(src, mode, False)
- if owner is not None:
- module.set_owner_if_different(src, owner, False)
- if group is not None:
- module.set_group_if_different(src, group, False)
+ module.set_mode_if_different(src, mode, False)
+ chown_path(module, src, owner, group)
if "%s" not in validate:
module.fail_json(msg="validate must contain %%s: %s" % (validate))
(rc, out, err) = module.run_command(validate % src)
@@ -686,59 +642,18 @@ def main():
changed = True
# If neither have checksums, both src and dest are directories.
- 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)
- changed = True
- 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 module.check_mode and not os.path.exists(b_dest):
- changed = True
+ checksums_none = checksum_src is None and checksum_dest is None
+ both_directories = os.path.isdir(module.params['src']) and (os.path.isdir(module.params['dest']) or not os.path.exists(module.params['dest']))
+ if checksums_none and remote_src and both_directories:
+ b_src = to_bytes(module.params['src'], errors='surrogate_or_strict')
+ b_dest = to_bytes(module.params['dest'], errors='surrogate_or_strict')
+
+ if not b_src.endswith(to_bytes(os.path.sep)):
+ b_basename = os.path.basename(b_src)
+ b_dest = os.path.join(b_dest, b_basename)
+ b_src = os.path.join(b_src, b'')
+
+ changed |= copy_directory(b_src, b_dest, module)
res_args = dict(
dest=dest, src=src, md5sum=md5sum_src, checksum=checksum_src, changed=changed