mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 08:58:59 +00:00
Merge branch '2015.5' of https://github.com/saltstack/salt into rabbitmq_vhost_states-unit-test
This commit is contained in:
commit
4bb6087722
@ -15,6 +15,14 @@ Description
|
||||
The salt-call command is used to run module functions locally on a minion
|
||||
instead of executing them from the master.
|
||||
|
||||
salt-call is used to run a :ref:`Standalone Minion <tutorial-standalone-minion>`,
|
||||
and was originally created for :ref:`troubleshooting <troubleshooting-minion-salt-call>`.
|
||||
Be aware that ``salt-call`` commands execute from the current user's shell
|
||||
context, while ``salt`` commands execute from the system's default context.
|
||||
|
||||
By default, the Salt Master is contacted to retrieve state files and other resources
|
||||
during execution unless the ``--local`` option is specified.:w
|
||||
|
||||
Options
|
||||
=======
|
||||
|
||||
|
@ -87,11 +87,6 @@ Execution Options
|
||||
for this influx of vm creation. When creating large groups of VMs watch the
|
||||
cloud provider carefully.
|
||||
|
||||
.. option:: -Q, --query
|
||||
|
||||
Execute a query and print out information about all cloud VMs. Can be used
|
||||
in conjunction with -m to display only information about the specified map.
|
||||
|
||||
.. option:: -u, --update-bootstrap
|
||||
|
||||
Update salt-bootstrap to the latest develop version on GitHub.
|
||||
|
@ -2432,3 +2432,15 @@ List of git repositories to include with the local repo.
|
||||
|
||||
win_gitrepos:
|
||||
- 'https://github.com/saltstack/salt-winrepo.git'
|
||||
|
||||
To specify a specific revision of the repository, preface the
|
||||
repository location with a commit ID:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
win_gitrepos:
|
||||
- '<commit_id> https://github.com/saltstack/salt-winrepo.git'
|
||||
|
||||
Replacing ``<commit_id>`` with the ID from GitHub. Specifying a commit
|
||||
ID is useful if you need to revert to a previous version if an error
|
||||
is introduced in the latest version.
|
||||
|
@ -289,6 +289,22 @@ executed. By default this feature is disabled, to enable set cache_jobs to
|
||||
|
||||
cache_jobs: False
|
||||
|
||||
.. conf_minion:: grains_cache
|
||||
|
||||
``grains_cache``
|
||||
----------------
|
||||
|
||||
Default: ``False``
|
||||
|
||||
The minion can locally cache grain data instead of refreshing the data
|
||||
each time the grain is referenced. By default this feature is disabled,
|
||||
to enable set grains_cache to ``True``.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
cache_jobs: False
|
||||
|
||||
|
||||
.. conf_minion:: sock_dir
|
||||
|
||||
``sock_dir``
|
||||
|
@ -24,6 +24,21 @@ The cp module is the home of minion side file server operations. The cp module
|
||||
is used by the Salt state system, salt-cp, and can be used to distribute files
|
||||
presented by the Salt file server.
|
||||
|
||||
Escaping Special Characters
|
||||
```````````````````````````
|
||||
|
||||
The ``salt://`` url format can potentially contain a query string, for example
|
||||
``salt://dir/file.txt?saltenv=base``. You can prevent the fileclient/fileserver from
|
||||
interpreting ``?`` as the initial token of a query string by referencing the file
|
||||
with ``salt://|`` rather than ``salt://``.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
/etc/marathon/conf/?checkpoint:
|
||||
file.managed:
|
||||
- source: salt://|hw/config/?checkpoint
|
||||
- makedirs: True
|
||||
|
||||
Environments
|
||||
````````````
|
||||
|
||||
|
@ -3,4 +3,4 @@ salt.modules.ipmi
|
||||
=================
|
||||
|
||||
.. automodule:: salt.modules.ipmi
|
||||
:members
|
||||
:members:
|
@ -63,6 +63,7 @@ Full list of builtin state modules
|
||||
influxdb_database
|
||||
influxdb_user
|
||||
ini_manage
|
||||
ipmi
|
||||
ipset
|
||||
iptables
|
||||
jboss7
|
||||
@ -142,6 +143,7 @@ Full list of builtin state modules
|
||||
sysrc
|
||||
test
|
||||
timezone
|
||||
tls
|
||||
tomcat
|
||||
user
|
||||
vbox_guest
|
||||
|
6
doc/ref/states/all/salt.states.ipmi.rst
Normal file
6
doc/ref/states/all/salt.states.ipmi.rst
Normal file
@ -0,0 +1,6 @@
|
||||
================
|
||||
salt.states.ipmi
|
||||
================
|
||||
|
||||
.. automodule:: salt.states.ipmi
|
||||
:members:
|
6
doc/ref/states/all/salt.states.tls.rst
Normal file
6
doc/ref/states/all/salt.states.tls.rst
Normal file
@ -0,0 +1,6 @@
|
||||
===============
|
||||
salt.states.tls
|
||||
===============
|
||||
|
||||
.. automodule:: salt.states.tls
|
||||
:members:
|
@ -173,6 +173,7 @@ Cloud Provider Specifics
|
||||
Getting Started With Rackspace <rackspace>
|
||||
Getting Started With SoftLayer <softlayer>
|
||||
Getting Started With Vexxhost <vexxhost>
|
||||
Getting Started With vSphere <vsphere>
|
||||
|
||||
|
||||
|
||||
|
121
doc/topics/cloud/vsphere.rst
Normal file
121
doc/topics/cloud/vsphere.rst
Normal file
@ -0,0 +1,121 @@
|
||||
============================
|
||||
Getting Started With vSphere
|
||||
============================
|
||||
|
||||
.. note::
|
||||
|
||||
.. deprecated:: Carbon
|
||||
|
||||
The :py:func:`vsphere <salt.cloud.clouds.vsphere>` cloud driver has been
|
||||
deprecated in favor of the :py:func:`vmware <salt.cloud.clouds.vmware>`
|
||||
cloud driver and will be removed in Salt Carbon. Please refer to
|
||||
:doc:`Getting started with VMware </topics/cloud/vmware>` instead to get
|
||||
started with the configuration.
|
||||
|
||||
VMware vSphere is a management platform for virtual infrastructure and cloud
|
||||
computing.
|
||||
|
||||
|
||||
Dependencies
|
||||
============
|
||||
The vSphere module for Salt Cloud requires the PySphere package, which is
|
||||
available at PyPI:
|
||||
|
||||
https://pypi.python.org/pypi/pysphere
|
||||
|
||||
This package can be installed using `pip` or `easy_install`:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# pip install pysphere
|
||||
# easy_install pysphere
|
||||
|
||||
|
||||
Configuration
|
||||
=============
|
||||
Set up the cloud config at ``/etc/salt/cloud.providers`` or in the
|
||||
``/etc/salt/cloud.providers.d/`` directory:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
my-vsphere-config:
|
||||
provider: vsphere
|
||||
# Set the vSphere access credentials
|
||||
user: marco
|
||||
password: polo
|
||||
# Set the URL of your vSphere server
|
||||
url: 'vsphere.example.com'
|
||||
|
||||
|
||||
Profiles
|
||||
========
|
||||
|
||||
Cloud Profiles
|
||||
~~~~~~~~~~~~~~
|
||||
vSphere uses a Managed Object Reference to identify objects located in vCenter.
|
||||
The MOR ID's are used when configuring a vSphere cloud profile. Use the
|
||||
following reference when locating the MOR's for the cloud profile.
|
||||
|
||||
http://kb.vmware.com/selfservice/microsites/search.do?cmd=displayKC&docType=kc&externalId=1017126&sliceId=1&docTypeID=DT_KB_1_1&dialogID=520386078&stateId=1%200%20520388386
|
||||
|
||||
Set up an initial profile at ``/etc/salt/cloud.profiles`` or in the
|
||||
``/etc/salt/cloud.profiles.d`` directory:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
vsphere-centos:
|
||||
provider: my-vsphere-config
|
||||
image: centos
|
||||
# Optional
|
||||
datastore: datastore-15
|
||||
resourcepool: resgroup-8
|
||||
folder: salt-cloud
|
||||
host: host-9
|
||||
template: False
|
||||
|
||||
|
||||
provider
|
||||
--------
|
||||
Enter the name that was specified when the cloud provider profile was created.
|
||||
|
||||
image
|
||||
-----
|
||||
Images available to build an instance can be found using the `--list-images`
|
||||
option:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# salt-cloud --list-images my-vsphere-config
|
||||
|
||||
datastore
|
||||
---------
|
||||
The MOR of the datastore where the virtual machine should be located. If not
|
||||
specified, the current datastore is used.
|
||||
|
||||
resourcepool
|
||||
------------
|
||||
The MOR of the resourcepool to be used for the new vm. If not set, it will use
|
||||
the same resourcepool as the original vm.
|
||||
|
||||
folder
|
||||
------
|
||||
Name of the folder that will contain the new VM. If not set, the VM will be
|
||||
added to the folder the original VM belongs to.
|
||||
|
||||
host
|
||||
----
|
||||
The MOR of the host where the vm should be registered.
|
||||
|
||||
If not specified:
|
||||
* if resourcepool is not specified, the current host is used.
|
||||
* if resourcepool is specified, and the target pool represents a
|
||||
stand-alone host, the host is used.
|
||||
* if resourcepool is specified, and the target pool represents a
|
||||
DRS-enabled cluster, a host selected by DRS is used.
|
||||
* if resourcepool is specified, and the target pool represents a
|
||||
cluster without DRS enabled, an InvalidArgument exception will be thrown.
|
||||
|
||||
template
|
||||
--------
|
||||
Specifies whether or not the new virtual machine should be marked as a
|
||||
template. Default is False.
|
@ -1,6 +1,8 @@
|
||||
===================
|
||||
.. _external-pillars:
|
||||
|
||||
================
|
||||
External Pillars
|
||||
===================
|
||||
================
|
||||
|
||||
Salt provides a mechanism for generating pillar data by calling external
|
||||
pillar interfaces. This document will describe an outline of an ext_pillar
|
||||
|
@ -44,6 +44,7 @@ minion exe>` should match the contents of the corresponding md5 file.
|
||||
* Salt-Minion-2014.7.0-1-win32-Setup.exe | md5
|
||||
* Salt-Minion-2014.7.0-AMD64-Setup.exe | md5
|
||||
.. note::
|
||||
|
||||
The 2014.7.0 installers have been removed because of a regression. Please use the 2014.7.1 release instead.
|
||||
|
||||
* 2014.1.13
|
||||
|
@ -66,6 +66,8 @@ check that no additional access control system such as `SELinux`_ or
|
||||
.. _`SELinux`: https://en.wikipedia.org/wiki/Security-Enhanced_Linux
|
||||
.. _`AppArmor`: http://wiki.apparmor.net/index.php/Main_Page
|
||||
|
||||
.. _troubleshooting-minion-salt-call:
|
||||
|
||||
Using salt-call
|
||||
===============
|
||||
|
||||
|
@ -34,9 +34,9 @@ Variables:
|
||||
minions can be defined in pillar and then accessed inside sls formulas
|
||||
and template files.
|
||||
Arbitrary Data:
|
||||
Pillar can contain any basic data structure, so a list of values, or a
|
||||
key/value store can be defined making it easy to iterate over a group
|
||||
of values in sls formulas
|
||||
Pillar can contain any basic data structure in dictionary format,
|
||||
so a key/value store can be defined making it easy to iterate over a group
|
||||
of values in sls formulas.
|
||||
|
||||
Pillar is therefore one of the most important systems when using Salt. This
|
||||
walkthrough is designed to get a simple Pillar up and running in a few minutes
|
||||
@ -309,12 +309,6 @@ line:
|
||||
|
||||
salt '*' state.sls my_sls_file pillar='{"hello": "world"}'
|
||||
|
||||
Lists can be passed in pillar as well:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' state.highstate pillar='["foo", "bar", "baz"]'
|
||||
|
||||
.. note::
|
||||
|
||||
If a key is passed on the command line that already exists on the minion,
|
||||
|
@ -1,3 +1,5 @@
|
||||
.. _tutorial-standalone-minion:
|
||||
|
||||
=================
|
||||
Standalone Minion
|
||||
=================
|
||||
@ -78,3 +80,9 @@ it unnecessary to change the configuration file:
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call state.highstate --local
|
||||
|
||||
External Pillars
|
||||
================
|
||||
|
||||
:ref:`External pillars <external-pillars>` are supported when running in masterless mode.
|
||||
|
||||
|
@ -178,8 +178,8 @@ and all changes made.
|
||||
salt-minion -l debug
|
||||
|
||||
Run the minion in the foreground
|
||||
By not starting the minion in daemon mode (:option:`-d <salt-minion
|
||||
-d>`) one can view any output from the minion as it works:
|
||||
By not starting the minion in daemon mode (:option:`-d <salt-minion -d>`)
|
||||
one can view any output from the minion as it works:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
@ -84,6 +84,7 @@ def beacon(config):
|
||||
|
||||
The mask list can contain the following events (the default mask is create,
|
||||
delete, and modify):
|
||||
|
||||
* access File accessed
|
||||
* attrib File metadata changed
|
||||
* close_nowrite Unwritable file closed
|
||||
@ -98,6 +99,7 @@ def beacon(config):
|
||||
* open File opened
|
||||
|
||||
The mask can also contain the following options:
|
||||
|
||||
* dont_follow Don't dereference symbolic links
|
||||
* excl_unlink Omit events for children after they have been unlinked
|
||||
* oneshot Remove watch after one event
|
||||
|
@ -139,10 +139,10 @@ class Batch(object):
|
||||
for ping_ret in self.ping_gen:
|
||||
if ping_ret is None:
|
||||
break
|
||||
if ping_ret not in self.minions:
|
||||
self.minions.append(ping_ret)
|
||||
to_run.append(ping_ret)
|
||||
|
||||
m = next(ping_ret.iterkeys())
|
||||
if m not in self.minions:
|
||||
self.minions.append(m)
|
||||
to_run.append(m)
|
||||
for queue in iters:
|
||||
try:
|
||||
# Gather returns until we get to the bottom
|
||||
|
@ -13,6 +13,7 @@ class SaltSSH(parsers.SaltSSHOptionParser):
|
||||
|
||||
def run(self):
|
||||
self.parse_args()
|
||||
self.setup_logfile_logger()
|
||||
|
||||
ssh = salt.client.ssh.SSH(self.config)
|
||||
ssh.run()
|
||||
|
@ -3,7 +3,15 @@
|
||||
vSphere Cloud Module
|
||||
====================
|
||||
|
||||
.. versionadded:: 2014.7.0
|
||||
.. note::
|
||||
|
||||
.. deprecated:: Carbon
|
||||
|
||||
The :py:func:`vsphere <salt.cloud.clouds.vsphere>` cloud driver has been
|
||||
deprecated in favor of the :py:func:`vmware <salt.cloud.clouds.vmware>`
|
||||
cloud driver and will be removed in Salt Carbon. Please refer to
|
||||
:doc:`Getting started with VMware </topics/cloud/vmware>` to get started
|
||||
and convert your vsphere provider configurations to use the vmware driver.
|
||||
|
||||
The vSphere cloud module is used to control access to VMWare vSphere.
|
||||
|
||||
@ -76,6 +84,7 @@ import time
|
||||
import salt.utils.cloud
|
||||
import salt.utils.xmlutil
|
||||
from salt.exceptions import SaltCloudSystemExit
|
||||
from salt.utils import warn_until
|
||||
|
||||
# Import salt cloud libs
|
||||
import salt.config as config
|
||||
@ -110,6 +119,11 @@ def get_configured_provider():
|
||||
'''
|
||||
Return the first configured instance.
|
||||
'''
|
||||
warn_until(
|
||||
'Carbon',
|
||||
'The vsphere driver is deprecated in favor of the vmware driver and will be removed '
|
||||
'in Salt Carbon. Please convert your vsphere provider configs to use the vmware driver.'
|
||||
)
|
||||
return config.is_provider_configured(
|
||||
__opts__,
|
||||
__active_provider_name__ or 'vsphere',
|
||||
|
@ -795,7 +795,8 @@ class Minion(MinionBase):
|
||||
' {0}'.format(opts['master']))
|
||||
if opts['master_shuffle']:
|
||||
shuffle(opts['master'])
|
||||
elif isinstance(opts['master'], str):
|
||||
# if opts['master'] is a str and we have never created opts['master_list']
|
||||
elif isinstance(opts['master'], str) and ('master_list' not in opts):
|
||||
# We have a string, but a list was what was intended. Convert.
|
||||
# See issue 23611 for details
|
||||
opts['master'] = list(opts['master'])
|
||||
|
@ -1249,13 +1249,18 @@ def get_repo(repo, **kwargs):
|
||||
ppa_name, dist)
|
||||
else:
|
||||
if HAS_SOFTWAREPROPERTIES:
|
||||
try:
|
||||
if hasattr(softwareproperties.ppa, 'PPAShortcutHandler'):
|
||||
repo = softwareproperties.ppa.PPAShortcutHandler(repo).expand(
|
||||
__grains__['lsb_distrib_codename'])[0]
|
||||
repo = softwareproperties.ppa.PPAShortcutHandler(
|
||||
repo).expand(dist)[0]
|
||||
else:
|
||||
repo = softwareproperties.ppa.expand_ppa_line(
|
||||
repo,
|
||||
__grains__['lsb_distrib_codename'])[0]
|
||||
dist)[0]
|
||||
except NameError as name_error:
|
||||
raise CommandExecutionError(
|
||||
'Could not find ppa {0}: {1}'.format(repo, name_error)
|
||||
)
|
||||
else:
|
||||
repo = LP_SRC_FORMAT.format(owner_name, ppa_name, dist)
|
||||
|
||||
|
@ -647,6 +647,7 @@ def list_permissions(username=None, resource=None, resource_type='keyspace', per
|
||||
:rtype: dict
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'minion1' cassandra_cql.list_permissions
|
||||
|
||||
salt 'minion1' cassandra_cql.list_permissions username=joe resource=test_keyspace permission=select
|
||||
@ -702,6 +703,7 @@ def grant_permission(username, resource=None, resource_type='keyspace', permissi
|
||||
:rtype:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'minion1' cassandra_cql.grant_permission
|
||||
|
||||
salt 'minion1' cassandra_cql.grant_permission username=joe resource=test_keyspace permission=select
|
||||
|
@ -579,8 +579,9 @@ def run(cmd,
|
||||
Note that ``env`` represents the environment variables for the command, and
|
||||
should be formatted as a dict, or a YAML string which resolves to a dict.
|
||||
|
||||
*************************************************************************
|
||||
WARNING: This function does not process commands through a shell
|
||||
.. warning::
|
||||
|
||||
This function does not process commands through a shell
|
||||
unless the python_shell flag is set to True. This means that any
|
||||
shell-specific functionality such as 'echo' or the use of pipes,
|
||||
redirection or &&, should either be migrated to cmd.shell or
|
||||
@ -590,7 +591,6 @@ def run(cmd,
|
||||
including potentially malicious commands such as 'good_command;rm -rf /'.
|
||||
Be absolutely certain that you have sanitized your input prior to using
|
||||
python_shell=True
|
||||
*************************************************************************
|
||||
|
||||
CLI Example:
|
||||
|
||||
@ -707,12 +707,12 @@ def shell(cmd,
|
||||
|
||||
.. versionadded:: 2015.5.0
|
||||
|
||||
************************************************************
|
||||
WARNING: This passes the cmd argument directly to the shell
|
||||
.. warning ::
|
||||
|
||||
This passes the cmd argument directly to the shell
|
||||
without any further processing! Be absolutely sure that you
|
||||
have properly santized the command passed to this function
|
||||
and do not use untrusted inputs.
|
||||
************************************************************
|
||||
|
||||
Note that ``env`` represents the environment variables for the command, and
|
||||
should be formatted as a dict, or a YAML string which resolves to a dict.
|
||||
|
@ -563,7 +563,8 @@ def create_container(image,
|
||||
volumes_from=None,
|
||||
name=None,
|
||||
cpu_shares=None,
|
||||
cpuset=None):
|
||||
cpuset=None,
|
||||
binds=None):
|
||||
'''
|
||||
Create a new container
|
||||
|
||||
@ -582,10 +583,26 @@ def create_container(image,
|
||||
ports
|
||||
port redirections ``({'222': {}})``
|
||||
volumes
|
||||
list of volume mappings::
|
||||
list of volume mappings in either local volume, bound volume, or read-only
|
||||
bound volume form::
|
||||
|
||||
(['/mountpoint/in/container:/guest/foo', '/same/path/mounted/point'])
|
||||
(['/var/lib/mysql/', '/usr/local/etc/ssl:/etc/ssl', '/etc/passwd:/etc/passwd:ro'])
|
||||
binds
|
||||
complete dictionary of bound volume mappings::
|
||||
|
||||
{ '/usr/local/etc/ssl/certs/internal.crt': {
|
||||
'bind': '/etc/ssl/certs/com.example.internal.crt',
|
||||
'ro': True
|
||||
},
|
||||
'/var/lib/mysql': {
|
||||
'bind': '/var/lib/mysql/',
|
||||
'ro': False
|
||||
}
|
||||
}
|
||||
|
||||
This dictionary is suitable for feeding directly into the Docker API, and all
|
||||
keys are required.
|
||||
(see http://docker-py.readthedocs.org/en/latest/volumes/)
|
||||
tty
|
||||
attach ttys, Default is ``False``
|
||||
stdin_open
|
||||
@ -604,23 +621,31 @@ def create_container(image,
|
||||
salt '*' docker.create_container o/ubuntu volumes="['/s','/m:/f']"
|
||||
|
||||
'''
|
||||
log.trace("modules.dockerio.create_container() called for image " + image)
|
||||
status = base_status.copy()
|
||||
client = _get_client()
|
||||
try:
|
||||
mountpoints = {}
|
||||
binds = {}
|
||||
# create empty mountpoints for them to be
|
||||
# editable
|
||||
# either we have a list of guest or host:guest
|
||||
|
||||
# In order to permit specification of bind volumes in the volumes field,
|
||||
# we'll look through it for bind-style specs and move them. This is purely
|
||||
# for CLI convenience and backwards-compatibility, as states.dockerio
|
||||
# should parse volumes before this, and the binds argument duplicates this.
|
||||
# N.B. this duplicates code in states.dockerio._parse_volumes()
|
||||
if isinstance(volumes, list):
|
||||
for mountpoint in volumes:
|
||||
mounted = mountpoint
|
||||
if ':' in mountpoint:
|
||||
parts = mountpoint.split(':')
|
||||
mountpoint = parts[1]
|
||||
mounted = parts[0]
|
||||
mountpoints[mountpoint] = {}
|
||||
binds[mounted] = mountpoint
|
||||
for volume in volumes:
|
||||
if ':' in volume:
|
||||
volspec = volume.split(':')
|
||||
source = volspec[0]
|
||||
target = volspec[1]
|
||||
ro = False
|
||||
try:
|
||||
if len(volspec) > 2:
|
||||
ro = volspec[2] == "ro"
|
||||
except IndexError:
|
||||
pass
|
||||
binds[source] = {'bind': target, 'ro': ro}
|
||||
volumes.remove(volume)
|
||||
|
||||
try:
|
||||
container_info = client.create_container(
|
||||
image=image,
|
||||
command=command,
|
||||
@ -633,12 +658,14 @@ def create_container(image,
|
||||
ports=ports,
|
||||
environment=environment,
|
||||
dns=dns,
|
||||
volumes=mountpoints,
|
||||
volumes=volumes,
|
||||
volumes_from=volumes_from,
|
||||
name=name,
|
||||
cpu_shares=cpu_shares,
|
||||
cpuset=cpuset
|
||||
cpuset=cpuset,
|
||||
host_config=docker.utils.create_host_config(binds=binds)
|
||||
)
|
||||
log.trace("docker.client.create_container returned: " + str(container_info))
|
||||
container = container_info['Id']
|
||||
callback = _valid
|
||||
comment = 'Container created'
|
||||
@ -648,8 +675,9 @@ def create_container(image,
|
||||
}
|
||||
__salt__['mine.send']('docker.get_containers', host=True)
|
||||
return callback(status, id_=container, comment=comment, out=out)
|
||||
except Exception:
|
||||
except Exception, e:
|
||||
_invalid(status, id_=image, out=traceback.format_exc())
|
||||
raise e
|
||||
__salt__['mine.send']('docker.get_containers', host=True)
|
||||
return status
|
||||
|
||||
|
@ -590,9 +590,7 @@ def import_key(user=None,
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' gpg.import_key text='-----BEGIN PGP PUBLIC KEY BLOCK-----\n ... -----END PGP PUBLIC KEY BLOCK-----'
|
||||
|
||||
salt '*' gpg.import_key filename='/path/to/public-key-file'
|
||||
|
||||
'''
|
||||
ret = {
|
||||
'res': True,
|
||||
@ -749,7 +747,6 @@ def trust_key(keyid=None,
|
||||
salt '*' gpg.trust_key fingerprint='53C96788253E58416D20BCD352952C84C3252192' trust_level='not_trusted'
|
||||
|
||||
salt '*' gpg.trust_key keys=3FAD9F1E trust_level='ultimately' user='username'
|
||||
|
||||
'''
|
||||
ret = {
|
||||
'res': True,
|
||||
|
@ -123,16 +123,18 @@ def shadow_hash(crypt_salt=None, password=None, algorithm='sha512'):
|
||||
|
||||
def rand_int(start=1, end=10):
|
||||
'''
|
||||
.. versionadded: 2015.5.3
|
||||
|
||||
Returns a random integer number between the start and end number.
|
||||
|
||||
.. versionadded: 2015.5.3
|
||||
|
||||
start : 1
|
||||
Any valid integer number
|
||||
|
||||
end : 10
|
||||
Any valid integer number
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' random.rand_int 1 10
|
||||
|
@ -687,7 +687,7 @@ def mount(name, device, mkmnt=False, fstype='', opts='defaults', user=None):
|
||||
opts = opts.split(',')
|
||||
|
||||
if not os.path.exists(name) and mkmnt:
|
||||
__salt__['file.mkdir'](name=name, user=user)
|
||||
__salt__['file.mkdir'](name, user=user)
|
||||
|
||||
args = ''
|
||||
if opts is not None:
|
||||
|
@ -1,11 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
:requires: libnacl
|
||||
https://github.com/saltstack/libnacl
|
||||
|
||||
This module helps include encrypted passwords in pillars, grains and salt state files.
|
||||
This is often usefull if you wish to store your pillars in source control or
|
||||
share your pillar data with others that you trust. I dont advise making your pillars public
|
||||
|
||||
:depends: libnacl, https://github.com/saltstack/libnacl
|
||||
|
||||
This is often useful if you wish to store your pillars in source control or
|
||||
share your pillar data with others that you trust. I don't advise making your pillars public
|
||||
regardless if they are encrypted or not.
|
||||
|
||||
When generating keys and encrypting passwords use --local when using salt-call for extra
|
||||
@ -14,20 +14,28 @@ security. Also consider using just the salt runner nacl when encrypting pillar p
|
||||
The nacl lib uses 32byte keys, these keys are base64 encoded to make your life more simple.
|
||||
To generate your `key` or `keyfile` you can use:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call --local nacl.keygen keyfile=/root/.nacl
|
||||
|
||||
Now with your key, you can encrypt some data
|
||||
Now with your key, you can encrypt some data:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call --local nacl.enc mypass keyfile=/root/.nacl
|
||||
DRB7Q6/X5gGSRCTpZyxS6hXO5LnlJIIJ4ivbmUlbWj0llUA+uaVyvou3vJ4=
|
||||
|
||||
To decrypt the data
|
||||
To decrypt the data:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call --local nacl.dec data='DRB7Q6/X5gGSRCTpZyxS6hXO5LnlJIIJ4ivbmUlbWj0llUA+uaVyvou3vJ4=' keyfile=/root/.nacl
|
||||
mypass
|
||||
|
||||
The following optional configurations can be defined in the
|
||||
minion or master config. Avoide storeing the config in pillars!
|
||||
minion or master config. Avoid storing the config in pillars!
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
cat /etc/salt/master.d/nacl.conf
|
||||
nacl.config:
|
||||
@ -36,15 +44,21 @@ minion or master config. Avoide storeing the config in pillars!
|
||||
|
||||
When the key is defined in the master config you can use it from the nacl runner:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-run nacl.enc 'myotherpass'
|
||||
|
||||
Now you can create a pillar with protected data like:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
pillarexample:
|
||||
user: root
|
||||
password: {{ salt.nacl.dec('DRB7Q6/X5gGSRCTpZyxS6hXO5LnlJIIJ4ivbmUlbWj0llUA+uaVyvou3vJ4=') }}
|
||||
|
||||
Or do somthing interesting with grains like:
|
||||
Or do something interesting with grains like:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
salt-call nacl.enc minionname:dbrole
|
||||
AL24Z2C5OlkReer3DuQTFdrNLchLuz3NGIhGjZkLtKRYry/b/CksWM8O9yskLwH2AGVLoEXI5jAa
|
||||
|
@ -119,6 +119,11 @@ def install(pkg=None,
|
||||
elif pkgs:
|
||||
cmd += ' "{0}"'.format('" "'.join(pkgs))
|
||||
|
||||
if runas:
|
||||
uid = salt.utils.get_uid(runas)
|
||||
if uid:
|
||||
env.update({'SUDO_UID': uid, 'SUDO_USER': ''})
|
||||
|
||||
result = __salt__['cmd.run_all'](cmd, python_shell=False, cwd=dir, runas=runas, env=env)
|
||||
|
||||
if result['retcode'] != 0:
|
||||
@ -151,7 +156,8 @@ def install(pkg=None,
|
||||
|
||||
def uninstall(pkg,
|
||||
dir=None,
|
||||
runas=None):
|
||||
runas=None,
|
||||
env=None):
|
||||
'''
|
||||
Uninstall an NPM package.
|
||||
|
||||
@ -167,6 +173,13 @@ def uninstall(pkg,
|
||||
runas
|
||||
The user to run NPM with
|
||||
|
||||
env
|
||||
Environment variables to set when invoking npm. Uses the same ``env``
|
||||
format as the :py:func:`cmd.run <salt.modules.cmdmod.run>` execution
|
||||
function.
|
||||
|
||||
.. versionadded:: 2015.5.3
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
@ -175,6 +188,11 @@ def uninstall(pkg,
|
||||
|
||||
'''
|
||||
|
||||
if runas:
|
||||
uid = salt.utils.get_uid(runas)
|
||||
if uid:
|
||||
env.update({'SUDO_UID': uid, 'SUDO_USER': ''})
|
||||
|
||||
cmd = 'npm uninstall'
|
||||
|
||||
if dir is None:
|
||||
@ -182,7 +200,7 @@ def uninstall(pkg,
|
||||
|
||||
cmd += ' "{0}"'.format(pkg)
|
||||
|
||||
result = __salt__['cmd.run_all'](cmd, python_shell=False, cwd=dir, runas=runas)
|
||||
result = __salt__['cmd.run_all'](cmd, python_shell=False, cwd=dir, runas=runas, env=env)
|
||||
|
||||
if result['retcode'] != 0:
|
||||
log.error(result['stderr'])
|
||||
@ -227,6 +245,11 @@ def list_(pkg=None,
|
||||
|
||||
'''
|
||||
|
||||
if runas:
|
||||
uid = salt.utils.get_uid(runas)
|
||||
if uid:
|
||||
env.update({'SUDO_UID': uid, 'SUDO_USER': ''})
|
||||
|
||||
cmd = 'npm list --silent --json'
|
||||
|
||||
if dir is None:
|
||||
|
@ -225,11 +225,13 @@ def enable():
|
||||
def disable(message=None):
|
||||
'''
|
||||
.. versionadded:: 2014.7.0
|
||||
|
||||
Disable the puppet agent
|
||||
|
||||
message
|
||||
.. versionadded:: 2015.5.2
|
||||
disable message to send to puppet
|
||||
|
||||
Disable message to send to puppet
|
||||
|
||||
CLI Example:
|
||||
|
||||
@ -237,7 +239,6 @@ def disable(message=None):
|
||||
|
||||
salt '*' puppet.disable
|
||||
salt '*' puppet.disable 'disabled for a good reason'
|
||||
|
||||
'''
|
||||
|
||||
_check_puppet()
|
||||
|
@ -681,10 +681,9 @@ def generateBlobs(api_key=None,
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' get_intergers number=5 min=1 max=6
|
||||
|
||||
salt '*' get_intergers number=5 min=1 max=6
|
||||
salt '*' get_integers number=5 min=1 max=6
|
||||
|
||||
salt '*' get_integers number=5 min=1 max=6
|
||||
'''
|
||||
ret = {'res': True}
|
||||
|
||||
|
@ -1,6 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Control the state system on the minion
|
||||
Control the state system on the minion.
|
||||
|
||||
State Caching
|
||||
-------------
|
||||
|
||||
When a highstate is called, the minion automatically caches a copy of the last high data.
|
||||
If you then run a highstate with cache=True it will use that cached highdata and won't hit the fileserver.
|
||||
'''
|
||||
from __future__ import absolute_import
|
||||
|
||||
|
@ -52,8 +52,7 @@ def _call_system_profiler(datatype):
|
||||
def receipts():
|
||||
'''
|
||||
Return the results of a call to
|
||||
`system_profiler -xml -detail full
|
||||
SPInstallHistoryDataType`
|
||||
``system_profiler -xml -detail full SPInstallHistoryDataType``
|
||||
as a dictionary. Top-level keys of the dictionary
|
||||
are the names of each set of install receipts, since
|
||||
there can be multiple receipts with the same name.
|
||||
@ -93,12 +92,11 @@ def receipts():
|
||||
def applications():
|
||||
'''
|
||||
Return the results of a call to
|
||||
`system_profiler -xml -detail full
|
||||
SPApplicationsDataType`
|
||||
``system_profiler -xml -detail full SPApplicationsDataType``
|
||||
as a dictionary. Top-level keys of the dictionary
|
||||
are the names of each set of install receipts, since
|
||||
there can be multiple receipts with the same name.
|
||||
Contents of each key are a list of dicttionaries.
|
||||
Contents of each key are a list of dictionaries.
|
||||
|
||||
Note that this can take a long time depending on how many
|
||||
applications are installed on the target Mac.
|
||||
|
@ -7,7 +7,8 @@ A REST API for Salt
|
||||
|
||||
.. py:currentmodule:: salt.netapi.rest_cherrypy.app
|
||||
|
||||
:depends: - CherryPy Python module. Versions 3.2.{2,3,4} are strongly
|
||||
:depends:
|
||||
- CherryPy Python module. Versions 3.2.{2,3,4} are strongly
|
||||
recommended due to a known `SSL error
|
||||
<https://bitbucket.org/cherrypy/cherrypy/issue/1298/ssl-not-working>`_
|
||||
introduced in version 3.2.5. The issue was reportedly resolved with
|
||||
@ -16,7 +17,8 @@ A REST API for Salt
|
||||
:client_libraries:
|
||||
- Java: https://github.com/SUSE/saltstack-netapi-client-java
|
||||
- Python: https://github.com/saltstack/pepper
|
||||
:configuration: All authentication is done through Salt's :ref:`external auth
|
||||
:configuration:
|
||||
All authentication is done through Salt's :ref:`external auth
|
||||
<acl-eauth>` system which requires additional configuration not described
|
||||
here.
|
||||
|
||||
|
@ -84,6 +84,7 @@ There is also the option of specifying a dynamic inventory, and generating it on
|
||||
This is the format that an inventory script needs to output to work with ansible, and thus here.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
[~]# salt-ssh --roster-file /etc/salt/hosts salt.gtmanfred.com test.ping
|
||||
salt.gtmanfred.com:
|
||||
True
|
||||
|
@ -349,7 +349,7 @@ def lock(backend=None, remote=None):
|
||||
.. note::
|
||||
|
||||
This will only operate on enabled backends (those configured in
|
||||
:master_conf:`fileserver_backend`).
|
||||
:conf_master:`fileserver_backend`).
|
||||
|
||||
backend
|
||||
Only set the update lock for the specified backend(s).
|
||||
|
@ -19,7 +19,7 @@ def query(url, output=True, **kwargs):
|
||||
'''
|
||||
Query a resource, and decode the return data
|
||||
|
||||
.. versionaddedd:: 2015.2
|
||||
.. versionadded:: 2015.5.0
|
||||
|
||||
CLI Example:
|
||||
|
||||
@ -44,7 +44,7 @@ def update_ca_bundle(target=None, source=None, merge_files=None):
|
||||
'''
|
||||
Update the local CA bundle file from a URL
|
||||
|
||||
.. versionaddedd:: 2015.2
|
||||
.. versionadded:: 2015.5.0
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -74,6 +74,7 @@ Available Functions
|
||||
my_service:
|
||||
docker.running:
|
||||
- container: mysuperdocker
|
||||
- image: corp/mysuperdocker_img
|
||||
- port_bindings:
|
||||
"5000/tcp":
|
||||
HostIp: ""
|
||||
@ -184,6 +185,103 @@ def _invalid(exec_status=None, name='', comment='', changes=None):
|
||||
result=False)
|
||||
|
||||
|
||||
def _parse_volumes(volumes):
|
||||
'''
|
||||
Parse a given volumes state specification for later use in
|
||||
modules.docker.create_container(). This produces a dict that can be directly
|
||||
consumed by the Docker API /containers/create.
|
||||
|
||||
Note: this only really exists for backwards-compatibility, and because
|
||||
modules.dockerio.start() currently takes a binds argument.
|
||||
|
||||
volumes
|
||||
A structure containing information about the volumes to be included in the
|
||||
container that will be created, either:
|
||||
- a bare dictionary
|
||||
- a list of dictionaries and lists
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# bare dict style
|
||||
- volumes:
|
||||
/usr/local/etc/ssl/certs/example.crt:
|
||||
bind: /etc/ssl/certs/com.example.internal.crt
|
||||
ro: True
|
||||
/var/run:
|
||||
bind: /var/run/host/
|
||||
ro: False
|
||||
|
||||
# list of dicts style:
|
||||
- volumes:
|
||||
- /usr/local/etc/ssl/certs/example.crt:
|
||||
bind: /etc/ssl/certs/com.example.internal.crt
|
||||
ro: True
|
||||
- /var/run: /var/run/host/ # read-write bound volume
|
||||
- /var/lib/mysql # un-bound, container-only volume
|
||||
|
||||
note: bind mounts specified like "/etc/timezone:/tmp/host_tz" will fall
|
||||
through this parser.
|
||||
|
||||
Returns a dict of volume specifications:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
{
|
||||
'bindvols': {
|
||||
'/usr/local/etc/ssl/certs/example.crt': {
|
||||
'bind': '/etc/ssl/certs/com.example.internal.crt',
|
||||
'ro': True
|
||||
},
|
||||
'/var/run/': {
|
||||
'bind': '/var/run/host',
|
||||
'ro': False
|
||||
},
|
||||
},
|
||||
'contvols': [ '/var/lib/mysql/' ]
|
||||
}
|
||||
|
||||
'''
|
||||
log.trace("Parsing given volumes dict: " + str(volumes))
|
||||
bindvolumes = {}
|
||||
contvolumes = []
|
||||
if isinstance(volumes, dict):
|
||||
# If volumes as a whole is a dict, then there's no way to specify a non-bound volume
|
||||
# so we exit early and assume the dict is properly formed.
|
||||
bindvolumes = volumes
|
||||
if isinstance(volumes, list):
|
||||
for vol in volumes:
|
||||
if isinstance(vol, dict):
|
||||
for volsource, voldef in vol.items():
|
||||
if isinstance(voldef, dict):
|
||||
target = voldef['bind']
|
||||
read_only = voldef.get('ro', False)
|
||||
else:
|
||||
target = str(voldef)
|
||||
read_only = False
|
||||
source = volsource
|
||||
else: # isinstance(vol, dict)
|
||||
if ':' in vol:
|
||||
volspec = vol.split(':')
|
||||
source = volspec[0]
|
||||
target = volspec[1]
|
||||
read_only = False
|
||||
try:
|
||||
if len(volspec) > 2:
|
||||
read_only = volspec[2] == "ro"
|
||||
except IndexError:
|
||||
pass
|
||||
else:
|
||||
contvolumes.append(str(vol))
|
||||
continue
|
||||
bindvolumes[source] = {
|
||||
'bind': target,
|
||||
'ro': read_only
|
||||
}
|
||||
result = {'bindvols': bindvolumes, 'contvols': contvolumes}
|
||||
log.trace("Finished parsing volumes, with result: " + str(result))
|
||||
return result
|
||||
|
||||
|
||||
def mod_watch(name, sfun=None, *args, **kw):
|
||||
if sfun == 'built':
|
||||
# Needs to refresh the image
|
||||
@ -479,7 +577,7 @@ def installed(name,
|
||||
- a port to map
|
||||
- a mapping of mapping portInHost : PortInContainer
|
||||
volumes
|
||||
List of volumes
|
||||
List of volumes (see notes for the running function)
|
||||
|
||||
For other parameters, see absolutely first the salt.modules.dockerio
|
||||
execution module and the docker-py python bindings for docker
|
||||
@ -502,7 +600,7 @@ def installed(name,
|
||||
# if container exists but is not started, try to start it
|
||||
if already_exists:
|
||||
return _valid(comment='image {0!r} already exists'.format(name))
|
||||
dports, dvolumes, denvironment = {}, [], {}
|
||||
dports, denvironment = {}, {}
|
||||
if not ports:
|
||||
ports = []
|
||||
if not volumes:
|
||||
@ -521,15 +619,13 @@ def installed(name,
|
||||
else:
|
||||
for k in p:
|
||||
dports[str(p)] = {}
|
||||
for p in volumes:
|
||||
vals = []
|
||||
if not isinstance(p, dict):
|
||||
vals.append('{0}'.format(p))
|
||||
else:
|
||||
for k in p:
|
||||
vals.append('{0}:{1}'.format(k, p[k]))
|
||||
dvolumes.extend(vals)
|
||||
|
||||
parsed_volumes = _parse_volumes(volumes)
|
||||
bindvolumes = parsed_volumes['bindvols']
|
||||
contvolumes = parsed_volumes['contvols']
|
||||
|
||||
a, kw = [image], dict(
|
||||
binds=bindvolumes,
|
||||
command=command,
|
||||
hostname=hostname,
|
||||
user=user,
|
||||
@ -540,7 +636,7 @@ def installed(name,
|
||||
ports=dports,
|
||||
environment=denvironment,
|
||||
dns=dns,
|
||||
volumes=dvolumes,
|
||||
volumes=contvolumes,
|
||||
volumes_from=volumes_from,
|
||||
name=name,
|
||||
cpu_shares=cpu_shares,
|
||||
@ -799,44 +895,47 @@ def running(name,
|
||||
volumes
|
||||
List of volumes to mount or create in the container (like ``-v`` of ``docker run`` command),
|
||||
mapping host directory to container directory.
|
||||
To create a volume in the container:
|
||||
|
||||
To specify a volume in the container in terse list format:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
- volumes:
|
||||
- "/var/log/service"
|
||||
- "/var/log/service" # container-only volume
|
||||
- "/srv/timezone:/etc/timezone" # bound volume
|
||||
- "/usr/local/etc/passwd:/etc/passwd:ro" # read-only bound volume
|
||||
|
||||
For read-write mounting, use the short form (note that the notion of
|
||||
You can also use the short dictionary form (note that the notion of
|
||||
source:target from docker is preserved):
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
- volumes:
|
||||
- /var/log/service: /var/log/service
|
||||
- /var/log/service: /var/log/service # mandatory read-write implied
|
||||
|
||||
Or, to specify read-only mounting, use the extended form:
|
||||
Or, alternatively, to specify read-only mounting, use the extended form:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
- volumes:
|
||||
- /home/user1:
|
||||
bind: /mnt/vol2
|
||||
ro: true
|
||||
ro: True
|
||||
- /var/www:
|
||||
bind: /mnt/vol1
|
||||
ro: false
|
||||
ro: False
|
||||
|
||||
Or (mostly for backwards compatibility) a dict style
|
||||
Or (for backwards compatibility) another dict style:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
- volumes:
|
||||
/home/user1:
|
||||
bind: /mnt/vol2
|
||||
ro: true
|
||||
ro: True
|
||||
/var/www:
|
||||
bind: /mnt/vol1
|
||||
ro: false
|
||||
ro: False
|
||||
|
||||
volumes_from
|
||||
List of containers to share volumes with
|
||||
@ -934,27 +1033,6 @@ def running(name,
|
||||
if isinstance(var, dict):
|
||||
for key in var:
|
||||
denvironment[six.text_type(key)] = six.text_type(var[key])
|
||||
if isinstance(volumes, dict):
|
||||
bindvolumes = volumes
|
||||
if isinstance(volumes, list):
|
||||
for vol in volumes:
|
||||
if isinstance(vol, dict):
|
||||
# get source as the dict key
|
||||
source = list(vol.keys())[0]
|
||||
# then find target
|
||||
if isinstance(vol[source], dict):
|
||||
target = vol[source]['bind']
|
||||
read_only = vol[source].get('ro', False)
|
||||
else:
|
||||
target = str(vol[source])
|
||||
read_only = False
|
||||
bindvolumes[source] = {
|
||||
'bind': target,
|
||||
'ro': read_only
|
||||
}
|
||||
else:
|
||||
# assume just an own volumes
|
||||
contvolumes.append(str(vol))
|
||||
if isinstance(ports, dict):
|
||||
bindports = ports
|
||||
# in dict form all ports bind, so no need for exposeports
|
||||
@ -976,6 +1054,11 @@ def running(name,
|
||||
else:
|
||||
#assume just a port to expose
|
||||
exposeports.append(str(port))
|
||||
|
||||
parsed_volumes = _parse_volumes(volumes)
|
||||
bindvolumes = parsed_volumes['bindvols']
|
||||
contvolumes = parsed_volumes['contvols']
|
||||
|
||||
if not already_exists:
|
||||
args, kwargs = [image], dict(
|
||||
command=command,
|
||||
@ -988,6 +1071,7 @@ def running(name,
|
||||
ports=exposeports,
|
||||
environment=denvironment,
|
||||
dns=dns,
|
||||
binds=bindvolumes,
|
||||
volumes=contvolumes,
|
||||
name=name,
|
||||
cpu_shares=cpu_shares,
|
||||
|
@ -73,6 +73,7 @@ def send_message(name,
|
||||
The message that is to be sent to the Hipchat room.
|
||||
|
||||
The following parameters are optional:
|
||||
|
||||
api_key
|
||||
The api key for Hipchat to use for authentication,
|
||||
if not specified in the configuration options of master or minion.
|
||||
|
@ -163,8 +163,10 @@ def user_present(name, uid, password, channel=14, callback=False,
|
||||
|
||||
callback
|
||||
User Restricted to Callback
|
||||
|
||||
False = User Privilege Limit is determined by the User Privilege Limit
|
||||
parameter privilege_level, for both callback and non-callback connections.
|
||||
|
||||
True = User Privilege Limit is determined by the privilege_level
|
||||
parameter for callback connections, but is restricted to Callback
|
||||
level for non-callback connections. Thus, a user can only initiate
|
||||
|
@ -5,6 +5,7 @@ Linux File Access Control Lists
|
||||
Ensure a Linux ACL is present
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
root:
|
||||
acl.present:
|
||||
- name: /root
|
||||
@ -15,6 +16,7 @@ Ensure a Linux ACL is present
|
||||
Ensure a Linux ACL does not exist
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
root:
|
||||
acl.absent:
|
||||
- name: /root
|
||||
|
@ -19,7 +19,7 @@ def license_present(name):
|
||||
on the host.
|
||||
|
||||
name
|
||||
The licnese key to ensure is present
|
||||
The license key to ensure is present
|
||||
'''
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
@ -61,7 +61,7 @@ def license_absent(name):
|
||||
on the host.
|
||||
|
||||
name
|
||||
The licnese key to ensure is absent
|
||||
The license key to ensure is absent
|
||||
'''
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
|
@ -66,10 +66,10 @@ def post_message(name,
|
||||
The message that is to be sent to the Hipchat room.
|
||||
|
||||
The following parameters are optional:
|
||||
|
||||
api_key
|
||||
The api key for Slack to use for authentication,
|
||||
if not specified in the configuration options of master or minion.
|
||||
|
||||
'''
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
|
@ -73,23 +73,26 @@ def installed(name, recurse=False, force=False):
|
||||
def removed(name):
|
||||
'''
|
||||
Remove the windows feature
|
||||
|
||||
name:
|
||||
short name of the feature (the right column in win_servermanager.list_available)
|
||||
|
||||
Note:
|
||||
.. note::
|
||||
|
||||
Some features require a reboot after uninstallation. If so the feature will not be completly uninstalled until
|
||||
the server is restarted.
|
||||
|
||||
Example:
|
||||
|
||||
Run ``salt MinionName win_servermanager.list_installed`` to get a list of all features installed. Use the top
|
||||
name listed for each feature, not the indented one. Do not use the role or feature names mentioned in the
|
||||
PKGMGR documentation.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
ISWebserverRole:
|
||||
win_servermanager.removed:
|
||||
- name: Web-Server
|
||||
|
||||
'''
|
||||
ret = {'name': name,
|
||||
'result': True,
|
||||
|
@ -30,6 +30,12 @@ try:
|
||||
except ImportError:
|
||||
# Older jinja does not need markupsafe
|
||||
HAS_MARKUPSAFE = False
|
||||
|
||||
try:
|
||||
import xml
|
||||
HAS_XML = True
|
||||
except ImportError:
|
||||
HAS_XML = False
|
||||
# pylint: enable=import-error,no-name-in-module
|
||||
|
||||
try:
|
||||
@ -115,6 +121,10 @@ def gen_thin(cachedir, extra_mods='', overwrite=False, so_mods=''):
|
||||
if HAS_SSL_MATCH_HOSTNAME:
|
||||
tops.append(os.path.dirname(os.path.dirname(ssl_match_hostname.__file__)))
|
||||
|
||||
if HAS_XML:
|
||||
# For openSUSE, which apparently doesn't include the whole stdlib
|
||||
tops.append(os.path.dirname(xml.__file__))
|
||||
|
||||
for mod in [m for m in extra_mods.split(',') if m]:
|
||||
if mod not in locals() and mod not in globals():
|
||||
try:
|
||||
|
@ -52,10 +52,13 @@ def update_config(file_name, yaml_contents):
|
||||
specified by ``default_include``.
|
||||
This folder is named ``master.d`` by
|
||||
default. Please look at
|
||||
http://docs.saltstack.com/en/latest/ref/configuration/master.html#include-configuration
|
||||
:conf_master:`include-configuration`
|
||||
for more information.
|
||||
|
||||
Example low data::
|
||||
Example low data:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
data = {
|
||||
'username': 'salt',
|
||||
'password': 'salt',
|
||||
|
113
tests/unit/states/rabbitmq_user_test.py
Normal file
113
tests/unit/states/rabbitmq_user_test.py
Normal file
@ -0,0 +1,113 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
:codeauthor: :email:`Jayesh Kariya <jayeshk@saltstack.com>`
|
||||
'''
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import Salt Testing Libs
|
||||
from salttesting import skipIf, TestCase
|
||||
from salttesting.mock import (
|
||||
NO_MOCK,
|
||||
NO_MOCK_REASON,
|
||||
MagicMock,
|
||||
patch
|
||||
)
|
||||
|
||||
from salttesting.helpers import ensure_in_syspath
|
||||
|
||||
ensure_in_syspath('../../')
|
||||
|
||||
# Import Salt Libs
|
||||
from salt.states import rabbitmq_user
|
||||
|
||||
rabbitmq_user.__opts__ = {}
|
||||
rabbitmq_user.__salt__ = {}
|
||||
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
class RabbitmqUserTestCase(TestCase):
|
||||
'''
|
||||
Test cases for salt.states.rabbitmq_user
|
||||
'''
|
||||
# 'present' function tests: 1
|
||||
|
||||
def test_present(self):
|
||||
'''
|
||||
Test to ensure the RabbitMQ user exists.
|
||||
'''
|
||||
name = 'foo'
|
||||
passwd = 'password'
|
||||
tag = 'user'
|
||||
perms = [{'/': ['.*', '.*']}]
|
||||
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
'result': True,
|
||||
'comment': ''}
|
||||
|
||||
mock = MagicMock(side_effect=[True, False, True, True,
|
||||
True, True, True])
|
||||
mock_dct = MagicMock(return_value={name: set(tag)})
|
||||
mock_pr = MagicMock(return_value=perms)
|
||||
mock_add = MagicMock(return_value={'Added': name})
|
||||
with patch.dict(rabbitmq_user.__salt__,
|
||||
{'rabbitmq.user_exists': mock,
|
||||
'rabbitmq.list_users': mock_dct,
|
||||
'rabbitmq.list_user_permissions': mock_pr,
|
||||
'rabbitmq.set_user_tags': mock_add}):
|
||||
comt = ('User foo already presents')
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(rabbitmq_user.present(name), ret)
|
||||
|
||||
with patch.dict(rabbitmq_user.__opts__, {'test': True}):
|
||||
comt = ('User foo is set to be created')
|
||||
ret.update({'comment': comt, 'result': None})
|
||||
self.assertDictEqual(rabbitmq_user.present(name), ret)
|
||||
|
||||
comt = ("User foo's password is set to be updated")
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(rabbitmq_user.present(name,
|
||||
password=passwd,
|
||||
force=True), ret)
|
||||
|
||||
comt = ("User foo's password is set to be removed")
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(rabbitmq_user.present(name, force=True),
|
||||
ret)
|
||||
|
||||
comt = ('Tags for user foo is set to be changed')
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(rabbitmq_user.present(name, tags=tag), ret)
|
||||
|
||||
comt = ('Permissions for user foo is set to be changed')
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(rabbitmq_user.present(name, perms=perms),
|
||||
ret)
|
||||
|
||||
with patch.dict(rabbitmq_user.__opts__, {'test': False}):
|
||||
ret.update({'comment': name, 'result': True,
|
||||
'changes': {'new': 'Set tags: user\n', 'old': ''}})
|
||||
self.assertDictEqual(rabbitmq_user.present(name, tags=tag), ret)
|
||||
|
||||
# 'absent' function tests: 1
|
||||
|
||||
def test_absent(self):
|
||||
'''
|
||||
Test to ensure the named user is absent.
|
||||
'''
|
||||
name = 'foo'
|
||||
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
'result': True,
|
||||
'comment': 'User {0} is not present'.format(name)}
|
||||
|
||||
mock = MagicMock(return_value=False)
|
||||
with patch.dict(rabbitmq_user.__salt__, {'rabbitmq.user_exists': mock}):
|
||||
self.assertDictEqual(rabbitmq_user.absent(name), ret)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
run_tests(RabbitmqUserTestCase, needs_daemon=False)
|
135
tests/unit/states/rbenv_test.py
Normal file
135
tests/unit/states/rbenv_test.py
Normal file
@ -0,0 +1,135 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
:codeauthor: :email:`Jayesh Kariya <jayeshk@saltstack.com>`
|
||||
'''
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import Salt Testing Libs
|
||||
from salttesting import skipIf, TestCase
|
||||
from salttesting.mock import (
|
||||
NO_MOCK,
|
||||
NO_MOCK_REASON,
|
||||
MagicMock,
|
||||
patch
|
||||
)
|
||||
|
||||
from salttesting.helpers import ensure_in_syspath
|
||||
|
||||
ensure_in_syspath('../../')
|
||||
|
||||
# Import Salt Libs
|
||||
from salt.states import rbenv
|
||||
|
||||
rbenv.__opts__ = {}
|
||||
rbenv.__salt__ = {}
|
||||
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
class RbenvTestCase(TestCase):
|
||||
'''
|
||||
Test cases for salt.states.rbenv
|
||||
'''
|
||||
# 'installed' function tests: 1
|
||||
|
||||
def test_installed(self):
|
||||
'''
|
||||
Test to verify that the specified ruby is installed with rbenv.
|
||||
'''
|
||||
name = 'rbenv-deps'
|
||||
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
'result': True,
|
||||
'comment': ''}
|
||||
|
||||
mock_t = MagicMock(side_effect=[False, True, True])
|
||||
mock_f = MagicMock(return_value=False)
|
||||
mock_def = MagicMock(return_value='2.7')
|
||||
mock_ver = MagicMock(return_value=['2.7'])
|
||||
with patch.dict(rbenv.__salt__,
|
||||
{'rbenv.is_installed': mock_f,
|
||||
'rbenv.install': mock_t,
|
||||
'rbenv.default': mock_def,
|
||||
'rbenv.versions': mock_ver,
|
||||
'rbenv.install_ruby': mock_t}):
|
||||
with patch.dict(rbenv.__opts__, {'test': True}):
|
||||
comt = ('Ruby rbenv-deps is set to be installed')
|
||||
ret.update({'comment': comt, 'result': None})
|
||||
self.assertDictEqual(rbenv.installed(name), ret)
|
||||
|
||||
with patch.dict(rbenv.__opts__, {'test': False}):
|
||||
comt = ('Rbenv failed to install')
|
||||
ret.update({'comment': comt, 'result': False})
|
||||
self.assertDictEqual(rbenv.installed(name), ret)
|
||||
|
||||
comt = ('Successfully installed ruby')
|
||||
ret.update({'comment': comt, 'result': True, 'default': False,
|
||||
'changes': {name: 'Installed'}})
|
||||
self.assertDictEqual(rbenv.installed(name), ret)
|
||||
|
||||
# 'absent' function tests: 1
|
||||
|
||||
def test_absent(self):
|
||||
'''
|
||||
Test to verify that the specified ruby is not installed with rbenv.
|
||||
'''
|
||||
name = 'myqueue'
|
||||
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
'result': True,
|
||||
'comment': ''}
|
||||
|
||||
mock = MagicMock(side_effect=[False, True])
|
||||
mock_def = MagicMock(return_value='2.7')
|
||||
mock_ver = MagicMock(return_value=['2.7'])
|
||||
with patch.dict(rbenv.__salt__,
|
||||
{'rbenv.is_installed': mock,
|
||||
'rbenv.default': mock_def,
|
||||
'rbenv.versions': mock_ver}):
|
||||
with patch.dict(rbenv.__opts__, {'test': True}):
|
||||
comt = ('Ruby myqueue is set to be uninstalled')
|
||||
ret.update({'comment': comt, 'result': None})
|
||||
self.assertDictEqual(rbenv.absent(name), ret)
|
||||
|
||||
with patch.dict(rbenv.__opts__, {'test': False}):
|
||||
comt = ('Rbenv not installed, myqueue not either')
|
||||
ret.update({'comment': comt, 'result': True})
|
||||
self.assertDictEqual(rbenv.absent(name), ret)
|
||||
|
||||
comt = ('Ruby myqueue is already absent')
|
||||
ret.update({'comment': comt, 'result': True})
|
||||
self.assertDictEqual(rbenv.absent(name), ret)
|
||||
|
||||
# 'install_rbenv' function tests: 1
|
||||
|
||||
def test_install_rbenv(self):
|
||||
'''
|
||||
Test to install rbenv if not installed.
|
||||
'''
|
||||
name = 'myqueue'
|
||||
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
'result': True,
|
||||
'comment': ''}
|
||||
|
||||
with patch.dict(rbenv.__opts__, {'test': True}):
|
||||
comt = ('Rbenv is set to be installed')
|
||||
ret.update({'comment': comt, 'result': None})
|
||||
self.assertDictEqual(rbenv.install_rbenv(name), ret)
|
||||
|
||||
with patch.dict(rbenv.__opts__, {'test': False}):
|
||||
mock = MagicMock(side_effect=[False, True])
|
||||
with patch.dict(rbenv.__salt__,
|
||||
{'rbenv.is_installed': mock,
|
||||
'rbenv.install': mock}):
|
||||
comt = ('Rbenv installed')
|
||||
ret.update({'comment': comt, 'result': True})
|
||||
self.assertDictEqual(rbenv.install_rbenv(name), ret)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
run_tests(RbenvTestCase, needs_daemon=False)
|
Loading…
Reference in New Issue
Block a user