diff --git a/lib/ansible/modules/copy.py b/lib/ansible/modules/copy.py index 07351a9bf07..4d2e8ce16f9 100644 --- a/lib/ansible/modules/copy.py +++ b/lib/ansible/modules/copy.py @@ -430,19 +430,23 @@ def copy_left_only(src, dest, module): def copy_common_dirs(src, dest, module): changed = False - common_dirs = filecmp.dircmp(src, dest).common_dirs - for item in common_dirs: + dircmp = filecmp.dircmp(src, dest) + for item in dircmp.common_dirs: src_item_path = os.path.join(src, item) dest_item_path = os.path.join(dest, item) b_src_item_path = to_bytes(src_item_path, errors='surrogate_or_strict') b_dest_item_path = to_bytes(dest_item_path, errors='surrogate_or_strict') diff_files_changed = copy_diff_files(b_src_item_path, b_dest_item_path, module) left_only_changed = copy_left_only(b_src_item_path, b_dest_item_path, module) - if diff_files_changed or left_only_changed: + ownership_changed = chown_path(module, b_dest_item_path, module.params['owner'], module.params['group']) + if diff_files_changed or left_only_changed or ownership_changed: changed = True # recurse into subdirectory changed = copy_common_dirs(os.path.join(src, item), os.path.join(dest, item), module) or changed + for item in dircmp.same_files: + dest_item_path = os.path.join(dest, item) + changed |= chown_path(module, dest_item_path, module.params['owner'], module.params['group']) return changed @@ -456,8 +460,7 @@ def copy_directory(src, dest, module): 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]) + changed = any([diff_files_changed, left_only_changed, common_dirs_changed]) return changed diff --git a/test/integration/targets/copy/tasks/tests.yml b/test/integration/targets/copy/tasks/tests.yml index c4a0cce357d..17ad2e41cf4 100644 --- a/test/integration/targets/copy/tasks/tests.yml +++ b/test/integration/targets/copy/tasks/tests.yml @@ -2139,55 +2139,58 @@ register: testcase5 become: true - - name: gather - Stat the new_dir_with_chown + - name: Stat destination to verify ownership stat: - path: '{{ remote_dir }}/new_dir_with_chown' - register: stat_new_dir_with_chown + path: "{{ remote_dir }}/{{ item }}" + loop: + - 'new_dir_with_chown' + - 'new_dir_with_chown/file1' + - 'new_dir_with_chown/subdir' + - 'new_dir_with_chown/subdir/file12' + - 'new_dir_with_chown/link_file12' + register: testcase5_stat + + - assert: + that: + - testcase5 is changed + - testcase5_stat.results | map(attribute='stat') | map(attribute='uid') | unique == [ansible_copy_test_user.uid] + - testcase5_stat.results | map(attribute='stat') | map(attribute='gid') | unique == [ansible_copy_test_group.gid] + - testcase5_stat.results | map(attribute='stat') | map(attribute='pw_name') | unique == [ansible_copy_test_user_name] + - testcase5_stat.results | map(attribute='stat') | map(attribute='gr_name') | unique == [ansible_copy_test_user_name] - - 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 + - command: whoami + register: current_user - - 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 + - command: id -gn + register: current_group - - 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: Modify ownership recursively + copy: + remote_src: True + src: '{{ remote_dir_expanded }}/remote_dir_src/' + dest: '{{ remote_dir_expanded }}/new_dir_with_chown' + owner: '{{ current_user.stdout }}' + group: '{{ current_group.stdout }}' + follow: true + register: testcase5_updated + become: true - - name: gather - Stat the new_dir_with_chown/link_file12 + - name: Stat destination to verify updated ownership 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: + path: "{{ remote_dir }}/{{ item }}" + loop: + - 'new_dir_with_chown' + - 'new_dir_with_chown/file1' + - 'new_dir_with_chown/subdir' + - 'new_dir_with_chown/subdir/file12' + - 'new_dir_with_chown/link_file12' + register: testcase5_updated_stat + + - 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 + - testcase5_updated is changed + - testcase5_updated_stat.results | map(attribute='stat') | map(attribute='pw_name') | unique == [current_user.stdout] + - testcase5_updated_stat.results | map(attribute='stat') | map(attribute='gr_name') | unique == [current_group.stdout] always: - name: execute - remove the user for test