From 17f369838420e4a9f4451e1b2a2030134410270a Mon Sep 17 00:00:00 2001 From: Abhijeet Kasurde Date: Tue, 25 Nov 2025 07:14:05 -0800 Subject: [PATCH] copy: honor directory_mode when specified with remote_src=True (#86184) * copy: honor directory_mode when specified with remote_src=True * Honor directory_mode specified by user when copying directories and remote_src=True Fixes: #81292 Signed-off-by: Abhijeet Kasurde --- .../copy_directory_mode_remote_src.yml | 3 ++ lib/ansible/modules/copy.py | 3 ++ .../tasks/dest_remote_src_directory_mode.yml | 43 +++++++++++++++++++ test/integration/targets/copy/tasks/tests.yml | 4 ++ 4 files changed, 53 insertions(+) create mode 100644 changelogs/fragments/copy_directory_mode_remote_src.yml create mode 100644 test/integration/targets/copy/tasks/dest_remote_src_directory_mode.yml diff --git a/changelogs/fragments/copy_directory_mode_remote_src.yml b/changelogs/fragments/copy_directory_mode_remote_src.yml new file mode 100644 index 00000000000..57dd399d43a --- /dev/null +++ b/changelogs/fragments/copy_directory_mode_remote_src.yml @@ -0,0 +1,3 @@ +--- +bugfixes: + - copy - honor directory_mode when copying directories with remote_src=True (https://github.com/ansible/ansible/issues/81292). diff --git a/lib/ansible/modules/copy.py b/lib/ansible/modules/copy.py index 28c14f4d71f..07351a9bf07 100644 --- a/lib/ansible/modules/copy.py +++ b/lib/ansible/modules/copy.py @@ -661,6 +661,9 @@ def main(): res_args['backup_file'] = backup_file file_args = module.load_file_common_arguments(module.params, path=dest) + directory_mode = module.params['directory_mode'] + if os.path.isdir(b_dest) and directory_mode is not None: + file_args['mode'] = directory_mode res_args['changed'] = module.set_fs_attributes_if_different(file_args, res_args['changed']) module.exit_json(**res_args) diff --git a/test/integration/targets/copy/tasks/dest_remote_src_directory_mode.yml b/test/integration/targets/copy/tasks/dest_remote_src_directory_mode.yml new file mode 100644 index 00000000000..e1337d903e9 --- /dev/null +++ b/test/integration/targets/copy/tasks/dest_remote_src_directory_mode.yml @@ -0,0 +1,43 @@ +- name: Ensure that dest top directory doesn't exist + file: + path: '{{ remote_dir }}/{{ item }}' + state: absent + loop: + - dir1 + - dir2 + +- name: Create directories + file: + path: "{{ item }}" + state: directory + mode: "0755" + loop: + - dir1 + - dir2 + +- name: Copy file + copy: + src: 'dir1/' + dest: '{{ remote_dir }}/dir2/' + remote_src: true + mode: "0644" + directory_mode: "0755" + register: copy_result + +- name: assert copy worked + assert: + that: + - 'copy_result is successful' + - 'copy_result is changed' + +- name: stat copied file + stat: + path: '{{ remote_dir }}/dir2' + register: stat_dir2_result + +- name: assert that dir2 exists and has correct mode + assert: + that: + - stat_dir2_result.stat.exists + - stat_dir2_result.stat.isdir + - stat_dir2_result.stat.mode == "0755" diff --git a/test/integration/targets/copy/tasks/tests.yml b/test/integration/targets/copy/tasks/tests.yml index 44067ae319f..06643b97a03 100644 --- a/test/integration/targets/copy/tasks/tests.yml +++ b/test/integration/targets/copy/tasks/tests.yml @@ -1604,6 +1604,10 @@ - 'new_sub_dir1/foo.txt' loop_control: loop_var: 'dest' + +# Test that directory_mode is respected when copying a directory with remote_src +- include_tasks: file=dest_remote_src_directory_mode.yml + # # Recursive copying on remote host #