mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 08:58:59 +00:00
Merge pull request #18908 from Unity-Technologies/win-add-unzip
Added unzipping via zipfile module
This commit is contained in:
commit
1f39a65665
@ -5,6 +5,8 @@ A module to wrap (non-Windows) archive calls
|
|||||||
.. versionadded:: 2014.1.0
|
.. versionadded:: 2014.1.0
|
||||||
'''
|
'''
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
import os
|
||||||
|
from salt.exceptions import CommandExecutionError
|
||||||
|
|
||||||
from salt.ext.six import string_types
|
from salt.ext.six import string_types
|
||||||
|
|
||||||
@ -12,6 +14,7 @@ from salt.ext.six import string_types
|
|||||||
from salt.utils import \
|
from salt.utils import \
|
||||||
which as _which, which_bin as _which_bin, is_windows as _is_windows
|
which as _which, which_bin as _which_bin, is_windows as _is_windows
|
||||||
import salt.utils.decorators as decorators
|
import salt.utils.decorators as decorators
|
||||||
|
import salt.utils
|
||||||
|
|
||||||
# TODO: Check that the passed arguments are correct
|
# TODO: Check that the passed arguments are correct
|
||||||
|
|
||||||
@ -21,9 +24,17 @@ __func_alias__ = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HAS_ZIPFILE = False
|
||||||
|
try:
|
||||||
|
import zipfile
|
||||||
|
HAS_ZIPFILE = True
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def __virtual__():
|
def __virtual__():
|
||||||
if _is_windows():
|
if _is_windows():
|
||||||
return False
|
return HAS_ZIPFILE
|
||||||
commands = ('tar', 'gzip', 'gunzip', 'zip', 'unzip', 'rar', 'unrar')
|
commands = ('tar', 'gzip', 'gunzip', 'zip', 'unzip', 'rar', 'unrar')
|
||||||
# If none of the above commands are in $PATH this module is a no-go
|
# If none of the above commands are in $PATH this module is a no-go
|
||||||
if not any(_which(cmd) for cmd in commands):
|
if not any(_which(cmd) for cmd in commands):
|
||||||
@ -149,7 +160,7 @@ def gunzip(gzipfile, template=None, runas=None):
|
|||||||
|
|
||||||
|
|
||||||
@decorators.which('zip')
|
@decorators.which('zip')
|
||||||
def zip_(zipfile, sources, template=None, runas=None):
|
def cmd_zip_(zipfile, sources, template=None, runas=None):
|
||||||
'''
|
'''
|
||||||
Uses the zip command to create zip files
|
Uses the zip command to create zip files
|
||||||
|
|
||||||
@ -175,8 +186,53 @@ def zip_(zipfile, sources, template=None, runas=None):
|
|||||||
return __salt__['cmd.run'](cmd, template=template, runas=runas).splitlines()
|
return __salt__['cmd.run'](cmd, template=template, runas=runas).splitlines()
|
||||||
|
|
||||||
|
|
||||||
|
@decorators.depends('zipfile', fallback_function=cmd_zip_)
|
||||||
|
def zip_(archive, sources, template=None, runas=None):
|
||||||
|
'''
|
||||||
|
Uses the zipfile module to create zip files
|
||||||
|
|
||||||
|
CLI Example:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
salt '*' archive.zip /tmp/zipfile.zip /tmp/sourcefile1,/tmp/sourcefile2
|
||||||
|
|
||||||
|
The template arg can be set to 'jinja' or another supported template
|
||||||
|
engine to render the command arguments before execution.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
salt '*' archive.zip template=jinja /tmp/zipfile.zip /tmp/sourcefile1,/tmp/{{grains.id}}.txt
|
||||||
|
|
||||||
|
'''
|
||||||
|
(archive, sources) = _render_filenames(archive, sources, None, template)
|
||||||
|
|
||||||
|
if isinstance(sources, string_types):
|
||||||
|
sources = [s.strip() for s in sources.split(',')]
|
||||||
|
|
||||||
|
archived_files = []
|
||||||
|
with zipfile.ZipFile(archive, "w", zipfile.ZIP_DEFLATED) as zf:
|
||||||
|
for src in sources:
|
||||||
|
if os.path.exists(src):
|
||||||
|
if os.path.isdir(src):
|
||||||
|
rel_root = os.path.abspath(os.path.join(src, os.pardir))
|
||||||
|
for dir_name, sub_dirs, files in os.walk(src):
|
||||||
|
for filename in files:
|
||||||
|
abs_name = os.path.abspath(os.path.join(dir_name, filename))
|
||||||
|
arc_name = os.path.join(os.path.relpath(dir_name, rel_root), filename)
|
||||||
|
archived_files.append(arc_name)
|
||||||
|
zf.write(abs_name, arc_name)
|
||||||
|
else:
|
||||||
|
archived_files.append(src)
|
||||||
|
zf.write(src)
|
||||||
|
|
||||||
|
return archived_files
|
||||||
|
|
||||||
|
|
||||||
@decorators.which('unzip')
|
@decorators.which('unzip')
|
||||||
def unzip(zipfile, dest, excludes=None, template=None, options=None, runas=None):
|
def unzip_cmd(zipfile, dest, excludes=None, template=None, options=None, runas=None):
|
||||||
'''
|
'''
|
||||||
Uses the unzip command to unpack zip files
|
Uses the unzip command to unpack zip files
|
||||||
|
|
||||||
@ -212,6 +268,45 @@ def unzip(zipfile, dest, excludes=None, template=None, options=None, runas=None)
|
|||||||
return __salt__['cmd.run'](cmd, template=template, runas=runas).splitlines()
|
return __salt__['cmd.run'](cmd, template=template, runas=runas).splitlines()
|
||||||
|
|
||||||
|
|
||||||
|
@decorators.depends('zipfile', fallback_function=unzip_cmd)
|
||||||
|
def unzip(archive, dest, excludes=None, template=None, options=None, runas=None):
|
||||||
|
'''
|
||||||
|
Uses the zipfile module to unpack zip files
|
||||||
|
|
||||||
|
options:
|
||||||
|
Options to pass to the ``unzip`` binary.
|
||||||
|
|
||||||
|
CLI Example:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
salt '*' archive.unzip /tmp/zipfile.zip /home/strongbad/ excludes=file_1,file_2
|
||||||
|
|
||||||
|
The template arg can be set to 'jinja' or another supported template
|
||||||
|
engine to render the command arguments before execution.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
salt '*' archive.unzip template=jinja /tmp/zipfile.zip /tmp/{{grains.id}}/ excludes=file_1,file_2
|
||||||
|
|
||||||
|
'''
|
||||||
|
(archive, dest) = _render_filenames(archive, dest, None, template)
|
||||||
|
with zipfile.ZipFile(archive) as zf:
|
||||||
|
files = zf.namelist()
|
||||||
|
if excludes is None:
|
||||||
|
zf.extractall(dest)
|
||||||
|
return files
|
||||||
|
|
||||||
|
excludes = excludes.split(",")
|
||||||
|
cleaned_files = [x for x in files if x not in excludes]
|
||||||
|
for f in cleaned_files:
|
||||||
|
if f not in excludes:
|
||||||
|
zf.extract(f, dest)
|
||||||
|
return cleaned_files
|
||||||
|
|
||||||
|
|
||||||
@decorators.which('rar')
|
@decorators.which('rar')
|
||||||
def rar(rarfile, sources, template=None, runas=None):
|
def rar(rarfile, sources, template=None, runas=None):
|
||||||
'''
|
'''
|
||||||
@ -272,3 +367,56 @@ def unrar(rarfile, dest, excludes=None, template=None, runas=None):
|
|||||||
cmd.extend(['-x', exclude])
|
cmd.extend(['-x', exclude])
|
||||||
cmd.append(dest)
|
cmd.append(dest)
|
||||||
return __salt__['cmd.run'](' '.join(cmd), template=template, runas=runas).splitlines()
|
return __salt__['cmd.run'](' '.join(cmd), template=template, runas=runas).splitlines()
|
||||||
|
|
||||||
|
|
||||||
|
def _render_filenames(filenames, zipfile, saltenv, template):
|
||||||
|
'''
|
||||||
|
Process markup in the :param:`filenames` and :param:`zipfile` variables (NOT the
|
||||||
|
files under the paths they ultimately point to) according to the markup
|
||||||
|
format provided by :param:`template`.
|
||||||
|
'''
|
||||||
|
if not template:
|
||||||
|
return (filenames, zipfile)
|
||||||
|
|
||||||
|
# render the path as a template using path_template_engine as the engine
|
||||||
|
if template not in salt.utils.templates.TEMPLATE_REGISTRY:
|
||||||
|
raise CommandExecutionError(
|
||||||
|
'Attempted to render file paths with unavailable engine '
|
||||||
|
'{0}'.format(template)
|
||||||
|
)
|
||||||
|
|
||||||
|
kwargs = {}
|
||||||
|
kwargs['salt'] = __salt__
|
||||||
|
kwargs['pillar'] = __pillar__
|
||||||
|
kwargs['grains'] = __grains__
|
||||||
|
kwargs['opts'] = __opts__
|
||||||
|
kwargs['saltenv'] = saltenv
|
||||||
|
|
||||||
|
def _render(contents):
|
||||||
|
'''
|
||||||
|
Render :param:`contents` into a literal pathname by writing it to a
|
||||||
|
temp file, rendering that file, and returning the result.
|
||||||
|
'''
|
||||||
|
# write out path to temp file
|
||||||
|
tmp_path_fn = salt.utils.mkstemp()
|
||||||
|
with salt.utils.fopen(tmp_path_fn, 'w+') as fp_:
|
||||||
|
fp_.write(contents)
|
||||||
|
data = salt.utils.templates.TEMPLATE_REGISTRY[template](
|
||||||
|
tmp_path_fn,
|
||||||
|
to_str=True,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
salt.utils.safe_rm(tmp_path_fn)
|
||||||
|
if not data['result']:
|
||||||
|
# Failed to render the template
|
||||||
|
raise CommandExecutionError(
|
||||||
|
'Failed to render file path with error: {0}'.format(
|
||||||
|
data['data']
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return data['data']
|
||||||
|
|
||||||
|
filenames = _render(filenames)
|
||||||
|
zipfile = _render(zipfile)
|
||||||
|
return (filenames, zipfile)
|
||||||
|
@ -97,8 +97,13 @@ class Depends(object):
|
|||||||
)
|
)
|
||||||
# if not, unload dependent_set
|
# if not, unload dependent_set
|
||||||
if module:
|
if module:
|
||||||
|
try:
|
||||||
|
func_name = module.__func_alias__[func.__name__]
|
||||||
|
except (AttributeError, KeyError):
|
||||||
|
func_name = func.__name__
|
||||||
|
|
||||||
mod_key = '{0}.{1}'.format(module.__name__.split('.')[-1],
|
mod_key = '{0}.{1}'.format(module.__name__.split('.')[-1],
|
||||||
func.__name__)
|
func_name)
|
||||||
|
|
||||||
# if we don't have this module loaded, skip it!
|
# if we don't have this module loaded, skip it!
|
||||||
if mod_key not in functions:
|
if mod_key not in functions:
|
||||||
|
Loading…
Reference in New Issue
Block a user