From 705d0201cf9c4eeb32084b3da92b831dddff5efe Mon Sep 17 00:00:00 2001 From: Martin Krizek Date: Wed, 5 Jun 2019 15:25:43 +0200 Subject: [PATCH] file: fix setting attributes for symlinked file (#57217) --- ...-file-fix-setting-attr-symlink-follow.yaml | 2 + lib/ansible/modules/files/file.py | 7 +++- .../targets/file/tasks/state_link.yml | 39 ++++++++++++++++++- 3 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/56928-file-fix-setting-attr-symlink-follow.yaml diff --git a/changelogs/fragments/56928-file-fix-setting-attr-symlink-follow.yaml b/changelogs/fragments/56928-file-fix-setting-attr-symlink-follow.yaml new file mode 100644 index 0000000000..6135dc1e71 --- /dev/null +++ b/changelogs/fragments/56928-file-fix-setting-attr-symlink-follow.yaml @@ -0,0 +1,2 @@ +bugfixes: + - file - fix setting attributes for symlinked file (https://github.com/ansible/ansible/issues/56928) diff --git a/lib/ansible/modules/files/file.py b/lib/ansible/modules/files/file.py index 63d6abd466..0656dce4df 100644 --- a/lib/ansible/modules/files/file.py +++ b/lib/ansible/modules/files/file.py @@ -635,7 +635,6 @@ def ensure_symlink(path, src, follow, force, timestamps): b_path = to_bytes(path, errors='surrogate_or_strict') b_src = to_bytes(src, errors='surrogate_or_strict') prev_state = get_state(b_path) - file_args = module.load_file_common_arguments(module.params) mtime = get_timestamp_for_time(timestamps['modification_time'], timestamps['modification_time_format']) atime = get_timestamp_for_time(timestamps['access_time'], timestamps['access_time_format']) # source is both the source of a symlink or an informational passing of the src for a template module @@ -732,6 +731,12 @@ def ensure_symlink(path, src, follow, force, timestamps): if module.check_mode and not os.path.exists(b_path): return {'dest': path, 'src': src, 'changed': changed, 'diff': diff} + # Now that we might have created the symlink, get the arguments. + # We need to do it now so we can properly follow the symlink if needed + # because load_file_common_arguments sets 'path' according + # the value of follow and the symlink existance. + file_args = module.load_file_common_arguments(module.params) + # Whenever we create a link to a nonexistent target we know that the nonexistent target # cannot have any permissions set on it. Skip setting those and emit a warning (the user # can set follow=False to remove the warning) diff --git a/test/integration/targets/file/tasks/state_link.yml b/test/integration/targets/file/tasks/state_link.yml index 60ea54542c..f4338ec7eb 100644 --- a/test/integration/targets/file/tasks/state_link.yml +++ b/test/integration/targets/file/tasks/state_link.yml @@ -5,7 +5,7 @@ # # Basic absolute symlink to a file -# +# - name: create soft link to file file: src={{output_file}} dest={{output_dir}}/soft.txt state=link register: file1_result @@ -308,3 +308,40 @@ that: - 'file10_result is changed' - 'file10_target_stat["stat"]["mode"] == "0644"' + + +# https://github.com/ansible/ansible/issues/56928 +- block: + + - name: Create a testing file + file: + path: "{{ output_dir }}/test_follow1" + state: touch + + - name: Create a symlink and change mode of the original file, since follow == yes by default + file: + src: "{{ output_dir }}/test_follow1" + dest: "{{ output_dir }}/test_follow1_link" + state: link + mode: 0700 + + - name: stat the original file + stat: + path: "{{ output_dir }}/test_follow1" + register: stat_out + + - name: Check if the mode of the original file was set + assert: + that: + - 'stat_out.stat.mode == "0700"' + + always: + - name: Clean up + file: + path: "{{ item }}" + state: absent + loop: + - "{{ output_dir }}/test_follow1" + - "{{ output_dir }}/test_follow1_link" + +# END #56928