mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 17:09:03 +00:00
Merge branch 'develop' of github.com:saltstack/salt into 42713_mine.get_back_compat
... and fixed conflict
This commit is contained in:
commit
5c01c74fbc
4
.github/stale.yml
vendored
4
.github/stale.yml
vendored
@ -1,8 +1,8 @@
|
||||
# Probot Stale configuration file
|
||||
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
# 910 is approximately 2 years and 6 months
|
||||
daysUntilStale: 910
|
||||
# 900 is approximately 2 years and 5 months
|
||||
daysUntilStale: 900
|
||||
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -91,3 +91,8 @@ tests/integration/cloud/providers/pki/minions
|
||||
|
||||
# Ignore tox virtualenvs
|
||||
/.tox/
|
||||
|
||||
# Kitchen tests files
|
||||
.kitchen/
|
||||
.bundle/
|
||||
Gemfile.lock
|
||||
|
@ -44,6 +44,11 @@ may take a few moments for someone to reply.
|
||||
|
||||
`<http://webchat.freenode.net/?channels=salt&uio=Mj10cnVlJjk9dHJ1ZSYxMD10cnVl83>`_
|
||||
|
||||
**SaltStack Slack** - Alongside IRC is our SaltStack Community Slack for the
|
||||
SaltStack Working groups. Use the following link to request an invitation.
|
||||
|
||||
`<https://saltstackcommunity.herokuapp.com/>`_
|
||||
|
||||
**Mailing List** - The SaltStack community users mailing list is hosted by
|
||||
Google groups. Anyone can post to ask questions about SaltStack products and
|
||||
anyone can help answer. Join the conversation!
|
||||
|
@ -718,7 +718,7 @@ Note that ping_on_rotate may cause high load on the master immediately after
|
||||
the key rotation event as minions reconnect. Consider this carefully if this
|
||||
salt master is managing a large number of minions.
|
||||
|
||||
.. code-black:: yaml
|
||||
.. code-block:: yaml
|
||||
|
||||
ping_on_rotate: False
|
||||
|
||||
@ -904,7 +904,7 @@ is set to ``tcp`` by default on Windows.
|
||||
|
||||
ipc_mode: ipc
|
||||
|
||||
.. conf_master::
|
||||
.. conf_master:: tcp_master_pub_port
|
||||
|
||||
``tcp_master_pub_port``
|
||||
-----------------------
|
||||
@ -4237,6 +4237,7 @@ Default: ``10``
|
||||
The number of workers for the runner/wheel in the reactor.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
reactor_worker_threads: 10
|
||||
|
||||
.. conf_master:: reactor_worker_hwm
|
||||
|
@ -2387,6 +2387,7 @@ Default: ``10``
|
||||
The number of workers for the runner/wheel in the reactor.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
reactor_worker_threads: 10
|
||||
|
||||
.. conf_minion:: reactor_worker_hwm
|
||||
|
@ -51,7 +51,7 @@ actually speed things up.
|
||||
To run the above state much faster make sure that the ``sleep 5`` is evaluated
|
||||
before the ``nginx`` state
|
||||
|
||||
.. code_block:: yaml
|
||||
.. code-block:: yaml
|
||||
|
||||
sleep 10:
|
||||
cmd.run:
|
||||
|
@ -68,8 +68,8 @@ Each salt minion establishes a connection to the master Publisher.
|
||||
EventPublisher
|
||||
--------------
|
||||
|
||||
The EventPublisher publishes events onto the event bus. It is bound to the
|
||||
following:
|
||||
The EventPublisher publishes master events out to any event listeners. It is
|
||||
bound to the following:
|
||||
|
||||
* IPC: master_event_pull.ipc
|
||||
* IPC: master_event_pub.ipc
|
||||
@ -110,48 +110,37 @@ The typical lifecycle of a salt job from the perspective of the master
|
||||
might be as follows:
|
||||
|
||||
1) A command is issued on the CLI. For example, 'salt my_minion test.ping'.
|
||||
|
||||
2) The 'salt' command uses LocalClient to generate a request to the salt master
|
||||
by connecting to the ReqServer on TCP:4506 and issuing the job.
|
||||
|
||||
3) The salt-master ReqServer sees the request and passes it to an available
|
||||
MWorker over workers.ipc.
|
||||
|
||||
4) A worker picks up the request and handles it. First, it checks to ensure
|
||||
that the requested user has permissions to issue the command. Then, it sends
|
||||
the publish command to all connected minions. For the curious, this happens
|
||||
in ClearFuncs.publish().
|
||||
|
||||
5) The worker announces on the master event bus that it is about to publish
|
||||
a job to connected minions. This happens by placing the event on the master
|
||||
event bus (master_event_pull.ipc) where the EventPublisher picks it up and
|
||||
distributes it to all connected event listeners on master_event_pub.ipc.
|
||||
|
||||
6) The message to the minions is encrypted and sent to the Publisher via IPC
|
||||
on publish_pull.ipc.
|
||||
|
||||
7) Connected minions have a TCP session established with the Publisher on TCP
|
||||
port 4505 where they await commands. When the Publisher receives the job over
|
||||
publish_pull, it sends the jobs across the wire to the minions for processing.
|
||||
|
||||
8) After the minions receive the request, they decrypt it and perform any
|
||||
requested work, if they determine that they are targeted to do so.
|
||||
|
||||
9) When the minion is ready to respond, it publishes the result of its job back
|
||||
to the master by sending the encrypted result back to the master on TCP 4506
|
||||
where it is again picked up by the ReqServer and forwarded to an available
|
||||
MWorker for processing. (Again, this happens by passing this message across
|
||||
workers.ipc to an available worker.)
|
||||
|
||||
10) When the MWorker receives the job it decrypts it and fires an event onto
|
||||
the master event bus (master_event_pull.ipc). (Again for the curious, this
|
||||
happens in AESFuncs._return().
|
||||
|
||||
11) The EventPublisher sees this event and re-publishes it on the bus to all
|
||||
connected listeners of the master event bus (on master_event_pub.ipc). This
|
||||
is where the LocalClient has been waiting, listening to the event bus for
|
||||
minion replies. It gathers the job and stores the result.
|
||||
|
||||
12) When all targeted minions have replied or the timeout has been exceeded,
|
||||
the salt client displays the results of the job to the user on the CLI.
|
||||
|
||||
@ -167,8 +156,8 @@ Salt. It can either operate as a stand-alone daemon which accepts commands
|
||||
locally via 'salt-call' or it can connect back to a master and receive commands
|
||||
remotely.
|
||||
|
||||
When starting up, salt minions connect _back_ to a master defined in the minion
|
||||
config file. The connect to two ports on the master:
|
||||
When starting up, salt minions connect *back* to a master defined in the minion
|
||||
config file. They connect to two ports on the master:
|
||||
|
||||
* TCP: 4505
|
||||
This is the connection to the master Publisher. It is on this port that
|
||||
@ -196,8 +185,8 @@ permissions can read or write to the bus as a common interface with the salt
|
||||
minion.
|
||||
|
||||
|
||||
Job Flow
|
||||
--------
|
||||
Minion Job Flow
|
||||
---------------
|
||||
|
||||
When a salt minion starts up, it attempts to connect to the Publisher and the
|
||||
ReqServer on the salt master. It then attempts to authenticate and once the
|
||||
@ -206,28 +195,22 @@ minion has successfully authenticated, it simply listens for jobs.
|
||||
Jobs normally come either come from the 'salt-call' script run by a local user
|
||||
on the salt minion or they can come directly from a master.
|
||||
|
||||
Master Job Flow
|
||||
---------------
|
||||
The job flow on a minion, coming from the master via a 'salt' command is as
|
||||
follows:
|
||||
|
||||
1) A master publishes a job that is received by a minion as outlined by the
|
||||
master's job flow above.
|
||||
|
||||
2) The minion is polling its receive socket that's connected to the master
|
||||
Publisher (TCP 4505 on master). When it detects an incoming message, it picks it
|
||||
up from the socket and decrypts it.
|
||||
|
||||
3) A new minion process or thread is created and provided with the contents of the
|
||||
decrypted message. The _thread_return() method is provided with the contents of
|
||||
the received message.
|
||||
|
||||
4) The new minion thread is created. The _thread_return() function starts up
|
||||
and actually calls out to the requested function contained in the job.
|
||||
|
||||
5) The requested function runs and returns a result. [Still in thread.]
|
||||
|
||||
6) The result of the function that's run is encrypted and returned to the
|
||||
master's ReqServer (TCP 4506 on master). [Still in thread.]
|
||||
|
||||
7) Thread exits. Because the main thread was only blocked for the time that it
|
||||
took to initialize the worker thread, many other requests could have been
|
||||
received and processed during this time.
|
||||
@ -241,6 +224,5 @@ clear and when they are passed using encryption. There are two rules governing
|
||||
this behaviour:
|
||||
|
||||
1) ClearFuncs is used for intra-master communication and during the initial
|
||||
authentication handshake between a minion and master during the key exhange.
|
||||
|
||||
authentication handshake between a minion and master during the key exchange.
|
||||
2) AESFuncs is used everywhere else.
|
||||
|
@ -4,12 +4,25 @@ Event System
|
||||
|
||||
The Salt Event System is used to fire off events enabling third party
|
||||
applications or external processes to react to behavior within Salt.
|
||||
The event system uses a publish-subscribe pattern, otherwise know as pub/sub.
|
||||
|
||||
The event system is comprised of a two primary components:
|
||||
Event Bus
|
||||
=========
|
||||
|
||||
The event system is comprised of a two primary components, which make up the
|
||||
concept of an Event Bus:
|
||||
|
||||
* The event sockets which publishes events.
|
||||
* The event library which can listen to events and send events into the salt system.
|
||||
|
||||
Events are published onto the event bus and event bus subscribers listen for the
|
||||
published events.
|
||||
|
||||
The event bus is used for both inter-process communication as well as network transport
|
||||
in Salt. Inter-process communication is provided through UNIX domain sockets (UDX).
|
||||
|
||||
The Salt Master and each Salt Minion has their own event bus.
|
||||
|
||||
Event types
|
||||
===========
|
||||
|
||||
@ -21,7 +34,7 @@ Event types
|
||||
Listening for Events
|
||||
====================
|
||||
|
||||
Salt's Event Bus is used heavily within Salt and it is also written to
|
||||
Salt's event system is used heavily within Salt and it is also written to
|
||||
integrate heavily with existing tooling and scripts. There is a variety of
|
||||
ways to consume it.
|
||||
|
||||
|
@ -174,11 +174,13 @@ to create it.
|
||||
The generated grain information will appear similar to:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
grains:
|
||||
salt-cloud:
|
||||
driver: ec2
|
||||
provider: my_ec2:ec2
|
||||
profile: ec2-web
|
||||
|
||||
The generation of salt-cloud grains can be surpressed by the
|
||||
option ``enable_cloud_grains: 'False'`` in the cloud configuration file.
|
||||
|
||||
|
@ -29,6 +29,7 @@ the name of the repository, and the link to the repository:
|
||||
For HTTP/HTTPS Basic authorization you can define credentials:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
my_repo:
|
||||
url: https://spm.example.com/
|
||||
username: user
|
||||
|
@ -164,7 +164,7 @@ states are evaluated before ``tgt`` states.
|
||||
Each of these sections needs to be evaluated as text, rather than as YAML.
|
||||
Consider the following block:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: text
|
||||
|
||||
pre_local_state: >
|
||||
echo test > /tmp/spmtest:
|
||||
@ -187,7 +187,7 @@ a minion.
|
||||
the ``>`` marker to denote that the state is evaluated as text, not a data
|
||||
structure.
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: text
|
||||
|
||||
pre_local_state: >
|
||||
echo test > /tmp/spmtest:
|
||||
@ -203,7 +203,7 @@ the ``spm`` command is running on is a master.
|
||||
Because ``tgt`` states require that a target be specified, their code blocks
|
||||
are a little different. Consider the following state:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: text
|
||||
|
||||
pre_tgt_state:
|
||||
tgt: '*'
|
||||
@ -229,7 +229,7 @@ This means that you can use Jinja or any other supported renderer inside of
|
||||
Salt. All formula variables are available to the renderer, so you can reference
|
||||
``FORMULA`` data inside your state if you need to:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: text
|
||||
|
||||
pre_tgt_state:
|
||||
tgt: '*'
|
||||
|
@ -34,7 +34,7 @@ passing on a single socket.
|
||||
TLS Support
|
||||
===========
|
||||
|
||||
.. version_added:: 2016.11.1
|
||||
.. versionadded:: 2016.11.1
|
||||
|
||||
The TCP transport allows for the master/minion communication to be optionally
|
||||
wrapped in a TLS connection. Enabling this is simple, the master and minion need
|
||||
|
@ -260,14 +260,11 @@ the retention time defined by
|
||||
|
||||
250 jobs/day * 2000 minions returns = 500,000 files a day
|
||||
|
||||
If no job history is needed, the job cache can be disabled:
|
||||
Use and External Job Cache
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
job_cache: False
|
||||
|
||||
|
||||
If the job cache is necessary there are (currently) 2 options:
|
||||
An external job cache allows for job storage to be placed on an external
|
||||
system, such as a database.
|
||||
|
||||
- ext_job_cache: this will have the minions store their return data directly
|
||||
into a returner (not sent through the Master)
|
||||
@ -287,3 +284,20 @@ for up to sixty seconds by default.
|
||||
|
||||
To enable the master key cache, set `key_cache: 'sched'` in the master
|
||||
configuration file.
|
||||
|
||||
Disable The Job Cache
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The job cache is a central component of the Salt Master and many aspects of
|
||||
the Salt Master will not function correctly without a running job cache.
|
||||
|
||||
Disabling the job cache is **STRONGLY DISCOURAGED** and should not be done
|
||||
unless the master is being used to execute routines that require no history
|
||||
or reliable feedback!
|
||||
|
||||
The job cache can be disabled:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
job_cache: False
|
||||
|
||||
|
@ -9,3 +9,4 @@ SaltPyLint>=v2017.3.6
|
||||
pytest
|
||||
git+https://github.com/eisensheng/pytest-catchlog.git@develop#egg=Pytest-catchlog
|
||||
git+https://github.com/saltstack/pytest-salt.git@master#egg=pytest-salt
|
||||
testinfra>=1.7.0
|
||||
|
@ -13,3 +13,5 @@ httpretty
|
||||
SaltPyLint>=v2017.2.29
|
||||
pytest
|
||||
git+https://github.com/saltstack/pytest-salt.git@master#egg=pytest-salt
|
||||
git+https://github.com/eisensheng/pytest-catchlog.git@develop#egg=Pytest-catchlog
|
||||
testinfra>=1.7.0
|
||||
|
@ -6,8 +6,6 @@ This system allows for authentication to be managed in a module pluggable way
|
||||
so that any external authentication system can be used inside of Salt
|
||||
'''
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
# 1. Create auth loader instance
|
||||
# 2. Accept arguments as a dict
|
||||
# 3. Verify with function introspection
|
||||
@ -16,7 +14,7 @@ from __future__ import absolute_import
|
||||
# 6. Interface to verify tokens
|
||||
|
||||
# Import python libs
|
||||
from __future__ import print_function
|
||||
from __future__ import absolute_import, print_function
|
||||
import collections
|
||||
import time
|
||||
import logging
|
||||
@ -31,6 +29,7 @@ import salt.transport.client
|
||||
import salt.utils.args
|
||||
import salt.utils.dictupdate
|
||||
import salt.utils.files
|
||||
import salt.utils.master
|
||||
import salt.utils.minions
|
||||
import salt.utils.user
|
||||
import salt.utils.versions
|
||||
@ -430,13 +429,26 @@ class LoadAuth(object):
|
||||
|
||||
auth_list = self.get_auth_list(load)
|
||||
elif auth_type == 'user':
|
||||
if not self.authenticate_key(load, key):
|
||||
auth_ret = self.authenticate_key(load, key)
|
||||
msg = 'Authentication failure of type "user" occurred'
|
||||
if not auth_ret: # auth_ret can be a boolean or the effective user id
|
||||
if show_username:
|
||||
msg = 'Authentication failure of type "user" occurred for user {0}.'.format(username)
|
||||
else:
|
||||
msg = 'Authentication failure of type "user" occurred'
|
||||
msg = '{0} for user {1}.'.format(msg, username)
|
||||
ret['error'] = {'name': 'UserAuthenticationError', 'message': msg}
|
||||
return ret
|
||||
|
||||
# Verify that the caller has root on master
|
||||
if auth_ret is not True:
|
||||
if AuthUser(load['user']).is_sudo():
|
||||
if not self.opts['sudo_acl'] or not self.opts['publisher_acl']:
|
||||
auth_ret = True
|
||||
|
||||
if auth_ret is not True:
|
||||
auth_list = salt.utils.master.get_values_of_matching_keys(
|
||||
self.opts['publisher_acl'], auth_ret)
|
||||
if not auth_list:
|
||||
ret['error'] = {'name': 'UserAuthenticationError', 'message': msg}
|
||||
return ret
|
||||
else:
|
||||
ret['error'] = {'name': 'SaltInvocationError',
|
||||
'message': 'Authentication type not supported.'}
|
||||
|
@ -194,6 +194,7 @@ def create(vm_):
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-cloud -p my_profile new_node_1
|
||||
|
||||
'''
|
||||
|
@ -198,7 +198,9 @@ def list_nodes_full(kwargs=None, call=None):
|
||||
This is because some functions both within Salt and 3rd party will break if an expected field is not present.
|
||||
This function is normally called with the -F option:
|
||||
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-cloud -F
|
||||
|
||||
|
||||
@ -244,6 +246,7 @@ def list_nodes(kwargs=None, call=None):
|
||||
This function is normally called with the -Q option:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-cloud -Q
|
||||
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
Common salt configuration schemas
|
||||
'''
|
||||
|
||||
# Import Pythosn libs
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import salt libs
|
||||
|
@ -14,6 +14,7 @@ import time
|
||||
import stat
|
||||
|
||||
# Import salt libs
|
||||
import salt.acl
|
||||
import salt.crypt
|
||||
import salt.cache
|
||||
import salt.client
|
||||
@ -1186,88 +1187,50 @@ class LocalFuncs(object):
|
||||
)
|
||||
minions = _res['minions']
|
||||
|
||||
# Check for external auth calls
|
||||
if extra.get('token', False):
|
||||
# Authenticate
|
||||
token = self.loadauth.authenticate_token(extra)
|
||||
if not token:
|
||||
return ''
|
||||
|
||||
# Get acl from eauth module.
|
||||
auth_list = self.loadauth.get_auth_list(extra, token)
|
||||
|
||||
# Authorize the request
|
||||
if not self.ckminions.auth_check(
|
||||
auth_list,
|
||||
load['fun'],
|
||||
load['arg'],
|
||||
load['tgt'],
|
||||
load.get('tgt_type', 'glob'),
|
||||
minions=minions,
|
||||
# always accept find_job
|
||||
whitelist=['saltutil.find_job'],
|
||||
):
|
||||
log.warning('Authentication failure of type "token" occurred.')
|
||||
return ''
|
||||
load['user'] = token['name']
|
||||
log.debug('Minion tokenized user = "{0}"'.format(load['user']))
|
||||
elif 'eauth' in extra:
|
||||
# Authenticate.
|
||||
if not self.loadauth.authenticate_eauth(extra):
|
||||
return ''
|
||||
|
||||
# Get acl from eauth module.
|
||||
auth_list = self.loadauth.get_auth_list(extra)
|
||||
|
||||
# Authorize the request
|
||||
if not self.ckminions.auth_check(
|
||||
auth_list,
|
||||
load['fun'],
|
||||
load['arg'],
|
||||
load['tgt'],
|
||||
load.get('tgt_type', 'glob'),
|
||||
minions=minions,
|
||||
# always accept find_job
|
||||
whitelist=['saltutil.find_job'],
|
||||
):
|
||||
log.warning('Authentication failure of type "eauth" occurred.')
|
||||
return ''
|
||||
load['user'] = self.loadauth.load_name(extra) # The username we are attempting to auth with
|
||||
# Verify that the caller has root on master
|
||||
# Check for external auth calls and authenticate
|
||||
auth_type, err_name, key = self._prep_auth_info(extra)
|
||||
if auth_type == 'user':
|
||||
auth_check = self.loadauth.check_authentication(load, auth_type, key=key)
|
||||
else:
|
||||
auth_ret = self.loadauth.authenticate_key(load, self.key)
|
||||
if auth_ret is False:
|
||||
auth_check = self.loadauth.check_authentication(extra, auth_type)
|
||||
|
||||
# Setup authorization list variable and error information
|
||||
auth_list = auth_check.get('auth_list', [])
|
||||
error = auth_check.get('error')
|
||||
err_msg = 'Authentication failure of type "{0}" occurred.'.format(auth_type)
|
||||
|
||||
if error:
|
||||
# Authentication error occurred: do not continue.
|
||||
log.warning(err_msg)
|
||||
return ''
|
||||
|
||||
# All Token, Eauth, and non-root users must pass the authorization check
|
||||
if auth_type != 'user' or (auth_type == 'user' and auth_list):
|
||||
# Authorize the request
|
||||
authorized = self.ckminions.auth_check(
|
||||
auth_list,
|
||||
load['fun'],
|
||||
load['arg'],
|
||||
load['tgt'],
|
||||
load.get('tgt_type', 'glob'),
|
||||
minions=minions,
|
||||
# always accept find_job
|
||||
whitelist=['saltutil.find_job'],
|
||||
)
|
||||
|
||||
if not authorized:
|
||||
# Authorization error occurred. Log warning and do not continue.
|
||||
log.warning(err_msg)
|
||||
return ''
|
||||
|
||||
if auth_ret is not True:
|
||||
if salt.auth.AuthUser(load['user']).is_sudo():
|
||||
if not self.opts['sudo_acl'] or not self.opts['publisher_acl']:
|
||||
auth_ret = True
|
||||
|
||||
if auth_ret is not True:
|
||||
# Avoid circular import
|
||||
import salt.utils.master
|
||||
auth_list = salt.utils.master.get_values_of_matching_keys(
|
||||
self.opts['publisher_acl'],
|
||||
auth_ret)
|
||||
if not auth_list:
|
||||
log.warning(
|
||||
'Authentication failure of type "user" occurred.'
|
||||
)
|
||||
return ''
|
||||
|
||||
if not self.ckminions.auth_check(
|
||||
auth_list,
|
||||
load['fun'],
|
||||
load['arg'],
|
||||
load['tgt'],
|
||||
load.get('tgt_type', 'glob'),
|
||||
minions=minions,
|
||||
# always accept find_job
|
||||
whitelist=['saltutil.find_job'],
|
||||
):
|
||||
log.warning('Authentication failure of type "user" occurred.')
|
||||
return ''
|
||||
# Perform some specific auth_type tasks after the authorization check
|
||||
if auth_type == 'token':
|
||||
username = auth_check.get('username')
|
||||
load['user'] = username
|
||||
log.debug('Minion tokenized user = "{0}"'.format(username))
|
||||
elif auth_type == 'eauth':
|
||||
# The username we are attempting to auth with
|
||||
load['user'] = self.loadauth.load_name(extra)
|
||||
|
||||
# If we order masters (via a syndic), don't short circuit if no minions
|
||||
# are found
|
||||
|
@ -40,7 +40,7 @@ event <tag> [<extra>, <data>]
|
||||
|
||||
Example of usage
|
||||
|
||||
.. code:: txt
|
||||
.. code-block:: txt
|
||||
|
||||
08:33:57 @gtmanfred > !ping
|
||||
08:33:57 gtmanbot > gtmanfred: pong
|
||||
@ -49,7 +49,7 @@ Example of usage
|
||||
08:34:17 @gtmanfred > !event test/tag/ircbot irc is usefull
|
||||
08:34:17 gtmanbot > gtmanfred: TaDa!
|
||||
|
||||
.. code:: txt
|
||||
.. code-block:: txt
|
||||
|
||||
[DEBUG ] Sending event: tag = salt/engines/ircbot/test/tag/ircbot; data = {'_stamp': '2016-11-28T14:34:16.633623', 'data': [u'irc', u'is', u'usefull']}
|
||||
|
||||
|
@ -13,7 +13,6 @@ as those returned here
|
||||
# Import python libs
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
import json
|
||||
import socket
|
||||
import sys
|
||||
import glob
|
||||
@ -936,8 +935,6 @@ def _virtual(osdata):
|
||||
zone = __salt__['cmd.run']('{0}'.format(zonename))
|
||||
if zone != 'global':
|
||||
grains['virtual'] = 'zone'
|
||||
if salt.utils.platform.is_smartos_zone():
|
||||
grains.update(_smartos_zone_data())
|
||||
# Check if it's a branded zone (i.e. Solaris 8/9 zone)
|
||||
if isdir('/.SUNWnative'):
|
||||
grains['virtual'] = 'zone'
|
||||
@ -1671,8 +1668,6 @@ def os_data():
|
||||
])
|
||||
# store a untouched copy of the timestamp in osrelease_stamp
|
||||
grains['osrelease_stamp'] = uname_v
|
||||
if salt.utils.platform.is_smartos_globalzone():
|
||||
grains.update(_smartos_computenode_data())
|
||||
elif os.path.isfile('/etc/release'):
|
||||
with salt.utils.files.fopen('/etc/release', 'r') as fp_:
|
||||
rel_data = fp_.read()
|
||||
@ -1777,9 +1772,6 @@ def os_data():
|
||||
# Get the hardware and bios data
|
||||
grains.update(_hw_data(grains))
|
||||
|
||||
# Get zpool data
|
||||
grains.update(_zpool_data(grains))
|
||||
|
||||
# Load the virtual machine info
|
||||
grains.update(_virtual(grains))
|
||||
grains.update(_ps(grains))
|
||||
@ -2371,123 +2363,6 @@ def _hw_data(osdata):
|
||||
return grains
|
||||
|
||||
|
||||
def _smartos_computenode_data():
|
||||
'''
|
||||
Return useful information from a SmartOS compute node
|
||||
'''
|
||||
# Provides:
|
||||
# vms_total
|
||||
# vms_running
|
||||
# vms_stopped
|
||||
# sdc_version
|
||||
# vm_capable
|
||||
# vm_hw_virt
|
||||
|
||||
if salt.utils.platform.is_proxy():
|
||||
return {}
|
||||
|
||||
grains = {}
|
||||
|
||||
# *_vms grains
|
||||
grains['computenode_vms_total'] = len(__salt__['cmd.run']('vmadm list -p').split("\n"))
|
||||
grains['computenode_vms_running'] = len(__salt__['cmd.run']('vmadm list -p state=running').split("\n"))
|
||||
grains['computenode_vms_stopped'] = len(__salt__['cmd.run']('vmadm list -p state=stopped').split("\n"))
|
||||
|
||||
# sysinfo derived grains
|
||||
sysinfo = json.loads(__salt__['cmd.run']('sysinfo'))
|
||||
grains['computenode_sdc_version'] = sysinfo['SDC Version']
|
||||
grains['computenode_vm_capable'] = sysinfo['VM Capable']
|
||||
if sysinfo['VM Capable']:
|
||||
grains['computenode_vm_hw_virt'] = sysinfo['CPU Virtualization']
|
||||
|
||||
# sysinfo derived smbios grains
|
||||
grains['manufacturer'] = sysinfo['Manufacturer']
|
||||
grains['productname'] = sysinfo['Product']
|
||||
grains['uuid'] = sysinfo['UUID']
|
||||
|
||||
return grains
|
||||
|
||||
|
||||
def _smartos_zone_data():
|
||||
'''
|
||||
Return useful information from a SmartOS zone
|
||||
'''
|
||||
# Provides:
|
||||
# pkgsrcversion
|
||||
# imageversion
|
||||
# pkgsrcpath
|
||||
# zonename
|
||||
# zoneid
|
||||
# hypervisor_uuid
|
||||
# datacenter
|
||||
|
||||
if salt.utils.platform.is_proxy():
|
||||
return {}
|
||||
|
||||
grains = {}
|
||||
|
||||
pkgsrcversion = re.compile('^release:\\s(.+)')
|
||||
imageversion = re.compile('Image:\\s(.+)')
|
||||
pkgsrcpath = re.compile('PKG_PATH=(.+)')
|
||||
if os.path.isfile('/etc/pkgsrc_version'):
|
||||
with salt.utils.files.fopen('/etc/pkgsrc_version', 'r') as fp_:
|
||||
for line in fp_:
|
||||
match = pkgsrcversion.match(line)
|
||||
if match:
|
||||
grains['pkgsrcversion'] = match.group(1)
|
||||
if os.path.isfile('/etc/product'):
|
||||
with salt.utils.files.fopen('/etc/product', 'r') as fp_:
|
||||
for line in fp_:
|
||||
match = imageversion.match(line)
|
||||
if match:
|
||||
grains['imageversion'] = match.group(1)
|
||||
if os.path.isfile('/opt/local/etc/pkg_install.conf'):
|
||||
with salt.utils.files.fopen('/opt/local/etc/pkg_install.conf', 'r') as fp_:
|
||||
for line in fp_:
|
||||
match = pkgsrcpath.match(line)
|
||||
if match:
|
||||
grains['pkgsrcpath'] = match.group(1)
|
||||
if 'pkgsrcversion' not in grains:
|
||||
grains['pkgsrcversion'] = 'Unknown'
|
||||
if 'imageversion' not in grains:
|
||||
grains['imageversion'] = 'Unknown'
|
||||
if 'pkgsrcpath' not in grains:
|
||||
grains['pkgsrcpath'] = 'Unknown'
|
||||
|
||||
grains['zonename'] = __salt__['cmd.run']('zonename')
|
||||
grains['zoneid'] = __salt__['cmd.run']('zoneadm list -p | awk -F: \'{ print $1 }\'', python_shell=True)
|
||||
|
||||
return grains
|
||||
|
||||
|
||||
def _zpool_data(grains):
|
||||
'''
|
||||
Provide grains about zpools
|
||||
'''
|
||||
# quickly return if windows or proxy
|
||||
if salt.utils.platform.is_windows() or 'proxyminion' in __opts__:
|
||||
return {}
|
||||
|
||||
# quickly return if NetBSD (ZFS still under development)
|
||||
if salt.utils.platform.is_netbsd():
|
||||
return {}
|
||||
|
||||
# quickly return if no zpool and zfs command
|
||||
if not salt.utils.path.which('zpool'):
|
||||
return {}
|
||||
|
||||
# collect zpool data
|
||||
zpool_grains = {}
|
||||
for zpool in __salt__['cmd.run']('zpool list -H -o name,size').splitlines():
|
||||
zpool = zpool.split()
|
||||
zpool_grains[zpool[0]] = zpool[1]
|
||||
|
||||
# return grain data
|
||||
if len(zpool_grains.keys()) < 1:
|
||||
return {}
|
||||
return {'zpool': zpool_grains}
|
||||
|
||||
|
||||
def get_server_id():
|
||||
'''
|
||||
Provides an integer based on the FQDN of a machine.
|
||||
|
196
salt/grains/smartos.py
Normal file
196
salt/grains/smartos.py
Normal file
@ -0,0 +1,196 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
SmartOS grain provider
|
||||
|
||||
:maintainer: Jorge Schrauwen <sjorge@blackdot.be>
|
||||
:maturity: new
|
||||
:depends: salt.utils, salt.ext.six, salt.module.cmdmod
|
||||
:platform: SmartOS
|
||||
|
||||
.. versionadded:: nitrogen
|
||||
|
||||
'''
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import python libs
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
import logging
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils.dictupdate
|
||||
import salt.utils.path
|
||||
import salt.utils.platform
|
||||
from salt.ext.six.moves import zip
|
||||
|
||||
# Solve the Chicken and egg problem where grains need to run before any
|
||||
# of the modules are loaded and are generally available for any usage.
|
||||
import salt.modules.cmdmod
|
||||
|
||||
__virtualname__ = 'smartos'
|
||||
__salt__ = {
|
||||
'cmd.run': salt.modules.cmdmod.run,
|
||||
}
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Only load when we are on SmartOS
|
||||
'''
|
||||
if salt.utils.platform.is_smartos():
|
||||
return __virtualname__
|
||||
return False
|
||||
|
||||
|
||||
def _smartos_computenode_data():
|
||||
'''
|
||||
Return useful information from a SmartOS compute node
|
||||
'''
|
||||
# Provides:
|
||||
# vms_total
|
||||
# vms_running
|
||||
# vms_stopped
|
||||
# vms_type
|
||||
# sdc_version
|
||||
# vm_capable
|
||||
# vm_hw_virt
|
||||
|
||||
grains = {}
|
||||
|
||||
# collect vm data
|
||||
vms = {}
|
||||
for vm in __salt__['cmd.run']('vmadm list -p -o uuid,alias,state,type').split("\n"):
|
||||
vm = dict(list(zip(['uuid', 'alias', 'state', 'type'], vm.split(':'))))
|
||||
vms[vm['uuid']] = vm
|
||||
del vms[vm['uuid']]['uuid']
|
||||
|
||||
# set vm grains
|
||||
grains['computenode_vms_total'] = len(vms)
|
||||
grains['computenode_vms_running'] = 0
|
||||
grains['computenode_vms_stopped'] = 0
|
||||
grains['computenode_vms_type'] = {'KVM': 0, 'LX': 0, 'OS': 0}
|
||||
for vm in vms:
|
||||
if vms[vm]['state'].lower() == 'running':
|
||||
grains['computenode_vms_running'] += 1
|
||||
elif vms[vm]['state'].lower() == 'stopped':
|
||||
grains['computenode_vms_stopped'] += 1
|
||||
|
||||
if vms[vm]['type'] not in grains['computenode_vms_type']:
|
||||
# NOTE: be prepared for when bhyve gets its own type
|
||||
grains['computenode_vms_type'][vms[vm]['type']] = 0
|
||||
grains['computenode_vms_type'][vms[vm]['type']] += 1
|
||||
|
||||
# sysinfo derived grains
|
||||
sysinfo = json.loads(__salt__['cmd.run']('sysinfo'))
|
||||
grains['computenode_sdc_version'] = sysinfo['SDC Version']
|
||||
grains['computenode_vm_capable'] = sysinfo['VM Capable']
|
||||
if sysinfo['VM Capable']:
|
||||
grains['computenode_vm_hw_virt'] = sysinfo['CPU Virtualization']
|
||||
|
||||
# sysinfo derived smbios grains
|
||||
grains['manufacturer'] = sysinfo['Manufacturer']
|
||||
grains['productname'] = sysinfo['Product']
|
||||
grains['uuid'] = sysinfo['UUID']
|
||||
|
||||
return grains
|
||||
|
||||
|
||||
def _smartos_zone_data():
|
||||
'''
|
||||
Return useful information from a SmartOS zone
|
||||
'''
|
||||
# Provides:
|
||||
# zoneid
|
||||
# zonename
|
||||
# imageversion
|
||||
|
||||
grains = {
|
||||
'zoneid': __salt__['cmd.run']('zoneadm list -p | awk -F: \'{ print $1 }\'', python_shell=True),
|
||||
'zonename': __salt__['cmd.run']('zonename'),
|
||||
'imageversion': 'Unknown',
|
||||
}
|
||||
|
||||
imageversion = re.compile('Image:\\s(.+)')
|
||||
if os.path.isfile('/etc/product'):
|
||||
with salt.utils.files.fopen('/etc/product', 'r') as fp_:
|
||||
for line in fp_:
|
||||
match = imageversion.match(line)
|
||||
if match:
|
||||
grains['imageversion'] = match.group(1)
|
||||
|
||||
return grains
|
||||
|
||||
|
||||
def _smartos_zone_pkgsrc_data():
|
||||
'''
|
||||
SmartOS zone pkgsrc information
|
||||
'''
|
||||
# Provides:
|
||||
# pkgsrcversion
|
||||
# pkgsrcpath
|
||||
|
||||
grains = {
|
||||
'pkgsrcversion': 'Unknown',
|
||||
'pkgsrcpath': 'Unknown',
|
||||
}
|
||||
|
||||
pkgsrcversion = re.compile('^release:\\s(.+)')
|
||||
if os.path.isfile('/etc/pkgsrc_version'):
|
||||
with salt.utils.files.fopen('/etc/pkgsrc_version', 'r') as fp_:
|
||||
for line in fp_:
|
||||
match = pkgsrcversion.match(line)
|
||||
if match:
|
||||
grains['pkgsrcversion'] = match.group(1)
|
||||
|
||||
pkgsrcpath = re.compile('PKG_PATH=(.+)')
|
||||
if os.path.isfile('/opt/local/etc/pkg_install.conf'):
|
||||
with salt.utils.files.fopen('/opt/local/etc/pkg_install.conf', 'r') as fp_:
|
||||
for line in fp_:
|
||||
match = pkgsrcpath.match(line)
|
||||
if match:
|
||||
grains['pkgsrcpath'] = match.group(1)
|
||||
|
||||
return grains
|
||||
|
||||
|
||||
def _smartos_zone_pkgin_data():
|
||||
'''
|
||||
SmartOS zone pkgsrc information
|
||||
'''
|
||||
# Provides:
|
||||
# pkgin_repositories
|
||||
|
||||
grains = {
|
||||
'pkgin_repositories': [],
|
||||
}
|
||||
|
||||
pkginrepo = re.compile('^(?:https|http|ftp|file)://.*$')
|
||||
if os.path.isfile('/opt/local/etc/pkgin/repositories.conf'):
|
||||
with salt.utils.files.fopen('/opt/local/etc/pkgin/repositories.conf', 'r') as fp_:
|
||||
for line in fp_:
|
||||
if pkginrepo.match(line):
|
||||
grains['pkgin_repositories'].append(line)
|
||||
|
||||
return grains
|
||||
|
||||
|
||||
def smartos():
|
||||
'''
|
||||
Provide grains for SmartOS
|
||||
'''
|
||||
grains = {}
|
||||
|
||||
if salt.utils.platform.is_smartos_zone():
|
||||
grains = salt.utils.dictupdate.update(grains, _smartos_zone_data(), merge_lists=True)
|
||||
grains = salt.utils.dictupdate.update(grains, _smartos_zone_pkgsrc_data(), merge_lists=True)
|
||||
grains = salt.utils.dictupdate.update(grains, _smartos_zone_pkgin_data(), merge_lists=True)
|
||||
elif salt.utils.platform.is_smartos_globalzone():
|
||||
grains = salt.utils.dictupdate.update(grains, _smartos_computenode_data(), merge_lists=True)
|
||||
|
||||
return grains
|
||||
|
||||
|
||||
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
115
salt/grains/zfs.py
Normal file
115
salt/grains/zfs.py
Normal file
@ -0,0 +1,115 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
ZFS grain provider
|
||||
|
||||
:maintainer: Jorge Schrauwen <sjorge@blackdot.be>
|
||||
:maturity: new
|
||||
:depends: salt.utils, salt.module.cmdmod
|
||||
:platform: illumos,freebsd,linux
|
||||
|
||||
.. versionadded:: Oxygen
|
||||
|
||||
'''
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import python libs
|
||||
import logging
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils.dictupdate
|
||||
import salt.utils.path
|
||||
import salt.utils.platform
|
||||
|
||||
# Solve the Chicken and egg problem where grains need to run before any
|
||||
# of the modules are loaded and are generally available for any usage.
|
||||
import salt.modules.cmdmod
|
||||
|
||||
__virtualname__ = 'zfs'
|
||||
__salt__ = {
|
||||
'cmd.run': salt.modules.cmdmod.run,
|
||||
}
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Load zfs grains
|
||||
'''
|
||||
# NOTE: we always load this grain so we can properly export
|
||||
# atleast the zfs_support grain
|
||||
return __virtualname__
|
||||
|
||||
|
||||
def _check_retcode(cmd):
|
||||
'''
|
||||
Simple internal wrapper for cmdmod.retcode
|
||||
'''
|
||||
return salt.modules.cmdmod.retcode(cmd, output_loglevel='quiet', ignore_retcode=True) == 0
|
||||
|
||||
|
||||
def _zfs_support():
|
||||
'''
|
||||
Provide information about zfs kernel module
|
||||
'''
|
||||
grains = {'zfs_support': False}
|
||||
|
||||
# Check for zfs support
|
||||
# NOTE: ZFS on Windows is in development
|
||||
# NOTE: ZFS on NetBSD is in development
|
||||
on_supported_platform = False
|
||||
if salt.utils.platform.is_sunos() and salt.utils.path.which('zfs'):
|
||||
on_supported_platform = True
|
||||
elif salt.utils.platform.is_freebsd() and _check_retcode('kldstat -q -m zfs'):
|
||||
on_supported_platform = True
|
||||
elif salt.utils.platform.is_linux():
|
||||
modinfo = salt.utils.path.which('modinfo')
|
||||
if modinfo:
|
||||
on_supported_platform = _check_retcode('{0} zfs'.format(modinfo))
|
||||
else:
|
||||
on_supported_platform = _check_retcode('ls /sys/module/zfs')
|
||||
|
||||
# NOTE: fallback to zfs-fuse if needed
|
||||
if not on_supported_platform:
|
||||
_zfs_fuse = lambda f: __salt__['service.' + f]('zfs-fuse')
|
||||
if _zfs_fuse('available') and (_zfs_fuse('status') or _zfs_fuse('start')):
|
||||
on_supported_platform = True
|
||||
|
||||
# Additional check for the zpool command
|
||||
if on_supported_platform and salt.utils.path.which('zpool'):
|
||||
grains['zfs_support'] = True
|
||||
|
||||
return grains
|
||||
|
||||
|
||||
def _zfs_pool_data():
|
||||
'''
|
||||
Provide grains about zpools
|
||||
'''
|
||||
grains = {}
|
||||
|
||||
# collect zpool data
|
||||
zpool_cmd = salt.utils.path.which('zpool')
|
||||
for zpool in __salt__['cmd.run']('{zpool} list -H -o name,size'.format(zpool=zpool_cmd)).splitlines():
|
||||
if 'zpool' not in grains:
|
||||
grains['zpool'] = {}
|
||||
zpool = zpool.split()
|
||||
grains['zpool'][zpool[0]] = zpool[1]
|
||||
|
||||
# return grain data
|
||||
return grains
|
||||
|
||||
|
||||
def zfs():
|
||||
'''
|
||||
Provide grains for zfs/zpool
|
||||
'''
|
||||
grains = {}
|
||||
|
||||
grains = salt.utils.dictupdate.update(grains, _zfs_support(), merge_lists=True)
|
||||
if grains['zfs_support']:
|
||||
grains = salt.utils.dictupdate.update(grains, _zfs_pool_data(), merge_lists=True)
|
||||
|
||||
return grains
|
||||
|
||||
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
121
salt/master.py
121
salt/master.py
@ -1840,89 +1840,52 @@ class ClearFuncs(object):
|
||||
clear_load.get(u'tgt_type', u'glob'),
|
||||
delimiter
|
||||
)
|
||||
minions = _res.get('minions', list())
|
||||
missing = _res.get('missing', list())
|
||||
minions = _res.get(u'minions', list())
|
||||
missing = _res.get(u'missing', list())
|
||||
|
||||
# Check for external auth calls
|
||||
if extra.get(u'token', False):
|
||||
# Authenticate.
|
||||
token = self.loadauth.authenticate_token(extra)
|
||||
if not token:
|
||||
return u''
|
||||
|
||||
# Get acl
|
||||
auth_list = self.loadauth.get_auth_list(extra, token)
|
||||
|
||||
# Authorize the request
|
||||
if not self.ckminions.auth_check(
|
||||
auth_list,
|
||||
clear_load[u'fun'],
|
||||
clear_load[u'arg'],
|
||||
clear_load[u'tgt'],
|
||||
clear_load.get(u'tgt_type', u'glob'),
|
||||
minions=minions,
|
||||
# always accept find_job
|
||||
whitelist=[u'saltutil.find_job'],
|
||||
):
|
||||
log.warning(u'Authentication failure of type "token" occurred.')
|
||||
return u''
|
||||
clear_load[u'user'] = token[u'name']
|
||||
log.debug(u'Minion tokenized user = "%s"', clear_load[u'user'])
|
||||
elif u'eauth' in extra:
|
||||
# Authenticate.
|
||||
if not self.loadauth.authenticate_eauth(extra):
|
||||
return u''
|
||||
|
||||
# Get acl from eauth module.
|
||||
auth_list = self.loadauth.get_auth_list(extra)
|
||||
|
||||
# Authorize the request
|
||||
if not self.ckminions.auth_check(
|
||||
auth_list,
|
||||
clear_load[u'fun'],
|
||||
clear_load[u'arg'],
|
||||
clear_load[u'tgt'],
|
||||
clear_load.get(u'tgt_type', u'glob'),
|
||||
minions=minions,
|
||||
# always accept find_job
|
||||
whitelist=[u'saltutil.find_job'],
|
||||
):
|
||||
log.warning(u'Authentication failure of type "eauth" occurred.')
|
||||
return u''
|
||||
clear_load[u'user'] = self.loadauth.load_name(extra) # The username we are attempting to auth with
|
||||
# Verify that the caller has root on master
|
||||
# Check for external auth calls and authenticate
|
||||
auth_type, err_name, key, sensitive_load_keys = self._prep_auth_info(extra)
|
||||
if auth_type == 'user':
|
||||
auth_check = self.loadauth.check_authentication(clear_load, auth_type, key=key)
|
||||
else:
|
||||
auth_ret = self.loadauth.authenticate_key(clear_load, self.key)
|
||||
if auth_ret is False:
|
||||
auth_check = self.loadauth.check_authentication(extra, auth_type)
|
||||
|
||||
# Setup authorization list variable and error information
|
||||
auth_list = auth_check.get(u'auth_list', [])
|
||||
err_msg = u'Authentication failure of type "{0}" occurred.'.format(auth_type)
|
||||
|
||||
if auth_check.get(u'error'):
|
||||
# Authentication error occurred: do not continue.
|
||||
log.warning(err_msg)
|
||||
return u''
|
||||
|
||||
# All Token, Eauth, and non-root users must pass the authorization check
|
||||
if auth_type != u'user' or (auth_type == u'user' and auth_list):
|
||||
# Authorize the request
|
||||
authorized = self.ckminions.auth_check(
|
||||
auth_list,
|
||||
clear_load[u'fun'],
|
||||
clear_load[u'arg'],
|
||||
clear_load[u'tgt'],
|
||||
clear_load.get(u'tgt_type', u'glob'),
|
||||
minions=minions,
|
||||
# always accept find_job
|
||||
whitelist=[u'saltutil.find_job'],
|
||||
)
|
||||
|
||||
if not authorized:
|
||||
# Authorization error occurred. Do not continue.
|
||||
log.warning(err_msg)
|
||||
return u''
|
||||
|
||||
if auth_ret is not True:
|
||||
if salt.auth.AuthUser(clear_load[u'user']).is_sudo():
|
||||
if not self.opts[u'sudo_acl'] or not self.opts[u'publisher_acl']:
|
||||
auth_ret = True
|
||||
|
||||
if auth_ret is not True:
|
||||
auth_list = salt.utils.master.get_values_of_matching_keys(
|
||||
self.opts[u'publisher_acl'],
|
||||
auth_ret)
|
||||
if not auth_list:
|
||||
log.warning(
|
||||
u'Authentication failure of type "user" occurred.'
|
||||
)
|
||||
return u''
|
||||
|
||||
if not self.ckminions.auth_check(
|
||||
auth_list,
|
||||
clear_load[u'fun'],
|
||||
clear_load[u'arg'],
|
||||
clear_load[u'tgt'],
|
||||
clear_load.get(u'tgt_type', u'glob'),
|
||||
minions=minions,
|
||||
# always accept find_job
|
||||
whitelist=[u'saltutil.find_job'],
|
||||
):
|
||||
log.warning(u'Authentication failure of type "user" occurred.')
|
||||
return u''
|
||||
# Perform some specific auth_type tasks after the authorization check
|
||||
if auth_type == u'token':
|
||||
username = auth_check.get(u'username')
|
||||
clear_load[u'user'] = username
|
||||
log.debug(u'Minion tokenized user = "%s"', username)
|
||||
elif auth_type == u'eauth':
|
||||
# The username we are attempting to auth with
|
||||
clear_load[u'user'] = self.loadauth.load_name(extra)
|
||||
|
||||
# If we order masters (via a syndic), don't short circuit if no minions
|
||||
# are found
|
||||
|
@ -1037,7 +1037,7 @@ class Minion(MinionBase):
|
||||
u'may result in loss of contact with minions. Please '
|
||||
u'upgrade your ZMQ!'
|
||||
)
|
||||
# Late setup the of the opts grains, so we can log from the grains
|
||||
# Late setup of the opts grains, so we can log from the grains
|
||||
# module. If this is a proxy, however, we need to init the proxymodule
|
||||
# before we can get the grains. We do this for proxies in the
|
||||
# post_master_init
|
||||
|
@ -2,7 +2,7 @@
|
||||
'''
|
||||
Connection module for Amazon APIGateway
|
||||
|
||||
.. versionadded::
|
||||
.. versionadded:: 2016.11.0
|
||||
|
||||
:configuration: This module accepts explicit Lambda credentials but can also
|
||||
utilize IAM roles assigned to the instance trough Instance Profiles.
|
||||
|
@ -1747,6 +1747,7 @@ def set_volumes_tags(tag_maps, authoritative=False, dry_run=False,
|
||||
YAML example fragment:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
- filters:
|
||||
attachment.instance_id: i-abcdef12
|
||||
tags:
|
||||
|
@ -156,7 +156,7 @@ def create_file_system(name,
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'my-minion' boto_efs.create_file_system efs-name generalPurpose
|
||||
'''
|
||||
@ -222,7 +222,7 @@ def create_mount_target(filesystemid,
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'my-minion' boto_efs.create_mount_target filesystemid subnetid
|
||||
'''
|
||||
@ -269,7 +269,7 @@ def create_tags(filesystemid,
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'my-minion' boto_efs.create_tags
|
||||
'''
|
||||
@ -301,7 +301,7 @@ def delete_file_system(filesystemid,
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'my-minion' boto_efs.delete_file_system filesystemid
|
||||
'''
|
||||
@ -335,7 +335,7 @@ def delete_mount_target(mounttargetid,
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'my-minion' boto_efs.delete_mount_target mounttargetid
|
||||
'''
|
||||
@ -363,7 +363,7 @@ def delete_tags(filesystemid,
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'my-minion' boto_efs.delete_tags
|
||||
'''
|
||||
@ -398,7 +398,7 @@ def get_file_systems(filesystemid=None,
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'my-minion' boto_efs.get_file_systems efs-id
|
||||
'''
|
||||
@ -454,7 +454,7 @@ def get_mount_targets(filesystemid=None,
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'my-minion' boto_efs.get_mount_targets
|
||||
'''
|
||||
@ -493,7 +493,7 @@ def get_tags(filesystemid,
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'my-minion' boto_efs.get_tags efs-id
|
||||
'''
|
||||
@ -527,7 +527,7 @@ def set_security_groups(mounttargetid,
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'my-minion' boto_efs.set_security_groups my-mount-target-id my-sec-group
|
||||
'''
|
||||
|
@ -1703,7 +1703,6 @@ def build_interface(iface, iface_type, enabled, **settings):
|
||||
salt '*' ip.build_interface eth0 eth <settings>
|
||||
'''
|
||||
|
||||
iface = iface.lower()
|
||||
iface_type = iface_type.lower()
|
||||
|
||||
if iface_type not in _IFACE_TYPES:
|
||||
@ -1773,7 +1772,6 @@ def build_routes(iface, **settings):
|
||||
salt '*' ip.build_routes eth0 <settings>
|
||||
'''
|
||||
|
||||
iface = iface.lower()
|
||||
opts = _parse_routes(iface, settings)
|
||||
try:
|
||||
template = JINJA.get_template('route_eth.jinja')
|
||||
|
@ -1,4 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Module to work with salt formula defaults files
|
||||
|
||||
'''
|
||||
|
||||
from __future__ import absolute_import
|
||||
import json
|
||||
import logging
|
||||
|
@ -1777,9 +1777,9 @@ def line(path, content=None, match=None, mode=None, location=None,
|
||||
|
||||
location
|
||||
Defines where to place content in the line. Note this option is only
|
||||
used when ``mode=insert`` is specified. If a location is passed in, it
|
||||
takes precedence over both the ``before`` and ``after`` kwargs. Valid
|
||||
locations are:
|
||||
used when ``mode=insert`` or ``mode=ensure`` is specified. If a location
|
||||
is passed in, it takes precedence over both the ``before`` and ``after``
|
||||
kwargs. Valid locations are:``
|
||||
|
||||
- start
|
||||
Place the content at the beginning of the file.
|
||||
@ -1930,63 +1930,83 @@ def line(path, content=None, match=None, mode=None, location=None,
|
||||
after = after and after.strip()
|
||||
before = before and before.strip()
|
||||
|
||||
if before and after:
|
||||
_assert_occurrence(body, before, 'before')
|
||||
_assert_occurrence(body, after, 'after')
|
||||
|
||||
a_idx = b_idx = -1
|
||||
idx = 0
|
||||
body = body.split(os.linesep)
|
||||
for _line in body:
|
||||
idx += 1
|
||||
if _line.find(before) > -1 and b_idx < 0:
|
||||
b_idx = idx
|
||||
if _line.find(after) > -1 and a_idx < 0:
|
||||
a_idx = idx
|
||||
|
||||
# Add
|
||||
if not b_idx - a_idx - 1:
|
||||
body = body[:a_idx] + [content] + body[b_idx - 1:]
|
||||
elif b_idx - a_idx - 1 == 1:
|
||||
if _starts_till(body[a_idx:b_idx - 1][0], content) > -1:
|
||||
body[a_idx] = _get_line_indent(body[a_idx - 1], content, indent)
|
||||
else:
|
||||
raise CommandExecutionError('Found more than one line between boundaries "before" and "after".')
|
||||
body = os.linesep.join(body)
|
||||
|
||||
elif before and not after:
|
||||
_assert_occurrence(body, before, 'before')
|
||||
body = body.split(os.linesep)
|
||||
if location:
|
||||
found = False
|
||||
out = []
|
||||
for idx in range(len(body)):
|
||||
if body[idx].find(before) > -1:
|
||||
prev = (idx > 0 and idx or 1) - 1
|
||||
out.append(_get_line_indent(body[prev], content, indent))
|
||||
if _starts_till(out[prev], content) > -1:
|
||||
del out[prev]
|
||||
out.append(body[idx])
|
||||
body = os.linesep.join(out)
|
||||
|
||||
elif not before and after:
|
||||
_assert_occurrence(body, after, 'after')
|
||||
body = body.split(os.linesep)
|
||||
skip = None
|
||||
out = []
|
||||
for idx in range(len(body)):
|
||||
if skip != body[idx]:
|
||||
out.append(body[idx])
|
||||
|
||||
if body[idx].find(after) > -1:
|
||||
next_line = idx + 1 < len(body) and body[idx + 1] or None
|
||||
if next_line is not None and _starts_till(next_line, content) > -1:
|
||||
skip = next_line
|
||||
out.append(_get_line_indent(body[idx], content, indent))
|
||||
body = os.linesep.join(out)
|
||||
|
||||
if body:
|
||||
for file_line in body.split(os.linesep):
|
||||
if file_line.find(match) > -1 and not file_line == content:
|
||||
out.append(_get_line_indent(file_line, content, indent))
|
||||
found = True
|
||||
elif file_line == content:
|
||||
out.append(file_line)
|
||||
found = True
|
||||
else:
|
||||
out.append(file_line)
|
||||
body = os.linesep.join(out)
|
||||
if not found:
|
||||
if location == 'start':
|
||||
body = os.linesep.join([content, body])
|
||||
elif location == 'end':
|
||||
body = os.linesep.join([body, _get_line_indent(body[-1], content, indent) if body else content])
|
||||
else:
|
||||
raise CommandExecutionError("Wrong conditions? "
|
||||
"Unable to ensure line without knowing "
|
||||
"where to put it before and/or after.")
|
||||
if before and after:
|
||||
_assert_occurrence(body, before, 'before')
|
||||
_assert_occurrence(body, after, 'after')
|
||||
|
||||
a_idx = b_idx = -1
|
||||
idx = 0
|
||||
body = body.split(os.linesep)
|
||||
for _line in body:
|
||||
idx += 1
|
||||
if _line.find(before) > -1 and b_idx < 0:
|
||||
b_idx = idx
|
||||
if _line.find(after) > -1 and a_idx < 0:
|
||||
a_idx = idx
|
||||
|
||||
# Add
|
||||
if not b_idx - a_idx - 1:
|
||||
body = body[:a_idx] + [content] + body[b_idx - 1:]
|
||||
elif b_idx - a_idx - 1 == 1:
|
||||
if _starts_till(body[a_idx:b_idx - 1][0], content) > -1:
|
||||
body[a_idx] = _get_line_indent(body[a_idx - 1], content, indent)
|
||||
else:
|
||||
raise CommandExecutionError('Found more than one line between boundaries "before" and "after".')
|
||||
body = os.linesep.join(body)
|
||||
|
||||
elif before and not after:
|
||||
_assert_occurrence(body, before, 'before')
|
||||
body = body.split(os.linesep)
|
||||
out = []
|
||||
for idx in range(len(body)):
|
||||
if body[idx].find(before) > -1:
|
||||
prev = (idx > 0 and idx or 1) - 1
|
||||
out.append(_get_line_indent(body[prev], content, indent))
|
||||
if _starts_till(out[prev], content) > -1:
|
||||
del out[prev]
|
||||
out.append(body[idx])
|
||||
body = os.linesep.join(out)
|
||||
|
||||
elif not before and after:
|
||||
_assert_occurrence(body, after, 'after')
|
||||
body = body.split(os.linesep)
|
||||
skip = None
|
||||
out = []
|
||||
for idx in range(len(body)):
|
||||
if skip != body[idx]:
|
||||
out.append(body[idx])
|
||||
|
||||
if body[idx].find(after) > -1:
|
||||
next_line = idx + 1 < len(body) and body[idx + 1] or None
|
||||
if next_line is not None and _starts_till(next_line, content) > -1:
|
||||
skip = next_line
|
||||
out.append(_get_line_indent(body[idx], content, indent))
|
||||
body = os.linesep.join(out)
|
||||
|
||||
else:
|
||||
raise CommandExecutionError("Wrong conditions? "
|
||||
"Unable to ensure line without knowing "
|
||||
"where to put it before and/or after.")
|
||||
|
||||
changed = body_before != hashlib.sha256(salt.utils.stringutils.to_bytes(body)).hexdigest()
|
||||
|
||||
|
@ -413,6 +413,7 @@ def delkey(key):
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' grains.delkey key
|
||||
'''
|
||||
setval(key, None, destructive=True)
|
||||
|
@ -112,7 +112,7 @@ def run(script):
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' jenkins.run 'Jenkins.instance.doSafeRestart()'
|
||||
|
||||
|
@ -28,6 +28,7 @@ For an item only one field should be provided. Either a `data` or a `file` entry
|
||||
In case both are provided the `file` entry is prefered.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' kubernetes.nodes api_url=http://k8s-api-server:port api_user=myuser api_password=pass
|
||||
|
||||
.. versionadded: 2017.7.0
|
||||
@ -35,6 +36,7 @@ In case both are provided the `file` entry is prefered.
|
||||
|
||||
# Import Python Futures
|
||||
from __future__ import absolute_import
|
||||
import sys
|
||||
import os.path
|
||||
import base64
|
||||
import logging
|
||||
@ -164,13 +166,16 @@ def _setup_conn(**kwargs):
|
||||
|
||||
if client_key_file:
|
||||
kubernetes.client.configuration.key_file = client_key_file
|
||||
if client_key:
|
||||
elif client_key:
|
||||
with tempfile.NamedTemporaryFile(prefix='salt-kube-', delete=False) as k:
|
||||
k.write(base64.b64decode(client_key))
|
||||
kubernetes.client.configuration.key_file = k.name
|
||||
else:
|
||||
kubernetes.client.configuration.key_file = None
|
||||
|
||||
# The return makes unit testing easier
|
||||
return vars(kubernetes.client.configuration)
|
||||
|
||||
|
||||
def _cleanup(**kwargs):
|
||||
ca = kubernetes.client.configuration.ssl_ca_cert
|
||||
@ -269,7 +274,7 @@ def node_labels(name, **kwargs):
|
||||
match = node(name, **kwargs)
|
||||
|
||||
if match is not None:
|
||||
return match.metadata.labels
|
||||
return match['metadata']['labels']
|
||||
|
||||
return {}
|
||||
|
||||
@ -1050,14 +1055,22 @@ def create_service(
|
||||
|
||||
def create_secret(
|
||||
name,
|
||||
namespace,
|
||||
data,
|
||||
source,
|
||||
template,
|
||||
saltenv,
|
||||
namespace='default',
|
||||
data=None,
|
||||
source=None,
|
||||
template=None,
|
||||
saltenv='base',
|
||||
**kwargs):
|
||||
'''
|
||||
Creates the kubernetes secret as defined by the user.
|
||||
|
||||
CLI Examples::
|
||||
|
||||
salt 'minion1' kubernetes.create_secret \
|
||||
passwords default '{"db": "letmein"}'
|
||||
|
||||
salt 'minion2' kubernetes.create_secret \
|
||||
name=passwords namespace=default data='{"db": "letmein"}'
|
||||
'''
|
||||
if source:
|
||||
data = __read_and_render_yaml_file(source, template, saltenv)
|
||||
@ -1099,12 +1112,20 @@ def create_configmap(
|
||||
name,
|
||||
namespace,
|
||||
data,
|
||||
source,
|
||||
template,
|
||||
saltenv,
|
||||
source=None,
|
||||
template=None,
|
||||
saltenv='base',
|
||||
**kwargs):
|
||||
'''
|
||||
Creates the kubernetes configmap as defined by the user.
|
||||
|
||||
CLI Examples::
|
||||
|
||||
salt 'minion1' kubernetes.create_configmap \
|
||||
settings default '{"example.conf": "# example file"}'
|
||||
|
||||
salt 'minion2' kubernetes.create_configmap \
|
||||
name=settings namespace=default data='{"example.conf": "# example file"}'
|
||||
'''
|
||||
if source:
|
||||
data = __read_and_render_yaml_file(source, template, saltenv)
|
||||
@ -1273,14 +1294,22 @@ def replace_service(name,
|
||||
|
||||
def replace_secret(name,
|
||||
data,
|
||||
source,
|
||||
template,
|
||||
saltenv,
|
||||
source=None,
|
||||
template=None,
|
||||
saltenv='base',
|
||||
namespace='default',
|
||||
**kwargs):
|
||||
'''
|
||||
Replaces an existing secret with a new one defined by name and namespace,
|
||||
having the specificed data.
|
||||
|
||||
CLI Examples::
|
||||
|
||||
salt 'minion1' kubernetes.replace_secret \
|
||||
name=passwords data='{"db": "letmein"}'
|
||||
|
||||
salt 'minion2' kubernetes.replace_secret \
|
||||
name=passwords namespace=saltstack data='{"db": "passw0rd"}'
|
||||
'''
|
||||
if source:
|
||||
data = __read_and_render_yaml_file(source, template, saltenv)
|
||||
@ -1320,14 +1349,22 @@ def replace_secret(name,
|
||||
|
||||
def replace_configmap(name,
|
||||
data,
|
||||
source,
|
||||
template,
|
||||
saltenv,
|
||||
source=None,
|
||||
template=None,
|
||||
saltenv='base',
|
||||
namespace='default',
|
||||
**kwargs):
|
||||
'''
|
||||
Replaces an existing configmap with a new one defined by name and
|
||||
namespace, having the specificed data.
|
||||
namespace with the specified data.
|
||||
|
||||
CLI Examples::
|
||||
|
||||
salt 'minion1' kubernetes.replace_configmap \
|
||||
settings default '{"example.conf": "# example file"}'
|
||||
|
||||
salt 'minion2' kubernetes.replace_configmap \
|
||||
name=settings namespace=default data='{"example.conf": "# example file"}'
|
||||
'''
|
||||
if source:
|
||||
data = __read_and_render_yaml_file(source, template, saltenv)
|
||||
@ -1444,6 +1481,13 @@ def __dict_to_object_meta(name, namespace, metadata):
|
||||
'''
|
||||
meta_obj = kubernetes.client.V1ObjectMeta()
|
||||
meta_obj.namespace = namespace
|
||||
|
||||
# Replicate `kubectl [create|replace|apply] --record`
|
||||
if 'annotations' not in metadata:
|
||||
metadata['annotations'] = {}
|
||||
if 'kubernetes.io/change-cause' not in metadata['annotations']:
|
||||
metadata['annotations']['kubernetes.io/change-cause'] = ' '.join(sys.argv)
|
||||
|
||||
for key, value in iteritems(metadata):
|
||||
if hasattr(meta_obj, key):
|
||||
setattr(meta_obj, key, value)
|
||||
|
@ -1,8 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
.. versionadded:: 2016.3.0
|
||||
Manage macOS local directory passwords and policies
|
||||
|
||||
Manage macOS local directory passwords and policies.
|
||||
.. versionadded:: 2016.3.0
|
||||
|
||||
Note that it is usually better to apply password policies through the creation
|
||||
of a configuration profile.
|
||||
|
@ -1,9 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
.. versionadded:: 2016.3.0
|
||||
System module for sleeping, restarting, and shutting down the system on Mac OS X
|
||||
|
||||
System module for sleeping, restarting, and shutting down the system on Mac OS
|
||||
X.
|
||||
.. versionadded:: 2016.3.0
|
||||
|
||||
.. warning::
|
||||
Using this module will enable ``atrun`` on the system if it is disabled.
|
||||
|
@ -85,6 +85,7 @@ without extra parameters:
|
||||
salt-run nacl.dec 'tqXzeIJnTAM9Xf0mdLcpEdklMbfBGPj2oTKmlgrm3S1DTVVHNnh9h8mU1GKllGq/+cYsk6m5WhGdk58='
|
||||
|
||||
.. code-block:: yam
|
||||
|
||||
# a salt developers minion could have pillar data that includes a nacl public key
|
||||
nacl.config:
|
||||
pk: '/kfGX7PbWeu099702PBbKWLpG/9p06IQRswkdWHCDk0='
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Namecheap management
|
||||
Namecheap dns management
|
||||
|
||||
.. versionadded:: 2017.7.0
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
the namecheap API:
|
||||
|
||||
* ``requests``
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install requests
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Namecheap management
|
||||
Namecheap domains management
|
||||
|
||||
.. versionadded:: 2017.7.0
|
||||
|
||||
@ -73,7 +73,7 @@ def reactivate(domain_name):
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'my-minion' namecheap_domains.reactivate my-domain-name
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Namecheap management
|
||||
Namecheap nameservers management
|
||||
|
||||
.. versionadded:: 2017.7.0
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
the namecheap API:
|
||||
|
||||
* ``requests``
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install requests
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Namecheap management
|
||||
Namecheap ssl management
|
||||
|
||||
.. versionadded:: 2017.7.0
|
||||
|
||||
@ -110,7 +110,7 @@ def reissue(csr_file,
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'my-minion' namecheap_ssl.reissue my-csr-file my-cert-id apachessl
|
||||
'''
|
||||
@ -164,7 +164,7 @@ def activate(csr_file,
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'my-minion' namecheap_ssl.activate my-csr-file my-cert-id apachessl
|
||||
'''
|
||||
@ -298,7 +298,7 @@ def renew(years, certificate_id, certificate_type, promotion_code=None):
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'my-minion' namecheap_ssl.renew 1 my-cert-id RapidSSL
|
||||
'''
|
||||
@ -460,7 +460,7 @@ Symantec Secure Site 1 25 24
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'my-minion' namecheap_ssl.create 2 RapidSSL
|
||||
'''
|
||||
@ -557,7 +557,7 @@ def parse_csr(csr_file, certificate_type, http_dc_validation=False):
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'my-minion' namecheap_ssl.parse_csr my-csr-file PremiumSSL
|
||||
'''
|
||||
@ -644,7 +644,7 @@ def get_list(**kwargs):
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'my-minion' namecheap_ssl.get_list Processing
|
||||
'''
|
||||
@ -688,7 +688,7 @@ def get_info(certificate_id, returncertificate=False, returntype=None):
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'my-minion' namecheap_ssl.get_info my-cert-id
|
||||
'''
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Namecheap management
|
||||
Namecheap users management
|
||||
|
||||
.. versionadded:: 2017.7.0
|
||||
|
||||
|
@ -500,7 +500,7 @@ def cli(*commands, **kwargs): # pylint: disable=unused-argument
|
||||
|
||||
CLI Example with TextFSM template:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' net.cli textfsm_parse=True textfsm_path=salt://textfsm/
|
||||
|
||||
@ -1238,6 +1238,7 @@ def load_config(filename=None,
|
||||
Example output:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
{
|
||||
'comment': 'Configuration discarded.',
|
||||
'already_configured': False,
|
||||
|
@ -1,4 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Module for OpenSCAP Management
|
||||
|
||||
'''
|
||||
|
||||
from __future__ import absolute_import
|
||||
import tempfile
|
||||
import shlex
|
||||
|
@ -10,7 +10,7 @@ What has not been implemented yet can be accessed through ``parallels.prlctl``
|
||||
and ``parallels.prlsrvctl`` (note the preceding double dash ``--`` as
|
||||
necessary):
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' parallels.prlctl installtools macvm runas=macdev
|
||||
salt -- '*' parallels.prlctl capture 'macvm --file macvm.display.png' runas=macdev
|
||||
|
@ -1,8 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
===========================
|
||||
Manage the Windows registry
|
||||
===========================
|
||||
|
||||
-----
|
||||
Hives
|
||||
|
@ -1079,7 +1079,6 @@ def build_routes(iface, **settings):
|
||||
pass
|
||||
log.debug('Template name: ' + template)
|
||||
|
||||
iface = iface.lower()
|
||||
opts = _parse_routes(iface, settings)
|
||||
log.debug("Opts: \n {0}".format(opts))
|
||||
try:
|
||||
|
@ -58,11 +58,16 @@ def renderer(path=None, string=None, default_renderer='jinja|yaml', **kwargs):
|
||||
'''
|
||||
Parse a string or file through Salt's renderer system
|
||||
|
||||
.. versionchanged:: Oxygen
|
||||
Add support for Salt fileserver URIs.
|
||||
|
||||
This is an open-ended function and can be used for a variety of tasks. It
|
||||
makes use of Salt's "renderer pipes" system to run a string or file through
|
||||
a pipe of any of the loaded renderer modules.
|
||||
|
||||
:param path: The path to a file on the filesystem.
|
||||
:param path: The path to a file on Salt's fileserver (any URIs supported by
|
||||
:py:func:`cp.get_url <salt.modules.cp.get_url>`) or on the local file
|
||||
system.
|
||||
:param string: An inline string to be used as the file to send through the
|
||||
renderer system. Note, not all renderer modules can work with strings;
|
||||
the 'py' renderer requires a file, for example.
|
||||
@ -113,6 +118,7 @@ def renderer(path=None, string=None, default_renderer='jinja|yaml', **kwargs):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' slsutil.renderer salt://path/to/file
|
||||
salt '*' slsutil.renderer /path/to/file
|
||||
salt '*' slsutil.renderer /path/to/file.jinja 'jinja'
|
||||
salt '*' slsutil.renderer /path/to/file.sls 'jinja|yaml'
|
||||
@ -126,7 +132,7 @@ def renderer(path=None, string=None, default_renderer='jinja|yaml', **kwargs):
|
||||
renderers = salt.loader.render(__opts__, __salt__)
|
||||
|
||||
if path:
|
||||
path_or_string = path
|
||||
path_or_string = __salt__['cp.get_url'](path)
|
||||
elif string:
|
||||
path_or_string = ':string:'
|
||||
kwargs['input_data'] = string
|
||||
|
@ -229,6 +229,7 @@ def set_config(name='root', **kwargs):
|
||||
snapper convention. The above example is equivalent to:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' snapper.set_config sync_acl=True
|
||||
'''
|
||||
try:
|
||||
|
@ -186,7 +186,7 @@ def extract_war_version(war):
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: text
|
||||
|
||||
/path/salt-2015.8.6.war -> 2015.8.6
|
||||
/path/V6R2013xD5.war -> None
|
||||
|
@ -170,6 +170,7 @@ def exportdb():
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' udev.exportdb
|
||||
'''
|
||||
|
||||
|
@ -1,13 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Functions to interact with Hashicorp Vault.
|
||||
|
||||
:maintainer: SaltStack
|
||||
:maturity: new
|
||||
:platform: all
|
||||
|
||||
Functions to interact with Hashicorp Vault.
|
||||
|
||||
:note: If you see the following error, you'll need to upgrade ``requests`` to atleast 2.4.2
|
||||
.. code-block:: shell
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
<timestamp> [salt.pillar][CRITICAL][14337] Pillar render error: Failed to load ext_pillar vault: {'error': "request() got an unexpected keyword argument 'json'"}
|
||||
|
||||
|
||||
@ -151,6 +154,7 @@ def write_secret(path, **kwargs):
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' vault.write_secret "secret/my/secret" user="foo" password="bar"
|
||||
'''
|
||||
log.debug(
|
||||
@ -176,6 +180,7 @@ def delete_secret(path):
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' vault.delete_secret "secret/my/secret"
|
||||
'''
|
||||
log.debug('Deleting vault secrets for {0} in {1}'
|
||||
@ -199,6 +204,7 @@ def list_secrets(path):
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' vault.list_secrets "secret/my/"
|
||||
'''
|
||||
log.debug('Listing vault secret keys for {0} in {1}'
|
||||
|
@ -4211,6 +4211,7 @@ def list_dvportgroups(dvs=None, portgroup_names=None, service_instance=None):
|
||||
Default is None.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' vsphere.list_dvporgroups
|
||||
|
||||
salt '*' vsphere.list_dvportgroups dvs=dvs1
|
||||
@ -4662,6 +4663,7 @@ def list_storage_policies(policy_names=None, service_instance=None):
|
||||
Default is None.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' vsphere.list_storage_policies
|
||||
|
||||
salt '*' vsphere.list_storage_policy policy_names=[policy_name]
|
||||
@ -4688,6 +4690,7 @@ def list_default_vsan_policy(service_instance=None):
|
||||
Default is None.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' vsphere.list_storage_policies
|
||||
|
||||
salt '*' vsphere.list_storage_policy policy_names=[policy_name]
|
||||
@ -4726,6 +4729,7 @@ def list_capability_definitions(service_instance=None):
|
||||
Default is None.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' vsphere.list_capabilities
|
||||
'''
|
||||
profile_manager = salt.utils.pbm.get_profile_manager(service_instance)
|
||||
@ -4806,6 +4810,7 @@ def create_storage_policy(policy_name, policy_dict, service_instance=None):
|
||||
Default is None.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' vsphere.create_storage_policy policy_name='policy name'
|
||||
policy_dict="$policy_dict"
|
||||
'''
|
||||
@ -4845,6 +4850,7 @@ def update_storage_policy(policy, policy_dict, service_instance=None):
|
||||
Default is None.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' vsphere.update_storage_policy policy='policy name'
|
||||
policy_dict="$policy_dict"
|
||||
'''
|
||||
@ -4882,6 +4888,7 @@ def list_default_storage_policy_of_datastore(datastore, service_instance=None):
|
||||
Default is None.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' vsphere.list_default_storage_policy_of_datastore datastore=ds1
|
||||
'''
|
||||
log.trace('Listing the default storage policy of datastore \'{0}\''
|
||||
@ -4920,6 +4927,7 @@ def assign_default_storage_policy_to_datastore(policy, datastore,
|
||||
Default is None.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' vsphere.assign_storage_policy_to_datastore
|
||||
policy='policy name' datastore=ds1
|
||||
'''
|
||||
@ -4964,6 +4972,7 @@ def list_datacenters_via_proxy(datacenter_names=None, service_instance=None):
|
||||
Default is None.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' vsphere.list_datacenters_via_proxy
|
||||
|
||||
salt '*' vsphere.list_datacenters_via_proxy dc1
|
||||
|
@ -1,9 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
This module is Alpha
|
||||
|
||||
Module for working with Windows PowerShell DSC (Desired State Configuration)
|
||||
|
||||
This module is Alpha
|
||||
|
||||
This module applies DSC Configurations in the form of PowerShell scripts or
|
||||
MOF (Managed Object Format) schema files.
|
||||
|
||||
|
@ -5374,7 +5374,7 @@ def set_(computer_policy=None, user_policy=None,
|
||||
_regedits[regedit]['policy']['Registry']['Type'])
|
||||
else:
|
||||
_ret = __salt__['reg.delete_value'](
|
||||
_regedits[regedit]['polic']['Registry']['Hive'],
|
||||
_regedits[regedit]['policy']['Registry']['Hive'],
|
||||
_regedits[regedit]['policy']['Registry']['Path'],
|
||||
_regedits[regedit]['policy']['Registry']['Value'])
|
||||
if not _ret:
|
||||
|
225
salt/modules/wordpress.py
Normal file
225
salt/modules/wordpress.py
Normal file
@ -0,0 +1,225 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
This module is used to manage Wordpress installations
|
||||
|
||||
:depends: wp binary from http://wp-cli.org/
|
||||
'''
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import Python Modules
|
||||
import collections
|
||||
|
||||
# Import Salt Modules
|
||||
import salt.utils
|
||||
from salt.ext.six.moves import map
|
||||
|
||||
Plugin = collections.namedtuple('Plugin', 'name status update versino')
|
||||
|
||||
|
||||
def __virtual__():
|
||||
if salt.utils.which('wp'):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _get_plugins(stuff):
|
||||
return Plugin(stuff)
|
||||
|
||||
|
||||
def list_plugins(path, user):
|
||||
'''
|
||||
List plugins in an installed wordpress path
|
||||
|
||||
path
|
||||
path to wordpress install location
|
||||
|
||||
user
|
||||
user to run the command as
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' wordpress.list_plugins /var/www/html apache
|
||||
'''
|
||||
ret = []
|
||||
resp = __salt__['cmd.shell']((
|
||||
'wp --path={0} plugin list'
|
||||
).format(path), runas=user)
|
||||
for line in resp.split('\n')[1:]:
|
||||
ret.append(line.split('\t'))
|
||||
return [plugin.__dict__ for plugin in map(_get_plugins, ret)]
|
||||
|
||||
|
||||
def show_plugin(name, path, user):
|
||||
'''
|
||||
Show a plugin in a wordpress install and check if it is installed
|
||||
|
||||
name
|
||||
Wordpress plugin name
|
||||
|
||||
path
|
||||
path to wordpress install location
|
||||
|
||||
user
|
||||
user to run the command as
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' wordpress.show_plugin HyperDB /var/www/html apache
|
||||
'''
|
||||
ret = {'name': name}
|
||||
resp = __salt__['cmd.shell']((
|
||||
'wp --path={0} plugin status {1}'
|
||||
).format(path, name), runas=user).split('\n')
|
||||
for line in resp:
|
||||
if 'Status' in line:
|
||||
ret['status'] = line.split(' ')[-1].lower()
|
||||
elif 'Version' in line:
|
||||
ret['version'] = line.split(' ')[-1].lower()
|
||||
return ret
|
||||
|
||||
|
||||
def activate(name, path, user):
|
||||
'''
|
||||
Activate a wordpress plugin
|
||||
|
||||
name
|
||||
Wordpress plugin name
|
||||
|
||||
path
|
||||
path to wordpress install location
|
||||
|
||||
user
|
||||
user to run the command as
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' wordpress.activate HyperDB /var/www/html apache
|
||||
'''
|
||||
check = show_plugin(name, path, user)
|
||||
if check['status'] == 'active':
|
||||
# already active
|
||||
return None
|
||||
resp = __salt__['cmd.shell']((
|
||||
'wp --path={0} plugin activate {1}'
|
||||
).format(path, name), runas=user)
|
||||
if 'Success' in resp:
|
||||
return True
|
||||
elif show_plugin(name, path, user)['status'] == 'active':
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def deactivate(name, path, user):
|
||||
'''
|
||||
Deactivate a wordpress plugin
|
||||
|
||||
name
|
||||
Wordpress plugin name
|
||||
|
||||
path
|
||||
path to wordpress install location
|
||||
|
||||
user
|
||||
user to run the command as
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' wordpress.deactivate HyperDB /var/www/html apache
|
||||
'''
|
||||
check = show_plugin(name, path, user)
|
||||
if check['status'] == 'inactive':
|
||||
# already inactive
|
||||
return None
|
||||
resp = __salt__['cmd.shell']((
|
||||
'wp --path={0} plugin deactivate {1}'
|
||||
).format(path, name), runas=user)
|
||||
if 'Success' in resp:
|
||||
return True
|
||||
elif show_plugin(name, path, user)['status'] == 'inactive':
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def is_installed(path, user=None):
|
||||
'''
|
||||
Check if wordpress is installed and setup
|
||||
|
||||
path
|
||||
path to wordpress install location
|
||||
|
||||
user
|
||||
user to run the command as
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' wordpress.is_installed /var/www/html apache
|
||||
'''
|
||||
retcode = __salt__['cmd.retcode']((
|
||||
'wp --path={0} core is-installed'
|
||||
).format(path), runas=user)
|
||||
if retcode == 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def install(path, user, admin_user, admin_password, admin_email, title, url):
|
||||
'''
|
||||
Run the initial setup functions for a wordpress install
|
||||
|
||||
path
|
||||
path to wordpress install location
|
||||
|
||||
user
|
||||
user to run the command as
|
||||
|
||||
admin_user
|
||||
Username for the Administrative user for the wordpress install
|
||||
|
||||
admin_password
|
||||
Initial Password for the Administrative user for the wordpress install
|
||||
|
||||
admin_email
|
||||
Email for the Administrative user for the wordpress install
|
||||
|
||||
title
|
||||
Title of the wordpress website for the wordpress install
|
||||
|
||||
url
|
||||
Url for the wordpress install
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' wordpress.install /var/www/html apache dwallace password123 \
|
||||
dwallace@example.com "Daniel's Awesome Blog" https://blog.dwallace.com
|
||||
'''
|
||||
retcode = __salt__['cmd.retcode']((
|
||||
'wp --path={0} core install '
|
||||
'--title="{1}" '
|
||||
'--admin_user={2} '
|
||||
"--admin_password='{3}' "
|
||||
'--admin_email={4} '
|
||||
'--url={5}'
|
||||
).format(
|
||||
path,
|
||||
title,
|
||||
admin_user,
|
||||
admin_password,
|
||||
admin_email,
|
||||
url
|
||||
), runas=user)
|
||||
|
||||
if retcode == 0:
|
||||
return True
|
||||
return False
|
@ -17,6 +17,7 @@ import salt.modules.cmdmod
|
||||
import salt.utils.decorators as decorators
|
||||
from salt.utils.odict import OrderedDict
|
||||
|
||||
__virtualname__ = 'zfs'
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# Function alias to set mapping.
|
||||
@ -25,6 +26,16 @@ __func_alias__ = {
|
||||
}
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Only load when the platform has zfs support
|
||||
'''
|
||||
if __grains__['zfs_support']:
|
||||
return __virtualname__
|
||||
else:
|
||||
return (False, "The zfs module cannot be loaded: zfs not supported")
|
||||
|
||||
|
||||
@decorators.memoize
|
||||
def _check_zfs():
|
||||
'''
|
||||
@ -51,42 +62,6 @@ def _check_features():
|
||||
return res['retcode'] == 0
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Makes sure that ZFS kernel module is loaded.
|
||||
'''
|
||||
on_freebsd = __grains__['kernel'] == 'FreeBSD'
|
||||
on_linux = __grains__['kernel'] == 'Linux'
|
||||
on_solaris = __grains__['kernel'] == 'SunOS' and __grains__['kernelrelease'] == '5.11'
|
||||
|
||||
cmd = ''
|
||||
if on_freebsd:
|
||||
cmd = 'kldstat -q -m zfs'
|
||||
elif on_linux:
|
||||
modinfo = salt.utils.path.which('modinfo')
|
||||
if modinfo:
|
||||
cmd = '{0} zfs'.format(modinfo)
|
||||
else:
|
||||
cmd = 'ls /sys/module/zfs'
|
||||
elif on_solaris:
|
||||
# not using salt.utils.path.which('zfs') to keep compatible with others
|
||||
cmd = 'which zfs'
|
||||
|
||||
if cmd and salt.modules.cmdmod.retcode(
|
||||
cmd, output_loglevel='quiet', ignore_retcode=True
|
||||
) == 0:
|
||||
return 'zfs'
|
||||
|
||||
if __grains__['kernel'] == 'OpenBSD':
|
||||
return False
|
||||
|
||||
_zfs_fuse = lambda f: __salt__['service.' + f]('zfs-fuse')
|
||||
if _zfs_fuse('available') and (_zfs_fuse('status') or _zfs_fuse('start')):
|
||||
return 'zfs'
|
||||
|
||||
return (False, "The zfs module cannot be loaded: zfs not found")
|
||||
|
||||
|
||||
def exists(name, **kwargs):
|
||||
'''
|
||||
.. versionadded:: 2015.5.0
|
||||
|
@ -1,11 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
:depends: kazoo
|
||||
:configuration: See :py:mod:`salt.modules.zookeeper` for setup instructions.
|
||||
|
||||
Concurrency controls in zookeeper
|
||||
=========================================================================
|
||||
|
||||
:depends: kazoo
|
||||
:configuration: See :py:mod:`salt.modules.zookeeper` for setup instructions.
|
||||
|
||||
This module allows you to acquire and release a slot. This is primarily useful
|
||||
for ensureing that no more than N hosts take a specific action at once. This can
|
||||
also be used to coordinate between masters.
|
||||
|
@ -34,6 +34,7 @@ Configuration
|
||||
be set up as different configuration profiles. For example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
zookeeper:
|
||||
prod:
|
||||
hosts: zoo1,zoo2,zoo3
|
||||
|
@ -19,12 +19,23 @@ from salt.utils.odict import OrderedDict
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
__virtualname__ = 'zpool'
|
||||
__func_alias__ = {
|
||||
'import_': 'import',
|
||||
'list_': 'list',
|
||||
}
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Only load when the platform has zfs support
|
||||
'''
|
||||
if __grains__['zfs_support']:
|
||||
return __virtualname__
|
||||
else:
|
||||
return (False, "The zpool module cannot be loaded: zfs not supported")
|
||||
|
||||
|
||||
@salt.utils.decorators.memoize
|
||||
def _check_zpool():
|
||||
'''
|
||||
@ -58,15 +69,6 @@ def _check_mkfile():
|
||||
return salt.utils.path.which('mkfile')
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Provides zpool.
|
||||
'''
|
||||
if _check_zpool():
|
||||
return 'zpool'
|
||||
return (False, "Module zpool: zpool not found")
|
||||
|
||||
|
||||
def healthy():
|
||||
'''
|
||||
.. versionadded:: 2016.3.0
|
||||
|
@ -71,12 +71,12 @@ A REST API for Salt
|
||||
log_access_file
|
||||
Path to a file to write HTTP access logs.
|
||||
|
||||
.. versionaddedd:: 2016.11.0
|
||||
.. versionadded:: 2016.11.0
|
||||
|
||||
log_error_file
|
||||
Path to a file to write HTTP error logs.
|
||||
|
||||
.. versionaddedd:: 2016.11.0
|
||||
.. versionadded:: 2016.11.0
|
||||
|
||||
ssl_crt
|
||||
The path to a SSL certificate. (See below)
|
||||
|
@ -221,6 +221,8 @@ def _format_host(host, data):
|
||||
tcolor = colors['GREEN']
|
||||
orchestration = ret.get('__orchestration__', False)
|
||||
schanged, ctext = _format_changes(ret['changes'], orchestration)
|
||||
if not ctext and 'pchanges' in ret:
|
||||
schanged, ctext = _format_changes(ret['pchanges'], orchestration)
|
||||
nchanges += 1 if schanged else 0
|
||||
|
||||
# Skip this state if it was successful & diff output was requested
|
||||
|
@ -2,7 +2,7 @@
|
||||
'''
|
||||
Store key/value pairs in a CSV file
|
||||
|
||||
.. versionaddedd:: 2016.11.0
|
||||
.. versionadded:: 2016.11.0
|
||||
|
||||
Example configuration:
|
||||
|
||||
|
@ -16,6 +16,7 @@ Command Line
|
||||
------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call pillar.get nodegroups
|
||||
local:
|
||||
- class_infra
|
||||
|
@ -466,7 +466,9 @@ def exit_success(jid, ext_source=None):
|
||||
The external job cache to use. Default: `None`.
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-run jobs.exit_success 20160520145827701627
|
||||
'''
|
||||
ret = dict()
|
||||
|
@ -85,6 +85,7 @@ without extra parameters:
|
||||
salt-run nacl.dec 'tqXzeIJnTAM9Xf0mdLcpEdklMbfBGPj2oTKmlgrm3S1DTVVHNnh9h8mU1GKllGq/+cYsk6m5WhGdk58='
|
||||
|
||||
.. code-block:: yam
|
||||
|
||||
# a salt developers minion could have pillar data that includes a nacl public key
|
||||
nacl.config:
|
||||
pk: '/kfGX7PbWeu099702PBbKWLpG/9p06IQRswkdWHCDk0='
|
||||
|
@ -85,7 +85,7 @@ def get_opts():
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: bash
|
||||
|
||||
salt-run test.get_opts
|
||||
'''
|
||||
|
@ -13,6 +13,7 @@ be configured in either the minion or master configuration file. This profile
|
||||
requires very little. For example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
myconsul:
|
||||
driver: consul
|
||||
host: 127.0.0.1
|
||||
|
@ -124,7 +124,9 @@ def present(name, api_name, swagger_file, stage_name, api_key_required,
|
||||
with the following schema. The lambda functions should throw exceptions for any non successful responses.
|
||||
An optional pattern field can be specified in errorMessage field to aid the response mapping from Lambda
|
||||
to the proper error return status codes.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
Error:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -984,7 +984,7 @@ def instance_absent(name, instance_name=None, instance_id=None,
|
||||
'''
|
||||
Ensure an EC2 instance does not exist (is stopped and removed).
|
||||
|
||||
.. versionupdated:: 2016.11.0
|
||||
.. versionchanged:: 2016.11.0
|
||||
|
||||
name
|
||||
(string) - The name of the state definition.
|
||||
@ -1010,6 +1010,7 @@ def instance_absent(name, instance_name=None, instance_id=None,
|
||||
YAML example fragment:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
- filters:
|
||||
vpc-id: vpc-abcdef12
|
||||
|
||||
@ -1230,6 +1231,7 @@ def volumes_tagged(name, tag_maps, authoritative=False, region=None, key=None,
|
||||
YAML example fragment:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
- filters:
|
||||
attachment.instance_id: i-abcdef12
|
||||
tags:
|
||||
|
@ -1636,7 +1636,7 @@ def policy_absent(name,
|
||||
def saml_provider_present(name, saml_metadata_document, region=None, key=None, keyid=None, profile=None):
|
||||
'''
|
||||
|
||||
.. versionadded::
|
||||
.. versionadded:: 2016.11.0
|
||||
|
||||
Ensure the SAML provider with the specified name is present.
|
||||
|
||||
@ -1694,7 +1694,7 @@ def saml_provider_present(name, saml_metadata_document, region=None, key=None, k
|
||||
def saml_provider_absent(name, region=None, key=None, keyid=None, profile=None):
|
||||
'''
|
||||
|
||||
.. versionadded::
|
||||
.. versionadded:: 2016.11.0
|
||||
|
||||
Ensure the SAML provider with the specified name is absent.
|
||||
|
||||
|
@ -153,6 +153,7 @@ def function_present(name, FunctionName, Runtime, Role, Handler, ZipFile=None,
|
||||
to the same VPC. This is a dict of the form:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
VpcConfig:
|
||||
SecurityGroupNames:
|
||||
- mysecgroup1
|
||||
|
@ -1,7 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
from salt.ext.six.moves import map
|
||||
|
||||
'''
|
||||
CSF Ip tables management
|
||||
========================
|
||||
@ -18,6 +15,9 @@ CSF Ip tables management
|
||||
method: allow
|
||||
''' # pylint: disable=W0105
|
||||
|
||||
from __future__ import absolute_import
|
||||
from salt.ext.six.moves import map
|
||||
|
||||
|
||||
def __virtual__():
|
||||
return 'csf'
|
||||
|
@ -300,7 +300,7 @@ def running(name,
|
||||
Additionally, the specified selinux context will be set within the
|
||||
container.
|
||||
|
||||
``<read_only>`` can be either ``ro`` for read-write access, or ``ro``
|
||||
``<read_only>`` can be either ``rw`` for read-write access, or ``ro``
|
||||
for read-only access. When omitted, it is assumed to be read-write.
|
||||
|
||||
``<selinux_context>`` can be ``z`` if the volume is shared between
|
||||
@ -1235,6 +1235,7 @@ def running(name,
|
||||
If ``True``, runs the exec process with extended privileges
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
foo:
|
||||
docker_container.running:
|
||||
- image: bar/baz:lates
|
||||
|
@ -65,6 +65,7 @@ def present(name, definition=None):
|
||||
**Example:**
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# Default settings
|
||||
mytestindex:
|
||||
elasticsearch_index.present
|
||||
|
@ -65,6 +65,7 @@ def present(name, definition):
|
||||
**Example:**
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
mytestindex2_template:
|
||||
elasticsearch_index_template.present:
|
||||
- definition:
|
||||
|
@ -45,6 +45,7 @@ Etcd profile configuration can be overriden using following arguments: ``host``,
|
||||
``port``, ``username``, ``password``, ``ca``, ``client_key`` and ``client_cert``.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
my-value:
|
||||
etcd.set:
|
||||
- name: /path/to/key
|
||||
|
@ -2364,10 +2364,8 @@ def managed(name,
|
||||
elif ret['pchanges']:
|
||||
ret['result'] = None
|
||||
ret['comment'] = u'The file {0} is set to be changed'.format(name)
|
||||
if show_changes and 'diff' in ret['pchanges']:
|
||||
ret['changes']['diff'] = ret['pchanges']['diff']
|
||||
if not show_changes:
|
||||
ret['changes']['diff'] = '<show_changes=False>'
|
||||
if 'diff' in ret['pchanges'] and not show_changes:
|
||||
ret['pchanges']['diff'] = '<show_changes=False>'
|
||||
else:
|
||||
ret['result'] = True
|
||||
ret['comment'] = u'The file {0} is in the correct state'.format(name)
|
||||
@ -3674,20 +3672,20 @@ def line(name, content=None, match=None, mode=None, location=None,
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
name
|
||||
:param name:
|
||||
Filesystem path to the file to be edited.
|
||||
|
||||
content
|
||||
:param content:
|
||||
Content of the line. Allowed to be empty if mode=delete.
|
||||
|
||||
match
|
||||
:param match:
|
||||
Match the target line for an action by
|
||||
a fragment of a string or regular expression.
|
||||
|
||||
If neither ``before`` nor ``after`` are provided, and ``match``
|
||||
is also ``None``, match becomes the ``content`` value.
|
||||
|
||||
mode
|
||||
:param mode:
|
||||
Defines how to edit a line. One of the following options is
|
||||
required:
|
||||
|
||||
@ -3707,7 +3705,7 @@ def line(name, content=None, match=None, mode=None, location=None,
|
||||
``after``. If ``location`` is used, it takes precedence
|
||||
over the other two options.
|
||||
|
||||
location
|
||||
:param location:
|
||||
Defines where to place content in the line. Note this option is only
|
||||
used when ``mode=insert`` is specified. If a location is passed in, it
|
||||
takes precedence over both the ``before`` and ``after`` kwargs. Valid
|
||||
@ -3718,17 +3716,17 @@ def line(name, content=None, match=None, mode=None, location=None,
|
||||
- end
|
||||
Place the content at the end of the file.
|
||||
|
||||
before
|
||||
:param before:
|
||||
Regular expression or an exact case-sensitive fragment of the string.
|
||||
This option is only used when either the ``ensure`` or ``insert`` mode
|
||||
is defined.
|
||||
|
||||
after
|
||||
:param after:
|
||||
Regular expression or an exact case-sensitive fragment of the string.
|
||||
This option is only used when either the ``ensure`` or ``insert`` mode
|
||||
is defined.
|
||||
|
||||
show_changes
|
||||
:param show_changes:
|
||||
Output a unified diff of the old file and the new file.
|
||||
If ``False`` return a boolean if any changes were made.
|
||||
Default is ``True``
|
||||
@ -3737,15 +3735,15 @@ def line(name, content=None, match=None, mode=None, location=None,
|
||||
Using this option will store two copies of the file in-memory
|
||||
(the original version and the edited version) in order to generate the diff.
|
||||
|
||||
backup
|
||||
:param backup:
|
||||
Create a backup of the original file with the extension:
|
||||
"Year-Month-Day-Hour-Minutes-Seconds".
|
||||
|
||||
quiet
|
||||
:param quiet:
|
||||
Do not raise any exceptions. E.g. ignore the fact that the file that is
|
||||
tried to be edited does not exist and nothing really happened.
|
||||
|
||||
indent
|
||||
:param indent:
|
||||
Keep indentation with the previous line. This option is not considered when
|
||||
the ``delete`` mode is specified.
|
||||
|
||||
|
@ -432,7 +432,7 @@ def namespace_present(name, **kwargs):
|
||||
Ensures that the named namespace is present.
|
||||
|
||||
name
|
||||
The name of the deployment.
|
||||
The name of the namespace.
|
||||
|
||||
'''
|
||||
ret = {'name': name,
|
||||
@ -449,6 +449,7 @@ def namespace_present(name, **kwargs):
|
||||
return ret
|
||||
|
||||
res = __salt__['kubernetes.create_namespace'](name, **kwargs)
|
||||
ret['result'] = True
|
||||
ret['changes']['namespace'] = {
|
||||
'old': {},
|
||||
'new': res}
|
||||
@ -504,8 +505,8 @@ def secret_present(
|
||||
name,
|
||||
namespace='default',
|
||||
data=None,
|
||||
source='',
|
||||
template='',
|
||||
source=None,
|
||||
template=None,
|
||||
**kwargs):
|
||||
'''
|
||||
Ensures that the named secret is present inside of the specified namespace
|
||||
@ -562,6 +563,7 @@ def secret_present(
|
||||
else:
|
||||
if __opts__['test']:
|
||||
ret['result'] = None
|
||||
ret['comment'] = 'The secret is going to be replaced'
|
||||
return ret
|
||||
|
||||
# TODO: improve checks # pylint: disable=fixme
|
||||
@ -594,7 +596,8 @@ def configmap_absent(name, namespace='default', **kwargs):
|
||||
The name of the configmap
|
||||
|
||||
namespace
|
||||
The name of the namespace
|
||||
The namespace holding the configmap. The 'default' one is going to be
|
||||
used unless a different one is specified.
|
||||
'''
|
||||
|
||||
ret = {'name': name,
|
||||
@ -631,8 +634,8 @@ def configmap_present(
|
||||
name,
|
||||
namespace='default',
|
||||
data=None,
|
||||
source='',
|
||||
template='',
|
||||
source=None,
|
||||
template=None,
|
||||
**kwargs):
|
||||
'''
|
||||
Ensures that the named configmap is present inside of the specified namespace
|
||||
@ -665,6 +668,8 @@ def configmap_present(
|
||||
ret,
|
||||
'\'source\' cannot be used in combination with \'data\''
|
||||
)
|
||||
elif data is None:
|
||||
data = {}
|
||||
|
||||
configmap = __salt__['kubernetes.show_configmap'](name, namespace, **kwargs)
|
||||
|
||||
@ -686,6 +691,7 @@ def configmap_present(
|
||||
else:
|
||||
if __opts__['test']:
|
||||
ret['result'] = None
|
||||
ret['comment'] = 'The configmap is going to be replaced'
|
||||
return ret
|
||||
|
||||
# TODO: improve checks # pylint: disable=fixme
|
||||
@ -975,6 +981,7 @@ def node_label_present(
|
||||
else:
|
||||
if __opts__['test']:
|
||||
ret['result'] = None
|
||||
ret['comment'] = 'The label is going to be updated'
|
||||
return ret
|
||||
|
||||
ret['comment'] = 'The label is already set, changing the value'
|
||||
|
@ -34,6 +34,7 @@ Example:
|
||||
Using States to deploy a load balancer with extended arguments to specify region
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
lb_test:
|
||||
libcloud_loadbalancer.balancer_present:
|
||||
- name: example
|
||||
|
@ -91,6 +91,7 @@ def installed(name, target="LocalSystem", dmg=False, store=False, app=False, mpk
|
||||
The command and version that we want to check against, the version number can use regex.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
version_check: python --version_check=2.7.[0-9]
|
||||
|
||||
'''
|
||||
|
@ -2,6 +2,7 @@
|
||||
'''
|
||||
Send a message card to Microsoft Teams
|
||||
=======================
|
||||
|
||||
This state is useful for sending messages to Teams during state runs.
|
||||
.. versionadded:: 2017.7.0
|
||||
.. code-block:: yaml
|
||||
|
@ -121,14 +121,15 @@ def present(name,
|
||||
if flag in mtdata:
|
||||
toupgrade = True
|
||||
mode = 'upgrade'
|
||||
if __opts__['test']:
|
||||
ret['result'] = None
|
||||
if mode:
|
||||
ret['comment'] = 'Extension {0} is set to be {1}ed'.format(
|
||||
name, mode).replace('eed', 'ed')
|
||||
return ret
|
||||
cret = None
|
||||
if toinstall or toupgrade:
|
||||
if __opts__['test']:
|
||||
ret['result'] = None
|
||||
if mode:
|
||||
ret['comment'] = 'Extension {0} is set to be {1}ed'.format(
|
||||
name, mode).replace('eed', 'ed')
|
||||
return ret
|
||||
|
||||
cret = __salt__['postgres.create_extension'](
|
||||
name=name,
|
||||
if_not_exists=if_not_exists,
|
||||
|
@ -1,8 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
r'''
|
||||
===========================
|
||||
Manage the Windows registry
|
||||
===========================
|
||||
|
||||
Many python developers think of registry keys as if they were python keys in a
|
||||
dictionary which is not the case. The windows registry is broken down into the
|
||||
following components:
|
||||
|
@ -1,4 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
State to work with sysrc
|
||||
|
||||
'''
|
||||
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
|
@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
.. versionadded:: 2016.3.0.
|
||||
|
||||
Manage Telemetry alert configurations
|
||||
=====================================
|
||||
|
||||
.. versionadded:: 2016.3.0
|
||||
|
||||
Create, Update and destroy Mongo Telemetry alert configurations.
|
||||
|
||||
This module uses requests, which can be installed via package, or pip.
|
||||
|
@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
r'''
|
||||
.. index:: Vagrant state function
|
||||
|
||||
Manage Vagrant VMs
|
||||
==================
|
||||
|
||||
.. index:: Vagrant state function
|
||||
|
||||
Manange execution of Vagrant virtual machines on Salt minions.
|
||||
|
||||
Vagrant_ is a tool for building and managing virtual machine environments.
|
||||
|
@ -1,13 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
States for managing Hashicorp Vault.
|
||||
Currently handles policies. Configuration instructions are documented in the execution module docs.
|
||||
|
||||
:maintainer: SaltStack
|
||||
:maturity: new
|
||||
:platform: all
|
||||
|
||||
.. versionadded:: 2017.7.0
|
||||
|
||||
States for managing Hashicorp Vault. Currently handles policies. Configuration
|
||||
instructions are documented in the execution module docs.
|
||||
'''
|
||||
from __future__ import absolute_import
|
||||
import logging
|
||||
|
@ -65,7 +65,8 @@ def exists(name, index=None):
|
||||
'''
|
||||
Add the directory to the system PATH at index location
|
||||
|
||||
index: where the directory should be placed in the PATH (default: None)
|
||||
index: where the directory should be placed in the PATH (default: None).
|
||||
This is 0-indexed, so 0 means to prepend at the very start of the PATH.
|
||||
[Note: Providing no index will append directory to PATH and
|
||||
will not enforce its location within the PATH.]
|
||||
|
||||
@ -96,7 +97,7 @@ def exists(name, index=None):
|
||||
|
||||
try:
|
||||
currIndex = sysPath.index(path)
|
||||
if index:
|
||||
if index is not None:
|
||||
index = int(index)
|
||||
if index < 0:
|
||||
index = len(sysPath) + index + 1
|
||||
@ -115,7 +116,7 @@ def exists(name, index=None):
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
if not index:
|
||||
if index is None:
|
||||
index = len(sysPath) # put it at the end
|
||||
ret['changes']['added'] = '{0} will be added at index {1}'.format(name, index)
|
||||
if __opts__['test']:
|
||||
|
189
salt/states/wordpress.py
Normal file
189
salt/states/wordpress.py
Normal file
@ -0,0 +1,189 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
This state module is used to manage Wordpress installations
|
||||
|
||||
:depends: wp binary from http://wp-cli.org/
|
||||
'''
|
||||
|
||||
|
||||
def __virtual__():
|
||||
return 'wordpress.show_plugin' in __salt__
|
||||
|
||||
|
||||
def installed(name, user, admin_user, admin_password, admin_email, title, url):
|
||||
'''
|
||||
Run the initial setup of wordpress
|
||||
|
||||
name
|
||||
path to the wordpress installation
|
||||
|
||||
user
|
||||
user that owns the files for the wordpress installation
|
||||
|
||||
admin_user
|
||||
username for wordpress website administrator user
|
||||
|
||||
admin_password
|
||||
password for wordpress website administrator user
|
||||
|
||||
admin_email
|
||||
email for wordpress website administrator user
|
||||
|
||||
title
|
||||
title for the wordpress website
|
||||
|
||||
url
|
||||
url for the wordpress website
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
/var/www/html:
|
||||
wordpress.installed:
|
||||
- title: Daniel's Awesome Blog
|
||||
- user: apache
|
||||
- admin_user: dwallace
|
||||
- admin_email: dwallace@example.com
|
||||
- admin_password: password123
|
||||
- url: https://blog.dwallace.com
|
||||
'''
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
'comment': '',
|
||||
'result': False}
|
||||
|
||||
check = __salt__['wordpress.is_installed'](name, user)
|
||||
|
||||
if check:
|
||||
ret['result'] = True
|
||||
ret['comment'] = 'Wordpress is already installed: {0}'.format(name)
|
||||
return ret
|
||||
elif __opts__['test']:
|
||||
ret['result'] = None
|
||||
ret['comment'] = 'Wordpress will be installed: {0}'.format(name)
|
||||
return ret
|
||||
|
||||
resp = __salt__['wordpress.install'](name, user, admin_user, admin_password, admin_email, title, url)
|
||||
if resp:
|
||||
ret['result'] = True
|
||||
ret['comment'] = 'Wordpress Installed: {0}'.format(name)
|
||||
ret['changes'] = {
|
||||
'new': resp
|
||||
}
|
||||
else:
|
||||
ret['comment'] = 'Failed to install wordpress: {0}'.format(name)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def activated(name, path, user):
|
||||
'''
|
||||
Activate wordpress plugins
|
||||
|
||||
name
|
||||
name of plugin to activate
|
||||
|
||||
path
|
||||
path to wordpress installation
|
||||
|
||||
user
|
||||
user who should own the files in the wordpress installation
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
HyperDB:
|
||||
wordpress.activated:
|
||||
- path: /var/www/html
|
||||
- user: apache
|
||||
'''
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
'comment': '',
|
||||
'result': False}
|
||||
|
||||
check = __salt__['wordpress.show_plugin'](name, path, user)
|
||||
|
||||
if check['status'] == 'active':
|
||||
ret['result'] = True
|
||||
ret['comment'] = 'Plugin already activated: {0}'.format(name)
|
||||
return ret
|
||||
elif __opts__['test']:
|
||||
ret['result'] = None
|
||||
ret['comment'] = 'Plugin will be activated: {0}'.format(name)
|
||||
return ret
|
||||
|
||||
resp = __salt__['wordpress.activate'](name, path, user)
|
||||
if resp is True:
|
||||
ret['result'] = True
|
||||
ret['comment'] = 'Plugin activated: {0}'.format(name)
|
||||
ret['changes'] = {
|
||||
'old': check,
|
||||
'new': __salt__['wordpress.show_plugin'](name, path, user)
|
||||
}
|
||||
elif resp is None:
|
||||
ret['result'] = True
|
||||
ret['comment'] = 'Plugin already activated: {0}'.format(name)
|
||||
ret['changes'] = {
|
||||
'old': check,
|
||||
'new': __salt__['wordpress.show_plugin'](name, path, user)
|
||||
}
|
||||
else:
|
||||
ret['comment'] = 'Plugin failed to activate: {0}'.format(name)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def deactivated(name, path, user):
|
||||
'''
|
||||
Deactivate wordpress plugins
|
||||
|
||||
name
|
||||
name of plugin to deactivate
|
||||
|
||||
path
|
||||
path to wordpress installation
|
||||
|
||||
user
|
||||
user who should own the files in the wordpress installation
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
HyperDB:
|
||||
wordpress.deactivated:
|
||||
- path: /var/www/html
|
||||
- user: apache
|
||||
'''
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
'comment': '',
|
||||
'result': False}
|
||||
|
||||
check = __salt__['wordpress.show_plugin'](name, path, user)
|
||||
|
||||
if check['status'] == 'inactive':
|
||||
ret['result'] = True
|
||||
ret['comment'] = 'Plugin already deactivated: {0}'.format(name)
|
||||
return ret
|
||||
elif __opts__['test']:
|
||||
ret['result'] = None
|
||||
ret['comment'] = 'Plugin will be deactivated: {0}'.format(name)
|
||||
return ret
|
||||
|
||||
resp = __salt__['wordpress.deactivate'](name, path, user)
|
||||
if resp is True:
|
||||
ret['result'] = True
|
||||
ret['comment'] = 'Plugin deactivated: {0}'.format(name)
|
||||
ret['changes'] = {
|
||||
'old': check,
|
||||
'new': __salt__['wordpress.show_plugin'](name, path, user)
|
||||
}
|
||||
elif resp is None:
|
||||
ret['result'] = True
|
||||
ret['comment'] = 'Plugin already deactivated: {0}'.format(name)
|
||||
ret['changes'] = {
|
||||
'old': check,
|
||||
'new': __salt__['wordpress.show_plugin'](name, path, user)
|
||||
}
|
||||
else:
|
||||
ret['comment'] = 'Plugin failed to deactivate: {0}'.format(name)
|
||||
|
||||
return ret
|
@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Control concurrency of steps within state execution using zookeeper
|
||||
===================================================================
|
||||
|
||||
:depends: kazoo
|
||||
:configuration: See :py:mod:`salt.modules.zookeeper` for setup instructions.
|
||||
|
||||
Control concurrency of steps within state execution using zookeeper
|
||||
===================================================================
|
||||
|
||||
This module allows you to "wrap" a state's execution with concurrency control.
|
||||
This is useful to protect against all hosts executing highstate simultaneously
|
||||
|
@ -177,7 +177,7 @@ class AsyncZeroMQReqChannel(salt.transport.client.ReqChannel):
|
||||
@tornado.gen.coroutine
|
||||
def crypted_transfer_decode_dictentry(self, load, dictkey=None, tries=3, timeout=60):
|
||||
if not self.auth.authenticated:
|
||||
# Return controle back to the caller, continue when authentication succeeds
|
||||
# Return control back to the caller, continue when authentication succeeds
|
||||
yield self.auth.authenticate()
|
||||
# Return control to the caller. When send() completes, resume by populating ret with the Future.result
|
||||
ret = yield self.message_client.send(
|
||||
@ -569,7 +569,7 @@ class ZeroMQReqServerChannel(salt.transport.mixins.auth.AESReqServerMixin, salt.
|
||||
@tornado.gen.coroutine
|
||||
def handle_message(self, stream, payload):
|
||||
'''
|
||||
Handle incoming messages from underylying TCP streams
|
||||
Handle incoming messages from underlying TCP streams
|
||||
|
||||
:stream ZMQStream stream: A ZeroMQ stream.
|
||||
See http://zeromq.github.io/pyzmq/api/generated/zmq.eventloop.zmqstream.html
|
||||
@ -876,7 +876,7 @@ class AsyncReqMessageClientPool(salt.transport.MessageClientPool):
|
||||
# TODO: unit tests!
|
||||
class AsyncReqMessageClient(object):
|
||||
'''
|
||||
This class wraps the underylying zeromq REQ socket and gives a future-based
|
||||
This class wraps the underlying zeromq REQ socket and gives a future-based
|
||||
interface to sending and recieving messages. This works around the primary
|
||||
limitation of serialized send/recv on the underlying socket by queueing the
|
||||
message sends in this class. In the future if we decide to attempt to multiplex
|
||||
|
@ -420,7 +420,7 @@ class SaltEvent(object):
|
||||
self.pulluri,
|
||||
io_loop=self.io_loop
|
||||
)
|
||||
# For the async case, the connect will be defered to when
|
||||
# For the async case, the connect will be deferred to when
|
||||
# fire_event() is invoked.
|
||||
self.cpush = True
|
||||
return self.cpush
|
||||
@ -576,16 +576,17 @@ class SaltEvent(object):
|
||||
auto_reconnect=False):
|
||||
'''
|
||||
Get a single publication.
|
||||
IF no publication available THEN block for up to wait seconds
|
||||
AND either return publication OR None IF no publication available.
|
||||
If no publication is available, then block for up to ``wait`` seconds.
|
||||
Return publication if it is available or ``None`` if no publication is
|
||||
available.
|
||||
|
||||
IF wait is 0 then block forever.
|
||||
If wait is 0, then block forever.
|
||||
|
||||
tag
|
||||
Only return events matching the given tag. If not specified, or set
|
||||
to an empty string, all events are returned. It is recommended to
|
||||
always be selective on what is to be returned in the event that
|
||||
multiple requests are being multiplexed
|
||||
multiple requests are being multiplexed.
|
||||
|
||||
match_type
|
||||
Set the function to match the search tag with event tags.
|
||||
@ -646,7 +647,8 @@ class SaltEvent(object):
|
||||
return ret['data']
|
||||
|
||||
def get_event_noblock(self):
|
||||
'''Get the raw event without blocking or any other niceties
|
||||
'''
|
||||
Get the raw event without blocking or any other niceties
|
||||
'''
|
||||
assert self._run_io_loop_sync
|
||||
|
||||
@ -660,8 +662,9 @@ class SaltEvent(object):
|
||||
return {'data': data, 'tag': mtag}
|
||||
|
||||
def get_event_block(self):
|
||||
'''Get the raw event in a blocking fashion
|
||||
Slower, but decreases the possibility of dropped events
|
||||
'''
|
||||
Get the raw event in a blocking fashion. This is slower, but it decreases the
|
||||
possibility of dropped events.
|
||||
'''
|
||||
assert self._run_io_loop_sync
|
||||
|
||||
|
85
tests/kitchen/.kitchen.yml
Normal file
85
tests/kitchen/.kitchen.yml
Normal file
@ -0,0 +1,85 @@
|
||||
driver:
|
||||
name: docker
|
||||
use_sudo: false
|
||||
privileged: true
|
||||
<% if File.exists?('driver.yml') %>
|
||||
<% File.read('driver.yml').split(/\n/).each do |line| %>
|
||||
<%= line %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
provisioner:
|
||||
name: salt_solo
|
||||
salt_install: pip
|
||||
pip_pkg: <%= ENV['SALT_SDIST_PATH'] || 'salt' %>
|
||||
pip_index_url: <%= ENV['SALT_INDEX_URL'] || 'https://pypi.python.org/simple' %>
|
||||
require_chef: false
|
||||
formula: states
|
||||
<% if File.exists?('provisioner.yml') %>
|
||||
<% File.read('provisioner.yml').split(/\n/).each do |line| %>
|
||||
<%= line %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if File.exists?('state_top.yml') %>
|
||||
<% File.read('state_top.yml').split(/\n/).each do |line| %>
|
||||
<%= line %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
state_top:
|
||||
base:
|
||||
'*':
|
||||
- states
|
||||
<% end %>
|
||||
<% if File.exists?('pillars.yml') %>
|
||||
<% File.read('pillars.yml').split(/\n/).each do |line| %>
|
||||
<%= line %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% if File.exists?('platforms.yml') %>
|
||||
<%= File.read('platforms.yml') %>
|
||||
<% else %>
|
||||
platforms:
|
||||
- name: centos
|
||||
driver_config:
|
||||
run_command: /usr/lib/systemd/systemd
|
||||
provision_command:
|
||||
- yum install -y epel-release
|
||||
- yum install -y python-pip python-devel gcc git gcc-c++
|
||||
- name: opensuse
|
||||
driver_config:
|
||||
run_command: /usr/lib/systemd/systemd
|
||||
provision_command:
|
||||
- systemctl enable sshd.service
|
||||
- zypper install -y python-pip python-devel gcc git gcc-c++
|
||||
- name: ubuntu
|
||||
driver_config:
|
||||
run_command: /lib/systemd/systemd
|
||||
provision_command:
|
||||
- DEBIAN_FRONTEND=noninteractive apt-get install -y python-pip python-dev gcc git locales console-data
|
||||
- name: debian
|
||||
driver_config:
|
||||
run_command: /lib/systemd/systemd
|
||||
provision_command:
|
||||
- DEBIAN_FRONTEND=noninteractive apt-get install -y python-pip python-dev gcc git locales console-data
|
||||
<% end %>
|
||||
|
||||
<% if File.exists?('suites.yml') %>
|
||||
<%= File.read('suites.yml') %>
|
||||
<% else %>
|
||||
suites:
|
||||
- name: salt
|
||||
<% end %>
|
||||
|
||||
<% if File.exists?('verifier.yml') %>
|
||||
<%= File.read('verifier.yml') %>
|
||||
<% else %>
|
||||
verifier:
|
||||
name: shell
|
||||
remote_exec: false
|
||||
<% if ENV['TESTS_JUNIT_XML_PATH'].nil? %>
|
||||
command: pytest -v tests/$KITCHEN_SUITE
|
||||
<% else %>
|
||||
command: pytest --junit-xml <%= ENV['TESTS_JUNIT_XML_PATH'] %> -v tests/$KITCHEN_SUITE
|
||||
<% end %>
|
||||
<% end %>
|
9
tests/kitchen/Gemfile
Normal file
9
tests/kitchen/Gemfile
Normal file
@ -0,0 +1,9 @@
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem 'test-kitchen'
|
||||
gem 'kitchen-salt', :git => 'https://github.com/saltstack/kitchen-salt.git'
|
||||
gem 'kitchen-docker', :git => 'https://github.com/test-kitchen/kitchen-docker.git'
|
||||
gem 'vagrant-wrapper'
|
||||
gem 'kitchen-vagrant'
|
||||
gem 'winrm', '~>2.0'
|
||||
gem 'winrm-fs', '~>1.0'
|
1
tests/kitchen/__init__.py
Normal file
1
tests/kitchen/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
0
tests/kitchen/pytest.ini
Normal file
0
tests/kitchen/pytest.ini
Normal file
83
tests/kitchen/test_kitchen.py
Normal file
83
tests/kitchen/test_kitchen.py
Normal file
@ -0,0 +1,83 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Test wrapper for running all KitchenSalt tests
|
||||
|
||||
All directories in 'tests/kitchen/' will be treated as a separate test under
|
||||
the KitchenTestCase.
|
||||
'''
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
|
||||
from tests.support.unit import TestCase, skipIf
|
||||
import setup
|
||||
|
||||
import salt.utils.path
|
||||
from salt.modules import cmdmod as cmd
|
||||
|
||||
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
|
||||
@skipIf(not salt.utils.path.which('bundle'), 'Bundler is not installed')
|
||||
class KitchenTestCase(TestCase):
|
||||
'''
|
||||
Test kitchen environments
|
||||
'''
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
'''
|
||||
setup kitchen tests
|
||||
'''
|
||||
cls.topdir = '/' + os.path.join(*CURRENT_DIR.split('/')[:-2])
|
||||
cls.use_vt = int(os.environ.get('TESTS_LOG_LEVEL')) >= 5
|
||||
cmd.run('python setup.py sdist', cwd=cls.topdir)
|
||||
cmd.run('bundle install', cwd=CURRENT_DIR)
|
||||
cls.env = {
|
||||
'KITCHEN_YAML': os.path.join(CURRENT_DIR, '.kitchen.yml'),
|
||||
'SALT_SDIST_PATH': os.path.join(cls.topdir, 'dist', 'salt-{0}.tar.gz'.format(setup.__version__)),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
del cls.topdir
|
||||
del cls.env
|
||||
|
||||
def tearDown(self):
|
||||
cmd.run(
|
||||
'bundle exec kitchen destroy all',
|
||||
cwd=os.path.join(CURRENT_DIR, 'tests', self.testdir),
|
||||
env=self.env,
|
||||
use_vt=self.use_vt,
|
||||
)
|
||||
del self.testdir
|
||||
|
||||
|
||||
def func_builder(testdir):
|
||||
def func(self):
|
||||
self.testdir = testdir
|
||||
if 'TESTS_XML_OUTPUT_DIR' in os.environ:
|
||||
self.env['TESTS_JUNIT_XML_PATH'] = '{0}/kitchen.tests.{1}.$KITCHEN_SUITE.$KITCHEN_PLATFORM.xml'.format(
|
||||
os.environ.get('TESTS_XML_OUTPUT_DIR'),
|
||||
self.testdir,
|
||||
)
|
||||
self.assertEqual(
|
||||
cmd.retcode(
|
||||
'bundle exec kitchen converge -c 999 all',
|
||||
cwd=os.path.join(CURRENT_DIR, 'tests', self.testdir),
|
||||
env=self.env,
|
||||
use_vt=self.use_vt,
|
||||
),
|
||||
0
|
||||
)
|
||||
self.assertEqual(
|
||||
cmd.retcode(
|
||||
'bundle exec kitchen verify all',
|
||||
cwd=os.path.join(CURRENT_DIR, 'tests', self.testdir),
|
||||
env=self.env,
|
||||
use_vt=self.use_vt,
|
||||
),
|
||||
0
|
||||
)
|
||||
return func
|
||||
|
||||
for testdir in os.listdir(os.path.join(CURRENT_DIR, 'tests')):
|
||||
setattr(KitchenTestCase, 'test_kitchen_{0}'.format(testdir), func_builder(testdir))
|
2
tests/kitchen/tests/wordpress/driver.yml
Normal file
2
tests/kitchen/tests/wordpress/driver.yml
Normal file
@ -0,0 +1,2 @@
|
||||
forward:
|
||||
- 80
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user