diff options
Diffstat (limited to 'library/files/unarchive')
-rw-r--r-- | library/files/unarchive | 250 |
1 files changed, 0 insertions, 250 deletions
diff --git a/library/files/unarchive b/library/files/unarchive deleted file mode 100644 index 657e464937..0000000000 --- a/library/files/unarchive +++ /dev/null @@ -1,250 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com> -# (c) 2013, Dylan Martin <dmartin@seattlecentral.edu> -# -# This file is part of Ansible -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see <http://www.gnu.org/licenses/>. - -DOCUMENTATION = ''' ---- -module: unarchive -version_added: 1.4 -short_description: Copies an archive to a remote location and unpack it -description: - - The M(unarchive) module copies an archive file from the local machine to a remote and unpacks it. -options: - src: - description: - - Local path to archive file to copy to the remote server; can be absolute or relative. - required: true - default: null - dest: - description: - - Remote absolute path where the archive should be unpacked - required: true - default: null - copy: - description: - - "if true, the file is copied from the 'master' to the target machine, otherwise, the plugin will look for src archive at the target machine." - required: false - choices: [ "yes", "no" ] - default: "yes" - creates: - description: - - a filename, when it already exists, this step will B(not) be run. - required: no - default: null - version_added: "1.6" -author: Dylan Martin -todo: - - detect changed/unchanged for .zip files - - handle common unarchive args, like preserve owner/timestamp etc... -notes: - - requires C(tar)/C(unzip) command on target host - - can handle I(gzip), I(bzip2) and I(xz) compressed as well as uncompressed tar files - - detects type of archive automatically - - uses tar's C(--diff arg) to calculate if changed or not. If this C(arg) is not - supported, it will always unpack the archive - - does not detect if a .zip file is different from destination - always unzips - - existing files/directories in the destination which are not in the archive - are not touched. This is the same behavior as a normal archive extraction - - existing files/directories in the destination which are not in the archive - are ignored for purposes of deciding if the archive should be unpacked or not -''' - -EXAMPLES = ''' -# Example from Ansible Playbooks -- unarchive: src=foo.tgz dest=/var/lib/foo - -# Unarchive a file that is already on the remote machine -- unarchive: src=/tmp/foo.zip dest=/usr/local/bin copy=no -''' - -import os - - -# class to handle .zip files -class ZipFile(object): - - def __init__(self, src, dest, module): - self.src = src - self.dest = dest - self.module = module - self.cmd_path = self.module.get_bin_path('unzip') - - def is_unarchived(self): - return dict(unarchived=False) - - def unarchive(self): - cmd = '%s -o "%s" -d "%s"' % (self.cmd_path, self.src, self.dest) - rc, out, err = self.module.run_command(cmd) - return dict(cmd=cmd, rc=rc, out=out, err=err) - - def can_handle_archive(self): - if not self.cmd_path: - return False - cmd = '%s -l "%s"' % (self.cmd_path, self.src) - rc, out, err = self.module.run_command(cmd) - if rc == 0: - return True - return False - - -# class to handle gzipped tar files -class TgzFile(object): - - def __init__(self, src, dest, module): - self.src = src - self.dest = dest - self.module = module - self.cmd_path = self.module.get_bin_path('tar') - self.zipflag = 'z' - - def is_unarchived(self): - cmd = '%s -v -C "%s" --diff -%sf "%s"' % (self.cmd_path, self.dest, self.zipflag, self.src) - rc, out, err = self.module.run_command(cmd) - unarchived = (rc == 0) - return dict(unarchived=unarchived, rc=rc, out=out, err=err, cmd=cmd) - - def unarchive(self): - cmd = '%s -x%sf "%s"' % (self.cmd_path, self.zipflag, self.src) - rc, out, err = self.module.run_command(cmd, cwd=self.dest) - return dict(cmd=cmd, rc=rc, out=out, err=err) - - def can_handle_archive(self): - if not self.cmd_path: - return False - cmd = '%s -t%sf "%s"' % (self.cmd_path, self.zipflag, self.src) - rc, out, err = self.module.run_command(cmd) - if rc == 0: - if len(out.splitlines(True)) > 0: - return True - return False - - -# class to handle tar files that aren't compressed -class TarFile(TgzFile): - def __init__(self, src, dest, module): - self.src = src - self.dest = dest - self.module = module - self.cmd_path = self.module.get_bin_path('tar') - self.zipflag = '' - - -# class to handle bzip2 compressed tar files -class TarBzip(TgzFile): - def __init__(self, src, dest, module): - self.src = src - self.dest = dest - self.module = module - self.cmd_path = self.module.get_bin_path('tar') - self.zipflag = 'j' - - -# class to handle xz compressed tar files -class TarXz(TgzFile): - def __init__(self, src, dest, module): - self.src = src - self.dest = dest - self.module = module - self.cmd_path = self.module.get_bin_path('tar') - self.zipflag = 'J' - - -# try handlers in order and return the one that works or bail if none work -def pick_handler(src, dest, module): - handlers = [TgzFile, ZipFile, TarFile, TarBzip, TarXz] - for handler in handlers: - obj = handler(src, dest, module) - if obj.can_handle_archive(): - return obj - module.fail_json(msg='Failed to find handler to unarchive. Make sure the required command to extract the file is installed.') - - -def main(): - module = AnsibleModule( - # not checking because of daisy chain to file module - argument_spec = dict( - src = dict(required=True), - original_basename = dict(required=False), # used to handle 'dest is a directory' via template, a slight hack - dest = dict(required=True), - copy = dict(default=True, type='bool'), - creates = dict(required=False), - ), - add_file_common_args=True, - ) - - src = os.path.expanduser(module.params['src']) - dest = os.path.expanduser(module.params['dest']) - copy = module.params['copy'] - creates = module.params['creates'] - - # did tar file arrive? - if not os.path.exists(src): - if copy: - module.fail_json(msg="Source '%s' failed to transfer" % src) - else: - module.fail_json(msg="Source '%s' does not exist" % src) - if not os.access(src, os.R_OK): - module.fail_json(msg="Source '%s' not readable" % src) - - if creates: - # do not run the command if the line contains creates=filename - # and the filename already exists. This allows idempotence - # of command executions. - v = os.path.expanduser(creates) - if os.path.exists(v): - module.exit_json( - stdout="skipped, since %s exists" % v, - skipped=True, - changed=False, - stderr=False, - rc=0 - ) - - # is dest OK to receive tar file? - if not os.path.isdir(dest): - module.fail_json(msg="Destination '%s' is not a directory" % dest) - if not os.access(dest, os.W_OK): - module.fail_json(msg="Destination '%s' not writable" % dest) - - handler = pick_handler(src, dest, module) - - res_args = dict(handler=handler.__class__.__name__, dest=dest, src=src) - - # do we need to do unpack? - res_args['check_results'] = handler.is_unarchived() - if res_args['check_results']['unarchived']: - res_args['changed'] = False - module.exit_json(**res_args) - - # do the unpack - try: - res_args['extract_results'] = handler.unarchive() - if res_args['extract_results']['rc'] != 0: - module.fail_json(msg="failed to unpack %s to %s" % (src, dest), **res_args) - except IOError: - module.fail_json(msg="failed to unpack %s to %s" % (src, dest)) - - res_args['changed'] = True - - module.exit_json(**res_args) - -# import module snippets -from ansible.module_utils.basic import * -main() |