From 49e1cb9f42fef6953c39ef0dd88470c361fce6a9 Mon Sep 17 00:00:00 2001 From: Jonathan Neuhauser Date: Tue, 14 Dec 2021 18:31:01 +0100 Subject: [PATCH] unarchive: fix non-english locales (#76542) * unarchive: fix non-english locales For GNU Gettext, the LANGUAGE environment variable takes precedence over LANG or LC_ALL. On systems where LANGUAGE was set to a non-english locale, the output of the tar command therefore not understood and the module failed silently ("changed": false, but the archive was not extracted). * add tests * changelog --- ...6542-fix-unarchive-on-nenglish-locales.yml | 2 + lib/ansible/modules/unarchive.py | 6 +-- .../targets/unarchive/tasks/main.yml | 1 + .../tasks/test_different_language_var.yml | 41 +++++++++++++++++++ 4 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 changelogs/fragments/76542-fix-unarchive-on-nenglish-locales.yml create mode 100644 test/integration/targets/unarchive/tasks/test_different_language_var.yml diff --git a/changelogs/fragments/76542-fix-unarchive-on-nenglish-locales.yml b/changelogs/fragments/76542-fix-unarchive-on-nenglish-locales.yml new file mode 100644 index 00000000000..8ce73d6263b --- /dev/null +++ b/changelogs/fragments/76542-fix-unarchive-on-nenglish-locales.yml @@ -0,0 +1,2 @@ +bugfixes: +- unarchive - Make extraction work when the LANGUAGE environment variable is set to a non-English locale. \ No newline at end of file diff --git a/lib/ansible/modules/unarchive.py b/lib/ansible/modules/unarchive.py index 38eb10bd8c7..0b265943b78 100644 --- a/lib/ansible/modules/unarchive.py +++ b/lib/ansible/modules/unarchive.py @@ -786,7 +786,7 @@ class TgzArchive(object): cmd.extend(self.include_files) locale = get_best_parsable_locale(self.module) - rc, out, err = self.module.run_command(cmd, cwd=self.b_dest, environ_update=dict(LANG=locale, LC_ALL=locale, LC_MESSAGES=locale)) + rc, out, err = self.module.run_command(cmd, cwd=self.b_dest, environ_update=dict(LANG=locale, LC_ALL=locale, LC_MESSAGES=locale, LANGUAGE=locale)) if rc != 0: raise UnarchiveError('Unable to list files in the archive') @@ -831,7 +831,7 @@ class TgzArchive(object): if self.include_files: cmd.extend(self.include_files) locale = get_best_parsable_locale(self.module) - rc, out, err = self.module.run_command(cmd, cwd=self.b_dest, environ_update=dict(LANG=locale, LC_ALL=locale, LC_MESSAGES=locale)) + rc, out, err = self.module.run_command(cmd, cwd=self.b_dest, environ_update=dict(LANG=locale, LC_ALL=locale, LC_MESSAGES=locale, LANGUAGE=locale)) # Check whether the differences are in something that we're # setting anyway @@ -885,7 +885,7 @@ class TgzArchive(object): if self.include_files: cmd.extend(self.include_files) locale = get_best_parsable_locale(self.module) - rc, out, err = self.module.run_command(cmd, cwd=self.b_dest, environ_update=dict(LANG=locale, LC_ALL=locale, LC_MESSAGES=locale)) + rc, out, err = self.module.run_command(cmd, cwd=self.b_dest, environ_update=dict(LANG=locale, LC_ALL=locale, LC_MESSAGES=locale, LANGUAGE=locale)) return dict(cmd=cmd, rc=rc, out=out, err=err) def can_handle_archive(self): diff --git a/test/integration/targets/unarchive/tasks/main.yml b/test/integration/targets/unarchive/tasks/main.yml index 035a5561505..baa2a8cf228 100644 --- a/test/integration/targets/unarchive/tasks/main.yml +++ b/test/integration/targets/unarchive/tasks/main.yml @@ -17,3 +17,4 @@ - import_tasks: test_symlink.yml - import_tasks: test_download.yml - import_tasks: test_unprivileged_user.yml +- import_tasks: test_different_language_var.yml diff --git a/test/integration/targets/unarchive/tasks/test_different_language_var.yml b/test/integration/targets/unarchive/tasks/test_different_language_var.yml new file mode 100644 index 00000000000..1d7d3f60a27 --- /dev/null +++ b/test/integration/targets/unarchive/tasks/test_different_language_var.yml @@ -0,0 +1,41 @@ +- name: test non-ascii with different LANGUAGE + when: ansible_os_family == 'Debian' + block: + - name: install de language pack + apt: + name: language-pack-de + state: present + + - name: create our unarchive destination + file: + path: "{{ remote_tmp_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: "{{ remote_tmp_dir }}/test-unarchive-nonascii-くらとみ-tar-gz" + mode: "u+rwX,go+rX" + remote_src: no + register: nonascii_result0 + + - name: Check that file is really there + stat: + path: "{{ remote_tmp_dir }}/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: "{{ remote_tmp_dir }}/test-unarchive-nonascii-くらとみ-tar-gz" + state: absent + + environment: + LANGUAGE: de_DE:en \ No newline at end of file