Merge branch '2015.5' into '2015.8'

Conflicts:
  - salt/modules/saltutil.py
  - salt/states/archive.py
This commit is contained in:
rallytime 2016-06-08 14:26:18 -06:00
commit b8e4706074
4 changed files with 257 additions and 70 deletions

View file

@ -258,18 +258,22 @@ def update(version=None):
def sync_beacons(saltenv=None, refresh=True):
'''
Sync the beacons from the _beacons directory on the salt master file
server. This function is environment aware, pass the desired environment
to grab the contents of the _beacons directory, base is the default
environment.
.. versionadded:: 2015.5.1
Sync the beacons from the ``salt://_beacons`` directory on the Salt
fileserver. This function is environment-aware, pass the desired
environment to grab the contents of the ``_beacons`` directory from that
environment. The default environment, if none is specified, is ``base``.
refresh : True
Also refresh the beacons available to the minion.
CLI Example:
.. code-block:: bash
salt '*' saltutil.sync_beacons
salt '*' saltutil.sync_beacons saltenv=dev
'''
ret = _sync('beacons', saltenv)
if refresh:
@ -279,18 +283,23 @@ def sync_beacons(saltenv=None, refresh=True):
def sync_sdb(saltenv=None, refresh=False):
'''
Sync sdb modules from the _sdb directory on the salt master file
server. This function is environment aware, pass the desired environment
to grab the contents of the _sdb directory, base is the default
environment.
.. versionadded:: 2015.5.7
Sync sdb modules from the ``salt://_sdb`` directory on the Salt
fileserver. This function is environment-aware, pass the desired
environment to grab the contents of the ``_sdb`` directory from that
environment. The default environment, if none is specified, is ``base``.
refresh : False
This argument has no affect and is included for consistency with the
other sync functions.
CLI Example:
.. code-block:: bash
salt '*' saltutil.sync_sdb
salt '*' saltutil.sync_sdb saltenv=dev
'''
ret = _sync('sdb', saltenv)
return ret
@ -298,10 +307,13 @@ def sync_sdb(saltenv=None, refresh=False):
def sync_modules(saltenv=None, refresh=True):
'''
Sync the modules from the _modules directory on the salt master file
server. This function is environment aware, pass the desired environment
to grab the contents of the _modules directory, base is the default
environment.
Sync the modules from the ``salt://_modules`` directory on the Salt
fileserver. This function is environment-aware, pass the desired
environment to grab the contents of the ``_modules`` directory from that
environment. The default environment, if none is specified, is ``base``.
refresh : True
Also refresh the execution modules available to the minion.
.. important::
@ -320,13 +332,12 @@ def sync_modules(saltenv=None, refresh=True):
See :ref:`here <reloading-modules>` for a more detailed explanation of
why this is necessary.
.. versionadded:: 2015.5.1
CLI Example:
.. code-block:: bash
salt '*' saltutil.sync_modules
salt '*' saltutil.sync_modules saltenv=dev
'''
ret = _sync('modules', saltenv)
if refresh:
@ -336,16 +347,20 @@ def sync_modules(saltenv=None, refresh=True):
def sync_states(saltenv=None, refresh=True):
'''
Sync the states from the _states directory on the salt master file
server. This function is environment aware, pass the desired environment
to grab the contents of the _states directory, base is the default
environment.
Sync the states from the ``salt://_states`` directory on the Salt
fileserver. This function is environment-aware, pass the desired
environment to grab the contents of the ``_states`` directory from that
environment. The default environment, if none is specified, is ``base``.
refresh : True
Also refresh the execution modules available to the minion.
CLI Example:
.. code-block:: bash
salt '*' saltutil.sync_states
salt '*' saltutil.sync_states saltenv=dev
'''
ret = _sync('states', saltenv)
if refresh:
@ -355,16 +370,21 @@ def sync_states(saltenv=None, refresh=True):
def sync_grains(saltenv=None, refresh=True):
'''
Sync the grains from the _grains directory on the salt master file
server. This function is environment aware, pass the desired environment
to grab the contents of the _grains directory, base is the default
environment.
Sync the grains from the ``salt://_grains`` directory on the Salt
fileserver. This function is environment-aware, pass the desired
environment to grab the contents of the ``_grains`` directory from that
environment. The default environment, if none is specified, is ``base``.
refresh : True
Also refresh the execution modules available to the minion, and refresh
pillar data.
CLI Example:
.. code-block:: bash
salt '*' saltutil.sync_grains
salt '*' saltutil.sync_grains saltenv=dev
'''
ret = _sync('grains', saltenv)
if refresh:
@ -375,16 +395,20 @@ def sync_grains(saltenv=None, refresh=True):
def sync_renderers(saltenv=None, refresh=True):
'''
Sync the renderers from the _renderers directory on the salt master file
server. This function is environment aware, pass the desired environment
to grab the contents of the _renderers directory, base is the default
environment.
Sync the renderers from the ``salt://_renderers`` directory on the Salt
fileserver. This function is environment-aware, pass the desired
environment to grab the contents of the ``_renderers`` directory from that
environment. The default environment, if none is specified, is ``base``.
refresh : True
Also refresh the execution modules available to the minion.
CLI Example:
.. code-block:: bash
salt '*' saltutil.sync_renderers
salt '*' saltutil.sync_renderers saltenv=dev
'''
ret = _sync('renderers', saltenv)
if refresh:
@ -394,16 +418,20 @@ def sync_renderers(saltenv=None, refresh=True):
def sync_returners(saltenv=None, refresh=True):
'''
Sync the returners from the _returners directory on the salt master file
server. This function is environment aware, pass the desired environment
to grab the contents of the _returners directory, base is the default
environment.
Sync the returners from the ``salt://_returners`` directory on the Salt
fileserver. This function is environment-aware, pass the desired
environment to grab the contents of the ``_returners`` directory from that
environment. The default environment, if none is specified, is ``base``.
refresh : True
Also refresh the execution modules available to the minion.
CLI Example:
.. code-block:: bash
salt '*' saltutil.sync_returners
salt '*' saltutil.sync_returners saltenv=dev
'''
ret = _sync('returners', saltenv)
if refresh:
@ -413,16 +441,19 @@ def sync_returners(saltenv=None, refresh=True):
def sync_proxymodules(saltenv=None, refresh=False):
'''
Sync the proxy modules from the _proxy directory on the salt master file
server. This function is environment aware, pass the desired environment
to grab the contents of the _returners directory, base is the default
environment.
.. versionadded:: 2015.8.2
Sync the proxy modules from the ``salt://_proxy`` directory on the Salt
fileserver. This function is environment-aware, pass the desired
environment to grab the contents of the ``_proxy`` directory from that
environment. The default environment, if none is specified, is ``base``.
CLI Example:
.. code-block:: bash
salt '*' saltutil.sync_proxymodules
salt '*' saltutil.sync_proxymodules saltenv=dev
'''
ret = _sync('proxy', saltenv)
if refresh:
@ -432,16 +463,20 @@ def sync_proxymodules(saltenv=None, refresh=False):
def sync_output(saltenv=None, refresh=True):
'''
Sync the output modules from the _output directory on the salt master file
server. This function is environment aware. Pass the desired environment
to grab the contents of the _output directory. Base is the default
environment.
Sync the output modules from the ``salt://_output`` directory on the Salt
fileserver. This function is environment-aware, pass the desired
environment to grab the contents of the ``_output`` directory from that
environment. The default environment, if none is specified, is ``base``.
refresh : True
Also refresh the execution modules available to the minion.
CLI Example:
.. code-block:: bash
salt '*' saltutil.sync_output
salt '*' saltutil.sync_output saltenv=dev
'''
ret = _sync('output', saltenv)
if refresh:
@ -453,16 +488,22 @@ sync_outputters = salt.utils.alias_function(sync_output, 'sync_outputters')
def sync_utils(saltenv=None, refresh=True):
'''
Sync utility source files from the _utils directory on the salt master file
server. This function is environment aware, pass the desired environment
to grab the contents of the _utils directory, base is the default
environment.
.. versionadded:: 2014.7.0
Sync utility source files from the ``salt://_utils`` directory on the Salt
fileserver. This function is environment-aware, pass the desired
environment to grab the contents of the ``_utils`` directory from that
environment. The default environment, if none is specified, is ``base``.
refresh : True
Also refresh the execution modules available to the minion.
CLI Example:
.. code-block:: bash
salt '*' saltutil.sync_utils
salt '*' saltutil.sync_utils saltenv=dev
'''
ret = _sync('utils', saltenv)
if refresh:
@ -474,25 +515,65 @@ def sync_log_handlers(saltenv=None, refresh=True):
'''
.. versionadded:: 2015.8.0
Sync utility source files from the _log_handlers directory on the salt master file
server. This function is environment aware, pass the desired environment
to grab the contents of the _log_handlers directory, base is the default
environment.
Sync utility source files from the ``salt://_log_handlers`` directory on
the Salt fileserver. This function is environment-aware, pass the desired
environment to grab the contents of the ``_log_handlers`` directory from
that environment. The default environment, if none is specified, is
``base``.
CLI Example:
.. code-block:: bash
salt '*' saltutil.sync_log_handlers
salt '*' saltutil.sync_log_handlers saltenv=dev
'''
ret = _sync('log_handlers', saltenv)
if refresh:
refresh_modules()
def sync_pillar(saltenv=None, refresh=True):
'''
.. versionadded:: 2015.8.11,2016.3.2
Sync pillar modules from the ``salt://_pillar`` directory on the Salt
fileserver. This function is environment-aware, pass the desired
environment to grab the contents of the ``_pillar`` directory from that
environment. The default environment, if none is specified, is ``base``.
refresh : True
Also refresh the execution modules available to the minion, and refresh
pillar data.
.. note::
This function will raise an error if executed on a traditional (i.e.
not masterless) minion
CLI Examples:
.. code-block:: bash
salt '*' saltutil.sync_pillar
salt '*' saltutil.sync_pillar saltenv=dev
'''
if __opts__['file_client'] != 'local':
raise CommandExecutionError(
'Pillar modules can only be synced to masterless minions'
)
ret = _sync('pillar', saltenv)
if refresh:
refresh_modules()
refresh_pillar()
return ret
def sync_all(saltenv=None, refresh=True):
'''
.. versionchanged:: 2015.8.11,2016.3.2
On masterless minions, pillar modules are now synced, and refreshed
when ``refresh`` is set to ``True``.
Sync down all of the dynamic modules from the file server for a specific
environment. This function synchronizes custom modules, states, beacons,
grains, returners, output modules, renderers, and utils.
@ -522,6 +603,7 @@ def sync_all(saltenv=None, refresh=True):
.. code-block:: bash
salt '*' saltutil.sync_all
salt '*' saltutil.sync_all saltenv=dev
'''
log.debug('Syncing all')
ret = {}
@ -536,8 +618,12 @@ def sync_all(saltenv=None, refresh=True):
ret['utils'] = sync_utils(saltenv, False)
ret['log_handlers'] = sync_log_handlers(saltenv, False)
ret['proxymodules'] = sync_proxymodules(saltenv, False)
if __opts__['file_client'] == 'local':
ret['pillar'] = sync_pillar(saltenv, False)
if refresh:
refresh_modules()
if __opts__['file_client'] == 'local':
refresh_pillar()
return ret

