mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 08:58:59 +00:00
Merge pull request #37956 from rallytime/merge-develop
[develop] Merge forward from 2016.11 to develop
This commit is contained in:
commit
2723188c6f
@ -494,7 +494,7 @@ Aliasing Functions
|
||||
|
||||
Sometimes one wishes to use a function name that would shadow a python built-in.
|
||||
A common example would be ``set()``. To support this, append an underscore to
|
||||
the function defintion, ``def set_():``, and use the ``__func_alias__`` feature
|
||||
the function definition, ``def set_():``, and use the ``__func_alias__`` feature
|
||||
to provide an alias to the function.
|
||||
|
||||
``__func_alias__`` is a dictionary where each key is the name of a function in
|
||||
|
@ -38,7 +38,7 @@ Changes:
|
||||
|
||||
- **PR** `#27516`_: (*basepi*) [2015.5] Merge forward from 2014.7 to 2015.5
|
||||
|
||||
- **PR** `#27472`_: (*cachedout*) Change recommeded schema for data field in mysql event table
|
||||
- **PR** `#27472`_: (*cachedout*) Change recommended schema for data field in mysql event table
|
||||
|
||||
- **PR** `#27468`_: (*cachedout*) Fix 27351
|
||||
|
||||
|
@ -1,15 +1,7 @@
|
||||
:orphan:
|
||||
|
||||
==============================================
|
||||
Salt 2016.11.0 Release Notes - Codename Carbon
|
||||
==============================================
|
||||
|
||||
Release Candidate
|
||||
=================
|
||||
|
||||
See :ref:`Installing/Testing a Salt Release Candidate <release-candidate>` for instructions to install the
|
||||
latest release candidate.
|
||||
|
||||
New Features
|
||||
============
|
||||
|
||||
@ -24,7 +16,7 @@ commands to be run inside docker containers as well. This makes
|
||||
container introspection simple and powerful. See the tutorial on using
|
||||
this new feature here:
|
||||
|
||||
#TODO: Add link to docker sls tutorial
|
||||
See :ref:`Salt in Docker Containers <docker-sls>`.
|
||||
|
||||
Advanced Ceph Control
|
||||
---------------------
|
||||
|
@ -290,7 +290,7 @@ Thorium - Provisional New Reactor
|
||||
---------------------------------
|
||||
|
||||
The 2016.3 release introduces the new Thorium Reactor. This reactor is an
|
||||
experimental new feature that implements a flow programing interface using
|
||||
experimental new feature that implements a flow programming interface using
|
||||
the salt state system as the engine. This means that the Thorium reactor uses
|
||||
a classic state tree approach to create a reactor that can aggregate event
|
||||
data from multiple sources and make aggregate decisions about executing
|
||||
|
@ -18,7 +18,7 @@ standard ``salt`` commands.
|
||||
- Python is required on the remote system (unless using the ``-r`` option to send raw ssh commands)
|
||||
- On many systems, the ``salt-ssh`` executable will be in its own package, usually named
|
||||
``salt-ssh``
|
||||
- The Salt SSH system does not supercede the standard Salt communication
|
||||
- The Salt SSH system does not supersede the standard Salt communication
|
||||
systems, it simply offers an SSH-based alternative that does not require
|
||||
ZeroMQ and a remote agent. Be aware that since all communication with Salt SSH is
|
||||
executed via SSH it is substantially slower than standard Salt with ZeroMQ.
|
||||
@ -184,7 +184,7 @@ Salt SSH with a regular user you have to modify some paths or you will get
|
||||
"Permission denied" messages. You have to modify two parameters: ``pki_dir``
|
||||
and ``cachedir``. Those should point to a full path writable for the user.
|
||||
|
||||
It's recommed not to modify /etc/salt for this purpose. Create a private copy
|
||||
It's recommended not to modify /etc/salt for this purpose. Create a private copy
|
||||
of /etc/salt for the user and run the command with ``-c /new/config/path``.
|
||||
|
||||
Define CLI Options with Saltfile
|
||||
|
@ -1,3 +1,6 @@
|
||||
.. _docker-sls:
|
||||
|
||||
=====================================================
|
||||
Running Salt States and Commands in Docker Containers
|
||||
=====================================================
|
||||
|
||||
|
@ -256,7 +256,7 @@ def create(name, allocated_storage, db_instance_class, engine,
|
||||
raise SaltInvocationError('master_username is required')
|
||||
if not master_user_password:
|
||||
raise SaltInvocationError('master_user_password is required')
|
||||
if availability_zone and MultiAZ:
|
||||
if availability_zone and multi_az:
|
||||
raise SaltInvocationError('availability_zone and multi_az are mutually'
|
||||
' exclusive arguments.')
|
||||
if wait_status:
|
||||
@ -529,6 +529,10 @@ def describe(name, tags=None, region=None, key=None, keyid=None,
|
||||
return {'results': bool(conn)}
|
||||
|
||||
rds = conn.describe_db_instances(DBInstanceIdentifier=name)
|
||||
rds = [
|
||||
i for i in rds.get('DBInstances', [])
|
||||
if i.get('DBInstanceIdentifier') == name
|
||||
].pop(0)
|
||||
|
||||
if rds:
|
||||
keys = ('DBInstanceIdentifier', 'DBInstanceClass', 'Engine',
|
||||
@ -549,6 +553,8 @@ def describe(name, tags=None, region=None, key=None, keyid=None,
|
||||
return {'rds': None}
|
||||
except ClientError as e:
|
||||
return {'error': salt.utils.boto3.get_error(e)}
|
||||
except IndexError:
|
||||
return {'rds': None}
|
||||
|
||||
|
||||
def get_endpoint(name, tags=None, region=None, key=None, keyid=None,
|
||||
|
@ -165,7 +165,12 @@ def update(zone, name, ttl, rdtype, data, nameserver='127.0.0.1', timeout=5,
|
||||
salt ns1 ddns.update example.com host1 60 A 10.0.0.1
|
||||
'''
|
||||
name = str(name)
|
||||
fqdn = '{0}.{1}'.format(name, zone)
|
||||
|
||||
if name[-1:] == '.':
|
||||
fqdn = name
|
||||
else:
|
||||
fqdn = '{0}.{1}'.format(name, zone)
|
||||
|
||||
request = dns.message.make_query(fqdn, rdtype)
|
||||
answer = dns.query.udp(request, nameserver, timeout, port)
|
||||
|
||||
@ -211,9 +216,13 @@ def delete(zone, name, rdtype=None, data=None, nameserver='127.0.0.1',
|
||||
salt ns1 ddns.delete example.com host1 A
|
||||
'''
|
||||
name = str(name)
|
||||
fqdn = '{0}.{1}'.format(name, zone)
|
||||
request = dns.message.make_query(fqdn, (rdtype or 'ANY'))
|
||||
|
||||
if name[-1:] == '.':
|
||||
fqdn = name
|
||||
else:
|
||||
fqdn = '{0}.{1}'.format(name, zone)
|
||||
|
||||
request = dns.message.make_query(fqdn, (rdtype or 'ANY'))
|
||||
answer = dns.query.udp(request, nameserver, timeout, port)
|
||||
if not answer.answer:
|
||||
return None
|
||||
|
@ -73,7 +73,11 @@ For example:
|
||||
username: foo
|
||||
|
||||
Reauth is an optional parameter that forces the docker login to reauthorize using
|
||||
the credentials passed in the pillar data. Defaults to false. For example:
|
||||
the credentials passed in the pillar data. Defaults to false.
|
||||
|
||||
.. versionadded:: 2016.3.5,2016.11.1
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
|
@ -257,7 +257,7 @@ def create_user(username, password, permissions, users=None):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt dell drac.create_user [USERNAME] [PASSWORD] [PRIVELEGES]
|
||||
salt dell drac.create_user [USERNAME] [PASSWORD] [PRIVILEGES]
|
||||
salt dell drac.create_user diana secret login,test_alerts,clear_logs
|
||||
|
||||
DRAC Privileges
|
||||
@ -320,7 +320,7 @@ def set_permissions(username, permissions, uid=None):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt dell drac.set_permissions [USERNAME] [PRIVELEGES] [USER INDEX - optional]
|
||||
salt dell drac.set_permissions [USERNAME] [PRIVILEGES] [USER INDEX - optional]
|
||||
salt dell drac.set_permissions diana login,test_alerts,clear_logs 4
|
||||
|
||||
DRAC Privileges
|
||||
|
@ -548,7 +548,7 @@ def create_user(username, password, permissions,
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt dell dracr.create_user [USERNAME] [PASSWORD] [PRIVELEGES]
|
||||
salt dell dracr.create_user [USERNAME] [PASSWORD] [PRIVILEGES]
|
||||
salt dell dracr.create_user diana secret login,test_alerts,clear_logs
|
||||
|
||||
DRAC Privileges
|
||||
@ -616,7 +616,7 @@ def set_permissions(username, permissions,
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt dell dracr.set_permissions [USERNAME] [PRIVELEGES]
|
||||
salt dell dracr.set_permissions [USERNAME] [PRIVILEGES]
|
||||
[USER INDEX - optional]
|
||||
salt dell dracr.set_permissions diana login,test_alerts,clear_logs 4
|
||||
|
||||
|
@ -245,6 +245,8 @@ def dump(device, args=None):
|
||||
elif line.startswith('Group') and not line.startswith('Group descriptor size'):
|
||||
mode = 'blocks'
|
||||
else:
|
||||
if len(comps) < 2:
|
||||
continue
|
||||
ret['attributes'][comps[0]] = comps[1].strip()
|
||||
|
||||
if mode == 'blocks':
|
||||
|
@ -704,7 +704,7 @@ def set_bootdev(bootdev='default', persist=False, uefiboot=False, **kwargs):
|
||||
this
|
||||
|
||||
:param uefiboot: If true, request UEFI boot explicitly. Strictly
|
||||
speaking, the spec sugests that if not set, the system
|
||||
speaking, the spec suggests that if not set, the system
|
||||
should BIOS boot and offers no "don't care" option.
|
||||
In practice, this flag not being set does not preclude
|
||||
UEFI boot on any system I've encountered.
|
||||
|
@ -78,6 +78,30 @@ Or do something interesting with grains like:
|
||||
'{{ opts['id'] }}':
|
||||
- {{ role }}
|
||||
{%- endif %}
|
||||
|
||||
Multi-line text items like certificates require a bit of extra work. You have to strip the new lines
|
||||
and replace them with '/n' characters. Certificates specifically require some leading white space when
|
||||
calling nacl.enc so that the '--' in the first line (commonly -----BEGIN CERTIFICATE-----) doesn't get
|
||||
interpreted as an argument to nacl.enc. For instance if you have a certificate file that lives in cert.crt:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cert=$(cat cert.crt |awk '{printf "%s\\n",$0} END {print ""}'); salt-run nacl.enc " $cert"
|
||||
|
||||
Pillar data should look the same, even though the secret will be quite long. However, when calling
|
||||
multiline encrypted secrets from pillar in a state, use the following format to avoid issues with /n
|
||||
creating extra whitespace at the beginning of each line in the cert file:
|
||||
|
||||
.. code-block:: yaml
|
||||
secret.txt:
|
||||
file.managed:
|
||||
- template: jinja
|
||||
- user: user
|
||||
- group: group
|
||||
- mode: 700
|
||||
- contents: "{{- salt['pillar.get']('secret') }}"
|
||||
|
||||
The '{{-' will tell jinja to strip the whitespace from the beginning of each of the new lines.
|
||||
'''
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
@ -601,6 +601,9 @@ def info(*packages, **attr):
|
||||
ret = dict()
|
||||
for pkg_data in reversed(sorted(_ret, cmp=lambda a_vrs, b_vrs: version_cmp(a_vrs['edition'], b_vrs['edition']))):
|
||||
pkg_name = pkg_data.pop('name')
|
||||
# Filter out GPG public keys packages
|
||||
if pkg_name.startswith('gpg-pubkey'):
|
||||
continue
|
||||
if pkg_name not in ret:
|
||||
ret[pkg_name] = pkg_data.copy()
|
||||
del ret[pkg_name]['edition']
|
||||
|
@ -266,16 +266,36 @@ def list_semod():
|
||||
|
||||
.. versionadded:: 2016.3.0
|
||||
'''
|
||||
mdata = __salt__['cmd.run']('semodule -l').splitlines()
|
||||
ret = {}
|
||||
for line in mdata[1:]:
|
||||
if not line.strip():
|
||||
continue
|
||||
comps = line.split()
|
||||
if len(comps) == 3:
|
||||
ret[comps[0]] = {'Enabled': False,
|
||||
'Version': comps[1]}
|
||||
else:
|
||||
ret[comps[0]] = {'Enabled': True,
|
||||
'Version': comps[1]}
|
||||
helptext = __salt__['cmd.run']('semodule -h').splitlines()
|
||||
semodule_version = ''
|
||||
for line in helptext:
|
||||
if line.strip().startswith('full'):
|
||||
semodule_version = 'new'
|
||||
|
||||
if semodule_version == 'new':
|
||||
mdata = __salt__['cmd.run']('semodule -lfull').splitlines()
|
||||
ret = {}
|
||||
for line in mdata:
|
||||
if not line.strip():
|
||||
continue
|
||||
comps = line.split()
|
||||
if len(comps) == 4:
|
||||
ret[comps[1]] = {'Enabled': False,
|
||||
'Version': None}
|
||||
else:
|
||||
ret[comps[1]] = {'Enabled': True,
|
||||
'Version': None}
|
||||
else:
|
||||
mdata = __salt__['cmd.run']('semodule -l').splitlines()
|
||||
ret = {}
|
||||
for line in mdata:
|
||||
if not line.strip():
|
||||
continue
|
||||
comps = line.split()
|
||||
if len(comps) == 3:
|
||||
ret[comps[0]] = {'Enabled': False,
|
||||
'Version': comps[1]}
|
||||
else:
|
||||
ret[comps[0]] = {'Enabled': True,
|
||||
'Version': comps[1]}
|
||||
return ret
|
||||
|
@ -551,7 +551,7 @@ def list_updates(verbose=False, fields=None, skips=None, retries=5, categories=N
|
||||
fields
|
||||
Return a list of specific fields for each update. The optional
|
||||
values here are those at the root level of the verbose list. This
|
||||
is superceded by the verbose option.
|
||||
is superseded by the verbose option.
|
||||
|
||||
retries
|
||||
Number of retries to make before giving up. This is total, not per
|
||||
|
@ -1089,7 +1089,7 @@ def create_certificate(
|
||||
- x509.sign_remote_certificate
|
||||
|
||||
subject properties:
|
||||
Any of the values below can be incldued to set subject properties
|
||||
Any of the values below can be included to set subject properties
|
||||
Any other subject properties supported by OpenSSL should also work.
|
||||
|
||||
C:
|
||||
|
@ -264,7 +264,7 @@ documentation, but in short:
|
||||
<salt.wheel.key>` exposes similar functionality as the ``salt-key`` CLI
|
||||
command.
|
||||
|
||||
Most clients have variants like synchronous or asyncronous execution as well as
|
||||
Most clients have variants like synchronous or asynchronous execution as well as
|
||||
others like batch execution. See the :ref:`full list of client interfaces
|
||||
<netapi-clients>`.
|
||||
|
||||
|
@ -265,7 +265,7 @@ def change(name, context=None, changes=None, lens=None,
|
||||
filename = re.sub('^/files|/$', '', context)
|
||||
|
||||
if __opts__['test']:
|
||||
ret['result'] = None
|
||||
ret['result'] = True
|
||||
ret['comment'] = 'Executing commands'
|
||||
if context:
|
||||
ret['comment'] += ' in file "{0}":\n'.format(context)
|
||||
|
@ -309,7 +309,7 @@ def present(name,
|
||||
'changes': {}
|
||||
}
|
||||
|
||||
r = __salt__['boto_rds.exists'](name, region, key, keyid, profile)
|
||||
r = __salt__['boto_rds.exists'](name, tags, region, key, keyid, profile)
|
||||
|
||||
if not r.get('exists'):
|
||||
if __opts__['test']:
|
||||
@ -350,7 +350,7 @@ def present(name,
|
||||
ret['comment'] = 'Failed to create RDS instance {0}.'.format(r['error']['message'])
|
||||
return ret
|
||||
|
||||
_describe = __salt__['boto_rds.describe'](name, region, key, keyid, profile)
|
||||
_describe = __salt__['boto_rds.describe'](name, tags, region, key, keyid, profile)
|
||||
ret['changes']['old'] = {'instance': None}
|
||||
ret['changes']['new'] = _describe
|
||||
ret['comment'] = 'RDS instance {0} created.'.format(name)
|
||||
@ -488,36 +488,33 @@ def subnet_group_present(name, description, subnet_ids=None, subnet_names=None,
|
||||
return ret
|
||||
subnet_ids.append(r['id'])
|
||||
|
||||
for i in subnet_ids:
|
||||
r = __salt__['boto_rds.create_subnet_group'](name=name,
|
||||
exists = __salt__['boto_rds.subnet_group_exists'](name=name, tags=tags, region=region, key=key,
|
||||
keyid=keyid, profile=profile)
|
||||
if not exists:
|
||||
if __opts__['test']:
|
||||
ret['comment'] = 'Subnet group {0} is set to be created.'.format(name)
|
||||
ret['result'] = None
|
||||
return ret
|
||||
if not r.get('created'):
|
||||
ret['result'] = False
|
||||
ret['comment'] = 'Failed to create {0} subnet group.'.format(r['error']['message'])
|
||||
return ret
|
||||
created = __salt__['boto_rds.create_subnet_group'](name=name,
|
||||
description=description,
|
||||
subnet_ids=subnet_ids,
|
||||
tags=tags, region=region,
|
||||
key=key, keyid=keyid,
|
||||
profile=profile)
|
||||
|
||||
if not r.get('exists'):
|
||||
if __opts__['test']:
|
||||
ret['comment'] = 'Subnet group {0} is set to be created.'.format(name)
|
||||
ret['result'] = None
|
||||
return ret
|
||||
if not r.get('created'):
|
||||
ret['result'] = False
|
||||
ret['comment'] = 'Failed to create {0} subnet group.'.format(r['error']['message'])
|
||||
return ret
|
||||
|
||||
_describe = __salt__['boto_rds.describe']('subnet',
|
||||
name=i,
|
||||
region=region,
|
||||
key=key,
|
||||
keyid=keyid,
|
||||
profile=profile)
|
||||
|
||||
ret['changes']['old'] = None
|
||||
ret['changes']['new'] = _describe
|
||||
ret['comment'] = 'Subnet {0} created.'.format(name)
|
||||
else:
|
||||
ret['comment'] = 'Subnet {0} present.'.format(name)
|
||||
if not created:
|
||||
ret['result'] = False
|
||||
ret['comment'] = 'Failed to create {0} subnet group.'.format(name)
|
||||
return ret
|
||||
ret['changes']['old'] = None
|
||||
ret['changes']['new'] = name
|
||||
ret['comment'] = 'Subnet {0} created.'.format(name)
|
||||
else:
|
||||
ret['comment'] = 'Subnet {0} present.'.format(name)
|
||||
|
||||
return ret
|
||||
|
||||
|
@ -31,8 +31,9 @@ def install(*args, **kwargs):
|
||||
installed(*args, **kwargs)
|
||||
|
||||
|
||||
def installed(name, version=None, source=None, force=False, install_args=None,
|
||||
override_args=False, force_x86=False, package_args=None):
|
||||
def installed(name, version=None, source=None, force=False, pre_versions=False,
|
||||
install_args=None, override_args=False, force_x86=False,
|
||||
package_args=None):
|
||||
'''
|
||||
Installs a package if not already installed
|
||||
|
||||
@ -50,6 +51,9 @@ def installed(name, version=None, source=None, force=False, install_args=None,
|
||||
force
|
||||
Reinstall the current version of an existing package. Default is false.
|
||||
|
||||
pre_versions
|
||||
Include pre-release packages. Default is False.
|
||||
|
||||
install_args
|
||||
A list of install arguments you want to pass to the installation
|
||||
process i.e product key or feature list
|
||||
@ -108,13 +112,11 @@ def installed(name, version=None, source=None, force=False, install_args=None,
|
||||
return ret
|
||||
|
||||
# Install the package
|
||||
ret['changes'] = {name: __salt__['chocolatey.install'](name, version,
|
||||
source,
|
||||
force,
|
||||
install_args,
|
||||
override_args,
|
||||
force_x86,
|
||||
package_args)}
|
||||
ret['changes'] = {name: __salt__['chocolatey.install'](
|
||||
name=name, version=version, source=source, force=force,
|
||||
pre_versions=pre_versions, install_args=install_args,
|
||||
override_args=override_args, force_x86=force_x86,
|
||||
package_args=package_args)}
|
||||
|
||||
if 'Running chocolatey failed' not in ret['changes']:
|
||||
ret['result'] = True
|
||||
|
@ -37,8 +37,9 @@ def present(name, zone, ttl, data, rdtype='A', **kwargs):
|
||||
|
||||
name
|
||||
The host portion of the DNS record, e.g., 'webserver'. Name and zone
|
||||
are concatenated when the entry is created, so make sure that
|
||||
information is not duplicated in these two arguments.
|
||||
are concatenated when the entry is created unless name includes a
|
||||
trailing dot, so make sure that information is not duplicated in these
|
||||
two arguments.
|
||||
|
||||
zone
|
||||
The zone to check/update
|
||||
@ -95,8 +96,9 @@ def absent(name, zone, data=None, rdtype=None, **kwargs):
|
||||
|
||||
name
|
||||
The host portion of the DNS record, e.g., 'webserver'. Name and zone
|
||||
are concatenated when the entry is created, so make sure that
|
||||
information is not duplicated in these two arguments.
|
||||
are concatenated when the entry is created unless name includes a
|
||||
trailing dot, so make sure that information is not duplicated in these
|
||||
two arguments.
|
||||
|
||||
zone
|
||||
The zone to check
|
||||
|
@ -111,8 +111,8 @@ def _compute_diff(configured, expected):
|
||||
remove_usernames = configured_users - expected_users
|
||||
common_usernames = expected_users & configured_users
|
||||
|
||||
add = {username: expected.get(username) for username in add_usernames} # pylint: disable=minimum-python-version
|
||||
remove = {username: configured.get(username) for username in remove_usernames} # pylint: disable=minimum-python-version
|
||||
add = dict((username, expected.get(username)) for (username, _) in add_usernames)
|
||||
remove = dict((username, configured.get(username)) for (username, _) in remove_usernames)
|
||||
update = {}
|
||||
|
||||
for username in common_usernames:
|
||||
|
@ -202,7 +202,8 @@ def module(name, module_state='Enabled', version='any'):
|
||||
installed_version = modules[name]['Version']
|
||||
if not installed_version == version:
|
||||
ret['comment'] = 'Module version is {0} and does not match ' \
|
||||
'the desired version of {1}'.format(installed_version, version)
|
||||
'the desired version of {1} or you are ' \
|
||||
'using semodule >= 2.4'.format(installed_version, version)
|
||||
ret['result'] = False
|
||||
return ret
|
||||
current_module_state = _refine_module_state(modules[name]['Enabled'])
|
||||
@ -211,7 +212,7 @@ def module(name, module_state='Enabled', version='any'):
|
||||
return ret
|
||||
if __opts__['test']:
|
||||
ret['result'] = None
|
||||
ret['comment'] = 'Module {0} is set to be togggled to {1}'.format(
|
||||
ret['comment'] = 'Module {0} is set to be toggled to {1}'.format(
|
||||
name, module_state)
|
||||
return ret
|
||||
|
||||
|
@ -102,6 +102,10 @@ def latest(name,
|
||||
('{0} doesn\'t exist and is set to be checked out.').format(target))
|
||||
svn_cmd = 'svn.diff'
|
||||
opts += ('-r', 'HEAD')
|
||||
|
||||
if trust:
|
||||
opts += ('--trust-server-cert',)
|
||||
|
||||
out = __salt__[svn_cmd](cwd, target, user, username, password, *opts)
|
||||
return _neutral_test(
|
||||
ret,
|
||||
|
@ -4,5 +4,7 @@
|
||||
{%endif%}{% if gateway %}GATEWAY={{gateway}}
|
||||
{%endif%}{% if gatewaydev %}GATEWAYDEV={{gatewaydev}}
|
||||
{%endif%}{% if nisdomain %}NISDOMAIN={{nisdomain}}
|
||||
{%endif%}{% if networkdelay %}NETWORKDELAY={{networkdelay}}
|
||||
{%endif%}{% if devtimeout %}DEVTIMEOUT={{devtimeout}}
|
||||
{%endif%}{% if nozeroconf %}NOZEROCONF={{nozeroconf}}
|
||||
{%endif%}
|
||||
|
64
salt/utils/sanitizers.py
Normal file
64
salt/utils/sanitizers.py
Normal file
@ -0,0 +1,64 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2016 SUSE LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
import re
|
||||
import os.path
|
||||
|
||||
# Import Salt libs
|
||||
from salt.ext.six import text_type as text
|
||||
from salt.exceptions import CommandExecutionError
|
||||
|
||||
|
||||
class InputSanitizer(object):
|
||||
@staticmethod
|
||||
def trim(value):
|
||||
'''
|
||||
Raise an exception if value is empty. Otherwise strip it down.
|
||||
:param value:
|
||||
:return:
|
||||
'''
|
||||
value = (value or '').strip()
|
||||
if not value:
|
||||
raise CommandExecutionError("Empty value during sanitation")
|
||||
|
||||
return text(value)
|
||||
|
||||
@staticmethod
|
||||
def filename(value):
|
||||
'''
|
||||
Remove everything that would affect paths in the filename
|
||||
|
||||
:param value:
|
||||
:return:
|
||||
'''
|
||||
return re.sub('[^a-zA-Z0-9.-_ ]', '', os.path.basename(InputSanitizer.trim(value)))
|
||||
|
||||
@staticmethod
|
||||
def hostname(value):
|
||||
'''
|
||||
Clean value for RFC1123.
|
||||
|
||||
:param value:
|
||||
:return:
|
||||
'''
|
||||
return re.sub(r'[^a-zA-Z0-9.-]', '', InputSanitizer.trim(value))
|
||||
|
||||
id = hostname
|
||||
|
||||
|
||||
clean = InputSanitizer()
|
@ -37,6 +37,8 @@ import logging
|
||||
from salt.key import get_key
|
||||
import salt.crypt
|
||||
import salt.utils
|
||||
from salt.utils.sanitizers import clean
|
||||
|
||||
|
||||
__func_alias__ = {
|
||||
'list_': 'list',
|
||||
@ -318,6 +320,8 @@ def gen(id_=None, keysize=2048):
|
||||
'''
|
||||
if id_ is None:
|
||||
id_ = hashlib.sha512(os.urandom(32)).hexdigest()
|
||||
else:
|
||||
id_ = clean.filename(id_)
|
||||
ret = {'priv': '',
|
||||
'pub': ''}
|
||||
priv = salt.crypt.gen_keys(__opts__['pki_dir'], id_, keysize)
|
||||
@ -371,6 +375,7 @@ def gen_accept(id_, keysize=2048, force=False):
|
||||
>>> wheel.cmd('key.list', ['accepted'])
|
||||
{'minions': ['foo', 'minion1', 'minion2', 'minion3']}
|
||||
'''
|
||||
id_ = clean.id(id_)
|
||||
ret = gen(id_, keysize)
|
||||
acc_path = os.path.join(__opts__['pki_dir'], 'minions', id_)
|
||||
if os.path.isfile(acc_path) and not force:
|
||||
|
@ -84,7 +84,7 @@ class AugeasTestCase(TestCase):
|
||||
comt = ('Executing commands in file "/files/etc/services":\n'
|
||||
'ins service-name after service-name[last()]'
|
||||
'\nset service-name[last()] zabbix-agent')
|
||||
self.ret.update({'comment': comt, 'result': None})
|
||||
self.ret.update({'comment': comt, 'result': True})
|
||||
|
||||
with patch.dict(augeas.__opts__, {'test': True}):
|
||||
self.assertDictEqual(
|
||||
|
Loading…
Reference in New Issue
Block a user