unarchive: add support for .tar.zst (zstd compression) (#73265)
This commit is contained in:
parent
ae241b407a
commit
6fd0a74601
5 changed files with 89 additions and 3 deletions
2
changelogs/fragments/unarchive-support-zst.yml
Normal file
2
changelogs/fragments/unarchive-support-zst.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- unarchive - Add support for .tar.zst (zstd compression) (https://github.com/ansible/ansible/pull/73265).
|
|
@ -110,8 +110,9 @@ todo:
|
|||
- Re-implement zip support using native zipfile module.
|
||||
notes:
|
||||
- Requires C(zipinfo) and C(gtar)/C(unzip) command on target host.
|
||||
- Can handle I(.zip) files using C(unzip) as well as I(.tar), I(.tar.gz), I(.tar.bz2) and I(.tar.xz) files using C(gtar).
|
||||
- Does not handle I(.gz) files, I(.bz2) files or I(.xz) files that do not contain a I(.tar) archive.
|
||||
- Requires C(zstd) command on target host to expand I(.tar.zst) files.
|
||||
- Can handle I(.zip) files using C(unzip) as well as I(.tar), I(.tar.gz), I(.tar.bz2), I(.tar.xz), and I(.tar.zst) files using C(gtar).
|
||||
- Does not handle I(.gz) files, I(.bz2) files, I(.xz), or I(.zst) files that do not contain a I(.tar) archive.
|
||||
- Uses gtar's C(--diff) arg to calculate if changed or not. If this C(arg) is not
|
||||
supported, it will always unpack the archive.
|
||||
- Existing files/directories in the destination which are not in the archive
|
||||
|
@ -891,9 +892,22 @@ class TarXzArchive(TgzArchive):
|
|||
self.zipflag = '-J'
|
||||
|
||||
|
||||
# Class to handle zstd compressed tar files
|
||||
class TarZstdArchive(TgzArchive):
|
||||
def __init__(self, src, b_dest, file_args, module):
|
||||
super(TarZstdArchive, self).__init__(src, b_dest, file_args, module)
|
||||
# GNU Tar supports the --use-compress-program option to
|
||||
# specify which executable to use for
|
||||
# compression/decompression.
|
||||
#
|
||||
# Note: some flavors of BSD tar support --zstd (e.g., FreeBSD
|
||||
# 12.2), but the TgzArchive class only supports GNU Tar.
|
||||
self.zipflag = '--use-compress-program=zstd'
|
||||
|
||||
|
||||
# try handlers in order and return the one that works or bail if none work
|
||||
def pick_handler(src, dest, file_args, module):
|
||||
handlers = [ZipArchive, TgzArchive, TarArchive, TarBzipArchive, TarXzArchive]
|
||||
handlers = [ZipArchive, TgzArchive, TarArchive, TarBzipArchive, TarXzArchive, TarZstdArchive]
|
||||
reasons = set()
|
||||
for handler in handlers:
|
||||
obj = handler(src, dest, file_args, module)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
- import_tasks: test_tar_gz_creates.yml
|
||||
- import_tasks: test_tar_gz_owner_group.yml
|
||||
- import_tasks: test_tar_gz_keep_newer.yml
|
||||
- import_tasks: test_tar_zst.yml
|
||||
- import_tasks: test_zip.yml
|
||||
- import_tasks: test_exclude.yml
|
||||
- import_tasks: test_include.yml
|
||||
|
|
|
@ -6,6 +6,13 @@
|
|||
- unzip
|
||||
when: ansible_pkg_mgr in ('yum', 'dnf', 'apt', 'pkgng')
|
||||
|
||||
- name: Ensure zstd is present, if available
|
||||
ignore_errors: true
|
||||
package:
|
||||
name:
|
||||
- zstd
|
||||
when: ansible_pkg_mgr in ('yum', 'dnf', 'apt', 'pkgng')
|
||||
|
||||
- name: prep our file
|
||||
copy:
|
||||
src: foo.txt
|
||||
|
@ -18,6 +25,28 @@
|
|||
- name: prep a tar.gz file
|
||||
shell: tar czvf test-unarchive.tar.gz foo-unarchive.txt chdir={{remote_tmp_dir}}
|
||||
|
||||
- name: see if we have the zstd executable
|
||||
ignore_errors: true
|
||||
shell: zstd --version
|
||||
register: zstd_available
|
||||
|
||||
- when: zstd_available.rc == 0
|
||||
block:
|
||||
- name: find gnu tar
|
||||
shell: |
|
||||
#!/bin/sh
|
||||
which gtar 2>/dev/null
|
||||
if test $? -ne 0; then
|
||||
if test -z "`tar --version | grep bsdtar`"; then
|
||||
which tar
|
||||
fi
|
||||
fi
|
||||
register: gnu_tar
|
||||
|
||||
- name: prep a tar.zst file
|
||||
shell: "{{ gnu_tar.stdout }} --use-compress-program=zstd -cvf test-unarchive.tar.zst foo-unarchive.txt chdir={{remote_tmp_dir}}"
|
||||
when: gnu_tar.stdout != ""
|
||||
|
||||
- name: prep a chmodded file for zip
|
||||
copy:
|
||||
src: foo.txt
|
||||
|
|
40
test/integration/targets/unarchive/tasks/test_tar_zst.yml
Normal file
40
test/integration/targets/unarchive/tasks/test_tar_zst.yml
Normal file
|
@ -0,0 +1,40 @@
|
|||
# Only do this whole file when the "zstd" executable is present
|
||||
- when:
|
||||
- zstd_available.rc == 0
|
||||
- gnu_tar.stdout != ""
|
||||
block:
|
||||
- name: create our tar.zst unarchive destination
|
||||
file:
|
||||
path: '{{remote_tmp_dir}}/test-unarchive-tar-zst'
|
||||
state: directory
|
||||
|
||||
- name: unarchive a tar.zst file
|
||||
unarchive:
|
||||
src: '{{remote_tmp_dir}}/test-unarchive.tar.zst'
|
||||
dest: '{{remote_tmp_dir}}/test-unarchive-tar-zst'
|
||||
remote_src: yes
|
||||
register: unarchive02
|
||||
|
||||
- name: verify that the file was marked as changed
|
||||
assert:
|
||||
that:
|
||||
- "unarchive02.changed == true"
|
||||
# Verify that no file list is generated
|
||||
- "'files' not in unarchive02"
|
||||
|
||||
- name: verify that the file was unarchived
|
||||
file:
|
||||
path: '{{remote_tmp_dir}}/test-unarchive-tar-zst/foo-unarchive.txt'
|
||||
state: file
|
||||
|
||||
- name: remove our tar.zst unarchive destination
|
||||
file:
|
||||
path: '{{remote_tmp_dir}}/test-unarchive-tar-zst'
|
||||
state: absent
|
||||
|
||||
- name: test owner/group perms
|
||||
include_tasks: test_owner_group.yml
|
||||
vars:
|
||||
ext: tar.zst
|
||||
archive: test-unarchive.tar.zst
|
||||
testfile: foo-unarchive.txt
|
Loading…
Reference in a new issue