diff options
Diffstat (limited to 'lib/ansible/modules/copy.py')
-rw-r--r-- | lib/ansible/modules/copy.py | 73 |
1 files changed, 38 insertions, 35 deletions
diff --git a/lib/ansible/modules/copy.py b/lib/ansible/modules/copy.py index 9bbc02f..0e7dfe2 100644 --- a/lib/ansible/modules/copy.py +++ b/lib/ansible/modules/copy.py @@ -14,10 +14,14 @@ module: copy version_added: historical short_description: Copy files to remote locations description: - - The C(copy) module copies a file from the local or remote machine to a location on the remote machine. + - The M(ansible.builtin.copy) module copies a file or a directory structure from the local or remote machine to a location on the remote machine. + File system meta-information (permissions, ownership, etc.) may be set, even when the file or directory already exists on the target system. + Some meta-information may be copied on request. + - Get meta-information with the M(ansible.builtin.stat) module. + - Set meta-information with the M(ansible.builtin.file) module. - Use the M(ansible.builtin.fetch) module to copy files from remote locations to the local box. - If you need variable interpolation in copied files, use the M(ansible.builtin.template) module. - Using a variable in the C(content) field will result in unpredictable output. + Using a variable with the O(content) parameter produces unpredictable results. - For Windows targets, use the M(ansible.windows.win_copy) module instead. options: src: @@ -31,19 +35,19 @@ options: type: path content: description: - - When used instead of C(src), sets the contents of a file directly to the specified value. - - Works only when C(dest) is a file. Creates the file if it does not exist. - - For advanced formatting or if C(content) contains a variable, use the + - When used instead of O(src), sets the contents of a file directly to the specified value. + - Works only when O(dest) is a file. Creates the file if it does not exist. + - For advanced formatting or if O(content) contains a variable, use the M(ansible.builtin.template) module. type: str version_added: '1.1' dest: description: - Remote absolute path where the file should be copied to. - - If C(src) is a directory, this must be a directory too. - - If C(dest) is a non-existent path and if either C(dest) ends with "/" or C(src) is a directory, C(dest) is created. - - If I(dest) is a relative path, the starting directory is determined by the remote host. - - If C(src) and C(dest) are files, the parent directory of C(dest) is not created and the task fails if it does not already exist. + - If O(src) is a directory, this must be a directory too. + - If O(dest) is a non-existent path and if either O(dest) ends with "/" or O(src) is a directory, O(dest) is created. + - If O(dest) is a relative path, the starting directory is determined by the remote host. + - If O(src) and O(dest) are files, the parent directory of O(dest) is not created and the task fails if it does not already exist. type: path required: yes backup: @@ -55,8 +59,8 @@ options: force: description: - Influence whether the remote file must always be replaced. - - If C(true), the remote file will be replaced when contents are different than the source. - - If C(false), the file will only be transferred if the destination does not exist. + - If V(true), the remote file will be replaced when contents are different than the source. + - If V(false), the file will only be transferred if the destination does not exist. type: bool default: yes version_added: '1.1' @@ -65,33 +69,34 @@ options: - The permissions of the destination file or directory. - For those used to C(/usr/bin/chmod) remember that modes are actually octal numbers. You must either add a leading zero so that Ansible's YAML parser knows it is an octal number - (like C(0644) or C(01777)) or quote it (like C('644') or C('1777')) so Ansible receives a string + (like V(0644) or V(01777)) or quote it (like V('644') or V('1777')) so Ansible receives a string and can do its own conversion from string into number. Giving Ansible a number without following one of these rules will end up with a decimal number which will have unexpected results. - - As of Ansible 1.8, the mode may be specified as a symbolic mode (for example, C(u+rwx) or C(u=rw,g=r,o=r)). - - As of Ansible 2.3, the mode may also be the special string C(preserve). - - C(preserve) means that the file will be given the same permissions as the source file. - - When doing a recursive copy, see also C(directory_mode). - - If C(mode) is not specified and the destination file B(does not) exist, the default C(umask) on the system will be used + - As of Ansible 1.8, the mode may be specified as a symbolic mode (for example, V(u+rwx) or V(u=rw,g=r,o=r)). + - As of Ansible 2.3, the mode may also be the special string V(preserve). + - V(preserve) means that the file will be given the same permissions as the source file. + - When doing a recursive copy, see also O(directory_mode). + - If O(mode) is not specified and the destination file B(does not) exist, the default C(umask) on the system will be used when setting the mode for the newly created file. - - If C(mode) is not specified and the destination file B(does) exist, the mode of the existing file will be used. - - Specifying C(mode) is the best way to ensure files are created with the correct permissions. + - If O(mode) is not specified and the destination file B(does) exist, the mode of the existing file will be used. + - Specifying O(mode) is the best way to ensure files are created with the correct permissions. See CVE-2020-1736 for further details. directory_mode: description: - - When doing a recursive copy set the mode for the directories. - - If this is not set we will use the system defaults. - - The mode is only set on directories which are newly created, and will not affect those that already existed. + - Set the access permissions of newly created directories to the given mode. + Permissions on existing directories do not change. + - See O(mode) for the syntax of accepted values. + - The target system's defaults determine permissions when this parameter is not set. type: raw version_added: '1.5' remote_src: description: - - Influence whether C(src) needs to be transferred or already is present remotely. - - If C(false), it will search for C(src) on the controller node. - - If C(true) it will search for C(src) on the managed (remote) node. - - C(remote_src) supports recursive copying as of version 2.8. - - C(remote_src) only works with C(mode=preserve) as of version 2.6. - - Autodecryption of files does not work when C(remote_src=yes). + - Influence whether O(src) needs to be transferred or already is present remotely. + - If V(false), it will search for O(src) on the controller node. + - If V(true) it will search for O(src) on the managed (remote) node. + - O(remote_src) supports recursive copying as of version 2.8. + - O(remote_src) only works with O(mode=preserve) as of version 2.6. + - Autodecryption of files does not work when O(remote_src=yes). type: bool default: no version_added: '2.0' @@ -293,7 +298,7 @@ import stat import tempfile import traceback -from ansible.module_utils._text import to_bytes, to_native +from ansible.module_utils.common.text.converters import to_bytes, to_native from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.common.process import get_bin_path from ansible.module_utils.common.locale import get_best_parsable_locale @@ -518,7 +523,7 @@ def copy_common_dirs(src, dest, module): changed = True # recurse into subdirectory - changed = changed or copy_common_dirs(os.path.join(src, item), os.path.join(dest, item), module) + changed = copy_common_dirs(os.path.join(src, item), os.path.join(dest, item), module) or changed return changed @@ -619,6 +624,7 @@ def main(): if module.check_mode: module.exit_json(msg='dest directory %s would be created' % dirname, changed=True, src=src) os.makedirs(b_dirname) + changed = True directory_args = module.load_file_common_arguments(module.params) directory_mode = module.params["directory_mode"] if directory_mode is not None: @@ -688,7 +694,7 @@ def main(): b_mysrc = b_src if remote_src and os.path.isfile(b_src): - _, b_mysrc = tempfile.mkstemp(dir=os.path.dirname(b_dest)) + dummy, b_mysrc = tempfile.mkstemp(dir=os.path.dirname(b_dest)) shutil.copyfile(b_src, b_mysrc) try: @@ -751,8 +757,6 @@ def main(): except (IOError, OSError): module.fail_json(msg="failed to copy: %s to %s" % (src, dest), traceback=traceback.format_exc()) changed = True - else: - changed = False # If neither have checksums, both src and dest are directories. if checksum_src is None and checksum_dest is None: @@ -800,13 +804,12 @@ def main(): 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 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 |