diff --git a/lib/ansible/plugins/action/__init__.py b/lib/ansible/plugins/action/__init__.py index f35d586eb9..210607f39a 100644 --- a/lib/ansible/plugins/action/__init__.py +++ b/lib/ansible/plugins/action/__init__.py @@ -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: diff --git a/lib/ansible/plugins/action/unarchive.py b/lib/ansible/plugins/action/unarchive.py index 590881165e..5b8d049985 100644 --- a/lib/ansible/plugins/action/unarchive.py +++ b/lib/ansible/plugins/action/unarchive.py @@ -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" diff --git a/test/integration/roles/test_unarchive/files/test-unarchive-nonascii-àâæçéèïîôœ.tar.gz b/test/integration/roles/test_unarchive/files/test-unarchive-nonascii-àâæçéèïîôœ.tar.gz new file mode 100644 index 0000000000..4882b9207a Binary files /dev/null and b/test/integration/roles/test_unarchive/files/test-unarchive-nonascii-àâæçéèïîôœ.tar.gz differ diff --git a/test/integration/roles/test_unarchive/tasks/main.yml b/test/integration/roles/test_unarchive/tasks/main.yml index e4f438e525..6e284c3aea 100644 --- a/test/integration/roles/test_unarchive/tasks/main.yml +++ b/test/integration/roles/test_unarchive/tasks/main.yml @@ -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