Fix unarchive failures when the destination is a symlink to a directory (#15999)

Also add integration tests for this problem and unicode filenames inside
a tarball.

Fixes #3725
This commit is contained in:
Toshio Kuratomi 2016-05-26 14:47:11 -07:00 committed by Toshio Kuratomi
parent a44743d142
commit 4304574c00
4 changed files with 101 additions and 6 deletions

View file

@ -428,7 +428,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
return mystat['stat']
def _remote_checksum(self, path, all_vars):
def _remote_checksum(self, path, all_vars, follow=False):
'''
Produces a remote checksum given a path,
Returns a number 0-4 for specific errors instead of checksum, also ensures it is different
@ -440,7 +440,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
'''
x = "0" # unknown error has occured
try:
remote_stat = self._execute_remote_stat(path, all_vars, follow=False)
remote_stat = self._execute_remote_stat(path, all_vars, follow=follow)
if remote_stat['exists'] and remote_stat['isdir']:
x = "3" # its a directory not a file
else:

View file

@ -71,7 +71,7 @@ class ActionModule(ActionBase):
else:
source = self._loader.path_dwim_relative(self._loader.get_basedir(), 'files', source)
remote_checksum = self._remote_checksum(dest, all_vars=task_vars)
remote_checksum = self._remote_checksum(dest, all_vars=task_vars, follow=True)
if remote_checksum == '4':
result['failed'] = True
result['msg'] = "python isn't present on the system. Unable to compute checksum"

View file

@ -21,9 +21,9 @@
yum: name=zip state=latest
when: ansible_pkg_mgr == 'yum'
- name: Ensure zip is present to create test archive (dnf)
dnf: name=zip state=latest
when: ansible_pkg_mgr == 'dnf'
#- name: Ensure zip is present to create test archive (dnf)
# dnf: name=zip state=latest
# when: ansible_pkg_mgr == 'dnf'
- name: Ensure zip is present to create test archive (apt)
apt: name=zip state=latest
@ -287,6 +287,35 @@
- name: remove quotable chars test
file: path="{{ output_dir }}/test-quotes~root" state=absent
- name: create our unarchive destination
file:
path: "{{ output_dir }}/test-unarchive-nonascii-àâæçéèïîôœ-tar-gz"
state: directory
- name: test that unarchive works with an archive that contains non-ascii filenames
unarchive:
# Both the filename of the tarball and the filename inside the tarball have
# nonascii chars
src: "test-unarchive-nonascii-àâæçéèïîôœ.tar.gz"
dest: "{{ output_dir }}/test-unarchive-nonascii-àâæçéèïîôœ-tar-gz"
mode: "u+rwX,go+rX"
copy: yes
register: nonascii_result0
- name: Check that file is really there
stat:
path: "{{ output_dir | expanduser }}/test-unarchive-nonascii-àâæçéèïîôœ-tar-gz/storage/àâæçéèïîôœ(copy)!@#$%^&-().jpg"
register: nonascii_stat0
- name: Assert that nonascii tests succeeded
assert:
that:
- "nonascii_result0.changed == true"
- "nonascii_stat0.stat.exists == true"
- name: remove nonascii test
file: path="{{ output_dir }}/test-unarchive-nonascii-àâæçéèïîôœ-tar-gz" state=absent
# Test that unarchiving is performed if files are missing
# https://github.com/ansible/ansible-modules-core/issues/1064
- name: create our unarchive destination
@ -330,3 +359,69 @@
- name: remove our tar.gz unarchive destination
file: path={{ output_dir }}/test-unarchive-tar-gz state=absent
#
# Symlink tests
#
- name: Create a destination dir
file:
path: "{{ output_dir }}/test-unarchive-tar-gz"
state: directory
- name: Create a symlink to the detination dir
file:
path: "{{ output_dir }}/link-to-unarchive-dir"
src: "{{ output_dir }}/test-unarchive-tar-gz"
state: "link"
- name: test that unarchive works when dest is a symlink to a dir
unarchive:
src: "{{ output_dir }}/test-unarchive.tar.gz"
dest: "{{ output_dir | expanduser }}/link-to-unarchive-dir"
mode: "u+rwX,go+rX"
copy: no
register: unarchive_11
- name: Check that file is really there
stat:
path: "{{ output_dir | expanduser }}/test-unarchive-tar-gz/foo-unarchive.txt"
register: unarchive11_stat0
- name: Assert that unarchive when dest is a symlink to a dir worked
assert:
that:
- "unarchive_11.changed == true"
- "unarchive11_stat0.stat.exists == true"
- name: remove our tar.gz unarchive destination
file: path={{ output_dir }}/test-unarchive-tar-gz state=absent
- name: Create a file
file:
path: "{{ output_dir }}/test-unarchive-tar-gz"
state: touch
- name: Create a symlink to the file
file:
path: "{{ output_dir }}/link-to-unarchive-file"
src: "{{ output_dir }}/test-unarchive-tar-gz"
state: "link"
- name: test that unarchive fails when dest is a link to a file
unarchive:
src: "{{ output_dir }}/test-unarchive.tar.gz"
dest: "{{ output_dir | expanduser }}/link-to-unarchive-file"
mode: "u+rwX,go+rX"
copy: no
ignore_errors: True
register: unarchive_12
- name: Assert that unarchive when dest is a file failed
assert:
that:
- "unarchive_12.failed == true"
- name: remove our tar.gz unarchive destination
file: path={{ output_dir }}/test-unarchive-tar-gz state=absent