Merge branch 'nitrogen' into 'develop'

Conflicts:
  - salt/runners/saltutil.py
This commit is contained in:
rallytime 2017-05-04 11:51:32 -06:00
commit 319dc45c1d
20 changed files with 327 additions and 87 deletions

View File

@ -194,6 +194,9 @@
# a previous deleted minion ID.
#preserve_minion_cache: False
# Allow or deny minions from requesting their own key revocation
#allow_minion_key_revoke: True
# If max_minions is used in large installations, the master might experience
# high-load situations because of having to check the number of connected
# minions for every authentication. This cache provides the minion-ids of

View File

@ -1258,6 +1258,21 @@ constant names without ssl module prefix: ``CERT_REQUIRED`` or ``PROTOCOL_SSLv23
certfile: <path_to_certfile>
ssl_version: PROTOCOL_TLSv1_2
.. conf_master:: allow_minion_key_revoke
``allow_minion_key_revoke``
------------------
Default: ``True``
Controls whether a minion can request its own key revocation. When True
the master will honor the minion's request and revoke its key. When False,
the master will drop the request and the minion's key will remain accepted.
.. code-block:: yaml
rotate_aes_key: True
Master Module Management
========================

View File

@ -3,3 +3,9 @@ Salt 2016.3.7 Release Notes
===========================
Version 2016.3.7 is a bugfix release for :ref:`2016.3.0 <release-2016-3-0>`.
New master configuration option `allow_minion_key_revoke`, defaults to True. This option
controls whether a minion can request that the master revoke its key. When True, a minion
can request a key revocation and the master will comply. If it is False, the key will not
be revoked by the msater.

View File