View file

@ -204,7 +204,7 @@ def get_load(jid):
{'jid': jid})
data = cur.fetchone()
if data:
return json.loads(data)
return json.loads(data[0].encode())
_close_conn(conn)
return {}

View file

@ -15,8 +15,10 @@ from contextlib import closing
# Import 3rd-party libs
import salt.ext.six as six
from salt.ext.six.moves import shlex_quote as _cmd_quote
# Import salt libs
import salt.utils
from salt.exceptions import CommandExecutionError
# remove after archive_user deprecation.
from salt.utils import warn_until
@ -35,6 +37,21 @@ def __virtual__():
else False
def _is_bsdtar():
return 'bsdtar' in __salt__['cmd.run'](['tar', '--version'],
python_shell=False)
def _cleanup_destdir(name):
'''
Attempt to remove the specified directory
'''
try:
os.rmdir(name)
except OSError:
pass
def extracted(name,
source,
archive_format,
@ -87,7 +104,7 @@ def extracted(name,
- if_missing: /opt/graylog2-server-0.9.6p1/
name
Directory name where to extract the archive
Location where archive should be extracted
source
Archive source, same syntax as file.managed source argument.
@ -116,21 +133,37 @@ def extracted(name,
.. versionadded:: 2015.8.0
if_missing
Some archives, such as tar, extract themselves in a subfolder.
This directive can be used to validate if the archive had been
previously extracted.
If specified, this path will be checked, and if it exists then the
archive will not be extracted. This can be helpful if the archive
extracts all files into a subfolder. This path can be either a
directory or a file, so this option can also be used to check for a
semaphore file and conditionally skip extraction.
tar_options
Required if used with ``archive_format: tar``, otherwise optional.
It needs to be the tar argument specific to the archive being extracted,
such as 'J' for LZMA or 'v' to verbosely list files processed.
Using this option means that the tar executable on the target will
be used, which is less platform independent.
Main operators like -x, --extract, --get, -c and -f/--file
**should not be used** here.
If ``archive_format`` is ``zip`` or ``rar`` and this option is not set,
then the Python tarfile module is used. The tarfile module supports gzip
and bz2 in Python 2.
If ``archive_format`` is set to ``tar``, this option can be used to
specify a string of additional arguments to pass to the tar command. If
``archive_format`` is set to ``tar`` and this option is *not* used,
then the minion will attempt to use Python's native tarfile_ support to
extract it. Python's native tarfile_ support can only handle gzip and
bzip2 compression, however.
.. versionchanged:: 2015.8.11,2016.3.2
XZ-compressed archives no longer require ``J`` to manually be set
in the ``tar_options``, they are now detected automatically and
Salt will extract them using ``xz-utils``. This is a more
platform-independent solution, as not all tar implementations
support the ``J`` argument for extracting archives.
.. note::
Main operators like -x, --extract, --get, -c and -f/--file **should
not be used** here.
Using this option means that the ``tar`` command will be used,
which is less platform-independent, so keep this in mind when using
this option; the options must be valid options for the ``tar``
implementation on the minion's OS.
.. _tarfile: https://docs.python.org/2/library/tarfile.html
keep
Keep the archive in the minion's cache
@ -220,7 +253,7 @@ def extracted(name,
log.debug('failed to download {0}'.format(source))
return file_result
else:
log.debug('Archive %s is already in cache', name)
log.debug('Archive %s is already in cache', source)
if __opts__['test']:
ret['result'] = None
@ -232,7 +265,15 @@ def extracted(name,
)
return ret
__salt__['file.makedirs'](name, user=user, group=group)
created_destdir = False
if __salt__['file.file_exists'](name.rstrip('/')):
ret['result'] = False
ret['comment'] = ('{0} exists and is not a directory'
.format(name.rstrip('/')))
return ret
elif not __salt__['file.directory_exists'](name):
__salt__['file.makedirs'](name, user=archive_user)
created_destdir = True
log.debug('Extracting {0} to {1}'.format(filename, name))
if archive_format == 'zip':
@ -241,11 +282,70 @@ def extracted(name,
files = __salt__['archive.unrar'](filename, name)
else:
if tar_options is None:
with closing(tarfile.open(filename, 'r')) as tar:
files = tar.getnames()
tar.extractall(name)
try:
with closing(tarfile.open(filename, 'r')) as tar:
files = tar.getnames()
tar.extractall(name)
except tarfile.ReadError:
if salt.utils.which('xz'):
if __salt__['cmd.retcode'](['xz', '-l', filename],
python_shell=False,
ignore_retcode=True) == 0:
# XZ-compressed data
log.debug(
'Tar file is XZ-compressed, attempting '
'decompression and extraction using xz-utils '
'and the tar command'
)
# Must use python_shell=True here because not all tar
# implementations support the -J flag for decompressing
# XZ-compressed data. We need to dump the decompressed
# data to stdout and pipe it to tar for extraction.
cmd = 'xz --decompress --stdout {0} | tar xvf -'
results = __salt__['cmd.run_all'](
cmd.format(_cmd_quote(filename)),
cwd=name,
python_shell=True)
if results['retcode'] != 0:
if created_destdir:
_cleanup_destdir(name)
ret['result'] = False
ret['changes'] = results
return ret
if _is_bsdtar():
files = results['stderr']
else:
files = results['stdout']
else:
# Failed to open tar archive and it is not
# XZ-compressed, gracefully fail the state
if created_destdir:
_cleanup_destdir(name)
ret['result'] = False
ret['comment'] = (
'Failed to read from tar archive using Python\'s '
'native tar file support. If archive is '
'compressed using something other than gzip or '
'bzip2, the \'tar_options\' parameter may be '
'required to pass the correct options to the tar '
'command in order to extract the archive.'
)
return ret
else:
if created_destdir:
_cleanup_destdir(name)
ret['result'] = False
ret['comment'] = (
'Failed to read from tar archive. If it is '
'XZ-compressed, install xz-utils to attempt '
'extraction.'
)
return ret
else:
tar_opts = tar_options.split(' ')
try:
tar_opts = tar_options.split(' ')
except AttributeError:
tar_opts = str(tar_options).split(' ')
tar_cmd = ['tar']
tar_shortopts = 'x'
@ -271,7 +371,7 @@ def extracted(name,
ret['result'] = False
ret['changes'] = results
return ret
if 'bsdtar' in __salt__['cmd.run']('tar --version', python_shell=False):
if _is_bsdtar():
files = results['stderr']
else:
files = results['stdout']

View file

@ -67,6 +67,7 @@ class SysModuleTest(integration.ModuleCase):
'runtests_decorators.missing_depends',
'runtests_decorators.missing_depends_will_fallback',
'swift.head',
'glance.warn_until',
'yumpkg.expand_repo_def',
'yumpkg5.expand_repo_def',
'container_resource.run',