ansible/test/integration/targets/copy/tasks/tests.yml
David Shrewsbury 0ae4dac65a
Fix copy module file perms with remote_src (#69993)
When using 'remote_src: yes' and 'mode: preserve', the code handling
the file modes has to be handled on the remote node because it's
the one that has access to the source files. This means that the
copy module itself must handle this, rather than the copy action
plugin (which is where all that logic exists). The copy module
handles this when we copy a single file over. But when it is a
directory as the src parameter value, the mode of the files
beneath it are not considered. Subdirectories are copied with
shutil.copytree() which will preserve permissions automatically.
Individual files are copied with shutil.copyfile() which does NOT
preserve permissions. We need to add some calls to shutil.copymode()
to correct that.

Note: This *always* retains individial file permissions. Specifying
a 'mode' other than 'preserve' when giving a source directory for
the 'src' param does not make sense so will be ignored in that case
only.

Fixes #69783

* Add changelog and test
2020-06-11 15:18:59 -04:00

2261 lines
73 KiB
YAML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# test code for the copy module and action plugin
# (c) 2014, Michael DeHaan <michael.dehaan@gmail.com>
# (c) 2017, Ansible Project
#
# GNU General Public License v3 or later (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt )
#
- name: Record the output directory
set_fact:
remote_file: "{{ remote_dir }}/foo.txt"
- name: Initiate a basic copy, and also test the mode
copy:
src: foo.txt
dest: "{{ remote_file }}"
mode: 0444
register: copy_result
- name: Record the sha of the test file for later tests
set_fact:
remote_file_hash: "{{ copy_result['checksum'] }}"
- name: Check the mode of the output file
file:
name: "{{ remote_file }}"
state: file
register: file_result_check
- name: Assert the mode is correct
assert:
that:
- "file_result_check.mode == '0444'"
# same as expanduser & expandvars
- command: 'echo {{ remote_dir }}'
register: echo
- set_fact:
remote_dir_expanded: '{{ echo.stdout }}'
remote_file_expanded: '{{ echo.stdout }}/foo.txt'
- debug:
var: copy_result
verbosity: 1
- name: Assert basic copy worked
assert:
that:
- "'changed' in copy_result"
- copy_result.dest == remote_file_expanded
- "'group' in copy_result"
- "'gid' in copy_result"
- "'checksum' in copy_result"
- "'owner' in copy_result"
- "'size' in copy_result"
- "'src' in copy_result"
- "'state' in copy_result"
- "'uid' in copy_result"
- name: Verify that the file was marked as changed
assert:
that:
- "copy_result.changed == true"
- name: Verify that the file checksums are correct
assert:
that:
- "copy_result.checksum == ('foo.txt\n'|hash('sha1'))"
- name: Verify that the legacy md5sum is correct
assert:
that:
- "copy_result.md5sum == ('foo.txt\n'|hash('md5'))"
when: ansible_fips|bool != True
- name: Check the stat results of the file
stat:
path: "{{ remote_file }}"
register: stat_results
- debug:
var: stat_results
verbosity: 1
- name: Assert the stat results are correct
assert:
that:
- "stat_results.stat.exists == true"
- "stat_results.stat.isblk == false"
- "stat_results.stat.isfifo == false"
- "stat_results.stat.isreg == true"
- "stat_results.stat.issock == false"
- "stat_results.stat.checksum == ('foo.txt\n'|hash('sha1'))"
- name: Overwrite the file via same means
copy:
src: foo.txt
dest: "{{ remote_file }}"
decrypt: no
register: copy_result2
- name: Assert that the file was not changed
assert:
that:
- "copy_result2 is not changed"
- name: Assert basic copy worked
assert:
that:
- "'changed' in copy_result2"
- copy_result2.dest == remote_file_expanded
- "'group' in copy_result2"
- "'gid' in copy_result2"
- "'checksum' in copy_result2"
- "'owner' in copy_result2"
- "'size' in copy_result2"
- "'state' in copy_result2"
- "'uid' in copy_result2"
- name: Overwrite the file using the content system
copy:
content: "modified"
dest: "{{ remote_file }}"
decrypt: no
register: copy_result3
- name: Check the stat results of the file
stat:
path: "{{ remote_file }}"
register: stat_results
- debug:
var: stat_results
verbosity: 1
- name: Assert that the file has changed
assert:
that:
- "copy_result3 is changed"
- "'content' not in copy_result3"
- "stat_results.stat.checksum == ('modified'|hash('sha1'))"
- "stat_results.stat.mode != '0700'"
- name: Overwrite the file again using the content system, also passing along file params
copy:
content: "modified"
dest: "{{ remote_file }}"
mode: 0700
decrypt: no
register: copy_result4
- name: Check the stat results of the file
stat:
path: "{{ remote_file }}"
register: stat_results
- debug:
var: stat_results
verbosity: 1
- name: Assert that the file has changed
assert:
that:
- "copy_result3 is changed"
- "'content' not in copy_result3"
- "stat_results.stat.checksum == ('modified'|hash('sha1'))"
- "stat_results.stat.mode == '0700'"
- name: Create a hardlink to the file
file:
src: '{{ remote_file }}'
dest: '{{ remote_dir }}/hard.lnk'
state: hard
- name: copy the same contents into place
copy:
content: 'modified'
dest: '{{ remote_file }}'
mode: 0700
decrypt: no
register: copy_results
- name: Check the stat results of the file
stat:
path: "{{ remote_file }}"
register: stat_results
- name: Check the stat results of the hard link
stat:
path: "{{ remote_dir }}/hard.lnk"
register: hlink_results
- name: Check that the file did not change
assert:
that:
- 'stat_results.stat.inode == hlink_results.stat.inode'
- 'copy_results.changed == False'
- "stat_results.stat.checksum == ('modified'|hash('sha1'))"
- name: copy the same contents into place but change mode
copy:
content: 'modified'
dest: '{{ remote_file }}'
mode: 0404
decrypt: no
register: copy_results
- name: Check the stat results of the file
stat:
path: "{{ remote_file }}"
register: stat_results
- name: Check the stat results of the hard link
stat:
path: "{{ remote_dir }}/hard.lnk"
register: hlink_results
- name: Check that the file changed permissions but is still the same
assert:
that:
- 'stat_results.stat.inode == hlink_results.stat.inode'
- 'copy_results.changed == True'
- 'stat_results.stat.mode == hlink_results.stat.mode'
- 'stat_results.stat.mode == "0404"'
- "stat_results.stat.checksum == ('modified'|hash('sha1'))"
- name: copy the different contents into place
copy:
content: 'adjusted'
dest: '{{ remote_file }}'
mode: 0404
register: copy_results
- name: Check the stat results of the file
stat:
path: "{{ remote_file }}"
register: stat_results
- name: Check the stat results of the hard link
stat:
path: "{{ remote_dir }}/hard.lnk"
register: hlink_results
- name: Check that the file changed and hardlink was broken
assert:
that:
- 'stat_results.stat.inode != hlink_results.stat.inode'
- 'copy_results.changed == True'
- "stat_results.stat.checksum == ('adjusted'|hash('sha1'))"
- "hlink_results.stat.checksum == ('modified'|hash('sha1'))"
- name: Try invalid copy input location fails
copy:
src: invalid_file_location_does_not_exist
dest: "{{ remote_dir }}/file.txt"
ignore_errors: True
register: failed_copy
- name: Assert that invalid source failed
assert:
that:
- "failed_copy.failed"
- "'invalid_file_location_does_not_exist' in failed_copy.msg"
- name: Try empty source to ensure it fails
copy:
src: ''
dest: "{{ remote_dir }}"
ignore_errors: True
register: failed_copy
- debug:
var: failed_copy
verbosity: 1
- name: Assert that empty source failed
assert:
that:
- failed_copy is failed
- "'src (or content) is required' in failed_copy.msg"
- name: Try without destination to ensure it fails
copy:
src: foo.txt
ignore_errors: True
register: failed_copy
- debug:
var: failed_copy
verbosity: 1
- name: Assert that missing destination failed
assert:
that:
- failed_copy is failed
- "'dest is required' in failed_copy.msg"
- name: Try without source to ensure it fails
copy:
dest: "{{ remote_file }}"
ignore_errors: True
register: failed_copy
- debug:
var: failed_copy
verbosity: 1
- name: Assert that missing source failed
assert:
that:
- failed_copy is failed
- "'src (or content) is required' in failed_copy.msg"
- name: Try with both src and content to ensure it fails
copy:
src: foo.txt
content: testing
dest: "{{ remote_file }}"
ignore_errors: True
register: failed_copy
- name: Assert that mutually exclusive parameters failed
assert:
that:
- failed_copy is failed
- "'mutually exclusive' in failed_copy.msg"
- name: Try with content and directory as destination to ensure it fails
copy:
content: testing
dest: "{{ remote_dir }}"
ignore_errors: True
register: failed_copy
- debug:
var: failed_copy
verbosity: 1
- name: Assert that content and directory as destination failed
assert:
that:
- failed_copy is failed
- "'can not use content with a dir as dest' in failed_copy.msg"
- name: Clean up
file:
path: "{{ remote_file }}"
state: absent
- name: Copy source file to destination directory with mode
copy:
src: foo.txt
dest: "{{ remote_dir }}"
mode: 0500
register: copy_results
- name: Check the stat results of the file
stat:
path: '{{ remote_file }}'
register: stat_results
- debug:
var: stat_results
verbosity: 1
- name: Assert that the file has changed
assert:
that:
- "copy_results is changed"
- "stat_results.stat.checksum == ('foo.txt\n'|hash('sha1'))"
- "stat_results.stat.mode == '0500'"
# Test copy with mode=preserve
- name: Create file and set perms to an odd value
copy:
content: "foo.txt\n"
dest: '{{ local_temp_dir }}/foo.txt'
mode: 0547
delegate_to: localhost
- name: Copy with mode=preserve
copy:
src: '{{ local_temp_dir }}/foo.txt'
dest: '{{ remote_dir }}/copy-foo.txt'
mode: preserve
register: copy_results
- name: Check the stat results of the file
stat:
path: '{{ remote_dir }}/copy-foo.txt'
register: stat_results
- name: Assert that the file has changed and has correct mode
assert:
that:
- "copy_results is changed"
- "copy_results.mode == '0547'"
- "stat_results.stat.checksum == ('foo.txt\n'|hash('sha1'))"
- "stat_results.stat.mode == '0547'"
- name: Test copy with mode=preserve and remote_src=True
copy:
src: '{{ remote_dir }}/copy-foo.txt'
dest: '{{ remote_dir }}/copy-foo2.txt'
mode: 'preserve'
remote_src: True
register: copy_results2
- name: Check the stat results of the file
stat:
path: '{{ remote_dir }}/copy-foo2.txt'
register: stat_results2
- name: Assert that the file has changed and has correct mode
assert:
that:
- "copy_results2 is changed"
- "copy_results2.mode == '0547'"
- "stat_results2.stat.checksum == ('foo.txt\n'|hash('sha1'))"
- "stat_results2.stat.mode == '0547'"
#
# test recursive copy local_follow=False, no trailing slash
#
- name: Create empty directory in the role we're copying from (git can't store empty dirs)
file:
path: '{{ role_path }}/files/subdir/subdira'
state: directory
delegate_to: localhost
- name: Set the output subdirectory
set_fact:
remote_subdir: "{{ remote_dir }}/sub"
- name: Make an output subdirectory
file:
name: "{{ remote_subdir }}"
state: directory
- name: Setup link target for absolute link
copy:
dest: /tmp/ansible-test-abs-link
content: target
delegate_to: localhost
- name: Setup link target dir for absolute link
file:
dest: /tmp/ansible-test-abs-link-dir
state: directory
delegate_to: localhost
- name: Test recursive copy to directory no trailing slash, local_follow=False
copy:
src: subdir
dest: "{{ remote_subdir }}"
directory_mode: 0700
local_follow: False
register: recursive_copy_result
- debug:
var: recursive_copy_result
verbosity: 1
- name: Assert that the recursive copy did something
assert:
that:
- "recursive_copy_result is changed"
- name: Check that a file in a directory was transferred
stat:
path: "{{ remote_dir }}/sub/subdir/bar.txt"
register: stat_bar
- name: Check that a file in a deeper directory was transferred
stat:
path: "{{ remote_dir }}/sub/subdir/subdir2/baz.txt"
register: stat_bar2
- name: Check that a file in a directory whose parent contains a directory alone was transferred
stat:
path: "{{ remote_dir }}/sub/subdir/subdir2/subdir3/subdir4/qux.txt"
register: stat_bar3
- name: Assert recursive copy files
assert:
that:
- "stat_bar.stat.exists"
- "stat_bar2.stat.exists"
- "stat_bar3.stat.exists"
- name: Check symlink to absolute path
stat:
path: '{{ remote_dir }}/sub/subdir/subdir1/ansible-test-abs-link'
register: stat_abs_link
- name: Check symlink to relative path
stat:
path: '{{ remote_dir }}/sub/subdir/subdir1/bar.txt'
register: stat_relative_link
- name: Check symlink to self
stat:
path: '{{ remote_dir }}/sub/subdir/subdir1/invalid'
register: stat_self_link
- name: Check symlink to nonexistent file
stat:
path: '{{ remote_dir }}/sub/subdir/subdir1/invalid2'
register: stat_invalid_link
- name: Check symlink to directory in copy
stat:
path: '{{ remote_dir }}/sub/subdir/subdir1/subdir3'
register: stat_dir_in_copy_link
- name: Check symlink to directory outside of copy
stat:
path: '{{ remote_dir }}/sub/subdir/subdir1/ansible-test-abs-link-dir'
register: stat_dir_outside_copy_link
- name: Assert recursive copy symlinks local_follow=False
assert:
that:
- "stat_abs_link.stat.exists"
- "stat_abs_link.stat.islnk"
- "'/tmp/ansible-test-abs-link' == stat_abs_link.stat.lnk_target"
- "stat_relative_link.stat.exists"
- "stat_relative_link.stat.islnk"
- "'../bar.txt' == stat_relative_link.stat.lnk_target"
- "stat_self_link.stat.exists"
- "stat_self_link.stat.islnk"
- "'invalid' in stat_self_link.stat.lnk_target"
- "stat_invalid_link.stat.exists"
- "stat_invalid_link.stat.islnk"
- "'../invalid' in stat_invalid_link.stat.lnk_target"
- "stat_dir_in_copy_link.stat.exists"
- "stat_dir_in_copy_link.stat.islnk"
- "'../subdir2/subdir3' in stat_dir_in_copy_link.stat.lnk_target"
- "stat_dir_outside_copy_link.stat.exists"
- "stat_dir_outside_copy_link.stat.islnk"
- "'/tmp/ansible-test-abs-link-dir' == stat_dir_outside_copy_link.stat.lnk_target"
- name: Stat the recursively copied directories
stat:
path: "{{ remote_dir }}/sub/{{ item }}"
register: dir_stats
with_items:
- "subdir"
- "subdir/subdira"
- "subdir/subdir1"
- "subdir/subdir2"
- "subdir/subdir2/subdir3"
- "subdir/subdir2/subdir3/subdir4"
- debug:
var: stat_results
verbosity: 1
- name: Assert recursive copied directories mode (1)
assert:
that:
- "item.stat.exists"
- "item.stat.mode == '0700'"
with_items: "{{dir_stats.results}}"
- name: Test recursive copy to directory no trailing slash, local_follow=False second time
copy:
src: subdir
dest: "{{ remote_subdir }}"
directory_mode: 0700
local_follow: False
register: recursive_copy_result
- name: Assert that the second copy did not change anything
assert:
that:
- "recursive_copy_result is not changed"
- name: Cleanup the recursive copy subdir
file:
name: "{{ remote_subdir }}"
state: absent
#
# Recursive copy with local_follow=False, trailing slash
#
- name: Set the output subdirectory
set_fact:
remote_subdir: "{{ remote_dir }}/sub"
- name: Make an output subdirectory
file:
name: "{{ remote_subdir }}"
state: directory
- name: Setup link target for absolute link
copy:
dest: /tmp/ansible-test-abs-link
content: target
delegate_to: localhost
- name: Setup link target dir for absolute link
file:
dest: /tmp/ansible-test-abs-link-dir
state: directory
delegate_to: localhost
- name: Test recursive copy to directory trailing slash, local_follow=False
copy:
src: subdir/
dest: "{{ remote_subdir }}"
directory_mode: 0700
local_follow: False
register: recursive_copy_result
- debug:
var: recursive_copy_result
verbosity: 1
- name: Assert that the recursive copy did something
assert:
that:
- "recursive_copy_result is changed"
- name: Check that a file in a directory was transferred
stat:
path: "{{ remote_dir }}/sub/bar.txt"
register: stat_bar
- name: Check that a file in a deeper directory was transferred
stat:
path: "{{ remote_dir }}/sub/subdir2/baz.txt"
register: stat_bar2
- name: Check that a file in a directory whose parent contains a directory alone was transferred
stat:
path: "{{ remote_dir }}/sub/subdir2/subdir3/subdir4/qux.txt"
register: stat_bar3
- name: Assert recursive copy files
assert:
that:
- "stat_bar.stat.exists"
- "stat_bar2.stat.exists"
- "stat_bar3.stat.exists"
- name: Check symlink to absolute path
stat:
path: '{{ remote_dir }}/sub/subdir1/ansible-test-abs-link'
register: stat_abs_link
- name: Check symlink to relative path
stat:
path: '{{ remote_dir }}/sub/subdir1/bar.txt'
register: stat_relative_link
- name: Check symlink to self
stat:
path: '{{ remote_dir }}/sub/subdir1/invalid'
register: stat_self_link
- name: Check symlink to nonexistent file
stat:
path: '{{ remote_dir }}/sub/subdir1/invalid2'
register: stat_invalid_link
- name: Check symlink to directory in copy
stat:
path: '{{ remote_dir }}/sub/subdir1/subdir3'
register: stat_dir_in_copy_link
- name: Check symlink to directory outside of copy
stat:
path: '{{ remote_dir }}/sub/subdir1/ansible-test-abs-link-dir'
register: stat_dir_outside_copy_link
- name: Assert recursive copy symlinks local_follow=False trailing slash
assert:
that:
- "stat_abs_link.stat.exists"
- "stat_abs_link.stat.islnk"
- "'/tmp/ansible-test-abs-link' == stat_abs_link.stat.lnk_target"
- "stat_relative_link.stat.exists"
- "stat_relative_link.stat.islnk"
- "'../bar.txt' == stat_relative_link.stat.lnk_target"
- "stat_self_link.stat.exists"
- "stat_self_link.stat.islnk"
- "'invalid' in stat_self_link.stat.lnk_target"
- "stat_invalid_link.stat.exists"
- "stat_invalid_link.stat.islnk"
- "'../invalid' in stat_invalid_link.stat.lnk_target"
- "stat_dir_in_copy_link.stat.exists"
- "stat_dir_in_copy_link.stat.islnk"
- "'../subdir2/subdir3' in stat_dir_in_copy_link.stat.lnk_target"
- "stat_dir_outside_copy_link.stat.exists"
- "stat_dir_outside_copy_link.stat.islnk"
- "'/tmp/ansible-test-abs-link-dir' == stat_dir_outside_copy_link.stat.lnk_target"
- name: Stat the recursively copied directories
stat:
path: "{{ remote_dir }}/sub/{{ item }}"
register: dir_stats
with_items:
- "subdira"
- "subdir1"
- "subdir2"
- "subdir2/subdir3"
- "subdir2/subdir3/subdir4"
- debug:
var: dir_stats
verbosity: 1
- name: Assert recursive copied directories mode (2)
assert:
that:
- "item.stat.mode == '0700'"
with_items: "{{dir_stats.results}}"
- name: Test recursive copy to directory trailing slash, local_follow=False second time
copy:
src: subdir/
dest: "{{ remote_subdir }}"
directory_mode: 0700
local_follow: False
register: recursive_copy_result
- name: Assert that the second copy did not change anything
assert:
that:
- "recursive_copy_result is not changed"
- name: Cleanup the recursive copy subdir
file:
name: "{{ remote_subdir }}"
state: absent
#
# test recursive copy local_follow=True, no trailing slash
#
- name: Set the output subdirectory
set_fact:
remote_subdir: "{{ remote_dir }}/sub"
- name: Make an output subdirectory
file:
name: "{{ remote_subdir }}"
state: directory
- name: Setup link target for absolute link
copy:
dest: /tmp/ansible-test-abs-link
content: target
delegate_to: localhost
- name: Setup link target dir for absolute link
file:
dest: /tmp/ansible-test-abs-link-dir
state: directory
delegate_to: localhost
- name: Test recursive copy to directory no trailing slash, local_follow=True
copy:
src: subdir
dest: "{{ remote_subdir }}"
directory_mode: 0700
local_follow: True
register: recursive_copy_result
- debug:
var: recursive_copy_result
verbosity: 1
- name: Assert that the recursive copy did something
assert:
that:
- "recursive_copy_result is changed"
- name: Check that a file in a directory was transferred
stat:
path: "{{ remote_dir }}/sub/subdir/bar.txt"
register: stat_bar
- name: Check that a file in a deeper directory was transferred
stat:
path: "{{ remote_dir }}/sub/subdir/subdir2/baz.txt"
register: stat_bar2
- name: Check that a file in a directory whose parent contains a directory alone was transferred
stat:
path: "{{ remote_dir }}/sub/subdir/subdir2/subdir3/subdir4/qux.txt"
register: stat_bar3
- name: Check that a file in a directory whose parent is a symlink was transferred
stat:
path: "{{ remote_dir }}/sub/subdir/subdir1/subdir3/subdir4/qux.txt"
register: stat_bar4
- name: Assert recursive copy files
assert:
that:
- "stat_bar.stat.exists"
- "stat_bar2.stat.exists"
- "stat_bar3.stat.exists"
- "stat_bar4.stat.exists"
- name: Check symlink to absolute path
stat:
path: '{{ remote_dir }}/sub/subdir/subdir1/ansible-test-abs-link'
register: stat_abs_link
- name: Check symlink to relative path
stat:
path: '{{ remote_dir }}/sub/subdir/subdir1/bar.txt'
register: stat_relative_link
- name: Check symlink to self
stat:
path: '{{ remote_dir }}/sub/subdir/subdir1/invalid'
register: stat_self_link
- name: Check symlink to nonexistent file
stat:
path: '{{ remote_dir }}/sub/subdir/subdir1/invalid2'
register: stat_invalid_link
- name: Check symlink to directory in copy
stat:
path: '{{ remote_dir }}/sub/subdir/subdir1/subdir3'
register: stat_dir_in_copy_link
- name: Check symlink to directory outside of copy
stat:
path: '{{ remote_dir }}/sub/subdir/subdir1/ansible-test-abs-link-dir'
register: stat_dir_outside_copy_link
- name: Assert recursive copy symlinks local_follow=True
assert:
that:
- "stat_abs_link.stat.exists"
- "not stat_abs_link.stat.islnk"
- "stat_abs_link.stat.checksum == ('target'|hash('sha1'))"
- "stat_relative_link.stat.exists"
- "not stat_relative_link.stat.islnk"
- "stat_relative_link.stat.checksum == ('baz\n'|hash('sha1'))"
- "stat_self_link.stat.exists"
- "stat_self_link.stat.islnk"
- "'invalid' in stat_self_link.stat.lnk_target"
- "stat_invalid_link.stat.exists"
- "stat_invalid_link.stat.islnk"
- "'../invalid' in stat_invalid_link.stat.lnk_target"
- "stat_dir_in_copy_link.stat.exists"
- "not stat_dir_in_copy_link.stat.islnk"
- "stat_dir_in_copy_link.stat.isdir"
-
- "stat_dir_outside_copy_link.stat.exists"
- "not stat_dir_outside_copy_link.stat.islnk"
- "stat_dir_outside_copy_link.stat.isdir"
- name: Stat the recursively copied directories
stat:
path: "{{ remote_dir }}/sub/{{ item }}"
register: dir_stats
with_items:
- "subdir"
- "subdir/subdira"
- "subdir/subdir1"
- "subdir/subdir1/subdir3"
- "subdir/subdir1/subdir3/subdir4"
- "subdir/subdir2"
- "subdir/subdir2/subdir3"
- "subdir/subdir2/subdir3/subdir4"
- debug:
var: dir_stats
verbosity: 1
- name: Assert recursive copied directories mode (3)
assert:
that:
- "item.stat.mode == '0700'"
with_items: "{{dir_stats.results}}"
- name: Test recursive copy to directory no trailing slash, local_follow=True second time
copy:
src: subdir
dest: "{{ remote_subdir }}"
directory_mode: 0700
local_follow: True
register: recursive_copy_result
- name: Assert that the second copy did not change anything
assert:
that:
- "recursive_copy_result is not changed"
- name: Cleanup the recursive copy subdir
file:
name: "{{ remote_subdir }}"
state: absent
#
# Recursive copy of tricky symlinks
#
- block:
- name: Create a directory to copy from
file:
path: '{{ local_temp_dir }}/source1'
state: directory
- name: Create a directory outside of the tree
file:
path: '{{ local_temp_dir }}/source2'
state: directory
- name: Create a symlink to a directory outside of the tree
file:
path: '{{ local_temp_dir }}/source1/link'
src: '{{ local_temp_dir }}/source2'
state: link
- name: Create a circular link back to the tree
file:
path: '{{ local_temp_dir }}/source2/circle'
src: '../source1'
state: link
- name: Create output directory
file:
path: '{{ local_temp_dir }}/dest1'
state: directory
delegate_to: localhost
- name: Recursive copy the source
copy:
src: '{{ local_temp_dir }}/source1'
dest: '{{ remote_dir }}/dest1'
local_follow: True
register: copy_result
- name: Check that the tree link is now a directory
stat:
path: '{{ remote_dir }}/dest1/source1/link'
register: link_result
- name: Check that the out of tree link is still a link
stat:
path: '{{ remote_dir }}/dest1/source1/link/circle'
register: circle_result
- name: Verify that the recursive copy worked
assert:
that:
- 'copy_result.changed'
- 'link_result.stat.isdir'
- 'not link_result.stat.islnk'
- 'circle_result.stat.islnk'
- '"../source1" == circle_result.stat.lnk_target'
- name: Recursive copy the source a second time
copy:
src: '{{ local_temp_dir }}/source1'
dest: '{{ remote_dir }}/dest1'
local_follow: True
register: copy_result
- name: Verify that the recursive copy made no changes
assert:
that:
- 'not copy_result.changed'
#
# Recursive copy with absolute paths (#27439)
#
- name: Test that remote_dir is appropriate for this test (absolute path)
assert:
that:
- '{{ remote_dir_expanded[0] == "/" }}'
- block:
- name: Create a directory to copy
file:
path: '{{ local_temp_dir }}/source_recursive'
state: directory
- name: Create a file inside of the directory
copy:
content: "testing"
dest: '{{ local_temp_dir }}/source_recursive/file'
- name: Create a directory to place the test output in
file:
path: '{{ local_temp_dir }}/destination'
state: directory
delegate_to: localhost
- name: Copy the directory and files within (no trailing slash)
copy:
src: '{{ local_temp_dir }}/source_recursive'
dest: '{{ remote_dir }}/destination'
- name: Stat the recursively copied directory
stat:
path: "{{ remote_dir }}/destination/{{ item }}"
register: copied_stat
with_items:
- "source_recursive"
- "source_recursive/file"
- "file"
- debug:
var: copied_stat
verbosity: 1
- name: Assert with no trailing slash, directory and file is copied
assert:
that:
- "copied_stat.results[0].stat.exists"
- "copied_stat.results[1].stat.exists"
- "not copied_stat.results[2].stat.exists"
- name: Cleanup
file:
path: '{{ remote_dir }}/destination'
state: absent
# Try again with no trailing slash
- name: Create a directory to place the test output in
file:
path: '{{ remote_dir }}/destination'
state: directory
- name: Copy just the files inside of the directory
copy:
src: '{{ local_temp_dir }}/source_recursive/'
dest: '{{ remote_dir }}/destination'
- name: Stat the recursively copied directory
stat:
path: "{{ remote_dir }}/destination/{{ item }}"
register: copied_stat
with_items:
- "source_recursive"
- "source_recursive/file"
- "file"
- debug:
var: copied_stat
verbosity: 1
- name: Assert with trailing slash, only the file is copied
assert:
that:
- "not copied_stat.results[0].stat.exists"
- "not copied_stat.results[1].stat.exists"
- "copied_stat.results[2].stat.exists"
#
# Recursive copy with relative paths (#34893)
#
- name: Create a directory to copy
file:
path: 'source_recursive'
state: directory
delegate_to: localhost
- name: Create a file inside of the directory
copy:
content: "testing"
dest: 'source_recursive/file'
delegate_to: localhost
- name: Create a directory to place the test output in
file:
path: 'destination'
state: directory
delegate_to: localhost
- name: Copy the directory and files within (no trailing slash)
copy:
src: 'source_recursive'
dest: 'destination'
- name: Stat the recursively copied directory
stat:
path: "destination/{{ item }}"
register: copied_stat
with_items:
- "source_recursive"
- "source_recursive/file"
- "file"
- debug:
var: copied_stat
verbosity: 1
- name: Assert with no trailing slash, directory and file is copied
assert:
that:
- "copied_stat.results[0].stat.exists"
- "copied_stat.results[1].stat.exists"
- "not copied_stat.results[2].stat.exists"
- name: Cleanup
file:
path: 'destination'
state: absent
# Try again with no trailing slash
- name: Create a directory to place the test output in
file:
path: 'destination'
state: directory
- name: Copy just the files inside of the directory
copy:
src: 'source_recursive/'
dest: 'destination'
- name: Stat the recursively copied directory
stat:
path: "destination/{{ item }}"
register: copied_stat
with_items:
- "source_recursive"
- "source_recursive/file"
- "file"
- debug:
var: copied_stat
verbosity: 1
- name: Assert with trailing slash, only the file is copied
assert:
that:
- "not copied_stat.results[0].stat.exists"
- "not copied_stat.results[1].stat.exists"
- "copied_stat.results[2].stat.exists"
- name: Cleanup
file:
path: 'destination'
state: absent
- name: Cleanup
file:
path: 'source_recursive'
state: absent
#
# issue 8394
#
- name: Create a file with content and a literal multiline block
copy:
content: |
this is the first line
this is the second line
this line is after an empty line
this line is the last line
dest: "{{ remote_dir }}/multiline.txt"
register: copy_result6
- debug:
var: copy_result6
verbosity: 1
- name: Assert the multiline file was created correctly
assert:
that:
- "copy_result6.changed"
- "copy_result6.dest == '{{remote_dir_expanded}}/multiline.txt'"
- "copy_result6.checksum == '9cd0697c6a9ff6689f0afb9136fa62e0b3fee903'"
# test overwriting a file as an unprivileged user (pull request #8624)
# this can't be relative to {{remote_dir}} as ~root usually has mode 700
- block:
- name: Create world writable directory
file:
dest: /tmp/worldwritable
state: directory
mode: 0777
- name: Create world writable file
copy:
dest: /tmp/worldwritable/file.txt
content: "bar"
mode: 0666
- name: Overwrite the file as user nobody
copy:
dest: /tmp/worldwritable/file.txt
content: "baz"
become: yes
become_user: nobody
register: copy_result7
- name: Assert the file was overwritten
assert:
that:
- "copy_result7.changed"
- "copy_result7.dest == '/tmp/worldwritable/file.txt'"
- "copy_result7.checksum == ('baz'|hash('sha1'))"
- name: Clean up
file:
dest: /tmp/worldwritable
state: absent
remote_user: root
#
# Follow=True tests
#
# test overwriting a link using "follow=yes" so that the link
# is preserved and the link target is updated
- name: Create a test file to symlink to
copy:
dest: "{{ remote_dir }}/follow_test"
content: "this is the follow test file\n"
- name: Create a symlink to the test file
file:
path: "{{ remote_dir }}/follow_link"
src: './follow_test'
state: link
- name: Update the test file using follow=True to preserve the link
copy:
dest: "{{ remote_dir }}/follow_link"
src: foo.txt
follow: yes
register: replace_follow_result
- name: Stat the link path
stat:
path: "{{ remote_dir }}/follow_link"
register: stat_link_result
- name: Assert that the link is still a link and contents were changed
assert:
that:
- stat_link_result['stat']['islnk']
- stat_link_result['stat']['lnk_target'] == './follow_test'
- replace_follow_result['changed']
- "replace_follow_result['checksum'] == remote_file_hash"
# Symlink handling when the dest is already there
# https://github.com/ansible/ansible-modules-core/issues/1568
- name: test idempotency by trying to copy to the symlink with the same contents
copy:
dest: "{{ remote_dir }}/follow_link"
src: foo.txt
follow: yes
register: replace_follow_result
- name: Stat the link path
stat:
path: "{{ remote_dir }}/follow_link"
register: stat_link_result
- name: Assert that the link is still a link and contents were changed
assert:
that:
- stat_link_result['stat']['islnk']
- stat_link_result['stat']['lnk_target'] == './follow_test'
- not replace_follow_result['changed']
- replace_follow_result['checksum'] == remote_file_hash
- name: Update the test file using follow=False to overwrite the link
copy:
dest: '{{ remote_dir }}/follow_link'
content: 'modified'
follow: False
register: copy_results
- name: Check the stat results of the file
stat:
path: '{{remote_dir}}/follow_link'
register: stat_results
- debug:
var: stat_results
verbosity: 1
- name: Assert that the file has changed and is not a link
assert:
that:
- "copy_results is changed"
- "'content' not in copy_results"
- "stat_results.stat.checksum == ('modified'|hash('sha1'))"
- "not stat_results.stat.islnk"
# test overwriting a link using "follow=yes" so that the link
# is preserved and the link target is updated when the thing being copied is a link
#
# File mode tests
#
- name: setup directory for test
file: state=directory dest={{remote_dir }}/directory mode=0755
- name: set file mode when the destination is a directory
copy: src=foo.txt dest={{remote_dir}}/directory/ mode=0705
- name: set file mode when the destination is a directory
copy: src=foo.txt dest={{remote_dir}}/directory/ mode=0604
register: file_result
- name: check that the file has the correct attributes
stat: path={{ remote_dir }}/directory/foo.txt
register: file_attrs
- assert:
that:
- "file_attrs.stat.mode == '0604'"
# The below assertions make an invalid assumption, these were not explicitly set
# - "file_attrs.stat.uid == 0"
# - "file_attrs.stat.pw_name == 'root'"
- name: check that the containing directory did not change attributes
stat: path={{ remote_dir }}/directory/
register: dir_attrs
- assert:
that:
- "dir_attrs.stat.mode == '0755'"
# Test that recursive copy of a directory containing a symlink to another
# directory, with mode=preserve and local_follow=no works.
# See: https://github.com/ansible/ansible/issues/68471
- name: Test recursive copy of dir with symlinks, mode=preserve, local_follow=False
copy:
src: '{{ role_path }}/files/subdir/'
dest: '{{ local_temp_dir }}/preserve_symlink/'
mode: preserve
local_follow: no
- name: check that we actually used and still have a symlink
stat: path={{ local_temp_dir }}/preserve_symlink/subdir1/bar.txt
register: symlink_path
- assert:
that:
- symlink_path.stat.exists
- symlink_path.stat.islnk
#
# I believe the below section is now covered in the recursive copying section.
# Hold on for now as an original test case but delete once confirmed that
# everything is passing
#
# Recursive copying with symlinks tests
#
- delegate_to: localhost
block:
- name: Create a test dir to copy
file:
path: '{{ local_temp_dir }}/top_dir'
state: directory
- name: Create a test dir to symlink to
file:
path: '{{ local_temp_dir }}/linked_dir'
state: directory
- name: Create a file in the test dir
copy:
dest: '{{ local_temp_dir }}/linked_dir/file1'
content: 'hello world'
- name: Create a link to the test dir
file:
path: '{{ local_temp_dir }}/top_dir/follow_link_dir'
src: '{{ local_temp_dir }}/linked_dir'
state: link
- name: Create a circular subdir
file:
path: '{{ local_temp_dir }}/top_dir/subdir'
state: directory
### FIXME: Also add a test for a relative symlink
- name: Create a circular symlink
file:
path: '{{ local_temp_dir }}/top_dir/subdir/circle'
src: '{{ local_temp_dir }}/top_dir/'
state: link
- name: Copy the directory's link
copy:
src: '{{ local_temp_dir }}/top_dir'
dest: '{{ remote_dir }}/new_dir'
local_follow: True
- name: Stat the copied path
stat:
path: '{{ remote_dir }}/new_dir/top_dir/follow_link_dir'
register: stat_dir_result
- name: Stat the copied file
stat:
path: '{{ remote_dir }}/new_dir/top_dir/follow_link_dir/file1'
register: stat_file_in_dir_result
- name: Stat the circular symlink
stat:
path: '{{ remote_dir }}/new_dir/top_dir/subdir/circle'
register: stat_circular_symlink_result
- name: Assert that the directory exists
assert:
that:
- stat_dir_result.stat.exists
- stat_dir_result.stat.isdir
- stat_file_in_dir_result.stat.exists
- stat_file_in_dir_result.stat.isreg
- stat_circular_symlink_result.stat.exists
- stat_circular_symlink_result.stat.islnk
# Relative paths in dest:
- name: Smoketest that copying content to an implicit relative path works
copy:
content: 'testing'
dest: 'ansible-testing.txt'
register: relative_results
- name: Assert that copying to an implicit relative path reported changed
assert:
that:
- 'relative_results["changed"]'
- 'relative_results["checksum"] == "dc724af18fbdd4e59189f5fe768a5f8311527050"'
- name: Test that copying the same content with an implicit relative path reports no change
copy:
content: 'testing'
dest: 'ansible-testing.txt'
register: relative_results
- name: Assert that copying the same content with an implicit relative path reports no change
assert:
that:
- 'not relative_results["changed"]'
- 'relative_results["checksum"] == "dc724af18fbdd4e59189f5fe768a5f8311527050"'
- name: Test that copying different content with an implicit relative path reports change
copy:
content: 'testing2'
dest: 'ansible-testing.txt'
register: relative_results
- name: Assert that copying different content with an implicit relative path reports changed
assert:
that:
- 'relative_results["changed"]'
- 'relative_results["checksum"] == "596b29ec9afea9e461a20610d150939b9c399d93"'
- name: Smoketest that explicit relative path works
copy:
content: 'testing'
dest: './ansible-testing.txt'
register: relative_results
- name: Assert that explicit relative paths reports change
assert:
that:
- 'relative_results["changed"]'
- 'relative_results["checksum"] == "dc724af18fbdd4e59189f5fe768a5f8311527050"'
- name: Cleanup relative path tests
file:
path: 'ansible-testing.txt'
state: absent
# src is a file, dest is a non-existent directory (2 levels of directories):
# using remote_src
# checks that dest is created
- include: dest_in_non_existent_directories_remote_src.yml
with_items:
- { src: 'foo.txt', dest: 'new_sub_dir1/sub_dir2/', check: 'new_sub_dir1/sub_dir2/foo.txt' }
# src is a file, dest is file in a non-existent directory: checks that a failure occurs
# using remote_src
- include: src_file_dest_file_in_non_existent_dir_remote_src.yml
with_items:
- 'new_sub_dir1/sub_dir2/foo.txt'
- 'new_sub_dir1/foo.txt'
loop_control:
loop_var: 'dest'
# src is a file, dest is a non-existent directory (2 levels of directories):
# checks that dest is created
- include: dest_in_non_existent_directories.yml
with_items:
- { src: 'foo.txt', dest: 'new_sub_dir1/sub_dir2/', check: 'new_sub_dir1/sub_dir2/foo.txt' }
- { src: 'subdir', dest: 'new_sub_dir1/sub_dir2/', check: 'new_sub_dir1/sub_dir2/subdir/bar.txt' }
- { src: 'subdir/', dest: 'new_sub_dir1/sub_dir2/', check: 'new_sub_dir1/sub_dir2/bar.txt' }
- { src: 'subdir', dest: 'new_sub_dir1/sub_dir2', check: 'new_sub_dir1/sub_dir2/subdir/bar.txt' }
- { src: 'subdir/', dest: 'new_sub_dir1/sub_dir2', check: 'new_sub_dir1/sub_dir2/bar.txt' }
# src is a file, dest is file in a non-existent directory: checks that a failure occurs
- include: src_file_dest_file_in_non_existent_dir.yml
with_items:
- 'new_sub_dir1/sub_dir2/foo.txt'
- 'new_sub_dir1/foo.txt'
loop_control:
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"
- block:
- name: execute - Clone the source directory on remote
copy:
remote_src: True
src: '{{ remote_dir }}/remote_dir_src/'
dest: '{{ remote_dir }}/testcase5_remote_src_subdirs_src'
- name: Create a 2nd level subdirectory
file:
path: '{{ remote_dir }}/testcase5_remote_src_subdirs_src/subdir/subdir2/'
state: directory
- name: execute - Copy the directory on remote
copy:
remote_src: True
src: '{{ remote_dir }}/testcase5_remote_src_subdirs_src/'
dest: '{{ remote_dir }}/testcase5_remote_src_subdirs_dest'
local_follow: True
- name: execute - Create a new file in the subdir
copy:
dest: '{{ remote_dir }}/testcase5_remote_src_subdirs_src/subdir/subdir2/file13'
content: 'very new file'
- name: gather - Stat the testcase5_remote_src_subdirs_src/subdir/subdir2/file13
stat:
path: '{{ remote_dir }}/testcase5_remote_src_subdirs_src/subdir/subdir2/file13'
- name: execute - Copy the directory on remote
copy:
remote_src: True
src: '{{ remote_dir }}/testcase5_remote_src_subdirs_src/'
dest: '{{ remote_dir }}/testcase5_remote_src_subdirs_dest/'
register: testcase5_new
- name: execute - Edit a file in the subdir
copy:
dest: '{{ remote_dir }}/testcase5_remote_src_subdirs_src/subdir/subdir2/file13'
content: 'NOT hello world 12'
- name: gather - Stat the testcase5_remote_src_subdirs_src/subdir/subdir2/file13
stat:
path: '{{ remote_dir }}/testcase5_remote_src_subdirs_src/subdir/subdir2/file13'
register: stat_testcase5_remote_src_subdirs_file13_before
- name: execute - Copy the directory on remote
copy:
remote_src: True
src: '{{ remote_dir }}/testcase5_remote_src_subdirs_src/'
dest: '{{ remote_dir }}/testcase5_remote_src_subdirs_dest/'
register: testcase5_edited
- name: gather - Stat the testcase5_remote_src_subdirs_dest/subdir/subdir2/file13
stat:
path: '{{ remote_dir }}/testcase5_remote_src_subdirs_dest/subdir/subdir2/file13'
register: stat_testcase5_remote_src_subdirs_file13
- name: assert - remote_dir_src has copied with local_follow False.
assert:
that:
- testcase5_new is changed
- testcase5_edited is changed
- "stat_testcase5_remote_src_subdirs_file13.stat.exists"
- "stat_testcase5_remote_src_subdirs_file13_before.stat.checksum == stat_testcase5_remote_src_subdirs_file13.stat.checksum"
## 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
become: true
register: ansible_copy_test_user
- name: execute - create a group for test
group:
name: '{{ ansible_copy_test_user_name }}'
state: present
become: true
register: ansible_copy_test_group
- name: execute - Copy the directory on remote with chown
copy:
remote_src: True
src: '{{ remote_dir_expanded }}/remote_dir_src/'
dest: '{{ remote_dir_expanded }}/new_dir_with_chown'
owner: '{{ ansible_copy_test_user_name }}'
group: '{{ ansible_copy_test_user_name }}'
follow: true
register: testcase5
become: true
- 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
become: true
- name: execute - remove the group for test
group:
name: '{{ ansible_copy_test_user_name }}'
state: absent
become: true
## 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"
# Test for issue 69783: copy with remote_src=yes and src='dir/' preserves all permissions
- block:
- name: Create directory structure
file:
path: "{{ local_temp_dir }}/test69783/{{ item }}"
state: directory
loop:
- "src/dir"
- "dest"
- name: Create source file structure
file:
path: "{{ local_temp_dir }}/test69783/src/{{ item.name }}"
state: touch
mode: "{{ item.mode }}"
loop:
- { name: 'readwrite', mode: '0644' }
- { name: 'executable', mode: '0755' }
- { name: 'readonly', mode: '0444' }
- { name: 'dir/readwrite', mode: '0644' }
- { name: 'dir/executable', mode: '0755' }
- { name: 'dir/readonly', mode: '0444' }
- name: Recursive remote copy with preserve
copy:
src: "{{ local_temp_dir }}/test69783/src/"
dest: "{{ local_temp_dir }}/test69783/dest/"
remote_src: yes
mode: preserve
- name: Stat dest 'readwrite' file
stat:
path: "{{ local_temp_dir}}/test69783/dest/readwrite"
register: dest_readwrite_stat
- name: Stat dest 'executable' file
stat:
path: "{{ local_temp_dir}}/test69783/dest/executable"
register: dest_executable_stat
- name: Stat dest 'readonly' file
stat:
path: "{{ local_temp_dir}}/test69783/dest/readonly"
register: dest_readonly_stat
- name: Stat dest 'dir/readwrite' file
stat:
path: "{{ local_temp_dir}}/test69783/dest/dir/readwrite"
register: dest_dir_readwrite_stat
- name: Stat dest 'dir/executable' file
stat:
path: "{{ local_temp_dir}}/test69783/dest/dir/executable"
register: dest_dir_executable_stat
- name: Stat dest 'dir/readonly' file
stat:
path: "{{ local_temp_dir}}/test69783/dest/dir/readonly"
register: dest_dir_readonly_stat
- name: Assert modes are preserved
assert:
that:
- "dest_readwrite_stat.stat.mode == '0644'"
- "dest_executable_stat.stat.mode == '0755'"
- "dest_readonly_stat.stat.mode == '0444'"
- "dest_dir_readwrite_stat.stat.mode == '0644'"
- "dest_dir_executable_stat.stat.mode == '0755'"
- "dest_dir_readonly_stat.stat.mode == '0444'"