@ -1080,7 +1080,7 @@ ARGS = {10}\n'''.format(self.minion_config,
with tempfile.NamedTemporaryFile(mode='w+b',
prefix='shim_',
delete=False) as shim_tmp_file:
shim_tmp_file.write(cmd_str)
shim_tmp_file.write(salt.utils.to_bytes(cmd_str))
# Copy shim to target system, under $HOME/.<randomized name>
target_shim_file = '.{0}.{1}'.format(binascii.hexlify(os.urandom(6)), extension)

View File

@ -1039,6 +1039,9 @@ VALID_OPTS = {
# Number of times to try to auth with the master on a reconnect with the
# tcp transport
'tcp_authentication_retries': int,
# Permit or deny allowing minions to request revoke of its own key
'allow_minion_key_revoke': bool,
}
# default configurations
@ -1594,6 +1597,7 @@ DEFAULT_MASTER_OPTS = {
'clean_dynamic_modules': True,
'django_auth_path': '',
'django_auth_settings': '',
'allow_minion_key_revoke': True,
}

View File

@ -6,16 +6,20 @@ NAPALM syslog engine
.. versionadded:: Nitrogen
An engine that takes syslog messages structured in
[OpenConfig](http://www.openconfig.net/) or IETF format
OpenConfig_ or IETF format
and fires Salt events.
.. _OpenConfig: http://www.openconfig.net/
As there can be many messages pushed into the event bus,
the user is able to filter based on the object structure.
Requirements
------------
- [napalm-logs](https://github.com/napalm-automation/napalm-logs)
- `napalm-logs`_
.. _`napalm-logs`: https://github.com/napalm-automation/napalm-logs
This engine transfers objects from the napalm-logs library
into the event bus. The top dictionary has the following keys:
@ -25,7 +29,7 @@ into the event bus. The top dictionary has the following keys:
- ``timestamp``
- ``os``: the network OS identified
- ``model_name``: the OpenConfig or IETF model name
- ``error`: the error name (consult the documentation)
- ``error``: the error name (consult the documentation)
- ``message_details``: details extracted from the syslog message
- ``open_config``: the OpenConfig model
@ -106,7 +110,6 @@ Output object example:
from __future__ import absolute_import
# Import python stdlib
import json
import logging
# Import third party libraries
@ -119,6 +122,7 @@ except ImportError:
try:
# pylint: disable=W0611
import napalm_logs
import napalm_logs.utils
# pylint: enable=W0611
HAS_NAPALM_LOGS = True
except ImportError:
@ -156,6 +160,7 @@ def _zmq(address, port):
addr=address,
port=port)
)
socket.setsockopt(zmq.SUBSCRIBE, '')
return socket.recv
@ -180,7 +185,11 @@ TRANSPORT_FUN_MAP = {
def start(transport='zmq',
address='0.0.0.0',
port=49017):
port=49017,
auth_address='0.0.0.0',
auth_port=49018,
disable_security=False,
certificate=None):
'''
Listen to napalm-logs and publish events into the Salt event bus.
@ -195,7 +204,25 @@ def start(transport='zmq',
port: ``49017``
The port of the publisher.
auth_address: ``0.0.0.0``
The address used for authentication
when security is not disabled.
auth_port: ``49018``
Port used for authentication.
disable_security: ``False``
Trust unencrypted messages.
Strongly discouraged in production.
certificate
Absolute path to the SSL certificate.
'''
if not disable_security:
priv_key, verify_key = napalm_logs.utils.authenticate(certificate,
address=auth_address,
port=auth_port)
transport_recv_fun = _get_transport_recv(name=transport,
address=address,
port=port)
@ -206,23 +233,23 @@ def start(transport='zmq',
if __opts__['__role'] == 'master':
master = True
while True:
log.debug('Waiting for napalm-logs to send anything...')
raw_object = transport_recv_fun()
log.debug('Received from napalm-logs:')
log.debug(raw_object)
if not disable_security:
dict_object = napalm_logs.utils.decrypt(raw_object, verify_key, priv_key)
else:
dict_object = napalm_logs.utils.unserialize(raw_object)
try:
dict_object = json.loads(raw_object)
except ValueError:
log.error('Unable to deserialise JSON object: {0}'.format(raw_object), exc_info=True)
continue # and go the the next item
if not isinstance(dict_object, dict):
log.error('Invalid object read from napalm-logs:')
log.error(dict_object)
continue # ignore
tag = 'napalm/syslog/{os}/{error}/{device}'.format(
os=dict_object['os'],
error=dict_object['error'],
device=dict_object.get('host', dict_object.get('ip'))
)
tag = 'napalm/syslog/{os}/{error}/{host}'.format(
os=dict_object['os'],
error=dict_object['error'],
host=(dict_object.get('host') or dict_object.get('ip'))
)
except KeyError as kerr:
log.warning('Missing keys from the napalm-logs object:', exc_info=True)
log.warning(dict_object)
log.debug('Sending event {0}'.format(tag))
log.debug(raw_object)
if master:

View File

@ -1577,6 +1577,11 @@ class AESFuncs(object):
:return: True if key was revoked, False if not
'''
load = self.__verify_load(load, ('id', 'tok'))
if not self.opts.get('allow_minion_key_revoke', False):
log.warning('Minion {0} requested key revoke, but allow_minion_key_revoke is False'.format(load['id']))
return load
if load is False:
return load
else:

View File

@ -3269,3 +3269,62 @@ class ProxyMinion(Minion):
self.functions['saltutil.sync_grains'](saltenv='base')
self.grains_cache = self.opts['grains']
self.ready = True
@classmethod
def _target(cls, minion_instance, opts, data, connected):
if not minion_instance:
minion_instance = cls(opts)
minion_instance.connected = connected
if not hasattr(minion_instance, 'functions'):
# Need to load the modules so they get all the dunder variables
functions, returners, function_errors, executors = (
minion_instance._load_modules(grains=opts['grains'])
)
minion_instance.functions = functions
minion_instance.returners = returners
minion_instance.function_errors = function_errors
minion_instance.executors = executors
# Pull in the utils
minion_instance.utils = salt.loader.utils(minion_instance.opts)
# Then load the proxy module
minion_instance.proxy = salt.loader.proxy(minion_instance.opts, utils=minion_instance.utils)
# And re-load the modules so the __proxy__ variable gets injected
functions, returners, function_errors, executors = (
minion_instance._load_modules(grains=opts['grains'])
)
minion_instance.functions = functions
minion_instance.returners = returners
minion_instance.function_errors = function_errors
minion_instance.executors = executors
minion_instance.functions.pack['__proxy__'] = minion_instance.proxy
minion_instance.proxy.pack['__salt__'] = minion_instance.functions
minion_instance.proxy.pack['__ret__'] = minion_instance.returners
minion_instance.proxy.pack['__pillar__'] = minion_instance.opts['pillar']
# Reload utils as well (chicken and egg, __utils__ needs __proxy__ and __proxy__ needs __utils__
minion_instance.utils = salt.loader.utils(minion_instance.opts, proxy=minion_instance.proxy)
minion_instance.proxy.pack['__utils__'] = minion_instance.utils
# Reload all modules so all dunder variables are injected
minion_instance.proxy.reload_modules()
fq_proxyname = opts['proxy']['proxytype']
proxy_init_fn = minion_instance.proxy[fq_proxyname+'.init']
proxy_init_fn(opts)
if not hasattr(minion_instance, 'serial'):
minion_instance.serial = salt.payload.Serial(opts)
if not hasattr(minion_instance, 'proc_dir'):
uid = salt.utils.get_uid(user=opts.get('user', None))
minion_instance.proc_dir = (
get_proc_dir(opts['cachedir'], uid=uid)
)
with tornado.stack_context.StackContext(minion_instance.ctx):
if isinstance(data['fun'], tuple) or isinstance(data['fun'], list):
Minion._thread_multi_return(minion_instance, opts, data)
else:
Minion._thread_return(minion_instance, opts, data)

View File

@ -83,14 +83,14 @@ in the ``docker-registries`` Pillar key, as well as any key ending in
username: foo
password: s3cr3t
To login to the configured registries, use the :py:func:`docker.login
<salt.modules.dockermod.login>` function. This only needs to be done once for a
To login to the configured registries, use the :py:func:`dockerng.login
<salt.modules.dockerng.login>` function. This only needs to be done once for a
given registry, and it will store/update the credentials in
``~/.docker/config.json``.
.. note::
For Salt releases before 2016.3.7 and 2016.11.4, :py:func:`docker.login
<salt.modules.dockermod.login>` is not available. Instead, Salt will try to
For Salt releases before 2016.3.7 and 2016.11.4, :py:func:`dockerng.login
<salt.modules.dockerng.login>` is not available. Instead, Salt will try to
authenticate using each of your configured registries for each push/pull,
behavior which is not correct and has been resolved in newer releases.
@ -921,9 +921,9 @@ def login(*registries):
.. code-block:: bash
salt myminion docker.login
salt myminion docker.login hub
salt myminion docker.login hub https://mydomain.tld/registry/
salt myminion dockerng.login
salt myminion dockerng.login hub
salt myminion dockerng.login hub https://mydomain.tld/registry/
'''
# NOTE: This function uses the "docker login" CLI command so that login
# information is added to the config.json, since docker-py isn't designed

View File

@ -146,6 +146,21 @@ def _format_opts(opts):
return opts
def _format_git_opts(opts):
'''
Do a version check and make sure that the installed version of git can
support git -c
'''
if opts:
version_ = version(versioninfo=False)
if _LooseVersion(version_) < _LooseVersion('1.7.2'):
raise SaltInvocationError(
'git_opts is only supported for git versions >= 1.7.2 '
'(detected: {0})'.format(version_)
)
return _format_opts(opts)
def _git_run(command, cwd=None, user=None, password=None, identity=None,
ignore_retcode=False, failhard=True, redirect_stderr=False,
saltenv='base', **kwargs):
@ -386,6 +401,9 @@ def add(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -415,7 +433,7 @@ def add(cwd,
cwd = _expand_path(cwd, user)
if not isinstance(filename, six.string_types):
filename = str(filename)
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.extend(['add', '--verbose'])
command.extend(
[x for x in _format_opts(opts) if x not in ('-v', '--verbose')]
@ -508,6 +526,9 @@ def archive(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -544,7 +565,7 @@ def archive(cwd,
if kwargs:
salt.utils.invalid_kwargs(kwargs)
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.append('archive')
# If prefix was set to '' then we skip adding the --prefix option
if prefix != '':
@ -610,6 +631,9 @@ def branch(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -643,7 +667,7 @@ def branch(cwd,
salt myminion git.branch /path/to/repo newbranch opts='-m oldbranch'
'''
cwd = _expand_path(cwd, user)
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.append('branch')
command.extend(_format_opts(opts))
if name is not None:
@ -686,6 +710,9 @@ def checkout(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
rev
The remote branch or revision to checkout.
@ -728,7 +755,7 @@ def checkout(cwd,
salt myminion git.checkout /path/to/repo opts='-b newbranch'
'''
cwd = _expand_path(cwd, user)
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.append('checkout')
if force:
command.append('--force')
@ -797,6 +824,9 @@ def clone(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -872,7 +902,7 @@ def clone(cwd,
except ValueError as exc:
raise SaltInvocationError(exc.__str__())
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.append('clone')
command.extend(_format_opts(opts))
command.extend(['--', url])
@ -938,6 +968,9 @@ def commit(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -976,7 +1009,7 @@ def commit(cwd,
salt myminion git.commit /path/to/repo 'The commit message' filename=foo/bar.py
'''
cwd = _expand_path(cwd, user)
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.extend(['commit', '-m', message])
command.extend(_format_opts(opts))
if filename:
@ -1565,6 +1598,9 @@ def diff(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -1625,7 +1661,7 @@ def diff(cwd,
'The \'no_index\' and \'cached\' options cannot be used together'
)
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.append('diff')
command.extend(_format_opts(opts))
@ -1733,6 +1769,9 @@ def fetch(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -1788,7 +1827,7 @@ def fetch(cwd,
salt myminion git.fetch /path/to/repo identity=/root/.ssh/id_rsa
'''
cwd = _expand_path(cwd, user)
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.append('fetch')
if force:
command.append('--force')
@ -1900,6 +1939,9 @@ def init(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -1931,7 +1973,7 @@ def init(cwd,
salt myminion git.init /path/to/bare/repo.git bare=True
'''
cwd = _expand_path(cwd, user)
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.append('init')
if bare:
command.append('--bare')
@ -2466,6 +2508,9 @@ def ls_remote(cwd=None,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -2539,7 +2584,7 @@ def ls_remote(cwd=None,
https_only=True)
except ValueError as exc:
raise SaltInvocationError(exc.__str__())
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.append('ls-remote')
command.extend(_format_opts(opts))
if not isinstance(remote, six.string_types):
@ -2601,6 +2646,9 @@ def merge(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -2636,7 +2684,7 @@ def merge(cwd,
salt.utils.invalid_kwargs(kwargs)
cwd = _expand_path(cwd, user)
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.append('merge')
command.extend(_format_opts(opts))
if rev:
@ -2730,6 +2778,9 @@ def merge_base(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -2819,7 +2870,7 @@ def merge_base(cwd,
password=password,
ignore_retcode=ignore_retcode) == first_commit
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.append('merge-base')
command.extend(_format_opts(opts))
if all_:
@ -2953,6 +3004,9 @@ def pull(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -3006,7 +3060,7 @@ def pull(cwd,
salt myminion git.pull /path/to/repo opts='--rebase origin master'
'''
cwd = _expand_path(cwd, user)
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.append('pull')
command.extend(_format_opts(opts))
return _git_run(command,
@ -3062,6 +3116,9 @@ def push(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -3125,7 +3182,7 @@ def push(cwd,
salt.utils.invalid_kwargs(kwargs)
cwd = _expand_path(cwd, user)
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.append('push')
command.extend(_format_opts(opts))
if not isinstance(remote, six.string_types):
@ -3173,6 +3230,9 @@ def rebase(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -3204,7 +3264,7 @@ def rebase(cwd,
opts = _format_opts(opts)
if any(x for x in opts if x in ('-i', '--interactive')):
raise SaltInvocationError('Interactive rebases are not supported')
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.append('rebase')
command.extend(opts)
if not isinstance(rev, six.string_types):
@ -3619,6 +3679,9 @@ def reset(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -3648,7 +3711,7 @@ def reset(cwd,
salt myminion git.reset /path/to/repo opts='--hard origin/master'
'''
cwd = _expand_path(cwd, user)
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.append('reset')
command.extend(_format_opts(opts))
return _git_run(command,
@ -3691,6 +3754,9 @@ def rev_parse(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -3726,7 +3792,7 @@ def rev_parse(cwd,
salt myminion git.rev_parse /path/to/repo opts='--is-bare-repository'
'''
cwd = _expand_path(cwd, user)
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.append('rev-parse')
command.extend(_format_opts(opts))
if rev is not None:
@ -3829,6 +3895,9 @@ def rm_(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -3857,7 +3926,7 @@ def rm_(cwd,
salt myminion git.rm /path/to/repo foo/baz opts='-r'
'''
cwd = _expand_path(cwd, user)
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.append('rm')
command.extend(_format_opts(opts))
command.extend(['--', filename])
@ -3895,6 +3964,9 @@ def stash(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -3928,7 +4000,7 @@ def stash(cwd,
# No numeric actions but this will prevent a traceback when the git
# command is run.
action = str(action)
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.extend(['stash', action])
command.extend(_format_opts(opts))
return _git_run(command,
@ -4043,6 +4115,9 @@ def submodule(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
init : False
If ``True``, ensures that new submodules are initialized
@ -4128,7 +4203,7 @@ def submodule(cwd,
)
if not isinstance(command, six.string_types):
command = str(command)
cmd = ['git'] + _format_opts(git_opts)
cmd = ['git'] + _format_git_opts(git_opts)
cmd.extend(['submodule', command])
cmd.extend(_format_opts(opts))
return _git_run(cmd,
@ -4178,6 +4253,9 @@ def symbolic_ref(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -4209,7 +4287,7 @@ def symbolic_ref(cwd,
salt myminion git.symbolic_ref /path/to/repo FOO opts='--delete'
'''
cwd = _expand_path(cwd, user)
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.append('symbolic-ref')
opts = _format_opts(opts)
if value is not None and any(x in opts for x in ('-d', '--delete')):
@ -4346,6 +4424,9 @@ def worktree_add(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -4384,7 +4465,7 @@ def worktree_add(cwd,
'Only one of \'branch\' and \'detach\' is allowed'
)
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.extend(['worktree', 'add'])
if detach:
if force:
@ -4468,6 +4549,9 @@ def worktree_prune(cwd,
.. versionadded:: Nitrogen
.. note::
This is only supported in git 1.7.2 and newer.
user
User under which to run the git command. By default, the command is run
by the user under which the minion is running.
@ -4498,7 +4582,7 @@ def worktree_prune(cwd,
'''
_check_worktree_support()
cwd = _expand_path(cwd, user)
command = ['git'] + _format_opts(git_opts)
command = ['git'] + _format_git_opts(git_opts)
command.extend(['worktree', 'prune'])
if dry_run:
command.append('--dry-run')

View File

@ -52,7 +52,7 @@ def __virtual__():
# -----------------------------------------------------------------------------
def _get_root_object(*models):
def _get_root_object(models):
'''
Read list of models and returns a Root object with the proper models added.
'''
@ -69,7 +69,7 @@ def _get_root_object(*models):
# -----------------------------------------------------------------------------
def diff(candidate, running, *models):
def diff(candidate, running, models):
'''
Returns the difference between two configuration entities structured
according to the YANG model.
@ -119,15 +119,15 @@ def diff(candidate, running, *models):
}
}
'''
first = _get_root_object(*models)
first = _get_root_object(models)
first.load_dict(candidate)
second = _get_root_object(*models)
second = _get_root_object(models)
second.load_dict(running)
return napalm_yang.utils.diff(first, second)
@proxy_napalm_wrap
def parse(*models, **kwargs):
def parse(models, **kwargs):
'''
Parse configuration from the device.
@ -345,20 +345,22 @@ def parse(*models, **kwargs):
profiles = kwargs.pop('profiles', [])
if not profiles and hasattr(napalm_device, 'profile'): # pylint: disable=undefined-variable
profiles = napalm_device.profile # pylint: disable=undefined-variable
root = _get_root_object(*models)
if not profiles:
profiles = [__grains__.get('os')]
root = _get_root_object(models)
parser_kwargs = {
'device': napalm_device, # pylint: disable=undefined-variable
'device': napalm_device.get('DRIVER'), # pylint: disable=undefined-variable
'profile': profiles
}
if config:
root.parse_config(**parser_kwargs)
if state:
root.parse_state(**parser_kwargs)
return root
return root.to_dict(filter=True)
@proxy_napalm_wrap
def get_config(data, *models, **kwargs):
def get_config(data, models, **kwargs):
'''
Return the native config.
@ -394,16 +396,21 @@ def get_config(data, *models, **kwargs):
profiles = kwargs.pop('profiles', [])
if not profiles and hasattr(napalm_device, 'profile'): # pylint: disable=undefined-variable
profiles = napalm_device.profile # pylint: disable=undefined-variable
if not profiles:
profiles = [__grains__.get('os')]
parser_kwargs = {
'profile': profiles
}
root = _get_root_object(*models)
root = _get_root_object(models)
root.load_dict(data)
return root.translate_config(**parser_kwargs)
native_config = root.translate_config(**parser_kwargs)
log.debug('Generated config')
log.debug(native_config)
return native_config
@proxy_napalm_wrap
def load_config(data, *models, **kwargs):
def load_config(data, models, **kwargs):
'''
Generate and load the config on the device using the OpenConfig or IETF
models and device profiles.
@ -538,12 +545,12 @@ def load_config(data, *models, **kwargs):
result:
True
'''
config = get_config(data, *models, **kwargs)
config = get_config(data, models, **kwargs)
test = kwargs.pop('test', False)
debug = kwargs.pop('debug', False)
commit = kwargs.pop('commit', True)
replace = kwargs.pop('replace', False)
return __salt__['net.load_config'](config=config,
return __salt__['net.load_config'](text=config,
test=test,
debug=debug,
commit=commit,
@ -552,7 +559,7 @@ def load_config(data, *models, **kwargs):
@proxy_napalm_wrap
def compliance_report(data, *models, **kwargs):
def compliance_report(data, models, **kwargs):
'''
Return the compliance report using YANG objects.
@ -592,6 +599,6 @@ def compliance_report(data, *models, **kwargs):
}
'''
filepath = kwargs.pop('filepath', '')
root = _get_root_object(*models)
root = _get_root_object(models)
root.load_dict(data)
return root.compliance_report(filepath)

View File

@ -67,6 +67,8 @@ Functions to interact with Hashicorp Vault.
peer_run:
.*:
- vault.generate_token
.. _vault-setup
'''
from __future__ import absolute_import
import logging

View File

@ -10,7 +10,7 @@ Vault Pillar Module
This module allows pillar data to be stored in Hashicorp Vault.
Base configuration instructions are documented in the execution module docs.
Base configuration instructions are documented in the :ref:`execution module docs <vault-setup>`.
Below are noted extra configuration required for the pillar module, but the base
configuration must also be completed.

View File

@ -57,7 +57,7 @@ def sync_all(saltenv='base', extmod_whitelist=None, extmod_blacklist=None):
ret['sdb'] = sync_sdb(saltenv=saltenv, extmod_whitelist=extmod_whitelist, extmod_blacklist=extmod_blacklist)
ret['cache'] = sync_cache(saltenv=saltenv, extmod_whitelist=extmod_whitelist, extmod_blacklist=extmod_blacklist)
ret['fileserver'] = sync_fileserver(saltenv=saltenv, extmod_whitelist=extmod_whitelist, extmod_blacklist=extmod_blacklist)
ret['tops'] = sync_tops(saltenv=saltenv)
ret['tops'] = sync_tops(saltenv=saltenv, extmod_whitelist=extmod_whitelist, extmod_blacklist=extmod_blacklist)
return ret
@ -401,7 +401,7 @@ def sync_sdb(saltenv='base', extmod_whitelist=None, extmod_blacklist=None):
extmod_blacklist=extmod_blacklist)[0]
def sync_tops(saltenv='base'):
def sync_tops(saltenv='base', extmod_whitelist=None, extmod_blacklist=None):
'''
.. versionadded:: 2016.3.7,2016.11.4,Nitrogen
@ -417,7 +417,8 @@ def sync_tops(saltenv='base'):
salt-run saltutil.sync_tops
'''
return salt.utils.extmods.sync(__opts__, 'tops', saltenv=saltenv)[0]
return salt.utils.extmods.sync(__opts__, 'tops', saltenv=saltenv, extmod_whitelist=extmod_whitelist,
extmod_blacklist=extmod_blacklist)[0]
def sync_cache(saltenv='base', extmod_whitelist=None, extmod_blacklist=None):

View File

@ -23,6 +23,7 @@ Please check Installation_ for complete details.
'''
from __future__ import absolute_import
import json
import logging
log = logging.getLogger(__file__)
@ -75,7 +76,7 @@ def __virtual__():
def managed(name,
data,
*models,
models,
**kwargs):
'''
Manage the device configuration given the input data strucuted
@ -131,7 +132,8 @@ def managed(name,
config:
mtu: 9000
Et2:
description: "description example"
config:
description: "description example"
'''
ret = salt.utils.napalm.default_ret(name)
test = kwargs.get('test', False) or __opts__.get('test', False)
@ -143,15 +145,16 @@ def managed(name,
log.debug('Creating temp file: {0}'.format(temp_file))
if 'to_dict' not in data:
data = {'to_dict': data}
data = [data]
with fopen(temp_file, 'w') as file_handle:
yaml.dump(data, file_handle)
device_config = __salt__['napalm_yang.parse'](*models,
yaml.safe_dump(json.loads(json.dumps(data)), file_handle, encoding='utf-8', allow_unicode=True)
device_config = __salt__['napalm_yang.parse'](models,
config=True,
profiles=profiles)
log.debug('Parsed the config from the device:')
log.debug(device_config)
compliance_report = __salt__['napalm_yang.compliance_report'](device_config,
*models,
models,
filepath=temp_file)
log.debug('Compliance report:')
log.debug(compliance_report)
@ -163,11 +166,12 @@ def managed(name,
})
log.debug('All good here.')
return ret
data = data['to_dict']
log.debug('Does not comply, trying to generate and load config')
data = data[0]['to_dict']
if '_kwargs' in data:
data.pop('_kwargs')
loaded_changes = __salt__['napalm_yang.load_config'](data,
*models,
models,
profiles=profiles,
test=test,
debug=debug,
@ -181,7 +185,7 @@ def managed(name,
def configured(name,
data,
*models,
models,
**kwargs):
'''
Configure the network device, given the input data strucuted
@ -248,7 +252,8 @@ def configured(name,
config:
mtu: 9000
Et2:
description: "description example"
config:
description: "description example"
'''
ret = salt.utils.napalm.default_ret(name)
test = kwargs.get('test', False) or __opts__.get('test', False)
@ -259,7 +264,7 @@ def configured(name,
if '_kwargs' in data:
data.pop('_kwargs')
loaded_changes = __salt__['napalm_yang.load_config'](data,
*models,
models,
profiles=profiles,
test=test,
debug=debug,

View File

@ -7,7 +7,7 @@ ret_port: 64506
worker_threads: 3
pidfile: master.pid
sock_dir: master_sock
timeout: 3
timeout: 12
open_mode: True
fileserver_list_cache_time: 0
file_buffer_size: 8192

View File

@ -7,7 +7,7 @@ ret_port: 54506
worker_threads: 3
pidfile: syndic_master.pid
sock_dir: syndic_master_sock
timeout: 1
timeout: 10
open_mode: True
fileserver_list_cache_time: 0
pillar_opts: True

View File

@ -1,6 +1,6 @@
uwsgi:
socket: 127.0.0.1:{{ pillar['git_pillar']['uwsgi_port'] }}
cgi: {{ salt['pillar.get']('git_pillar:libexec_dir', '/usr/libexec') }}/git-core/git-http-backend
cgi: {{ pillar['git_pillar']['git-http-backend'] }}
chdir: %d
daemonize: {{ pillar['git_pillar']['config_dir'] }}/uwsgi.log
pidfile: {{ pillar['git_pillar']['config_dir'] }}/uwsgi.pid

View File

@ -566,7 +566,7 @@ class ModuleCase(TestCase, SaltClientTestCaseMixin):
'''
return self.run_function(_function, args, **kw)
def run_function(self, function, arg=(), minion_tgt='minion', timeout=25, **kwargs):
def run_function(self, function, arg=(), minion_tgt='minion', timeout=90, **kwargs):
'''
Run a single salt function and condition the return down to match the
behavior of the raw function call

View File

@ -210,15 +210,28 @@ class WebserverMixin(ModuleCase, ProcessManager, SaltReturnAssertsMixin):
'uwsgi_port': self.uwsgi_port,
'auth_enabled': auth_enabled}}
if grains['os_family'] in ('Debian',):
# Different libexec dir for git backend on Debian-based systems
pillar['git_pillar']['libexec_dir'] = '/usr/lib'
# Different libexec dir for git backend on Debian-based systems
git_core = '/usr/libexec/git-core' \
if grains['os_family'] in ('RedHat') \
else '/usr/lib/git-core'
pillar['git_pillar']['git-http-backend'] = os.path.join(
git_core,
'git-http-backend')
ret = self.run_function(
'state.apply',
mods='git_pillar.http',
pillar=pillar)
if not os.path.exists(pillar['git_pillar']['git-http-backend']):
self.fail(
'{0} not found. Either git is not installed, or the test '
'class needs to be updated.'.format(
pillar['git_pillar']['git-http-backend']
)
)
try:
self.nginx_proc = self.wait_proc(name='nginx',
search=self.nginx_conf)
@ -247,6 +260,12 @@ class GitTestBase(ModuleCase):
def is_el7(self, grains):
return grains['os_family'] == 'RedHat' and grains['osmajorrelease'] == 7
# Cent OS 6 has too old a version of git to handle the make_repo code, as
# it lacks the -c option for git itself.
@requires_system_grains
def is_pre_el7(self, grains):
return grains['os_family'] == 'RedHat' and grains['osmajorrelease'] < 7
@classmethod
def setUpClass(cls):
cls.prep_server()
@ -257,6 +276,9 @@ class GitTestBase(ModuleCase):
# needing to spend the extra time creating an ssh server and user and
# then tear them down separately for each test.
self.update_class(self)
if self.is_pre_el7(): # pylint: disable=E1120
self.skipTest(
'RHEL < 7 has too old a version of git to run these tests')
@classmethod
def update_class(cls, case):
@ -307,7 +329,7 @@ class GitPillarTestBase(GitTestBase, LoaderModuleMockMixin):
Run git_pillar with the specified configuration
'''
cachedir = tempfile.mkdtemp(dir=TMP)
#self.addCleanup(shutil.rmtree, cachedir, ignore_errors=True)
self.addCleanup(shutil.rmtree, cachedir, ignore_errors=True)
ext_pillar_opts = yaml.safe_load(
ext_pillar_conf.format(
cachedir=cachedir,