mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 08:58:59 +00:00
Merge pull request #24539 from basepi/merge-forward-develop
Merge forward from 2015.5 to develop
This commit is contained in:
commit
359efdfc1c
@ -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.
|
||||
|
@ -2437,3 +2437,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.
|
||||
|
@ -313,6 +313,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:
|
||||
|
@ -158,6 +158,7 @@ Full list of builtin state modules
|
||||
sysrc
|
||||
test
|
||||
timezone
|
||||
tls
|
||||
tomcat
|
||||
tuned
|
||||
uptime
|
||||
|
@ -554,7 +554,7 @@ at the end of a state run, after all states have completed.
|
||||
|
||||
configure-apache2:
|
||||
file.managed:
|
||||
- path: /etc/apache2/apache2.conf
|
||||
- name: /etc/apache2/apache2.conf
|
||||
- source: salt://apache2/apache2.conf
|
||||
|
||||
This example will cause apache2 to be restarted when the apache2.conf file is
|
||||
@ -568,7 +568,7 @@ changed, but the apache2 restart will happen at the end of the state run.
|
||||
|
||||
configure-apache2:
|
||||
file.managed:
|
||||
- path: /etc/apache2/apache2.conf
|
||||
- name: /etc/apache2/apache2.conf
|
||||
- source: salt://apache2/apache2.conf
|
||||
- listen_in:
|
||||
- service: apache2
|
||||
@ -593,7 +593,7 @@ same privileges as the salt-minion.
|
||||
|
||||
comment-repo:
|
||||
file.replace:
|
||||
- path: /etc/yum.repos.d/fedora.repo
|
||||
- name: /etc/yum.repos.d/fedora.repo
|
||||
- pattern: ^enabled=0
|
||||
- repl: enabled=1
|
||||
- check_cmd:
|
||||
|
@ -104,7 +104,7 @@ added to the folder the original VM belongs to.
|
||||
|
||||
host
|
||||
----
|
||||
The MOR of the host where the vm should be registered.
|
||||
The MOR of the host where the vm should be registered.
|
||||
|
||||
If not specified:
|
||||
* if resourcepool is not specified, the current host is used.
|
||||
|
@ -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
|
||||
|
@ -212,7 +212,7 @@ To configure an LDAP group, append a ``%`` to the ID:
|
||||
.. code-block:: yaml
|
||||
|
||||
external_auth:
|
||||
ldap:
|
||||
test_ldap_group%:
|
||||
- '*':
|
||||
- test.echo
|
||||
ldap:
|
||||
test_ldap_group%:
|
||||
- '*':
|
||||
- test.echo
|
||||
|
@ -43,8 +43,9 @@ minion exe>` should match the contents of the corresponding md5 file.
|
||||
* 2014.7.0
|
||||
* 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.
|
||||
.. note::
|
||||
|
||||
The 2014.7.0 installers have been removed because of a regression. Please use the 2014.7.1 release instead.
|
||||
|
||||
* 2014.1.13
|
||||
* `Salt-Minion-2014.1.13-x86-Setup.exe <http://docs.saltstack.com/downloads/Salt-Minion-2014.1.13-x86-Setup.exe>`__ | `md5 <http://docs.saltstack.com/downloads/Salt-Minion-2014.1.13-x86-Setup.exe.md5>`__
|
||||
|
@ -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
|
||||
=================
|
||||
@ -77,4 +79,10 @@ it unnecessary to change the configuration file:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call state.highstate --local
|
||||
salt-call state.highstate --local
|
||||
|
||||
External Pillars
|
||||
================
|
||||
|
||||
:ref:`External pillars <external-pillars>` are supported when running in masterless mode.
|
||||
|
||||
|
@ -185,8 +185,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
|
||||
|
||||
|
@ -153,24 +153,26 @@ 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
|
||||
* close_write Writable file closed
|
||||
* create File created in watched directory
|
||||
* delete File deleted from watched directory
|
||||
* delete_self Watched file or directory deleted
|
||||
* modify File modified
|
||||
* moved_from File moved out of watched directory
|
||||
* moved_to File moved into watched directory
|
||||
* move_self Watched file moved
|
||||
* open File opened
|
||||
|
||||
* access File accessed
|
||||
* attrib File metadata changed
|
||||
* close_nowrite Unwritable file closed
|
||||
* close_write Writable file closed
|
||||
* create File created in watched directory
|
||||
* delete File deleted from watched directory
|
||||
* delete_self Watched file or directory deleted
|
||||
* modify File modified
|
||||
* moved_from File moved out of watched directory
|
||||
* moved_to File moved into watched directory
|
||||
* move_self Watched file moved
|
||||
* 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
|
||||
* onlydir Operate only if name is directory
|
||||
|
||||
* dont_follow Don't dereference symbolic links
|
||||
* excl_unlink Omit events for children after they have been unlinked
|
||||
* oneshot Remove watch after one event
|
||||
* onlydir Operate only if name is directory
|
||||
|
||||
recurse:
|
||||
Recursively watch files in the directory
|
||||
|
@ -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()
|
||||
|
@ -720,7 +720,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'])
|
||||
|
@ -1281,13 +1281,18 @@ def get_repo(repo, **kwargs):
|
||||
ppa_name, dist)
|
||||
else:
|
||||
if HAS_SOFTWAREPROPERTIES:
|
||||
if hasattr(softwareproperties.ppa, 'PPAShortcutHandler'):
|
||||
repo = softwareproperties.ppa.PPAShortcutHandler(repo).expand(
|
||||
__grains__['lsb_distrib_codename'])[0]
|
||||
else:
|
||||
repo = softwareproperties.ppa.expand_ppa_line(
|
||||
repo,
|
||||
__grains__['lsb_distrib_codename'])[0]
|
||||
try:
|
||||
if hasattr(softwareproperties.ppa, 'PPAShortcutHandler'):
|
||||
repo = softwareproperties.ppa.PPAShortcutHandler(
|
||||
repo).expand(dist)[0]
|
||||
else:
|
||||
repo = softwareproperties.ppa.expand_ppa_line(
|
||||
repo,
|
||||
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)
|
||||
|
||||
|
@ -745,7 +745,9 @@ 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.
|
||||
|
@ -575,7 +575,8 @@ def create_container(image,
|
||||
volumes_from=None,
|
||||
name=None,
|
||||
cpu_shares=None,
|
||||
cpuset=None):
|
||||
cpuset=None,
|
||||
binds=None):
|
||||
'''
|
||||
Create a new container
|
||||
|
||||
@ -594,10 +595,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
|
||||
@ -616,23 +633,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()
|
||||
|
||||
# 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 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:
|
||||
mountpoints = {}
|
||||
binds = {}
|
||||
# create empty mountpoints for them to be
|
||||
# editable
|
||||
# either we have a list of guest or host:guest
|
||||
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
|
||||
container_info = client.create_container(
|
||||
image=image,
|
||||
command=command,
|
||||
@ -645,12 +670,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'
|
||||
@ -660,8 +687,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 as e:
|
||||
_invalid(status, id_=image, out=traceback.format_exc())
|
||||
raise e
|
||||
__salt__['mine.send']('docker.get_containers', host=True)
|
||||
return status
|
||||
|
||||
|
@ -776,7 +776,6 @@ def trust_key(keyid=None,
|
||||
salt '*' gpg.trust_key keyid='3FAD9F1E' trust_level='marginally'
|
||||
salt '*' gpg.trust_key fingerprint='53C96788253E58416D20BCD352952C84C3252192' trust_level='not_trusted'
|
||||
salt '*' gpg.trust_key keys=3FAD9F1E trust_level='ultimately' user='username'
|
||||
|
||||
'''
|
||||
ret = {
|
||||
'res': True,
|
||||
|
@ -279,8 +279,11 @@ def get_channel_access(channel=14, read_mode='non_volatile', **kwargs):
|
||||
- api_port=623
|
||||
- api_kg=None
|
||||
|
||||
:return: A Python dict with the following keys/values:
|
||||
return
|
||||
A Python dict with the following keys/values:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
{
|
||||
alerting:
|
||||
per_msg_auth:
|
||||
@ -322,14 +325,17 @@ def get_channel_info(channel=14, **kwargs):
|
||||
- api_port=623
|
||||
- api_kg=None
|
||||
|
||||
:return:
|
||||
session_support:
|
||||
no_session: channel is session-less
|
||||
single: channel is single-session
|
||||
multi: channel is multi-session
|
||||
auto: channel is session-based (channel could alternate between
|
||||
single- and multi-session operation, as can occur with a
|
||||
serial/modem channel that supports connection mode auto-detect)
|
||||
return
|
||||
channel session supports:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
- no_session: channel is session-less
|
||||
- single: channel is single-session
|
||||
- multi: channel is multi-session
|
||||
- auto: channel is session-based (channel could alternate between
|
||||
single- and multi-session operation, as can occur with a
|
||||
serial/modem channel that supports connection mode auto-detect)
|
||||
|
||||
CLI Examples:
|
||||
|
||||
@ -419,19 +425,20 @@ def get_user_access(uid, channel=14, **kwargs):
|
||||
- api_port=623
|
||||
- api_kg=None
|
||||
|
||||
:return:
|
||||
channel_info:
|
||||
- max_user_count = maximum number of user IDs on this channel
|
||||
- enabled_users = count of User ID slots presently in use
|
||||
- users_with_fixed_names = count of user IDs with fixed names
|
||||
access:
|
||||
- callback
|
||||
- link_auth
|
||||
- ipmi_msg
|
||||
- privilege_level: [reserved, callback, user, operator
|
||||
administrator, proprietary, no_access]
|
||||
return
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
channel_info:
|
||||
- max_user_count = maximum number of user IDs on this channel
|
||||
- enabled_users = count of User ID slots presently in use
|
||||
- users_with_fixed_names = count of user IDs with fixed names
|
||||
access:
|
||||
- callback
|
||||
- link_auth
|
||||
- ipmi_msg
|
||||
- privilege_level: [reserved, callback, user, operator
|
||||
administrator, proprietary, no_access]
|
||||
|
||||
CLI Examples:
|
||||
|
||||
@ -770,16 +777,20 @@ def get_user(uid, channel=14, **kwargs):
|
||||
- api_port=623
|
||||
- api_kg=None
|
||||
|
||||
:return:
|
||||
name: (str)
|
||||
uid: (int)
|
||||
channel: (int)
|
||||
access:
|
||||
- callback (bool)
|
||||
- link_auth (bool)
|
||||
- ipmi_msg (bool)
|
||||
- privilege_level: (str)[callback, user, operatorm administrator,
|
||||
proprietary, no_access]
|
||||
return
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
name: (str)
|
||||
uid: (int)
|
||||
channel: (int)
|
||||
access:
|
||||
- callback (bool)
|
||||
- link_auth (bool)
|
||||
- ipmi_msg (bool)
|
||||
- privilege_level: (str)[callback, user, operatorm administrator,
|
||||
proprietary, no_access]
|
||||
|
||||
CLI Examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
@ -696,7 +696,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:
|
||||
|
@ -128,10 +128,7 @@ def list_upgrades(refresh=False):
|
||||
if refresh:
|
||||
options.append('-y')
|
||||
|
||||
cmd = (
|
||||
'pacman {0} | egrep -v '
|
||||
r'"^\s|^:"'
|
||||
).format(' '.join(options))
|
||||
cmd = ('pacman {0}').format(' '.join(options))
|
||||
|
||||
call = __salt__['cmd.run_all'](cmd, output_loglevel='trace')
|
||||
|
||||
@ -147,7 +144,9 @@ def list_upgrades(refresh=False):
|
||||
else:
|
||||
out = call['stdout']
|
||||
|
||||
for line in out.splitlines():
|
||||
output = iter(out.splitlines())
|
||||
next(output) # Skip informational output line
|
||||
for line in output:
|
||||
comps = line.split(' ')
|
||||
if len(comps) < 2:
|
||||
continue
|
||||
|
@ -228,11 +228,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:
|
||||
|
||||
@ -240,7 +242,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.
|
||||
'''
|
||||
|
||||
# Import python libs
|
||||
|
@ -58,8 +58,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.
|
||||
@ -99,12 +98,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,17 +7,18 @@ A REST API for Salt
|
||||
|
||||
.. py:currentmodule:: salt.netapi.rest_cherrypy.app
|
||||
|
||||
: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
|
||||
CherryPy milestone 3.3, but the patch was committed for version 3.6.1.
|
||||
- salt-api package
|
||||
: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
|
||||
CherryPy milestone 3.3, but the patch was committed for version 3.6.1.
|
||||
:optdepends: - ws4py Python module for websockets support.
|
||||
: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.
|
||||
|
||||
|
@ -16,7 +16,7 @@ them.
|
||||
An example Django module that registers a function called
|
||||
'returner_callback' with this module's 'returner' function:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
import salt.returners.django_return
|
||||
from django.dispatch import receiver
|
||||
|
@ -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
|
||||
|
||||
.. versionadded:: 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
|
||||
|
||||
.. versionadded:: 2015.2
|
||||
.. versionadded:: 2015.5.0
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -236,10 +236,10 @@ def present(
|
||||
listeners
|
||||
A list of listener lists; example::
|
||||
|
||||
[
|
||||
['443', 'HTTPS', 'arn:aws:iam::1111111:server-certificate/mycert'],
|
||||
['8443', '80', 'HTTPS', 'HTTP', 'arn:aws:iam::1111111:server-certificate/mycert']
|
||||
]
|
||||
[
|
||||
['443', 'HTTPS', 'arn:aws:iam::1111111:server-certificate/mycert'],
|
||||
['8443', '80', 'HTTPS', 'HTTP', 'arn:aws:iam::1111111:server-certificate/mycert']
|
||||
]
|
||||
|
||||
subnets
|
||||
A list of subnet IDs in your VPC to attach to your LoadBalancer.
|
||||
|
@ -69,6 +69,7 @@ Available Functions
|
||||
my_service:
|
||||
docker.running:
|
||||
- container: mysuperdocker
|
||||
- image: corp/mysuperdocker_img
|
||||
- ports:
|
||||
"5000/tcp":
|
||||
HostIp: ""
|
||||
@ -210,6 +211,103 @@ def _get_image_name(image, tag):
|
||||
return image
|
||||
|
||||
|
||||
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
|
||||
@ -531,7 +629,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
|
||||
@ -555,7 +653,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:
|
||||
@ -574,15 +672,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']
|
||||
|
||||
kw = dict(
|
||||
binds=bindvolumes,
|
||||
command=command,
|
||||
hostname=hostname,
|
||||
user=user,
|
||||
@ -593,7 +689,7 @@ def installed(name,
|
||||
ports=dports,
|
||||
environment=denvironment,
|
||||
dns=dns,
|
||||
volumes=dvolumes,
|
||||
volumes=contvolumes,
|
||||
volumes_from=volumes_from,
|
||||
name=name,
|
||||
cpu_shares=cpu_shares,
|
||||
@ -860,44 +956,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
|
||||
/var/www:
|
||||
bind: /mnt/vol1
|
||||
ro: false
|
||||
/home/user1:
|
||||
bind: /mnt/vol2
|
||||
ro: True
|
||||
/var/www:
|
||||
bind: /mnt/vol1
|
||||
ro: False
|
||||
|
||||
volumes_from
|
||||
List of containers to share volumes with
|
||||
@ -1084,6 +1183,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:
|
||||
kwargs = dict(command=command,
|
||||
hostname=hostname,
|
||||
@ -1095,6 +1199,7 @@ def running(name,
|
||||
ports=exposeports,
|
||||
environment=denvironment,
|
||||
dns=dns,
|
||||
binds=bindvolumes,
|
||||
volumes=contvolumes,
|
||||
name=name,
|
||||
cpu_shares=cpu_shares,
|
||||
|
@ -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
|
||||
|
@ -4,7 +4,7 @@ Linux File Access Control Lists
|
||||
|
||||
Ensure a Linux ACL is present
|
||||
|
||||
.. code-block:: yaml
|
||||
.. code-block:: yaml
|
||||
|
||||
root:
|
||||
acl.present:
|
||||
@ -15,7 +15,7 @@ Ensure a Linux ACL is present
|
||||
|
||||
Ensure a Linux ACL does not exist
|
||||
|
||||
.. code-block:: yaml
|
||||
.. code-block:: yaml
|
||||
|
||||
root:
|
||||
acl.absent:
|
||||
|
@ -228,7 +228,7 @@ def run(name, **kwargs):
|
||||
ret['result'] = False
|
||||
return ret
|
||||
else:
|
||||
if mret is not None:
|
||||
if mret is not None or mret is not {}:
|
||||
ret['changes']['ret'] = mret
|
||||
|
||||
if 'returner' in kwargs:
|
||||
|
@ -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': {},
|
||||
|
@ -81,7 +81,7 @@ def present(name,
|
||||
'information or see #6961.'
|
||||
)
|
||||
|
||||
if any(user, owner, conf, write, read):
|
||||
if any((user, owner, conf, write, read)):
|
||||
salt.utils.warn_until(
|
||||
'Beryllium',
|
||||
'Passed \'owner\', \'user\', \'conf\', \'write\' or \'read\' '
|
||||
|
@ -69,7 +69,6 @@ def post_message(name,
|
||||
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': {},
|
||||
|
@ -83,15 +83,16 @@ def removed(name):
|
||||
the server is restarted.
|
||||
|
||||
Example:
|
||||
Run ``salt MinionName win_servermanager.list_installed`` to get a list of all features installed. Use the top
|
||||
|
||||
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
|
||||
.. code-block:: yaml
|
||||
|
||||
ISWebserverRole:
|
||||
win_servermanager.removed:
|
||||
- name: Web-Server
|
||||
ISWebserverRole:
|
||||
win_servermanager.removed:
|
||||
- name: Web-Server
|
||||
'''
|
||||
ret = {'name': name,
|
||||
'result': True,
|
||||
|
@ -111,9 +111,12 @@ def yamlify_arg(arg):
|
||||
import salt.utils.yamlloader as yamlloader
|
||||
original_arg = arg
|
||||
if '#' in arg:
|
||||
# Don't yamlify this argument or the '#' and everything after
|
||||
# it will be interpreted as a comment.
|
||||
return arg
|
||||
# Only yamlify if it parses into a non-string type, to prevent
|
||||
# loss of content due to # as comment character
|
||||
parsed_arg = yamlloader.load(arg, Loader=yamlloader.SaltYamlSafeLoader)
|
||||
if isinstance(parsed_arg, six.string_types):
|
||||
return arg
|
||||
return parsed_arg
|
||||
if arg == 'None':
|
||||
arg = None
|
||||
else:
|
||||
|
@ -31,6 +31,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:
|
||||
@ -117,6 +123,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,12 @@ 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',
|
||||
|
94
tests/unit/states/pyrax_queues_test.py
Normal file
94
tests/unit/states/pyrax_queues_test.py
Normal file
@ -0,0 +1,94 @@
|
||||
# -*- 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 pyrax_queues
|
||||
|
||||
pyrax_queues.__opts__ = {}
|
||||
pyrax_queues.__salt__ = {}
|
||||
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
class PyraxQueuesTestCase(TestCase):
|
||||
'''
|
||||
Test cases for salt.states.pyrax_queues
|
||||
'''
|
||||
# 'present' function tests: 1
|
||||
|
||||
def test_present(self):
|
||||
'''
|
||||
Test to ensure the RackSpace queue exists.
|
||||
'''
|
||||
name = 'myqueue'
|
||||
provider = 'my-pyrax'
|
||||
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
'result': True,
|
||||
'comment': ''}
|
||||
|
||||
mock_dct = MagicMock(side_effect=[{provider: {'salt': True}},
|
||||
{provider: {'salt': False}},
|
||||
{provider: {'salt': False}}, False])
|
||||
with patch.dict(pyrax_queues.__salt__, {'cloud.action': mock_dct}):
|
||||
comt = ('{0} present.'.format(name))
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(pyrax_queues.present(name, provider), ret)
|
||||
|
||||
with patch.dict(pyrax_queues.__opts__, {'test': True}):
|
||||
comt = ('Rackspace queue myqueue is set to be created.')
|
||||
ret.update({'comment': comt, 'result': None})
|
||||
self.assertDictEqual(pyrax_queues.present(name, provider), ret)
|
||||
|
||||
with patch.dict(pyrax_queues.__opts__, {'test': False}):
|
||||
comt = ('Failed to create myqueue Rackspace queue.')
|
||||
ret.update({'comment': comt, 'result': False})
|
||||
self.assertDictEqual(pyrax_queues.present(name, provider), ret)
|
||||
|
||||
# 'absent' function tests: 1
|
||||
|
||||
def test_absent(self):
|
||||
'''
|
||||
Test to ensure the named Rackspace queue is deleted.
|
||||
'''
|
||||
name = 'myqueue'
|
||||
provider = 'my-pyrax'
|
||||
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
'result': True,
|
||||
'comment': ''}
|
||||
|
||||
mock_dct = MagicMock(side_effect=[{provider: {'salt': False}},
|
||||
{provider: {'salt': True}}])
|
||||
with patch.dict(pyrax_queues.__salt__, {'cloud.action': mock_dct}):
|
||||
comt = ('myqueue does not exist.')
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(pyrax_queues.absent(name, provider), ret)
|
||||
|
||||
with patch.dict(pyrax_queues.__opts__, {'test': True}):
|
||||
comt = ('Rackspace queue myqueue is set to be removed.')
|
||||
ret.update({'comment': comt, 'result': None})
|
||||
self.assertDictEqual(pyrax_queues.absent(name, provider), ret)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
run_tests(PyraxQueuesTestCase, needs_daemon=False)
|
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)
|
73
tests/unit/states/rabbitmq_vhost_test.py
Normal file
73
tests/unit/states/rabbitmq_vhost_test.py
Normal file
@ -0,0 +1,73 @@
|
||||
# -*- 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_vhost
|
||||
|
||||
rabbitmq_vhost.__opts__ = {}
|
||||
rabbitmq_vhost.__salt__ = {}
|
||||
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
class RabbitmqVhostTestCase(TestCase):
|
||||
'''
|
||||
Test cases for salt.states.rabbitmq_vhost
|
||||
'''
|
||||
# 'present' function tests: 1
|
||||
|
||||
def test_present(self):
|
||||
'''
|
||||
Test to ensure the RabbitMQ VHost exists.
|
||||
'''
|
||||
name = 'virtual_host'
|
||||
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
'result': None,
|
||||
'comment': 'Creating VHost virtual_host'}
|
||||
|
||||
mock = MagicMock(return_value=False)
|
||||
with patch.dict(rabbitmq_vhost.__salt__,
|
||||
{'rabbitmq.vhost_exists': mock}):
|
||||
with patch.dict(rabbitmq_vhost.__opts__, {'test': True}):
|
||||
self.assertDictEqual(rabbitmq_vhost.present(name), ret)
|
||||
|
||||
# 'absent' function tests: 1
|
||||
|
||||
def test_absent(self):
|
||||
'''
|
||||
Test to ensure the named user is absent.
|
||||
'''
|
||||
name = 'myqueue'
|
||||
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
'result': True,
|
||||
'comment': 'Virtual Host {0} is not present'.format(name)}
|
||||
|
||||
mock = MagicMock(return_value=False)
|
||||
with patch.dict(rabbitmq_vhost.__salt__,
|
||||
{'rabbitmq.vhost_exists': mock}):
|
||||
self.assertDictEqual(rabbitmq_vhost.absent(name), ret)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
run_tests(RabbitmqVhostTestCase, 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