Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ansible/ansible.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Coca <bcoca@users.noreply.github.com>2022-10-27 00:05:03 +0300
committerGitHub <noreply@github.com>2022-10-27 00:05:03 +0300
commita5480c330db2645c213081955273610b98c67a6c (patch)
treedb155b8692a8d116e02c794d7dc245d133744005
parent5dd04e54a8a29f830ce0459ebbe99143e8d62f1f (diff)
copy, avoid moving non temp remote 'non' files (#79102) (#79155)
* copy, avoid moving non temp remote files that are not dirs/files fix tests (cherry picked from commit f66016df0e22e1234417dc3538bea75299b4e9eb)
-rw-r--r--changelogs/fragments/dont_move_non_files.yml2
-rw-r--r--lib/ansible/modules/copy.py31
-rw-r--r--test/integration/targets/copy/tasks/main.yml3
-rw-r--r--test/integration/targets/copy/tasks/src_remote_file_is_not_file.yml39
4 files changed, 62 insertions, 13 deletions
diff --git a/changelogs/fragments/dont_move_non_files.yml b/changelogs/fragments/dont_move_non_files.yml
new file mode 100644
index 00000000000..1f6a1e7986f
--- /dev/null
+++ b/changelogs/fragments/dont_move_non_files.yml
@@ -0,0 +1,2 @@
+bugfixes:
+ - copy module will no longer move 'non files' set as src when remote_src=true.
diff --git a/lib/ansible/modules/copy.py b/lib/ansible/modules/copy.py
index ca6ae0df0eb..09ec4a7d792 100644
--- a/lib/ansible/modules/copy.py
+++ b/lib/ansible/modules/copy.py
@@ -576,23 +576,24 @@ def main():
module.params['mode'] = '0%03o' % stat.S_IMODE(os.stat(b_src).st_mode)
mode = module.params['mode']
+ changed = False
+
checksum_dest = None
+ checksum_src = None
+ md5sum_src = 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
- try:
- if os.path.isfile(src):
+ try:
+ checksum_src = module.sha1(src)
+ except (OSError, IOError) as e:
+ module.warn("Unable to calculate src checksum, assuming change: %s" % to_native(e))
+ try:
+ # Backwards compat only. This will be None in FIPS mode
md5sum_src = module.md5(src)
- else:
- md5sum_src = None
- except ValueError:
- md5sum_src = None
-
- changed = False
+ except ValueError:
+ pass
+ elif remote_src and not os.path.isdir(src):
+ module.fail_json("Cannot copy invalid source '%s': not a file" % to_native(src))
if checksum and checksum_src != checksum:
module.fail_json(
@@ -657,6 +658,7 @@ def main():
backup_file = None
if checksum_src != checksum_dest or os.path.islink(b_dest):
+
if not module.check_mode:
try:
if backup:
@@ -680,8 +682,10 @@ def main():
(rc, out, err) = module.run_command(validate % src)
if rc != 0:
module.fail_json(msg="failed to validate", exit_status=rc, stdout=out, stderr=err)
+
b_mysrc = b_src
if remote_src and os.path.isfile(b_src):
+
_, b_mysrc = tempfile.mkstemp(dir=os.path.dirname(b_dest))
shutil.copyfile(b_src, b_mysrc)
@@ -701,6 +705,7 @@ def main():
# assume unwanted ACLs by default
src_has_acls = True
+ # at this point we should always have tmp file
module.atomic_move(b_mysrc, dest, unsafe_writes=module.params['unsafe_writes'])
if PY3 and hasattr(os, 'listxattr') and platform.system() == 'Linux' and not remote_src:
diff --git a/test/integration/targets/copy/tasks/main.yml b/test/integration/targets/copy/tasks/main.yml
index a5211de1bd0..7538e72fd58 100644
--- a/test/integration/targets/copy/tasks/main.yml
+++ b/test/integration/targets/copy/tasks/main.yml
@@ -97,6 +97,9 @@
- 'diff_output.diff[0].before == ""'
- '"Ansible managed" in diff_output.diff[0].after'
+ - name: tests with remote_src and non files
+ import_tasks: src_remote_file_is_not_file.yml
+
always:
- name: Cleaning
file:
diff --git a/test/integration/targets/copy/tasks/src_remote_file_is_not_file.yml b/test/integration/targets/copy/tasks/src_remote_file_is_not_file.yml
new file mode 100644
index 00000000000..2cda7d37c95
--- /dev/null
+++ b/test/integration/targets/copy/tasks/src_remote_file_is_not_file.yml
@@ -0,0 +1,39 @@
+- name: test remote src non files
+ vars:
+ destfile: '{{remote_dir}}/whocares'
+ block:
+ - name: mess with dev/null
+ copy:
+ src: /dev/null
+ dest: "{{destfile}}"
+ remote_src: true
+ become: true
+ register: dev_null_fail
+ ignore_errors: true
+
+ - name: ensure we failed
+ assert:
+ that:
+ - dev_null_fail is failed
+ - "'not a file' in dev_null_fail.msg"
+
+ - name: now with file existing
+ file: state=touch path="{{destfile}}"
+
+ - name: mess with dev/null again
+ copy:
+ src: /dev/null
+ dest: "{{destfile}}"
+ remote_src: true
+ become: true
+ register: dev_null_fail
+ ignore_errors: true
+
+ - name: ensure we failed, again
+ assert:
+ that:
+ - dev_null_fail is failed
+ - "'not a file' in dev_null_fail.msg"
+ always:
+ - name: cleanup
+ file: state=absent path="{{destfile}}"