Fix copy to only follow symlinks for files in the non-recursive case

Revert "**Temporary**"

This reverts commit 28b86b1148.

We don't need this now that copy has been fixed
This commit is contained in:
Toshio Kuratomi 2017-11-06 09:26:41 -08:00
parent 9e028ab704
commit f332151f59
5 changed files with 66 additions and 18 deletions

View file

@ -0,0 +1,4 @@
---
bugfixes:
- copy - fixed copy to only follow symlinks for files in the non-recursive case
- file - fixed the default follow behaviour of file to be true

View file

@ -182,7 +182,7 @@ def main():
original_basename=dict(required=False), # Internal use only, for recursive ops original_basename=dict(required=False), # Internal use only, for recursive ops
recurse=dict(default=False, type='bool'), recurse=dict(default=False, type='bool'),
force=dict(required=False, default=False, type='bool'), force=dict(required=False, default=False, type='bool'),
follow=dict(required=False, default=False, type='bool'), follow=dict(required=False, default=True, type='bool'),
diff_peek=dict(default=None), # Internal use only, for internal checks in the action plugins diff_peek=dict(default=None), # Internal use only, for internal checks in the action plugins
validate=dict(required=False, default=None), # Internal use only, for template and copy validate=dict(required=False, default=None), # Internal use only, for template and copy
src=dict(required=False, default=None, type='path'), src=dict(required=False, default=None, type='path'),

View file

@ -192,9 +192,9 @@ class ActionModule(ActionBase):
# remove action plugin only keys # remove action plugin only keys
return dict((k, v) for k, v in module_args.items() if k not in ('content', 'decrypt')) return dict((k, v) for k, v in module_args.items() if k not in ('content', 'decrypt'))
def _copy_file(self, source_full, source_rel, content, content_tempfile, dest, task_vars): def _copy_file(self, source_full, source_rel, content, content_tempfile,
dest, task_vars, follow):
decrypt = boolean(self._task.args.get('decrypt', True), strict=False) decrypt = boolean(self._task.args.get('decrypt', True), strict=False)
follow = boolean(self._task.args.get('follow', False), strict=False)
force = boolean(self._task.args.get('force', 'yes'), strict=False) force = boolean(self._task.args.get('force', 'yes'), strict=False)
raw = boolean(self._task.args.get('raw', 'no'), strict=False) raw = boolean(self._task.args.get('raw', 'no'), strict=False)
@ -289,6 +289,7 @@ class ActionModule(ActionBase):
src=tmp_src, src=tmp_src,
dest=dest, dest=dest,
original_basename=source_rel, original_basename=source_rel,
follow=follow
) )
) )
if not self._task.args.get('checksum'): if not self._task.args.get('checksum'):
@ -491,7 +492,14 @@ class ActionModule(ActionBase):
for source_full, source_rel in source_files['files']: for source_full, source_rel in source_files['files']:
# copy files over. This happens first as directories that have # copy files over. This happens first as directories that have
# a file do not need to be created later # a file do not need to be created later
module_return = self._copy_file(source_full, source_rel, content, content_tempfile, dest, task_vars)
# We only follow symlinks for files in the non-recursive case
if source_files['directories']:
follow = False
else:
follow = boolean(self._task.args.get('follow', False), strict=False)
module_return = self._copy_file(source_full, source_rel, content, content_tempfile, dest, task_vars, follow)
if module_return is None: if module_return is None:
continue continue
@ -528,6 +536,9 @@ class ActionModule(ActionBase):
new_module_args['src'] = target_path new_module_args['src'] = target_path
new_module_args['state'] = 'link' new_module_args['state'] = 'link'
new_module_args['force'] = True new_module_args['force'] = True
# Only follow remote symlinks in the non-recursive case
if source_files['directories']:
new_module_args['follow'] = False
module_return = self._execute_module(module_name='file', module_args=new_module_args, task_vars=task_vars) module_return = self._execute_module(module_name='file', module_args=new_module_args, task_vars=task_vars)
module_executed = True module_executed = True

View file

