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
|
The salt-call command is used to run module functions locally on a minion
|
||||||
instead of executing them from the master.
|
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
|
Options
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
@ -87,11 +87,6 @@ Execution Options
|
|||||||
for this influx of vm creation. When creating large groups of VMs watch the
|
for this influx of vm creation. When creating large groups of VMs watch the
|
||||||
cloud provider carefully.
|
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
|
.. option:: -u, --update-bootstrap
|
||||||
|
|
||||||
Update salt-bootstrap to the latest develop version on GitHub.
|
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:
|
win_gitrepos:
|
||||||
- 'https://github.com/saltstack/salt-winrepo.git'
|
- '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
|
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
|
.. conf_minion:: sock_dir
|
||||||
|
|
||||||
``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
|
is used by the Salt state system, salt-cp, and can be used to distribute files
|
||||||
presented by the Salt file server.
|
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
|
Environments
|
||||||
````````````
|
````````````
|
||||||
|
|
||||||
|
@ -3,4 +3,4 @@ salt.modules.ipmi
|
|||||||
=================
|
=================
|
||||||
|
|
||||||
.. automodule:: salt.modules.ipmi
|
.. automodule:: salt.modules.ipmi
|
||||||
:members
|
:members:
|
||||||
|
@ -158,6 +158,7 @@ Full list of builtin state modules
|
|||||||
sysrc
|
sysrc
|
||||||
test
|
test
|
||||||
timezone
|
timezone
|
||||||
|
tls
|
||||||
tomcat
|
tomcat
|
||||||
tuned
|
tuned
|
||||||
uptime
|
uptime
|
||||||
|
@ -554,7 +554,7 @@ at the end of a state run, after all states have completed.
|
|||||||
|
|
||||||
configure-apache2:
|
configure-apache2:
|
||||||
file.managed:
|
file.managed:
|
||||||
- path: /etc/apache2/apache2.conf
|
- name: /etc/apache2/apache2.conf
|
||||||
- source: salt://apache2/apache2.conf
|
- source: salt://apache2/apache2.conf
|
||||||
|
|
||||||
This example will cause apache2 to be restarted when the apache2.conf file is
|
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:
|
configure-apache2:
|
||||||
file.managed:
|
file.managed:
|
||||||
- path: /etc/apache2/apache2.conf
|
- name: /etc/apache2/apache2.conf
|
||||||
- source: salt://apache2/apache2.conf
|
- source: salt://apache2/apache2.conf
|
||||||
- listen_in:
|
- listen_in:
|
||||||
- service: apache2
|
- service: apache2
|
||||||
@ -593,7 +593,7 @@ same privileges as the salt-minion.
|
|||||||
|
|
||||||
comment-repo:
|
comment-repo:
|
||||||
file.replace:
|
file.replace:
|
||||||
- path: /etc/yum.repos.d/fedora.repo
|
- name: /etc/yum.repos.d/fedora.repo
|
||||||
- pattern: ^enabled=0
|
- pattern: ^enabled=0
|
||||||
- repl: enabled=1
|
- repl: enabled=1
|
||||||
- check_cmd:
|
- check_cmd:
|
||||||
|
@ -104,7 +104,7 @@ added to the folder the original VM belongs to.
|
|||||||
|
|
||||||
host
|
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 not specified:
|
||||||
* if resourcepool is not specified, the current host is used.
|
* if resourcepool is not specified, the current host is used.
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
===================
|
.. _external-pillars:
|
||||||
|
|
||||||
|
================
|
||||||
External Pillars
|
External Pillars
|
||||||
===================
|
================
|
||||||
|
|
||||||
Salt provides a mechanism for generating pillar data by calling external
|
Salt provides a mechanism for generating pillar data by calling external
|
||||||
pillar interfaces. This document will describe an outline of an ext_pillar
|
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
|
.. code-block:: yaml
|
||||||
|
|
||||||
external_auth:
|
external_auth:
|
||||||
ldap:
|
ldap:
|
||||||
test_ldap_group%:
|
test_ldap_group%:
|
||||||
- '*':
|
- '*':
|
||||||
- test.echo
|
- test.echo
|
||||||
|
@ -43,8 +43,9 @@ minion exe>` should match the contents of the corresponding md5 file.
|
|||||||
* 2014.7.0
|
* 2014.7.0
|
||||||
* Salt-Minion-2014.7.0-1-win32-Setup.exe | md5
|
* Salt-Minion-2014.7.0-1-win32-Setup.exe | md5
|
||||||
* Salt-Minion-2014.7.0-AMD64-Setup.exe | md5
|
* Salt-Minion-2014.7.0-AMD64-Setup.exe | md5
|
||||||
.. note::
|
.. note::
|
||||||
The 2014.7.0 installers have been removed because of a regression. Please use the 2014.7.1 release instead.
|
|
||||||
|
The 2014.7.0 installers have been removed because of a regression. Please use the 2014.7.1 release instead.
|
||||||
|
|
||||||
* 2014.1.13
|
* 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>`__
|
* `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
|
.. _`SELinux`: https://en.wikipedia.org/wiki/Security-Enhanced_Linux
|
||||||
.. _`AppArmor`: http://wiki.apparmor.net/index.php/Main_Page
|
.. _`AppArmor`: http://wiki.apparmor.net/index.php/Main_Page
|
||||||
|
|
||||||
|
.. _troubleshooting-minion-salt-call:
|
||||||
|
|
||||||
Using salt-call
|
Using salt-call
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
@ -34,9 +34,9 @@ Variables:
|
|||||||
minions can be defined in pillar and then accessed inside sls formulas
|
minions can be defined in pillar and then accessed inside sls formulas
|
||||||
and template files.
|
and template files.
|
||||||
Arbitrary Data:
|
Arbitrary Data:
|
||||||
Pillar can contain any basic data structure, so a list of values, or a
|
Pillar can contain any basic data structure in dictionary format,
|
||||||
key/value store can be defined making it easy to iterate over a group
|
so a key/value store can be defined making it easy to iterate over a group
|
||||||
of values in sls formulas
|
of values in sls formulas.
|
||||||
|
|
||||||
Pillar is therefore one of the most important systems when using Salt. This
|
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
|
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"}'
|
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::
|
.. note::
|
||||||
|
|
||||||
If a key is passed on the command line that already exists on the minion,
|
If a key is passed on the command line that already exists on the minion,
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
.. _tutorial-standalone-minion:
|
||||||
|
|
||||||
=================
|
=================
|
||||||
Standalone Minion
|
Standalone Minion
|
||||||
=================
|
=================
|
||||||
@ -77,4 +79,10 @@ it unnecessary to change the configuration file:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. 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
|
salt-minion -l debug
|
||||||
|
|
||||||
Run the minion in the foreground
|
Run the minion in the foreground
|
||||||
By not starting the minion in daemon mode (:option:`-d <salt-minion
|
By not starting the minion in daemon mode (:option:`-d <salt-minion -d>`)
|
||||||
-d>`) one can view any output from the minion as it works:
|
one can view any output from the minion as it works:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
|
@ -153,24 +153,26 @@ def beacon(config):
|
|||||||
|
|
||||||
The mask list can contain the following events (the default mask is create,
|
The mask list can contain the following events (the default mask is create,
|
||||||
delete, and modify):
|
delete, and modify):
|
||||||
* access File accessed
|
|
||||||
* attrib File metadata changed
|
* access File accessed
|
||||||
* close_nowrite Unwritable file closed
|
* attrib File metadata changed
|
||||||
* close_write Writable file closed
|
* close_nowrite Unwritable file closed
|
||||||
* create File created in watched directory
|
* close_write Writable file closed
|
||||||
* delete File deleted from watched directory
|
* create File created in watched directory
|
||||||
* delete_self Watched file or directory deleted
|
* delete File deleted from watched directory
|
||||||
* modify File modified
|
* delete_self Watched file or directory deleted
|
||||||
* moved_from File moved out of watched directory
|
* modify File modified
|
||||||
* moved_to File moved into watched directory
|
* moved_from File moved out of watched directory
|
||||||
* move_self Watched file moved
|
* moved_to File moved into watched directory
|
||||||
* open File opened
|
* move_self Watched file moved
|
||||||
|
* open File opened
|
||||||
|
|
||||||
The mask can also contain the following options:
|
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
|
* dont_follow Don't dereference symbolic links
|
||||||
* oneshot Remove watch after one event
|
* excl_unlink Omit events for children after they have been unlinked
|
||||||
* onlydir Operate only if name is directory
|
* oneshot Remove watch after one event
|
||||||
|
* onlydir Operate only if name is directory
|
||||||
|
|
||||||
recurse:
|
recurse:
|
||||||
Recursively watch files in the directory
|
Recursively watch files in the directory
|
||||||
|
@ -13,6 +13,7 @@ class SaltSSH(parsers.SaltSSHOptionParser):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.parse_args()
|
self.parse_args()
|
||||||
|
self.setup_logfile_logger()
|
||||||
|
|
||||||
ssh = salt.client.ssh.SSH(self.config)
|
ssh = salt.client.ssh.SSH(self.config)
|
||||||
ssh.run()
|
ssh.run()
|
||||||
|
@ -720,7 +720,8 @@ class Minion(MinionBase):
|
|||||||
' {0}'.format(opts['master']))
|
' {0}'.format(opts['master']))
|
||||||
if opts['master_shuffle']:
|
if opts['master_shuffle']:
|
||||||
shuffle(opts['master'])
|
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.
|
# We have a string, but a list was what was intended. Convert.
|
||||||
# See issue 23611 for details
|
# See issue 23611 for details
|
||||||
opts['master'] = list(opts['master'])
|
opts['master'] = list(opts['master'])
|
||||||
|
@ -1281,13 +1281,18 @@ def get_repo(repo, **kwargs):
|
|||||||
ppa_name, dist)
|
ppa_name, dist)
|
||||||
else:
|
else:
|
||||||
if HAS_SOFTWAREPROPERTIES:
|
if HAS_SOFTWAREPROPERTIES:
|
||||||
if hasattr(softwareproperties.ppa, 'PPAShortcutHandler'):
|
try:
|
||||||
repo = softwareproperties.ppa.PPAShortcutHandler(repo).expand(
|
if hasattr(softwareproperties.ppa, 'PPAShortcutHandler'):
|
||||||
__grains__['lsb_distrib_codename'])[0]
|
repo = softwareproperties.ppa.PPAShortcutHandler(
|
||||||
else:
|
repo).expand(dist)[0]
|
||||||
repo = softwareproperties.ppa.expand_ppa_line(
|
else:
|
||||||
repo,
|
repo = softwareproperties.ppa.expand_ppa_line(
|
||||||
__grains__['lsb_distrib_codename'])[0]
|
repo,
|
||||||
|
dist)[0]
|
||||||
|
except NameError as name_error:
|
||||||
|
raise CommandExecutionError(
|
||||||
|
'Could not find ppa {0}: {1}'.format(repo, name_error)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
repo = LP_SRC_FORMAT.format(owner_name, ppa_name, dist)
|
repo = LP_SRC_FORMAT.format(owner_name, ppa_name, dist)
|
||||||
|
|
||||||
|
@ -745,7 +745,9 @@ def shell(cmd,
|
|||||||
|
|
||||||
.. versionadded:: 2015.5.0
|
.. 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
|
without any further processing! Be absolutely sure that you
|
||||||
have properly santized the command passed to this function
|
have properly santized the command passed to this function
|
||||||
and do not use untrusted inputs.
|
and do not use untrusted inputs.
|
||||||
|
@ -575,7 +575,8 @@ def create_container(image,
|
|||||||
volumes_from=None,
|
volumes_from=None,
|
||||||
name=None,
|
name=None,
|
||||||
cpu_shares=None,
|
cpu_shares=None,
|
||||||
cpuset=None):
|
cpuset=None,
|
||||||
|
binds=None):
|
||||||
'''
|
'''
|
||||||
Create a new container
|
Create a new container
|
||||||
|
|
||||||
@ -594,10 +595,26 @@ def create_container(image,
|
|||||||
ports
|
ports
|
||||||
port redirections ``({'222': {}})``
|
port redirections ``({'222': {}})``
|
||||||
volumes
|
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
|
tty
|
||||||
attach ttys, Default is ``False``
|
attach ttys, Default is ``False``
|
||||||
stdin_open
|
stdin_open
|
||||||
@ -616,23 +633,31 @@ def create_container(image,
|
|||||||
salt '*' docker.create_container o/ubuntu volumes="['/s','/m:/f']"
|
salt '*' docker.create_container o/ubuntu volumes="['/s','/m:/f']"
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
log.trace("modules.dockerio.create_container() called for image " + image)
|
||||||
status = base_status.copy()
|
status = base_status.copy()
|
||||||
client = _get_client()
|
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:
|
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(
|
container_info = client.create_container(
|
||||||
image=image,
|
image=image,
|
||||||
command=command,
|
command=command,
|
||||||
@ -645,12 +670,14 @@ def create_container(image,
|
|||||||
ports=ports,
|
ports=ports,
|
||||||
environment=environment,
|
environment=environment,
|
||||||
dns=dns,
|
dns=dns,
|
||||||
volumes=mountpoints,
|
volumes=volumes,
|
||||||
volumes_from=volumes_from,
|
volumes_from=volumes_from,
|
||||||
name=name,
|
name=name,
|
||||||
cpu_shares=cpu_shares,
|
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']
|
container = container_info['Id']
|
||||||
callback = _valid
|
callback = _valid
|
||||||
comment = 'Container created'
|
comment = 'Container created'
|
||||||
@ -660,8 +687,9 @@ def create_container(image,
|
|||||||
}
|
}
|
||||||
__salt__['mine.send']('docker.get_containers', host=True)
|
__salt__['mine.send']('docker.get_containers', host=True)
|
||||||
return callback(status, id_=container, comment=comment, out=out)
|
return callback(status, id_=container, comment=comment, out=out)
|
||||||
except Exception:
|
except Exception as e:
|
||||||
_invalid(status, id_=image, out=traceback.format_exc())
|
_invalid(status, id_=image, out=traceback.format_exc())
|
||||||
|
raise e
|
||||||
__salt__['mine.send']('docker.get_containers', host=True)
|
__salt__['mine.send']('docker.get_containers', host=True)
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
@ -776,7 +776,6 @@ def trust_key(keyid=None,
|
|||||||
salt '*' gpg.trust_key keyid='3FAD9F1E' trust_level='marginally'
|
salt '*' gpg.trust_key keyid='3FAD9F1E' trust_level='marginally'
|
||||||
salt '*' gpg.trust_key fingerprint='53C96788253E58416D20BCD352952C84C3252192' trust_level='not_trusted'
|
salt '*' gpg.trust_key fingerprint='53C96788253E58416D20BCD352952C84C3252192' trust_level='not_trusted'
|
||||||
salt '*' gpg.trust_key keys=3FAD9F1E trust_level='ultimately' user='username'
|
salt '*' gpg.trust_key keys=3FAD9F1E trust_level='ultimately' user='username'
|
||||||
|
|
||||||
'''
|
'''
|
||||||
ret = {
|
ret = {
|
||||||
'res': True,
|
'res': True,
|
||||||
|
@ -279,8 +279,11 @@ def get_channel_access(channel=14, read_mode='non_volatile', **kwargs):
|
|||||||
- api_port=623
|
- api_port=623
|
||||||
- api_kg=None
|
- api_kg=None
|
||||||
|
|
||||||
:return: A Python dict with the following keys/values:
|
return
|
||||||
|
A Python dict with the following keys/values:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
{
|
{
|
||||||
alerting:
|
alerting:
|
||||||
per_msg_auth:
|
per_msg_auth:
|
||||||
@ -322,14 +325,17 @@ def get_channel_info(channel=14, **kwargs):
|
|||||||
- api_port=623
|
- api_port=623
|
||||||
- api_kg=None
|
- api_kg=None
|
||||||
|
|
||||||
:return:
|
return
|
||||||
session_support:
|
channel session supports:
|
||||||
no_session: channel is session-less
|
|
||||||
single: channel is single-session
|
.. code-block:: none
|
||||||
multi: channel is multi-session
|
|
||||||
auto: channel is session-based (channel could alternate between
|
- no_session: channel is session-less
|
||||||
single- and multi-session operation, as can occur with a
|
- single: channel is single-session
|
||||||
serial/modem channel that supports connection mode auto-detect)
|
- 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:
|
CLI Examples:
|
||||||
|
|
||||||
@ -419,19 +425,20 @@ def get_user_access(uid, channel=14, **kwargs):
|
|||||||
- api_port=623
|
- api_port=623
|
||||||
- api_kg=None
|
- api_kg=None
|
||||||
|
|
||||||
:return:
|
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]
|
|
||||||
|
|
||||||
|
.. 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:
|
CLI Examples:
|
||||||
|
|
||||||
@ -770,16 +777,20 @@ def get_user(uid, channel=14, **kwargs):
|
|||||||
- api_port=623
|
- api_port=623
|
||||||
- api_kg=None
|
- api_kg=None
|
||||||
|
|
||||||
:return:
|
return
|
||||||
name: (str)
|
|
||||||
uid: (int)
|
.. code-block:: none
|
||||||
channel: (int)
|
|
||||||
access:
|
name: (str)
|
||||||
- callback (bool)
|
uid: (int)
|
||||||
- link_auth (bool)
|
channel: (int)
|
||||||
- ipmi_msg (bool)
|
access:
|
||||||
- privilege_level: (str)[callback, user, operatorm administrator,
|
- callback (bool)
|
||||||
proprietary, no_access]
|
- link_auth (bool)
|
||||||
|
- ipmi_msg (bool)
|
||||||
|
- privilege_level: (str)[callback, user, operatorm administrator,
|
||||||
|
proprietary, no_access]
|
||||||
|
|
||||||
CLI Examples:
|
CLI Examples:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
@ -696,7 +696,7 @@ def mount(name, device, mkmnt=False, fstype='', opts='defaults', user=None):
|
|||||||
opts = opts.split(',')
|
opts = opts.split(',')
|
||||||
|
|
||||||
if not os.path.exists(name) and mkmnt:
|
if not os.path.exists(name) and mkmnt:
|
||||||
__salt__['file.mkdir'](name=name, user=user)
|
__salt__['file.mkdir'](name, user=user)
|
||||||
|
|
||||||
args = ''
|
args = ''
|
||||||
if opts is not None:
|
if opts is not None:
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
'''
|
'''
|
||||||
:requires: libnacl
|
|
||||||
https://github.com/saltstack/libnacl
|
|
||||||
|
|
||||||
This module helps include encrypted passwords in pillars, grains and salt state files.
|
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.
|
regardless if they are encrypted or not.
|
||||||
|
|
||||||
When generating keys and encrypting passwords use --local when using salt-call for extra
|
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.
|
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:
|
To generate your `key` or `keyfile` you can use:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
salt-call --local nacl.keygen keyfile=/root/.nacl
|
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
|
salt-call --local nacl.enc mypass keyfile=/root/.nacl
|
||||||
DRB7Q6/X5gGSRCTpZyxS6hXO5LnlJIIJ4ivbmUlbWj0llUA+uaVyvou3vJ4=
|
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
|
salt-call --local nacl.dec data='DRB7Q6/X5gGSRCTpZyxS6hXO5LnlJIIJ4ivbmUlbWj0llUA+uaVyvou3vJ4=' keyfile=/root/.nacl
|
||||||
mypass
|
mypass
|
||||||
|
|
||||||
The following optional configurations can be defined in the
|
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
|
cat /etc/salt/master.d/nacl.conf
|
||||||
nacl.config:
|
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:
|
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'
|
salt-run nacl.enc 'myotherpass'
|
||||||
|
|
||||||
Now you can create a pillar with protected data like:
|
Now you can create a pillar with protected data like:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
pillarexample:
|
pillarexample:
|
||||||
user: root
|
user: root
|
||||||
password: {{ salt.nacl.dec('DRB7Q6/X5gGSRCTpZyxS6hXO5LnlJIIJ4ivbmUlbWj0llUA+uaVyvou3vJ4=') }}
|
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
|
salt-call nacl.enc minionname:dbrole
|
||||||
AL24Z2C5OlkReer3DuQTFdrNLchLuz3NGIhGjZkLtKRYry/b/CksWM8O9yskLwH2AGVLoEXI5jAa
|
AL24Z2C5OlkReer3DuQTFdrNLchLuz3NGIhGjZkLtKRYry/b/CksWM8O9yskLwH2AGVLoEXI5jAa
|
||||||
|
@ -119,6 +119,11 @@ def install(pkg=None,
|
|||||||
elif pkgs:
|
elif pkgs:
|
||||||
cmd += ' "{0}"'.format('" "'.join(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)
|
result = __salt__['cmd.run_all'](cmd, python_shell=False, cwd=dir, runas=runas, env=env)
|
||||||
|
|
||||||
if result['retcode'] != 0:
|
if result['retcode'] != 0:
|
||||||
@ -151,7 +156,8 @@ def install(pkg=None,
|
|||||||
|
|
||||||
def uninstall(pkg,
|
def uninstall(pkg,
|
||||||
dir=None,
|
dir=None,
|
||||||
runas=None):
|
runas=None,
|
||||||
|
env=None):
|
||||||
'''
|
'''
|
||||||
Uninstall an NPM package.
|
Uninstall an NPM package.
|
||||||
|
|
||||||
@ -167,6 +173,13 @@ def uninstall(pkg,
|
|||||||
runas
|
runas
|
||||||
The user to run NPM with
|
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:
|
CLI Example:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. 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'
|
cmd = 'npm uninstall'
|
||||||
|
|
||||||
if dir is None:
|
if dir is None:
|
||||||
@ -182,7 +200,7 @@ def uninstall(pkg,
|
|||||||
|
|
||||||
cmd += ' "{0}"'.format(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:
|
if result['retcode'] != 0:
|
||||||
log.error(result['stderr'])
|
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'
|
cmd = 'npm list --silent --json'
|
||||||
|
|
||||||
if dir is None:
|
if dir is None:
|
||||||
|
@ -128,10 +128,7 @@ def list_upgrades(refresh=False):
|
|||||||
if refresh:
|
if refresh:
|
||||||
options.append('-y')
|
options.append('-y')
|
||||||
|
|
||||||
cmd = (
|
cmd = ('pacman {0}').format(' '.join(options))
|
||||||
'pacman {0} | egrep -v '
|
|
||||||
r'"^\s|^:"'
|
|
||||||
).format(' '.join(options))
|
|
||||||
|
|
||||||
call = __salt__['cmd.run_all'](cmd, output_loglevel='trace')
|
call = __salt__['cmd.run_all'](cmd, output_loglevel='trace')
|
||||||
|
|
||||||
@ -147,7 +144,9 @@ def list_upgrades(refresh=False):
|
|||||||
else:
|
else:
|
||||||
out = call['stdout']
|
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(' ')
|
comps = line.split(' ')
|
||||||
if len(comps) < 2:
|
if len(comps) < 2:
|
||||||
continue
|
continue
|
||||||
|
@ -228,11 +228,13 @@ def enable():
|
|||||||
def disable(message=None):
|
def disable(message=None):
|
||||||
'''
|
'''
|
||||||
.. versionadded:: 2014.7.0
|
.. versionadded:: 2014.7.0
|
||||||
|
|
||||||
Disable the puppet agent
|
Disable the puppet agent
|
||||||
|
|
||||||
message
|
message
|
||||||
.. versionadded:: 2015.5.2
|
.. versionadded:: 2015.5.2
|
||||||
disable message to send to puppet
|
|
||||||
|
Disable message to send to puppet
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
|
|
||||||
@ -240,7 +242,6 @@ def disable(message=None):
|
|||||||
|
|
||||||
salt '*' puppet.disable
|
salt '*' puppet.disable
|
||||||
salt '*' puppet.disable 'disabled for a good reason'
|
salt '*' puppet.disable 'disabled for a good reason'
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
_check_puppet()
|
_check_puppet()
|
||||||
|
@ -681,10 +681,9 @@ def generateBlobs(api_key=None,
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
salt '*' get_intergers number=5 min=1 max=6
|
salt '*' get_integers number=5 min=1 max=6
|
||||||
|
|
||||||
salt '*' get_intergers number=5 min=1 max=6
|
|
||||||
|
|
||||||
|
salt '*' get_integers number=5 min=1 max=6
|
||||||
'''
|
'''
|
||||||
ret = {'res': True}
|
ret = {'res': True}
|
||||||
|
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- 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
|
# Import python libs
|
||||||
|
@ -58,8 +58,7 @@ def _call_system_profiler(datatype):
|
|||||||
def receipts():
|
def receipts():
|
||||||
'''
|
'''
|
||||||
Return the results of a call to
|
Return the results of a call to
|
||||||
`system_profiler -xml -detail full
|
``system_profiler -xml -detail full SPInstallHistoryDataType``
|
||||||
SPInstallHistoryDataType`
|
|
||||||
as a dictionary. Top-level keys of the dictionary
|
as a dictionary. Top-level keys of the dictionary
|
||||||
are the names of each set of install receipts, since
|
are the names of each set of install receipts, since
|
||||||
there can be multiple receipts with the same name.
|
there can be multiple receipts with the same name.
|
||||||
@ -99,12 +98,11 @@ def receipts():
|
|||||||
def applications():
|
def applications():
|
||||||
'''
|
'''
|
||||||
Return the results of a call to
|
Return the results of a call to
|
||||||
`system_profiler -xml -detail full
|
``system_profiler -xml -detail full SPApplicationsDataType``
|
||||||
SPApplicationsDataType`
|
|
||||||
as a dictionary. Top-level keys of the dictionary
|
as a dictionary. Top-level keys of the dictionary
|
||||||
are the names of each set of install receipts, since
|
are the names of each set of install receipts, since
|
||||||
there can be multiple receipts with the same name.
|
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
|
Note that this can take a long time depending on how many
|
||||||
applications are installed on the target Mac.
|
applications are installed on the target Mac.
|
||||||
|
@ -7,17 +7,18 @@ A REST API for Salt
|
|||||||
|
|
||||||
.. py:currentmodule:: salt.netapi.rest_cherrypy.app
|
.. py:currentmodule:: salt.netapi.rest_cherrypy.app
|
||||||
|
|
||||||
:depends: - CherryPy Python module. Versions 3.2.{2,3,4} are strongly
|
:depends:
|
||||||
recommended due to a known `SSL error
|
- CherryPy Python module. Versions 3.2.{2,3,4} are strongly
|
||||||
<https://bitbucket.org/cherrypy/cherrypy/issue/1298/ssl-not-working>`_
|
recommended due to a known `SSL error
|
||||||
introduced in version 3.2.5. The issue was reportedly resolved with
|
<https://bitbucket.org/cherrypy/cherrypy/issue/1298/ssl-not-working>`_
|
||||||
CherryPy milestone 3.3, but the patch was committed for version 3.6.1.
|
introduced in version 3.2.5. The issue was reportedly resolved with
|
||||||
- salt-api package
|
CherryPy milestone 3.3, but the patch was committed for version 3.6.1.
|
||||||
:optdepends: - ws4py Python module for websockets support.
|
:optdepends: - ws4py Python module for websockets support.
|
||||||
:client_libraries:
|
:client_libraries:
|
||||||
- Java: https://github.com/SUSE/saltstack-netapi-client-java
|
- Java: https://github.com/SUSE/saltstack-netapi-client-java
|
||||||
- Python: https://github.com/saltstack/pepper
|
- 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
|
<acl-eauth>` system which requires additional configuration not described
|
||||||
here.
|
here.
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ them.
|
|||||||
An example Django module that registers a function called
|
An example Django module that registers a function called
|
||||||
'returner_callback' with this module's 'returner' function:
|
'returner_callback' with this module's 'returner' function:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
import salt.returners.django_return
|
import salt.returners.django_return
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
|
@ -349,7 +349,7 @@ def lock(backend=None, remote=None):
|
|||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
This will only operate on enabled backends (those configured in
|
This will only operate on enabled backends (those configured in
|
||||||
:master_conf:`fileserver_backend`).
|
:conf_master:`fileserver_backend`).
|
||||||
|
|
||||||
backend
|
backend
|
||||||
Only set the update lock for the specified backend(s).
|
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
|
Query a resource, and decode the return data
|
||||||
|
|
||||||
.. versionadded:: 2015.2
|
.. versionadded:: 2015.5.0
|
||||||
|
|
||||||
CLI Example:
|
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
|
Update the local CA bundle file from a URL
|
||||||
|
|
||||||
.. versionadded:: 2015.2
|
.. versionadded:: 2015.5.0
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
|
|
||||||
|
@ -236,10 +236,10 @@ def present(
|
|||||||
listeners
|
listeners
|
||||||
A list of listener lists; example::
|
A list of listener lists; example::
|
||||||
|
|
||||||
[
|
[
|
||||||
['443', 'HTTPS', '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']
|
['8443', '80', 'HTTPS', 'HTTP', 'arn:aws:iam::1111111:server-certificate/mycert']
|
||||||
]
|
]
|
||||||
|
|
||||||
subnets
|
subnets
|
||||||
A list of subnet IDs in your VPC to attach to your LoadBalancer.
|
A list of subnet IDs in your VPC to attach to your LoadBalancer.
|
||||||
|
@ -69,6 +69,7 @@ Available Functions
|
|||||||
my_service:
|
my_service:
|
||||||
docker.running:
|
docker.running:
|
||||||
- container: mysuperdocker
|
- container: mysuperdocker
|
||||||
|
- image: corp/mysuperdocker_img
|
||||||
- ports:
|
- ports:
|
||||||
"5000/tcp":
|
"5000/tcp":
|
||||||
HostIp: ""
|
HostIp: ""
|
||||||
@ -210,6 +211,103 @@ def _get_image_name(image, tag):
|
|||||||
return image
|
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):
|
def mod_watch(name, sfun=None, *args, **kw):
|
||||||
if sfun == 'built':
|
if sfun == 'built':
|
||||||
# Needs to refresh the image
|
# Needs to refresh the image
|
||||||
@ -531,7 +629,7 @@ def installed(name,
|
|||||||
- a port to map
|
- a port to map
|
||||||
- a mapping of mapping portInHost : PortInContainer
|
- a mapping of mapping portInHost : PortInContainer
|
||||||
volumes
|
volumes
|
||||||
List of volumes
|
List of volumes (see notes for the running function)
|
||||||
|
|
||||||
For other parameters, see absolutely first the salt.modules.dockerio
|
For other parameters, see absolutely first the salt.modules.dockerio
|
||||||
execution module and the docker-py python bindings for docker
|
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 container exists but is not started, try to start it
|
||||||
if already_exists:
|
if already_exists:
|
||||||
return _valid(comment='image {0!r} already exists'.format(name))
|
return _valid(comment='image {0!r} already exists'.format(name))
|
||||||
dports, dvolumes, denvironment = {}, [], {}
|
dports, denvironment = {}, {}
|
||||||
if not ports:
|
if not ports:
|
||||||
ports = []
|
ports = []
|
||||||
if not volumes:
|
if not volumes:
|
||||||
@ -574,15 +672,13 @@ def installed(name,
|
|||||||
else:
|
else:
|
||||||
for k in p:
|
for k in p:
|
||||||
dports[str(p)] = {}
|
dports[str(p)] = {}
|
||||||
for p in volumes:
|
|
||||||
vals = []
|
parsed_volumes = _parse_volumes(volumes)
|
||||||
if not isinstance(p, dict):
|
bindvolumes = parsed_volumes['bindvols']
|
||||||
vals.append('{0}'.format(p))
|
contvolumes = parsed_volumes['contvols']
|
||||||
else:
|
|
||||||
for k in p:
|
|
||||||
vals.append('{0}:{1}'.format(k, p[k]))
|
|
||||||
dvolumes.extend(vals)
|
|
||||||
kw = dict(
|
kw = dict(
|
||||||
|
binds=bindvolumes,
|
||||||
command=command,
|
command=command,
|
||||||
hostname=hostname,
|
hostname=hostname,
|
||||||
user=user,
|
user=user,
|
||||||
@ -593,7 +689,7 @@ def installed(name,
|
|||||||
ports=dports,
|
ports=dports,
|
||||||
environment=denvironment,
|
environment=denvironment,
|
||||||
dns=dns,
|
dns=dns,
|
||||||
volumes=dvolumes,
|
volumes=contvolumes,
|
||||||
volumes_from=volumes_from,
|
volumes_from=volumes_from,
|
||||||
name=name,
|
name=name,
|
||||||
cpu_shares=cpu_shares,
|
cpu_shares=cpu_shares,
|
||||||
@ -860,44 +956,47 @@ def running(name,
|
|||||||
volumes
|
volumes
|
||||||
List of volumes to mount or create in the container (like ``-v`` of ``docker run`` command),
|
List of volumes to mount or create in the container (like ``-v`` of ``docker run`` command),
|
||||||
mapping host directory to container directory.
|
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
|
.. code-block:: yaml
|
||||||
|
|
||||||
- volumes:
|
- 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):
|
source:target from docker is preserved):
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
- volumes:
|
- 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
|
.. code-block:: yaml
|
||||||
|
|
||||||
- volumes:
|
- volumes:
|
||||||
- /home/user1:
|
- /home/user1:
|
||||||
bind: /mnt/vol2
|
bind: /mnt/vol2
|
||||||
ro: true
|
ro: True
|
||||||
- /var/www:
|
- /var/www:
|
||||||
bind: /mnt/vol1
|
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
|
.. code-block:: yaml
|
||||||
|
|
||||||
- volumes:
|
- volumes:
|
||||||
/home/user1:
|
/home/user1:
|
||||||
bind: /mnt/vol2
|
bind: /mnt/vol2
|
||||||
ro: true
|
ro: True
|
||||||
/var/www:
|
/var/www:
|
||||||
bind: /mnt/vol1
|
bind: /mnt/vol1
|
||||||
ro: false
|
ro: False
|
||||||
|
|
||||||
volumes_from
|
volumes_from
|
||||||
List of containers to share volumes with
|
List of containers to share volumes with
|
||||||
@ -1084,6 +1183,11 @@ def running(name,
|
|||||||
else:
|
else:
|
||||||
# assume just a port to expose
|
# assume just a port to expose
|
||||||
exposeports.append(str(port))
|
exposeports.append(str(port))
|
||||||
|
|
||||||
|
parsed_volumes = _parse_volumes(volumes)
|
||||||
|
bindvolumes = parsed_volumes['bindvols']
|
||||||
|
contvolumes = parsed_volumes['contvols']
|
||||||
|
|
||||||
if not already_exists:
|
if not already_exists:
|
||||||
kwargs = dict(command=command,
|
kwargs = dict(command=command,
|
||||||
hostname=hostname,
|
hostname=hostname,
|
||||||
@ -1095,6 +1199,7 @@ def running(name,
|
|||||||
ports=exposeports,
|
ports=exposeports,
|
||||||
environment=denvironment,
|
environment=denvironment,
|
||||||
dns=dns,
|
dns=dns,
|
||||||
|
binds=bindvolumes,
|
||||||
volumes=contvolumes,
|
volumes=contvolumes,
|
||||||
name=name,
|
name=name,
|
||||||
cpu_shares=cpu_shares,
|
cpu_shares=cpu_shares,
|
||||||
|
@ -163,8 +163,10 @@ def user_present(name, uid, password, channel=14, callback=False,
|
|||||||
|
|
||||||
callback
|
callback
|
||||||
User Restricted to Callback
|
User Restricted to Callback
|
||||||
|
|
||||||
False = User Privilege Limit is determined by the User Privilege Limit
|
False = User Privilege Limit is determined by the User Privilege Limit
|
||||||
parameter privilege_level, for both callback and non-callback connections.
|
parameter privilege_level, for both callback and non-callback connections.
|
||||||
|
|
||||||
True = User Privilege Limit is determined by the privilege_level
|
True = User Privilege Limit is determined by the privilege_level
|
||||||
parameter for callback connections, but is restricted to Callback
|
parameter for callback connections, but is restricted to Callback
|
||||||
level for non-callback connections. Thus, a user can only initiate
|
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
|
Ensure a Linux ACL is present
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
root:
|
root:
|
||||||
acl.present:
|
acl.present:
|
||||||
@ -15,7 +15,7 @@ Ensure a Linux ACL is present
|
|||||||
|
|
||||||
Ensure a Linux ACL does not exist
|
Ensure a Linux ACL does not exist
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
root:
|
root:
|
||||||
acl.absent:
|
acl.absent:
|
||||||
|
@ -228,7 +228,7 @@ def run(name, **kwargs):
|
|||||||
ret['result'] = False
|
ret['result'] = False
|
||||||
return ret
|
return ret
|
||||||
else:
|
else:
|
||||||
if mret is not None:
|
if mret is not None or mret is not {}:
|
||||||
ret['changes']['ret'] = mret
|
ret['changes']['ret'] = mret
|
||||||
|
|
||||||
if 'returner' in kwargs:
|
if 'returner' in kwargs:
|
||||||
|
@ -19,7 +19,7 @@ def license_present(name):
|
|||||||
on the host.
|
on the host.
|
||||||
|
|
||||||
name
|
name
|
||||||
The licnese key to ensure is present
|
The license key to ensure is present
|
||||||
'''
|
'''
|
||||||
ret = {'name': name,
|
ret = {'name': name,
|
||||||
'changes': {},
|
'changes': {},
|
||||||
@ -61,7 +61,7 @@ def license_absent(name):
|
|||||||
on the host.
|
on the host.
|
||||||
|
|
||||||
name
|
name
|
||||||
The licnese key to ensure is absent
|
The license key to ensure is absent
|
||||||
'''
|
'''
|
||||||
ret = {'name': name,
|
ret = {'name': name,
|
||||||
'changes': {},
|
'changes': {},
|
||||||
|
@ -81,7 +81,7 @@ def present(name,
|
|||||||
'information or see #6961.'
|
'information or see #6961.'
|
||||||
)
|
)
|
||||||
|
|
||||||
if any(user, owner, conf, write, read):
|
if any((user, owner, conf, write, read)):
|
||||||
salt.utils.warn_until(
|
salt.utils.warn_until(
|
||||||
'Beryllium',
|
'Beryllium',
|
||||||
'Passed \'owner\', \'user\', \'conf\', \'write\' or \'read\' '
|
'Passed \'owner\', \'user\', \'conf\', \'write\' or \'read\' '
|
||||||
|
@ -69,7 +69,6 @@ def post_message(name,
|
|||||||
api_key
|
api_key
|
||||||
The api key for Slack to use for authentication,
|
The api key for Slack to use for authentication,
|
||||||
if not specified in the configuration options of master or minion.
|
if not specified in the configuration options of master or minion.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
ret = {'name': name,
|
ret = {'name': name,
|
||||||
'changes': {},
|
'changes': {},
|
||||||
|
@ -83,15 +83,16 @@ def removed(name):
|
|||||||
the server is restarted.
|
the server is restarted.
|
||||||
|
|
||||||
Example:
|
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
|
name listed for each feature, not the indented one. Do not use the role or feature names mentioned in the
|
||||||
PKGMGR documentation.
|
PKGMGR documentation.
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
ISWebserverRole:
|
ISWebserverRole:
|
||||||
win_servermanager.removed:
|
win_servermanager.removed:
|
||||||
- name: Web-Server
|
- name: Web-Server
|
||||||
'''
|
'''
|
||||||
ret = {'name': name,
|
ret = {'name': name,
|
||||||
'result': True,
|
'result': True,
|
||||||
|
@ -111,9 +111,12 @@ def yamlify_arg(arg):
|
|||||||
import salt.utils.yamlloader as yamlloader
|
import salt.utils.yamlloader as yamlloader
|
||||||
original_arg = arg
|
original_arg = arg
|
||||||
if '#' in arg:
|
if '#' in arg:
|
||||||
# Don't yamlify this argument or the '#' and everything after
|
# Only yamlify if it parses into a non-string type, to prevent
|
||||||
# it will be interpreted as a comment.
|
# loss of content due to # as comment character
|
||||||
return arg
|
parsed_arg = yamlloader.load(arg, Loader=yamlloader.SaltYamlSafeLoader)
|
||||||
|
if isinstance(parsed_arg, six.string_types):
|
||||||
|
return arg
|
||||||
|
return parsed_arg
|
||||||
if arg == 'None':
|
if arg == 'None':
|
||||||
arg = None
|
arg = None
|
||||||
else:
|
else:
|
||||||
|
@ -31,6 +31,12 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
# Older jinja does not need markupsafe
|
# Older jinja does not need markupsafe
|
||||||
HAS_MARKUPSAFE = False
|
HAS_MARKUPSAFE = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
import xml
|
||||||
|
HAS_XML = True
|
||||||
|
except ImportError:
|
||||||
|
HAS_XML = False
|
||||||
# pylint: enable=import-error,no-name-in-module
|
# pylint: enable=import-error,no-name-in-module
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -117,6 +123,10 @@ def gen_thin(cachedir, extra_mods='', overwrite=False, so_mods=''):
|
|||||||
if HAS_SSL_MATCH_HOSTNAME:
|
if HAS_SSL_MATCH_HOSTNAME:
|
||||||
tops.append(os.path.dirname(os.path.dirname(ssl_match_hostname.__file__)))
|
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]:
|
for mod in [m for m in extra_mods.split(',') if m]:
|
||||||
if mod not in locals() and mod not in globals():
|
if mod not in locals() and mod not in globals():
|
||||||
try:
|
try:
|
||||||
|
@ -52,10 +52,12 @@ def update_config(file_name, yaml_contents):
|
|||||||
specified by ``default_include``.
|
specified by ``default_include``.
|
||||||
This folder is named ``master.d`` by
|
This folder is named ``master.d`` by
|
||||||
default. Please look at
|
default. Please look at
|
||||||
http://docs.saltstack.com/en/latest/ref/configuration/master.html#include-configuration
|
:conf_master:`include-configuration`
|
||||||
for more information.
|
for more information.
|
||||||
|
|
||||||
Example low data::
|
Example low data:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'username': 'salt',
|
'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