Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from
May 26, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/ansible/plugins/action/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ def _execute_remote_stat(self, path, all_vars, follow, tmp=None):

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
Expand All @@ -440,7 +440,7 @@ def _remote_checksum(self, path, all_vars):
'''
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:
Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/plugins/action/unarchive.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def run(self, tmp=None, task_vars=None):
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"
Expand Down
Binary file not shown.
101 changes: 98 additions & 3 deletions test/integration/roles/test_unarchive/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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