@ -14,7 +14,7 @@
name: ensure temp dir exists name: ensure temp dir exists
# file cannot do this properly, use command instead # file cannot do this properly, use command instead
- name: Create ciruclar symbolic link - name: Create circular symbolic link
command: ln -s ../ circles command: ln -s ../ circles
args: args:
chdir: '{{role_path}}/files/subdir/subdir1' chdir: '{{role_path}}/files/subdir/subdir1'
@ -57,7 +57,7 @@
- name: Remove circular symbolic link - name: Remove circular symbolic link
file: file:
path: subdir/subdir1/circles path: '{{ role_path }}/files/subdir/subdir1/circles'
state: absent state: absent
connection: local connection: local

View file

@ -16,6 +16,10 @@
mode: 0444 mode: 0444
register: copy_result 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 - name: Check the mode of the output file
file: file:
name: "{{ remote_file }}" name: "{{ remote_file }}"
@ -173,7 +177,7 @@
- name: Create a hardlink to the file - name: Create a hardlink to the file
file: file:
src: '{{ remote_file }}' src: '{{ remote_file }}'
dest: '{{ output_dir }}/hard.lnk' dest: '{{ remote_dir }}/hard.lnk'
state: hard state: hard
- name: copy the same contents into place - name: copy the same contents into place
@ -191,7 +195,7 @@
- name: Check the stat results of the hard link - name: Check the stat results of the hard link
stat: stat:
path: "{{ output_dir }}/hard.lnk" path: "{{ remote_dir }}/hard.lnk"
register: hlink_results register: hlink_results
- name: Check that the file did not change - name: Check that the file did not change
@ -216,7 +220,7 @@
- name: Check the stat results of the hard link - name: Check the stat results of the hard link
stat: stat:
path: "{{ output_dir }}/hard.lnk" path: "{{ remote_dir }}/hard.lnk"
register: hlink_results register: hlink_results
- name: Check that the file changed permissions but is still the same - name: Check that the file changed permissions but is still the same
@ -242,7 +246,7 @@
- name: Check the stat results of the hard link - name: Check the stat results of the hard link
stat: stat:
path: "{{ output_dir }}/hard.lnk" path: "{{ remote_dir }}/hard.lnk"
register: hlink_results register: hlink_results
- name: Check that the file changed and hardlink was broken - name: Check that the file changed and hardlink was broken
@ -1105,6 +1109,10 @@
remote_user: root remote_user: root
#
# Follow=True tests
#
# test overwriting a link using "follow=yes" so that the link # test overwriting a link using "follow=yes" so that the link
# is preserved and the link target is updated # is preserved and the link target is updated
@ -1122,7 +1130,7 @@
- name: Update the test file using follow=True to preserve the link - name: Update the test file using follow=True to preserve the link
copy: copy:
dest: "{{ remote_dir }}/follow_link" dest: "{{ remote_dir }}/follow_link"
content: "this is the new content\n" src: foo.txt
follow: yes follow: yes
register: replace_follow_result register: replace_follow_result
@ -1131,19 +1139,37 @@
path: "{{ remote_dir }}/follow_link" path: "{{ remote_dir }}/follow_link"
register: stat_link_result register: stat_link_result
- name: Assert that the link is still a link - name: Assert that the link is still a link and contents were changed
assert: assert:
that: that:
- stat_link_result.stat.islnk - stat_link_result['stat']['islnk']
- stat_link_result['stat']['lnk_target'] == './follow_test'
- replace_follow_result['changed']
- "replace_follow_result['checksum'] == remote_file_hash"
- name: Get the checksum of the link target # Symlink handling when the dest is already there
shell: "{{ ansible_python_interpreter }} -c 'import hashlib; print(hashlib.sha1(open(\"{{remote_dir | expanduser}}/follow_test\", \"rb\").read()).hexdigest())'" # https://github.com/ansible/ansible-modules-core/issues/1568
register: target_file_result
- name: Assert that the link target was updated - 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: assert:
that: that:
- replace_follow_result.checksum == target_file_result.stdout - 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 - name: Update the test file using follow=False to overwrite the link
copy: copy:
@ -1169,6 +1195,13 @@
- "stat_results.stat.checksum == ('modified'|hash('sha1'))" - "stat_results.stat.checksum == ('modified'|hash('sha1'))"
- "not stat_results.stat.islnk" - "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 - name: setup directory for test
file: state=directory dest={{remote_dir }}/directory mode=0755 file: state=directory dest={{remote_dir }}/directory mode=0755