summaryrefslogtreecommitdiffstats
path: root/lib/ansible/modules/unarchive.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ansible/modules/unarchive.py')
-rw-r--r--lib/ansible/modules/unarchive.py65
1 files changed, 42 insertions, 23 deletions
diff --git a/lib/ansible/modules/unarchive.py b/lib/ansible/modules/unarchive.py
index 26890b5..ec15a57 100644
--- a/lib/ansible/modules/unarchive.py
+++ b/lib/ansible/modules/unarchive.py
@@ -17,17 +17,17 @@ module: unarchive
version_added: '1.4'
short_description: Unpacks an archive after (optionally) copying it from the local machine
description:
- - The C(unarchive) module unpacks an archive. It will not unpack a compressed file that does not contain an archive.
+ - The M(ansible.builtin.unarchive) module unpacks an archive. It will not unpack a compressed file that does not contain an archive.
- By default, it will copy the source file from the local system to the target before unpacking.
- - Set C(remote_src=yes) to unpack an archive which already exists on the target.
- - If checksum validation is desired, use M(ansible.builtin.get_url) or M(ansible.builtin.uri) instead to fetch the file and set C(remote_src=yes).
+ - Set O(remote_src=yes) to unpack an archive which already exists on the target.
+ - If checksum validation is desired, use M(ansible.builtin.get_url) or M(ansible.builtin.uri) instead to fetch the file and set O(remote_src=yes).
- For Windows targets, use the M(community.windows.win_unzip) module instead.
options:
src:
description:
- - If C(remote_src=no) (default), local path to archive file to copy to the target server; can be absolute or relative. If C(remote_src=yes), path on the
+ - If O(remote_src=no) (default), local path to archive file to copy to the target server; can be absolute or relative. If O(remote_src=yes), path on the
target server to existing archive file to unpack.
- - If C(remote_src=yes) and C(src) contains C(://), the remote machine will download the file from the URL first. (version_added 2.0). This is only for
+ - If O(remote_src=yes) and O(src) contains V(://), the remote machine will download the file from the URL first. (version_added 2.0). This is only for
simple cases, for full download support use the M(ansible.builtin.get_url) module.
type: path
required: true
@@ -40,14 +40,14 @@ options:
copy:
description:
- If true, the file is copied from local controller to the managed (remote) node, otherwise, the plugin will look for src archive on the managed machine.
- - This option has been deprecated in favor of C(remote_src).
- - This option is mutually exclusive with C(remote_src).
+ - This option has been deprecated in favor of O(remote_src).
+ - This option is mutually exclusive with O(remote_src).
type: bool
default: yes
creates:
description:
- If the specified absolute path (file or directory) already exists, this step will B(not) be run.
- - The specified absolute path (file or directory) must be below the base path given with C(dest:).
+ - The specified absolute path (file or directory) must be below the base path given with O(dest).
type: path
version_added: "1.6"
io_buffer_size:
@@ -65,16 +65,16 @@ options:
exclude:
description:
- List the directory and file entries that you would like to exclude from the unarchive action.
- - Mutually exclusive with C(include).
+ - Mutually exclusive with O(include).
type: list
default: []
elements: str
version_added: "2.1"
include:
description:
- - List of directory and file entries that you would like to extract from the archive. If C(include)
+ - List of directory and file entries that you would like to extract from the archive. If O(include)
is not empty, only files listed here will be extracted.
- - Mutually exclusive with C(exclude).
+ - Mutually exclusive with O(exclude).
type: list
default: []
elements: str
@@ -92,20 +92,20 @@ options:
- Command-line options with multiple elements must use multiple lines in the array, one for each element.
type: list
elements: str
- default: ""
+ default: []
version_added: "2.1"
remote_src:
description:
- - Set to C(true) to indicate the archived file is already on the remote system and not local to the Ansible controller.
- - This option is mutually exclusive with C(copy).
+ - Set to V(true) to indicate the archived file is already on the remote system and not local to the Ansible controller.
+ - This option is mutually exclusive with O(copy).
type: bool
default: no
version_added: "2.2"
validate_certs:
description:
- This only applies if using a https URL as the source of the file.
- - This should only set to C(false) used on personally controlled sites using self-signed certificate.
- - Prior to 2.2 the code worked as if this was set to C(true).
+ - This should only set to V(false) used on personally controlled sites using self-signed certificate.
+ - Prior to 2.2 the code worked as if this was set to V(true).
type: bool
default: yes
version_added: "2.2"
@@ -188,7 +188,7 @@ dest:
sample: /opt/software
files:
description: List of all the files in the archive.
- returned: When I(list_files) is True
+ returned: When O(list_files) is V(True)
type: list
sample: '["file1", "file2"]'
gid:
@@ -224,7 +224,7 @@ size:
src:
description:
- The source archive's path.
- - If I(src) was a remote web URL, or from the local ansible controller, this shows the temporary location where the download was stored.
+ - If O(src) was a remote web URL, or from the local ansible controller, this shows the temporary location where the download was stored.
returned: always
type: str
sample: "/home/paul/test.tar.gz"
@@ -253,9 +253,9 @@ import stat
import time
import traceback
from functools import partial
-from zipfile import ZipFile, BadZipfile
+from zipfile import ZipFile
-from ansible.module_utils._text import to_bytes, to_native, to_text
+from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.common.process import get_bin_path
from ansible.module_utils.common.locale import get_best_parsable_locale
@@ -266,6 +266,11 @@ try: # python 3.3+
except ImportError: # older python
from pipes import quote
+try: # python 3.2+
+ from zipfile import BadZipFile # type: ignore[attr-defined]
+except ImportError: # older python
+ from zipfile import BadZipfile as BadZipFile
+
# String from tar that shows the tar contents are different from the
# filesystem
OWNER_DIFF_RE = re.compile(r': Uid differs$')
@@ -337,6 +342,7 @@ class ZipArchive(object):
def _legacy_file_list(self):
rc, out, err = self.module.run_command([self.cmd_path, '-v', self.src])
if rc:
+ self.module.debug(err)
raise UnarchiveError('Neither python zipfile nor unzip can read %s' % self.src)
for line in out.splitlines()[3:-2]:
@@ -350,7 +356,7 @@ class ZipArchive(object):
try:
archive = ZipFile(self.src)
- except BadZipfile as e:
+ except BadZipFile as e:
if e.args[0].lower().startswith('bad magic number'):
# Python2.4 can't handle zipfiles with > 64K files. Try using
# /usr/bin/unzip instead
@@ -375,7 +381,7 @@ class ZipArchive(object):
self._files_in_archive = []
try:
archive = ZipFile(self.src)
- except BadZipfile as e:
+ except BadZipFile as e:
if e.args[0].lower().startswith('bad magic number'):
# Python2.4 can't handle zipfiles with > 64K files. Try using
# /usr/bin/unzip instead
@@ -417,6 +423,7 @@ class ZipArchive(object):
if self.include_files:
cmd.extend(self.include_files)
rc, out, err = self.module.run_command(cmd)
+ self.module.debug(err)
old_out = out
diff = ''
@@ -745,6 +752,9 @@ class ZipArchive(object):
rc, out, err = self.module.run_command(cmd)
if rc == 0:
return True, None
+
+ self.module.debug(err)
+
return False, 'Command "%s" could not handle archive: %s' % (self.cmd_path, err)
@@ -794,6 +804,7 @@ class TgzArchive(object):
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, LANGUAGE=locale))
if rc != 0:
+ self.module.debug(err)
raise UnarchiveError('Unable to list files in the archive: %s' % err)
for filename in out.splitlines():
@@ -1022,7 +1033,12 @@ def main():
src = module.params['src']
dest = module.params['dest']
- b_dest = to_bytes(dest, errors='surrogate_or_strict')
+ abs_dest = os.path.abspath(dest)
+ b_dest = to_bytes(abs_dest, errors='surrogate_or_strict')
+
+ if not os.path.isabs(dest):
+ module.warn("Relative destination path '{dest}' was resolved to absolute path '{abs_dest}'.".format(dest=dest, abs_dest=abs_dest))
+
remote_src = module.params['remote_src']
file_args = module.load_file_common_arguments(module.params)
@@ -1038,6 +1054,9 @@ def main():
if not os.access(src, os.R_OK):
module.fail_json(msg="Source '%s' not readable" % src)
+ # ensure src is an absolute path before picking handlers
+ src = os.path.abspath(src)
+
# skip working with 0 size archives
try:
if os.path.getsize(src) == 0: