Merge pull request #42363 from rallytime/merge-2017.7

[2017.7] Merge forward from 2016.11 to 2017.7
This commit is contained in:
Nicole Thomas 2017-07-18 12:40:48 -06:00 committed by GitHub
commit 587138d771
22 changed files with 213 additions and 57 deletions

View file

@ -321,7 +321,27 @@ Restart using states
********************
Now we can apply the workaround to restart the Minion in reliable way.
The following example works on both UNIX-like and Windows operating systems:
The following example works on UNIX-like operating systems:
.. code-block:: jinja
{%- if grains['os'] != 'Windows' %
Restart Salt Minion:
cmd.run:
- name: 'salt-call --local service.restart salt-minion'
- bg: True
- onchanges:
- pkg: Upgrade Salt Minion
{%- endif %}
Note that restarting the ``salt-minion`` service on Windows operating systems is
not always necessary when performing an upgrade. The installer stops the
``salt-minion`` service, removes it, deletes the contents of the ``\salt\bin``
directory, installs the new code, re-creates the ``salt-minion`` service, and
starts it (by default). The restart step **would** be necessary during the
upgrade process, however, if the minion config was edited after the upgrade or
installation. If a minion restart is necessary, the state above can be edited
as follows:
.. code-block:: jinja
@ -337,8 +357,8 @@ The following example works on both UNIX-like and Windows operating systems:
- pkg: Upgrade Salt Minion
However, it requires more advanced tricks to upgrade from legacy version of
Salt (before ``2016.3.0``), where executing commands in the background is not
supported:
Salt (before ``2016.3.0``) on UNIX-like operating systems, where executing
commands in the background is not supported:
.. code-block:: jinja

View file

@ -1272,6 +1272,20 @@ A list of extra directories to search for Salt renderers
render_dirs:
- /var/lib/salt/renderers
.. conf_minion:: utils_dirs
``utils_dirs``
---------------
Default: ``[]``
A list of extra directories to search for Salt utilities
.. code-block:: yaml
utils_dirs:
- /var/lib/salt/utils
.. conf_minion:: cython_enable
``cython_enable``

View file

@ -78,6 +78,7 @@ parameters are discussed in more detail below.
# RHEL -> ec2-user
# CentOS -> ec2-user
# Ubuntu -> ubuntu
# Debian -> admin
#
ssh_username: ec2-user

View file

@ -371,7 +371,6 @@ both.
compute_name: cloudServersOpenStack
protocol: ipv4
compute_region: DFW
protocol: ipv4
user: myuser
tenant: 5555555
password: mypass

View file

@ -32,6 +32,8 @@ Builds for a few platforms are available as part of the RC at https://repo.salts
Available builds:
- Ubuntu16
- Redhat7
- Windows
.. FreeBSD

View file

@ -64,7 +64,8 @@ Deploy ssh key for salt-ssh
===========================
By default, salt-ssh will generate key pairs for ssh, the default path will be
/etc/salt/pki/master/ssh/salt-ssh.rsa
``/etc/salt/pki/master/ssh/salt-ssh.rsa``. The key generation happens when you run
``salt-ssh`` for the first time.
You can use ssh-copy-id, (the OpenSSH key deployment tool) to deploy keys to your servers.

View file

@ -28,6 +28,7 @@ hit `Enter`. Also, you can convert tabs to 2 spaces by these commands in Vim:
Indentation
===========
The suggested syntax for YAML files is to use 2 spaces for indentation,
but YAML will follow whatever indentation system that the individual file
uses. Indentation of two spaces works very well for SLS files given the
@ -112,8 +113,24 @@ PyYAML will load these values as boolean ``True`` or ``False``. Un-capitalized
versions will also be loaded as booleans (``true``, ``false``, ``yes``, ``no``,
``on``, and ``off``). This can be especially problematic when constructing
Pillar data. Make sure that your Pillars which need to use the string versions
of these values are enclosed in quotes. Pillars will be parsed twice by salt,
so you'll need to wrap your values in multiple quotes, for example '"false"'.
of these values are enclosed in quotes. Pillars will be parsed twice by salt,
so you'll need to wrap your values in multiple quotes, including double quotation
marks (``" "``) and single quotation marks (``' '``). Note that spaces are included
in the quotation type examples for clarity.
Multiple quoting examples looks like this:
.. code-block:: yaml
- '"false"'
- "'True'"
- "'YES'"
- '"No"'
.. note::
When using multiple quotes in this manner, they must be different. Using ``"" ""``
or ``'' ''`` won't work in this case (spaces are included in examples for clarity).
The '%' Sign
============

View file

@ -54,7 +54,7 @@ types like so:
salt '*' mymodule.observe_the_awesomeness
'''
print __utils__['foo.bar']()
return __utils__['foo.bar']()
Utility modules, like any other kind of Salt extension, support using a
:ref:`__virtual__ function <modules-virtual-name>` to conditionally load them,
@ -81,11 +81,56 @@ the ``foo`` utility module with a ``__virtual__`` function.
def bar():
return 'baz'
Also you could even write your utility modules in object oriented fashion:
.. code-block:: python
# -*- coding: utf-8 -*-
'''
My utils module
---------------
This module contains common functions for use in my other custom types.
'''
class Foo(object):
def __init__(self):
pass
def bar(self):
return 'baz'
And import them into other custom modules:
.. code-block:: python
# -*- coding: utf-8 -*-
'''
My awesome execution module
---------------------------
'''
import mymodule
def observe_the_awesomeness():
'''
Prints information from my utility module
CLI Example:
.. code-block:: bash
salt '*' mymodule.observe_the_awesomeness
'''
foo = mymodule.Foo()
return foo.bar()
These are, of course, contrived examples, but they should serve to show some of
the possibilities opened up by writing utility modules. Keep in mind though
that States still have access to all of the execution modules, so it is not
that states still have access to all of the execution modules, so it is not
necessary to write a utility module to make a function available to both a
state and an execution module. One good use case for utililty modules is one
state and an execution module. One good use case for utility modules is one
where it is necessary to invoke the same function from a custom :ref:`outputter
<all-salt.output>`/returner, as well as an execution module.

View file

@ -135,6 +135,14 @@ Alternatively, one could use the private IP to connect by specifying:
ssh_interface: private_ips
.. note::
When using floating ips from networks, if the OpenStack driver is unable to
allocate a new ip address for the server, it will check that for
unassociated ip addresses in the floating ip pool. If SaltCloud is running
in parallel mode, it is possible that more than one server will attempt to
use the same ip address.
'''
# Import python libs
@ -855,40 +863,43 @@ def _assign_floating_ips(vm_, conn, kwargs):
pool = OpenStack_1_1_FloatingIpPool(
net['floating'], conn.connection
)
for idx in pool.list_floating_ips():
if idx.node_id is None:
floating.append(idx)
try:
floating.append(pool.create_floating_ip())
except Exception as e:
log.debug('Cannot allocate IP from floating pool \'%s\'. Checking for unassociated ips.',
net['floating'])
for idx in pool.list_floating_ips():
if idx.node_id is None:
floating.append(idx)
break
if not floating:
try:
floating.append(pool.create_floating_ip())
except Exception as e:
raise SaltCloudSystemExit(
'Floating pool \'{0}\' does not have any more '
'please create some more or use a different '
'pool.'.format(net['floating'])
)
raise SaltCloudSystemExit(
'There are no more floating IP addresses '
'available, please create some more'
)
# otherwise, attempt to obtain list without specifying pool
# this is the same as 'nova floating-ip-list'
elif ssh_interface(vm_) != 'private_ips':
try:
# This try/except is here because it appears some
# *cough* Rackspace *cough*
# OpenStack providers return a 404 Not Found for the
# floating ip pool URL if there are no pools setup
pool = OpenStack_1_1_FloatingIpPool(
'', conn.connection
)
for idx in pool.list_floating_ips():
if idx.node_id is None:
floating.append(idx)
try:
floating.append(pool.create_floating_ip())
except Exception as e:
log.debug('Cannot allocate IP from the default floating pool. Checking for unassociated ips.')
for idx in pool.list_floating_ips():
if idx.node_id is None:
floating.append(idx)
break
if not floating:
try:
floating.append(pool.create_floating_ip())
except Exception as e:
raise SaltCloudSystemExit(
'There are no more floating IP addresses '
'available, please create some more'
)
raise SaltCloudSystemExit(
'There are no more floating IP addresses '
'available, please create some more'
)
except Exception as e:
if str(e).startswith('404'):
pass

View file

@ -150,7 +150,7 @@ def avail_locations(conn=None, call=None):
ret[img_name] = {}
for attr in dir(img):
if attr.startswith('_'):
if attr.startswith('_') or attr == 'driver':
continue
attr_value = getattr(img, attr)
@ -187,7 +187,7 @@ def avail_images(conn=None, call=None):
ret[img_name] = {}
for attr in dir(img):
if attr.startswith('_'):
if attr.startswith('_') or attr in ('driver', 'get_uuid'):
continue
attr_value = getattr(img, attr)
if isinstance(attr_value, string_types) and not six.PY3:
@ -222,7 +222,7 @@ def avail_sizes(conn=None, call=None):
ret[size_name] = {}
for attr in dir(size):
if attr.startswith('_'):
if attr.startswith('_') or attr in ('driver', 'get_uuid'):
continue
try:

View file

@ -2,7 +2,7 @@
'''
Subversion Fileserver Backend
After enabling this backend, branches, and tags in a remote subversion
After enabling this backend, branches and tags in a remote subversion
repository are exposed to salt as different environments. To enable this
backend, add ``svn`` to the :conf_master:`fileserver_backend` option in the
Master config file.
@ -697,7 +697,7 @@ def file_hash(load, fnd):
def _file_lists(load, form):
'''
Return a dict containing the file lists for files, dirs, emtydirs and symlinks
Return a dict containing the file lists for files, dirs, emptydirs and symlinks
'''
if 'env' in load:
salt.utils.warn_until(

View file

@ -194,7 +194,7 @@ def minion_mods(
generated modules in __context__
:param dict utils: Utility functions which should be made available to
Salt modules in __utils__. See `utils_dir` in
Salt modules in __utils__. See `utils_dirs` in
salt.config for additional information about
configuration.

View file

@ -1,6 +1,10 @@
# -*- coding: utf-8 -*-
'''
Compendium of generic DNS utilities
Compendium of generic DNS utilities.
.. note::
Some functions in the ``dnsutil`` execution module depend on ``dig``.
'''
from __future__ import absolute_import
@ -232,7 +236,7 @@ def check_ip(ip_addr):
.. code-block:: bash
salt ns1 dig.check_ip 127.0.0.1
salt ns1 dnsutil.check_ip 127.0.0.1
'''
if _has_dig():
return __salt__['dig.check_ip'](ip_addr)
@ -242,7 +246,7 @@ def check_ip(ip_addr):
def A(host, nameserver=None):
'''
Return the A record(s) for `host`.
Return the A record(s) for ``host``.
Always returns a list.
@ -267,7 +271,7 @@ def A(host, nameserver=None):
def AAAA(host, nameserver=None):
'''
Return the AAAA record(s) for `host`.
Return the AAAA record(s) for ``host``.
Always returns a list.
@ -302,7 +306,7 @@ def NS(domain, resolve=True, nameserver=None):
.. code-block:: bash
salt ns1 dig.NS google.com
salt ns1 dnsutil.NS google.com
'''
if _has_dig():
@ -323,7 +327,7 @@ def SPF(domain, record='SPF', nameserver=None):
.. code-block:: bash
salt ns1 dig.SPF google.com
salt ns1 dnsutil.SPF google.com
'''
if _has_dig():
return __salt__['dig.SPF'](domain, record, nameserver)
@ -346,7 +350,7 @@ def MX(domain, resolve=False, nameserver=None):
.. code-block:: bash
salt ns1 dig.MX google.com
salt ns1 dnsutil.MX google.com
'''
if _has_dig():
return __salt__['dig.MX'](domain, resolve, nameserver)

View file

@ -978,6 +978,10 @@ def login(*registries):
cmd = ['docker', 'login', '-u', username, '-p', password]
if registry.lower() != 'hub':
cmd.append(registry)
log.debug(
'Attempting to login to docker registry \'%s\' as user \'%s\'',
registry, username
)
login_cmd = __salt__['cmd.run_all'](
cmd,
python_shell=False,

View file

@ -185,15 +185,24 @@ def _git_run(command, cwd=None, user=None, password=None, identity=None,
identity = [identity]
# try each of the identities, independently
tmp_identity_file = None
for id_file in identity:
if 'salt://' in id_file:
_id_file = id_file
id_file = __salt__['cp.cache_file'](id_file, saltenv)
with salt.utils.files.set_umask(0o077):
tmp_identity_file = salt.utils.mkstemp()
_id_file = id_file
id_file = __salt__['cp.get_file'](id_file,
tmp_identity_file,
saltenv)
if not id_file:
log.error('identity {0} does not exist.'.format(_id_file))
__salt__['file.remove'](tmp_identity_file)
continue
else:
__salt__['file.set_mode'](id_file, '0600')
if user:
os.chown(id_file,
__salt__['file.user_to_uid'](user),
-1)
else:
if not __salt__['file.file_exists'](id_file):
missing_keys.append(id_file)
@ -264,6 +273,11 @@ def _git_run(command, cwd=None, user=None, password=None, identity=None,
if not salt.utils.is_windows() and 'GIT_SSH' in env:
os.remove(env['GIT_SSH'])
# Cleanup the temporary identify file
if tmp_identity_file and os.path.exists(tmp_identity_file):
log.debug('Removing identify file {0}'.format(tmp_identity_file))
#__salt__['file.remove'](tmp_identity_file)
# If the command was successful, no need to try additional IDs
if result['retcode'] == 0:
return result

View file

@ -262,7 +262,7 @@ def create_keytab(name, keytab, enctypes=None):
.. code-block:: bash
salt 'kdc.example.com' host/host1.example.com host1.example.com.keytab
salt 'kdc.example.com' kerberos.create_keytab host/host1.example.com host1.example.com.keytab
'''
ret = {}

View file

@ -345,9 +345,10 @@ def summary():
def plugin_sync():
'''
Runs a plugin synch between the puppet master and agent
Runs a plugin sync between the puppet master and agent
CLI Example:
.. code-block:: bash
salt '*' puppet.plugin_sync

View file

@ -1433,7 +1433,10 @@ def absent(name):
ret['comment'] = 'File {0} is set for removal'.format(name)
return ret
try:
__salt__['file.remove'](name)
if salt.utils.is_windows():
__salt__['file.remove'](name, force=True)
else:
__salt__['file.remove'](name)
ret['comment'] = 'Removed file {0}'.format(name)
ret['changes']['removed'] = name
return ret

View file

@ -1441,6 +1441,15 @@ def installed(
'result': True,
'comment': 'No packages to install provided'}
# If just a name (and optionally a version) is passed, just pack them into
# the pkgs argument.
if name and not any((pkgs, sources)):
if version:
pkgs = [{name: version}]
version = None
else:
pkgs = [name]
kwargs['saltenv'] = __env__
refresh = salt.utils.pkg.check_refresh(__opts__, refresh)
if not isinstance(pkg_verify, list):
@ -1607,7 +1616,7 @@ def installed(
if salt.utils.is_freebsd():
force = True # Downgrades need to be forced.
try:
pkg_ret = __salt__['pkg.install'](name,
pkg_ret = __salt__['pkg.install'](name=None,
refresh=refresh,
version=version,
force=force,

View file

@ -126,12 +126,14 @@ def _changes(name,
if shell and lusr['shell'] != shell:
change['shell'] = shell
if 'shadow.info' in __salt__ and 'shadow.default_hash' in __salt__:
if password:
if password and not empty_password:
default_hash = __salt__['shadow.default_hash']()
if lshad['passwd'] == default_hash \
or lshad['passwd'] != default_hash and enforce_password:
if lshad['passwd'] != password:
change['passwd'] = password
if empty_password and lshad['passwd'] != '':
change['empty_password'] = True
if date and date is not 0 and lshad['lstchg'] != date:
change['date'] = date
if mindays and mindays is not 0 and lshad['min'] != mindays:
@ -454,9 +456,6 @@ def present(name,
if gid_from_name:
gid = __salt__['file.group_to_gid'](name)
if empty_password:
__salt__['shadow.del_password'](name)
changes = _changes(name,
uid,
gid,
@ -510,6 +509,9 @@ def present(name,
if key == 'passwd' and empty_password:
log.warning("No password will be set when empty_password=True")
continue
if key == 'empty_password' and val:
__salt__['shadow.del_password'](name)
continue
if key == 'date':
__salt__['shadow.set_date'](name, date)
continue
@ -676,6 +678,14 @@ def present(name,
' {1}'.format(name, 'XXX-REDACTED-XXX')
ret['result'] = False
ret['changes']['password'] = 'XXX-REDACTED-XXX'
if empty_password and not password:
__salt__['shadow.del_password'](name)
spost = __salt__['shadow.info'](name)
if spost['passwd'] != '':
ret['comment'] = 'User {0} created but failed to ' \
'empty password'.format(name)
ret['result'] = False
ret['changes']['password'] = ''
if date:
__salt__['shadow.set_date'](name, date)
spost = __salt__['shadow.info'](name)

View file

@ -495,6 +495,7 @@ def container_setting(name, container, settings=None):
processModel.maxProcesses: 1
processModel.userName: TestUser
processModel.password: TestPassword
processModel.identityType: SpecificUser
Example of usage for the ``Sites`` container:

View file

@ -40,7 +40,7 @@ def _git_version():
git_version = subprocess.Popen(
['git', '--version'],
shell=False,
close_fds=False if salt.utils.is_windows else True,
close_fds=False if salt.utils.is_windows() else True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE).communicate()[0]
except OSError: