Merge remote-tracking branch 'upstream/develop' into sam_dev1

This commit is contained in:
Samuel M Smith 2014-10-29 14:47:46 -06:00
commit 4b82b72702
87 changed files with 2032 additions and 1375 deletions

View File

@ -8,7 +8,10 @@ Call for speakers now open. Early-bird and group discounts.
</p> </p>
<h4>SaltStack training</h4> <h4>SaltStack training</h4>
<p>
<a href="http://www.saltstack.com/training/"> <a href="http://www.saltstack.com/training/">
<img src="{{ pathto('_static/images/salt-training.png', 1) }}" alt="" style="padding-bottom: 1em;"> Now offering remote attendee training!
{# <img src="{{ pathto('_static/images/salt-training.png', 1) }}" alt="" style="padding-bottom: 1em;"> #}
</a> </a>
</p>
{% endif %} {% endif %}

View File

@ -10,5 +10,5 @@
<p>Latest Salt release: <a href="{{ pathto('topics/releases/{0}'.format(release)) }}">{{ release }}</a></p> <p>Latest Salt release: <a href="{{ pathto('topics/releases/{0}'.format(release)) }}">{{ release }}</a></p>
<p>Try the shiny new release candidate of Salt, <p>Try the shiny new release candidate of Salt,
<a href="{{ pathto('topics/releases/2014.7.0') }}">v2014.7.0rc3</a>! More info <a href="{{ pathto('topics/releases/2014.7.0') }}">v2014.7.0rc6</a>! More info
<a href="{{ pathto('topics/releases/releasecandidate') }}">here.</a></p> <a href="{{ pathto('topics/releases/releasecandidate') }}">here</a>.</p>

View File

@ -28,8 +28,9 @@ How to Use it
.. note:: .. note::
Since this option changes the basic behavior of the state runtime states Since this option changes the basic behavior of the state runtime, after
should be executed in it is enabled states should be executed using `test=True` to ensure that
the desired behavior is preserved.
Since this behavior can dramatically change the flow of configuration Since this behavior can dramatically change the flow of configuration
management inside of Salt it is disabled by default. But enabling it is easy. management inside of Salt it is disabled by default. But enabling it is easy.

View File

@ -210,10 +210,10 @@ examples of "changes" dictionaries.)
If the "changes" key contains a populated dictionary, it means that the If the "changes" key contains a populated dictionary, it means that the
pre-required state expects changes to occur when the state is actually pre-required state expects changes to occur when the state is actually
executed, as opposed to the test-run. The pre-required state will now executed, as opposed to the test-run. The pre-requiring state will now
actually run. If the pre-required state executes successfully, the actually run. If the pre-requiring state executes successfully, the
pre-requiring state will then execute. If the pre-required state fails, the pre-required state will then execute. If the pre-requiring state fails, the
pre-requiring state will not execute. pre-required state will not execute.
If the "changes" key contains an empty dictionary, this means that changes are If the "changes" key contains an empty dictionary, this means that changes are
not expected by the pre-required state. Neither the pre-required state nor the not expected by the pre-required state. Neither the pre-required state nor the

View File

@ -15,3 +15,4 @@ Full list of builtin wheel modules
file_roots file_roots
key key
pillar_roots pillar_roots
minions

View File

@ -0,0 +1,7 @@
==================
salt.wheel.minions
==================
.. automodule:: salt.wheel.minions
:members:

View File

@ -5,24 +5,19 @@ OS X
Dependency Installation Dependency Installation
----------------------- -----------------------
When installing via Homebrew, dependency resolution is handled for you. When using Homebrew, install this way:
.. code-block:: bash .. code-block:: bash
brew install saltstack sudo brew install saltstack
When using macports, zmq, swig, and pip may need to be installed this way: When using MacPorts, install this way:
.. code-block:: bash .. code-block:: bash
sudo port install py-zmq sudo port install salt
sudo port install py27-m2crypto
sudo port install py27-crypto
sudo port install py27-msgpack
sudo port install swig-python
sudo port install py-pip
For installs using the OS X system python, pip install needs to use 'sudo': When only using the OS X system's pip, install this way:
.. code-block:: bash .. code-block:: bash
@ -47,7 +42,7 @@ Now the salt-master should run without errors:
.. code-block:: bash .. code-block:: bash
sudo /usr/local/share/python/salt-master --log-level=all sudo salt-master --log-level=all
Post-installation tasks Post-installation tasks
======================= =======================

View File

@ -108,6 +108,18 @@ If this repo is added *before* Salt is installed, then installing either
additional states to upgrade ZeroMQ and pyzmq are unnecessary. additional states to upgrade ZeroMQ and pyzmq are unnecessary.
Package Management
==================
Salt's interface to :mod:`yum <salt.modules.yumpkg>` makes heavy use of the
**repoquery** utility, from the yum-utils_ package. This package will be
installed as a dependency if salt is installed via EPEL. However, if salt has
been installed using pip, or a host is being managed using salt-ssh, then as of
version 2014.7.0 yum-utils_ will be installed automatically to satisfy this
dependency.
.. _yum-utils: http://yum.baseurl.org/wiki/YumUtils
Post-installation tasks Post-installation tasks
======================= =======================

View File

@ -38,6 +38,9 @@ Mapping Events to Reactor SLS Files
Reactor SLS files and event tags are associated in the master config file. Reactor SLS files and event tags are associated in the master config file.
By default this is /etc/salt/master, or /etc/salt/master.d/reactor.conf. By default this is /etc/salt/master, or /etc/salt/master.d/reactor.conf.
.. versionadded:: 2014.7.0
Added Reactor support for ``salt://`` file paths.
In the master config section 'reactor:' is a list of event tags to be matched In the master config section 'reactor:' is a list of event tags to be matched
and each event tag has a list of reactor SLS files to be run. and each event tag has a list of reactor SLS files to be run.
@ -172,14 +175,28 @@ Understanding the Structure of Reactor Formulas
=============================================== ===============================================
While the reactor system uses the same data structure as the state system, this While the reactor system uses the same data structure as the state system, this
data does not translate the same way to operations. In state files formula data does not translate the same way to function calls.
information is mapped to the state functions, but in the reactor system
information is mapped to a number of available subsystems on the master. These .. versionchanged:: 2014.7.0
systems are the :strong:`LocalClient` and the :strong:`Runners`. The The ``cmd`` prefix was renamed to ``local`` for consistency with other
:strong:`state declaration` field takes a reference to the function to call in parts of Salt. A backward-compatible alias was added for ``cmd``.
each interface. So to trigger a salt-run call the :strong:`state declaration`
field will start with :strong:`runner`, followed by the runner function to In state files the minion generates the data structure locally and uses that to
call. This means that a call to what would be on the command line call local state functions. In the reactor system the master generates a data
structure that is used to call methods on one of Salt's client interfaces
described in :ref:`the Python API documentation <client-apis>`.
* :py:class:`~salt.client.LocalClient` is used to call Execution modules
remotely on minions. (The :command:`salt` CLI program uses this also.)
* :py:class:`~salt.runner.RunnerClient` calls Runner modules locally on the
master.
* :py:class:`~salt.wheel.WheelClient` calls Wheel modules locally on the
master.
The :strong:`state declaration` field takes a reference to the function to call
in each interface. So to trigger a salt-run call the :strong:`state
declaration` field will start with :strong:`runner`, followed by the runner
function to call. This means that a call to what would be on the command line
:strong:`salt-run manage.up` will be :strong:`runner.manage.up`. An example of :strong:`salt-run manage.up` will be :strong:`runner.manage.up`. An example of
this in a reactor formula would look like this: this in a reactor formula would look like this:

View File

@ -6,6 +6,20 @@ This release is the largest Salt release ever, with more features and commits
then any previous release of Salt. Everything from the new RAET transport to then any previous release of Salt. Everything from the new RAET transport to
major updates in Salt Cloud and the merging of Salt API into the main project. major updates in Salt Cloud and the merging of Salt API into the main project.
.. important::
The Fedora/RHEL/CentOS **salt-master** package has been modified for this
release. The following components of Salt have been broken out and placed
into their own packages:
* salt-syndic
* salt-cloud
* salt-ssh
When the **salt-master** package is upgraded, these components will be
removed, and they will need to be manually installed.
New Transport! New Transport!
============== ==============
@ -29,12 +43,12 @@ Simply stated, users running Salt with RAET should expect some hiccups as we
hammer out the update. This is a BETA release of Salt RAET. hammer out the update. This is a BETA release of Salt RAET.
For information about how to use Salt with RAET please see the For information about how to use Salt with RAET please see the
:doc:`tutorial </topics/transports/raet/programming_intro>`. :doc:`tutorial </topics/transports/raet/index>`.
Salt SSH Enhancements Salt SSH Enhancements
===================== =====================
Salt SSH has just entered a new league, which substantial updates and Salt SSH has just entered a new league, with substantial updates and
improvements to make salt-ssh more reliable and easier then ever! From new improvements to make salt-ssh more reliable and easier then ever! From new
features like the ansible roster and fileserver backends to the new pypi features like the ansible roster and fileserver backends to the new pypi
salt-ssh installer to lowered deps and a swath of bugfixes, salt-ssh is salt-ssh installer to lowered deps and a swath of bugfixes, salt-ssh is
@ -58,7 +72,7 @@ which may be seen can be safely ignored.
Fileserver Backends Fileserver Backends
------------------- -------------------
Salt-ssh can now use the salt fileserver backend system, this allows for Salt-ssh can now use the salt fileserver backend system. This allows for
the gitfs, hgfs, s3, and many more ways to centrally store states to be easily the gitfs, hgfs, s3, and many more ways to centrally store states to be easily
used with salt-ssh. This also allows for a distributed team to easily use used with salt-ssh. This also allows for a distributed team to easily use
a centralized source. a centralized source.
@ -78,8 +92,8 @@ to use salt-ssh with teams.
No More sshpass No More sshpass
--------------- ---------------
Thanks to the enhancements in the salt vt system salt-ssh no longer requires Thanks to the enhancements in the salt vt system, salt-ssh no longer requires
sshpass to send passwords to ssh, this also makes the manipulation of ssh sshpass to send passwords to ssh. This also makes the manipulation of ssh
calls substantially more flexible, allowing for intercepting ssh calls in calls substantially more flexible, allowing for intercepting ssh calls in
a much more fluid way. a much more fluid way.
@ -109,11 +123,11 @@ More Thin Directory Options
--------------------------- ---------------------------
Salt ssh functions by copying a subset of the salt code, or `salt thin` down Salt ssh functions by copying a subset of the salt code, or `salt thin` down
to the target system. In the past this was always transfered to /tmp/.salt to the target system. In the past this was always transferred to /tmp/.salt
and cached there for subsequent commands. and cached there for subsequent commands.
Now, salt thin can be sent to a random directory and removed when the call Now, salt thin can be sent to a random directory and removed when the call
is complete with the `-W` option. The new `-w` option still uses a static is complete with the `-W` option. The new `-W` option still uses a static
location but will clean up that location when finished. location but will clean up that location when finished.
The default `salt thin` location is now user defined, allowing multiple users The default `salt thin` location is now user defined, allowing multiple users
@ -125,9 +139,9 @@ State System Enhancements
New Imperative State Keyword "Listen" New Imperative State Keyword "Listen"
------------------------------------- -------------------------------------
The new ``listen`` keyword allows for completely imperative states by calling The new ``listen`` and ``listen_in`` keywords allow for completely imperative
the ``mod_watch()`` routine after all states have run instead of re-ordering states by calling the ``mod_watch()`` routine after all states have run instead
the states. of re-ordering the states.
Mod Aggregate Runtime Manipulator Mod Aggregate Runtime Manipulator
--------------------------------- ---------------------------------
@ -137,7 +151,7 @@ state data during execution. This allows for state definitions to be aggregated
dynamically at runtime. dynamically at runtime.
The best example is found in the :mod:`pkg <salt.states.pkg>` state. If The best example is found in the :mod:`pkg <salt.states.pkg>` state. If
``mod_aggregate`` is turned on, then when the first pkg state is reached the ``mod_aggregate`` is turned on, then when the first pkg state is reached, the
state system will scan all of the other running states for pkg states and take state system will scan all of the other running states for pkg states and take
all other packages set for install and install them all at once in the first all other packages set for install and install them all at once in the first
pkg state. pkg state.
@ -152,7 +166,15 @@ For more documentation on ``mod_aggregate``, see :doc:`the documentation
New Requisites: onchanges and onfail New Requisites: onchanges and onfail
------------------------------------ ------------------------------------
New requisites! The new ``onchanges`` and ``onchanges_in`` requisites make a state apply only if
there are changes in the required state. This is useful to execute post hooks
after changes occur on a system.
The other new requisites, ``onfail`` and ``onfail_in``, allow for a state to run
in reaction to the failure of another state.
For more information about these new requisites, see the
:doc:`requisites documentation </ref/states/requisites>`.
Global onlyif and unless Global onlyif and unless
@ -200,7 +222,7 @@ Fileserver Backends in salt-call
Fileserver backends like gitfs can now be used without a salt master! Just add Fileserver backends like gitfs can now be used without a salt master! Just add
the fileserver backend configuration to the minion config and execute the fileserver backend configuration to the minion config and execute
salt-call. This has been a much-requested feature and we are heppy to finally salt-call. This has been a much-requested feature and we are happy to finally
bring it to our users. bring it to our users.
Amazon Execution Modules Amazon Execution Modules

View File

@ -8,7 +8,7 @@ Salt SSH
.. note:: .. note::
On many systems, ``salt-ssh`` will be in its own package, usually named On many systems, the ``salt-ssh`` executable will be in its own package, usually named
``salt-ssh``. ``salt-ssh``.
In version 0.17.0 of Salt a new transport system was introduced, the ability In version 0.17.0 of Salt a new transport system was introduced, the ability

View File

@ -6,8 +6,10 @@ The RAET Transport
The RAET transport is in very early development, it is functional but no The RAET transport is in very early development, it is functional but no
promises are yet made as to its reliability or security. promises are yet made as to its reliability or security.
As for reliability and security, the encryption used has been audited and
This document is also not yet complete our tests show that raet is reliable. With this said we are still conducting
more security audits and pushing the reliability.
This document outlines the encryption used in RAET
.. versionadded:: 2014.7.0 .. versionadded:: 2014.7.0
@ -23,57 +25,12 @@ processes on multiple machines. Messages can also be restricted, allowing
processes to be sent messages of specific types from specific sources processes to be sent messages of specific types from specific sources
allowing for trust to be established. allowing for trust to be established.
Why?
====
Customer and User Request
-------------------------
Why make an alternative transport for Salt? There are many reasons, but the
primary motivation came from customer requests, many large companies came with
requests to run Salt over an alternative transport, the reasoning was varied,
from performance and scaling improvements to licensing concerns. These
customers have partnered with SaltStack to make RAET a reality.
RAET Reliability
================
RAET is reliable, hence the name (Reliable Asynchronous Event Transport).
The concern posed by some over RAET reliability is based on the fact that
RAET used UDP instead of TCP and UDP does not have built in reliability.
RAET itself implements the needed reliability layers that are not natively
present in UDP, this allows RAET to dynamically optimize packet delivery
in a way that keeps it both reliable and asynchronous.
RAET and ZeroMQ
===============
When using RAET, ZeroMQ is not required. RAET is a complete networking
replacement. It is noteworthy that RAET is not a ZeroMQ replacement in a
general sense, the ZeroMQ constructs are not reproduced in RAET, but they are
instead implemented in such a way that is specific to Salt's needs.
RAET is primarily an async communication layer over truly async connections,
defaulting to UDP. ZeroMQ is over TCP and abstracts async constructs within the
socket layer.
Salt is not dropping ZeroMQ support and has no immediate plans to do so.
Encryption
==========
RAET uses Dan Bernstein's NACL encryption libraries and CurveCP handshake.
The libnacl python binding binds to both libsodium and tweetnacl to execute
the underlying cryptography.
Using RAET in Salt Using RAET in Salt
================== ==================
Using RAET in Salt is easy, the main difference is that the core dependencies Using RAET in Salt is easy, the main difference is that the core dependencies
change, instead of needing pycrypto, M2Crypto, ZeroMQ and PYZMQ, the packages change, instead of needing pycrypto, M2Crypto, ZeroMQ and PYZMQ, the packages
libsodium, libnacl and ioflo are required. Encryption is handled very cleanly libsodium, libnacl, ioflo and raet are required. Encryption is handled very cleanly
by libnacl, while the queueing and flow control is handled by by libnacl, while the queueing and flow control is handled by
ioflo. Distribution packages are forthcoming, but libsodium can be easily ioflo. Distribution packages are forthcoming, but libsodium can be easily
installed from source, or many distributions do ship packages for it. installed from source, or many distributions do ship packages for it.
@ -104,3 +61,77 @@ Now start salt as it would normally be started, the minion will connect to the
master and share long term keys, which can then in turn be managed via master and share long term keys, which can then in turn be managed via
salt-key. Remote execution and salt states will function in the same way as salt-key. Remote execution and salt states will function in the same way as
with Salt over ZeroMQ. with Salt over ZeroMQ.
Limitations
===========
The 2014.7 release of RAET is not complete! The Syndic and Multi Master have
not been completed yet and these are slated for completetion in the Lithium
release.
Also, Salt-Raet allows for more control over the client but these hooks have
not been implimented yet, thereforre the client still uses the same system
as the ZeroMQ client. This means that the extra reliability that RAET exposes
has not yet been implimented in the CLI client.
Why?
====
Customer and User Request
-------------------------
Why make an alternative transport for Salt? There are many reasons, but the
primary motivation came from customer requests, many large companies came with
requests to run Salt over an alternative transport, the reasoning was varied,
from performance and scaling improvements to licensing concerns. These
customers have partnered with SaltStack to make RAET a reality.
More Capabilities
-----------------
RAET has been designed to allow salt to have greater communication
capabilities. It has been designed to allow for development into features
which out ZeroMQ topologies can't match.
Many of the proposed features are still under development and will be
announced as they enter proff of concept phases, but these features include
`salt-fuse` - a filesystem over salt, `salt-vt` - a paralell api driven shell
over the salt transport and many others.
RAET Reliability
================
RAET is reliable, hence the name (Reliable Asynchronous Event Transport).
The concern posed by some over RAET reliability is based on the fact that
RAET uses UDP instead of TCP and UDP does not have built in reliability.
RAET itself implements the needed reliability layers that are not natively
present in UDP, this allows RAET to dynamically optimize packet delivery
in a way that keeps it both reliable and asynchronous.
RAET and ZeroMQ
===============
When using RAET, ZeroMQ is not required. RAET is a complete networking
replacement. It is noteworthy that RAET is not a ZeroMQ replacement in a
general sense, the ZeroMQ constructs are not reproduced in RAET, but they are
instead implemented in such a way that is specific to Salt's needs.
RAET is primarily an async communication layer over truly async connections,
defaulting to UDP. ZeroMQ is over TCP and abstracts async constructs within the
socket layer.
Salt is not dropping ZeroMQ support and has no immediate plans to do so.
Encryption
==========
RAET uses Dan Bernstein's NACL encryption libraries and CurveCP handshake.
The libnacl python binding binds to both libsodium and tweetnacl to execute
the underlying cryptography. This allows us to completely rely on an
externally developed cryptography system.
For more information on libsodium and CurveCP please see:
http://doc.libsodium.org/
http://curvecp.org/

View File

@ -103,7 +103,7 @@ to them asking that they fetch their pillars from the master:
salt '*' saltutil.refresh_pillar salt '*' saltutil.refresh_pillar
Now that the minions have the new pillar, it can be retreived: Now that the minions have the new pillar, it can be retrieved:
.. code-block:: bash .. code-block:: bash

View File

@ -1,3 +1,18 @@
-------------------------------------------------------------------
Thu Oct 16 19:26:57 UTC 2014 - aboe76@gmail.com
- Updated to 2014.1.13 a bugfix release on 2014.1.12
+ fix module run exit code (issue 16420)
+ salt cloud Check the exit status code of scp before assuming it has failed. (issue 16599)
-------------------------------------------------------------------
Fri Oct 10 18:47:07 UTC 2014 - aboe76@gmail.com
ff
- Updated to 2014.1.12 a bugfix release on 2014.1.11
+ Fix scp_file always failing (which broke salt-cloud) (issue 16437)
+ Fix regression in pillar in masterless (issue 16210, issue 16416, issue 16428)
------------------------------------------------------------------- -------------------------------------------------------------------
Wed Sep 10 18:10:50 UTC 2014 - aboe76@gmail.com Wed Sep 10 18:10:50 UTC 2014 - aboe76@gmail.com

View File

@ -15,9 +15,8 @@
# Please submit bugfixes or comments via http://bugs.opensuse.org/ # Please submit bugfixes or comments via http://bugs.opensuse.org/
# #
Name: salt Name: salt
Version: 2014.1.11 Version: 2014.1.13
Release: 0 Release: 0
Summary: A parallel remote execution system Summary: A parallel remote execution system
License: Apache-2.0 License: Apache-2.0

View File

@ -1,7 +1,7 @@
Index: salt-2014.1.8/pkg/salt-master.service Index: salt-2014.1.8/pkg/salt-master.service
=================================================================== ===================================================================
--- salt-2014.1.11.orig/pkg/salt-master.service --- salt-2014.1.13.orig/pkg/salt-master.service
+++ salt-2014.1.11/pkg/salt-master.service +++ salt-2014.1.13/pkg/salt-master.service
@@ -3,8 +3,10 @@ Description=The Salt Master Server @@ -3,8 +3,10 @@ Description=The Salt Master Server
After=syslog.target network.target After=syslog.target network.target

View File

@ -540,7 +540,7 @@ class Single(object):
'root_dir': os.path.join(self.thin_dir, 'running_data'), 'root_dir': os.path.join(self.thin_dir, 'running_data'),
'id': self.id, 'id': self.id,
'sock_dir': '/', 'sock_dir': '/',
}).strip() }, width=1000).strip()
self.target = kwargs self.target = kwargs
self.target.update(args) self.target.update(args)
self.serial = salt.payload.Serial(opts) self.serial = salt.payload.Serial(opts)

View File

@ -93,6 +93,7 @@ def unpack_ext(ext_path):
'var', 'var',
'cache', 'cache',
'salt', 'salt',
'minion',
'extmods') 'extmods')
tfile = tarfile.TarFile.gzopen(ext_path) tfile = tarfile.TarFile.gzopen(ext_path)
tfile.extractall(path=modcache) tfile.extractall(path=modcache)

View File

@ -101,9 +101,9 @@ def avail_images(call=None):
items = query(method='images') items = query(method='images')
ret = {} ret = {}
for image in items['images']: for image in items['images']:
ret[image['name']] = {} ret[image['id']] = {}
for item in image.keys(): for item in image.keys():
ret[image['name']][item] = str(image[item]) ret[image['id']][item] = str(image[item])
return ret return ret

View File

@ -106,12 +106,12 @@ def avail_images(call=None):
items = query(method='images', command='?page=' + str(page)) items = query(method='images', command='?page=' + str(page))
for image in items['images']: for image in items['images']:
ret[image['name']] = {} ret[image['id']] = {}
for item in image.keys(): for item in image.keys():
ret[image['name']][item] = str(image[item]) ret[image['id']][item] = str(image[item])
page += 1 page += 1
fetch = next in items['links']['pages'] fetch = 'next' in items['links']['pages']
return ret return ret

View File

@ -43,6 +43,7 @@ Setting up Service Account Authentication:
- Consider using a more secure location for your private key. - Consider using a more secure location for your private key.
Supported commands: Supported commands:
# Create a few instances fro profile_name in /etc/salt/cloud.profiles # Create a few instances fro profile_name in /etc/salt/cloud.profiles
- salt-cloud -p profile_name inst1 inst2 inst3 - salt-cloud -p profile_name inst1 inst2 inst3
# Delete an instance # Delete an instance

View File

@ -17,7 +17,7 @@
# CREATED: 10/15/2012 09:49:37 PM WEST # CREATED: 10/15/2012 09:49:37 PM WEST
#====================================================================================================================== #======================================================================================================================
set -o nounset # Treat unset variables as an error set -o nounset # Treat unset variables as an error
__ScriptVersion="2014.10.14" __ScriptVersion="2014.10.28"
__ScriptName="bootstrap-salt.sh" __ScriptName="bootstrap-salt.sh"
#====================================================================================================================== #======================================================================================================================
@ -202,6 +202,7 @@ _INSECURE_DL=${BS_INSECURE_DL:-$BS_FALSE}
_WGET_ARGS=${BS_WGET_ARGS:-} _WGET_ARGS=${BS_WGET_ARGS:-}
_CURL_ARGS=${BS_CURL_ARGS:-} _CURL_ARGS=${BS_CURL_ARGS:-}
_FETCH_ARGS=${BS_FETCH_ARGS:-} _FETCH_ARGS=${BS_FETCH_ARGS:-}
_ENABLE_EXTERNAL_ZMQ_REPOS=${BS_ENABLE_EXTERNAL_ZMQ_REPOS:-$BS_FALSE}
_SALT_MASTER_ADDRESS=${BS_SALT_MASTER_ADDRESS:-null} _SALT_MASTER_ADDRESS=${BS_SALT_MASTER_ADDRESS:-null}
_SALT_MINION_ID="null" _SALT_MINION_ID="null"
# __SIMPLIFY_VERSION is mostly used in Solaris based distributions # __SIMPLIFY_VERSION is mostly used in Solaris based distributions
@ -242,6 +243,7 @@ usage() {
-D Show debug output. -D Show debug output.
-c Temporary configuration directory -c Temporary configuration directory
-g Salt repository URL. (default: git://github.com/saltstack/salt.git) -g Salt repository URL. (default: git://github.com/saltstack/salt.git)
-G Insteady of cloning from git://github.com/saltstack/salt.git, clone from https://github.com/saltstack/salt.git (Usually necessary on systems which have the regular git protocol port blocked, where https usualy is not)
-k Temporary directory holding the minion keys which will pre-seed -k Temporary directory holding the minion keys which will pre-seed
the master. the master.
-s Sleep time used when waiting for daemons to start, restart and when checking -s Sleep time used when waiting for daemons to start, restart and when checking
@ -271,12 +273,13 @@ usage() {
-p Extra-package to install while installing salt dependencies. One package -p Extra-package to install while installing salt dependencies. One package
per -p flag. You're responsible for providing the proper package name. per -p flag. You're responsible for providing the proper package name.
-H Use the specified http proxy for the installation -H Use the specified http proxy for the installation
-Z Enable external software source for newer ZeroMQ(Only available for RHEL/CentOS/Fedora based distributions)
EOT EOT
} # ---------- end of function usage ---------- } # ---------- end of function usage ----------
while getopts ":hvnDc:g:k:MSNXCPFUKIA:i:Lp:H:" opt while getopts ":hvnDc:Gg:k:MSNXCPFUKIA:i:Lp:H:Z" opt
do do
case "${opt}" in case "${opt}" in
@ -297,6 +300,13 @@ do
fi fi
;; ;;
g ) _SALT_REPO_URL=$OPTARG ;; g ) _SALT_REPO_URL=$OPTARG ;;
G ) if [ "${_SALT_REPO_URL}" = "${_SALTSTACK_REPO_URL}" ]; then
_SALTSTACK_REPO_URL="https://github.com/saltstack/salt.git"
_SALT_REPO_URL=${_SALTSTACK_REPO_URL}
else
_SALTSTACK_REPO_URL="https://github.com/saltstack/salt.git"
fi
;;
k ) _TEMP_KEYS_DIR="$OPTARG" k ) _TEMP_KEYS_DIR="$OPTARG"
# If the configuration directory does not exist, error out # If the configuration directory does not exist, error out
if [ ! -d "$_TEMP_KEYS_DIR" ]; then if [ ! -d "$_TEMP_KEYS_DIR" ]; then
@ -319,6 +329,7 @@ do
L ) _INSTALL_CLOUD=$BS_TRUE ;; L ) _INSTALL_CLOUD=$BS_TRUE ;;
p ) _EXTRA_PACKAGES="$_EXTRA_PACKAGES $OPTARG" ;; p ) _EXTRA_PACKAGES="$_EXTRA_PACKAGES $OPTARG" ;;
H ) _HTTP_PROXY="$OPTARG" ;; H ) _HTTP_PROXY="$OPTARG" ;;
Z) _ENABLE_EXTERNAL_ZMQ_REPOS=$BS_TRUE ;;
\?) echo \?) echo
@ -1124,7 +1135,10 @@ __git_clone_and_checkout() {
echodebug "Installed git version: $(git --version | awk '{ print $3 }')" echodebug "Installed git version: $(git --version | awk '{ print $3 }')"
__SALT_GIT_CHECKOUT_PARENT_DIR=$(dirname "${__SALT_GIT_CHECKOUT_DIR}") local __SALT_GIT_CHECKOUT_PARENT_DIR=$(dirname "${__SALT_GIT_CHECKOUT_DIR}" 2>/dev/null)
__SALT_GIT_CHECKOUT_PARENT_DIR="${__SALT_GIT_CHECKOUT_PARENT_DIR:-/tmp/git}"
local __SALT_CHECKOUT_REPONAME="$(basename "${__SALT_GIT_CHECKOUT_DIR}" 2>/dev/null)"
__SALT_CHECKOUT_REPONAME="${__SALT_CHECKOUT_REPONAME:-salt}"
[ -d "${__SALT_GIT_CHECKOUT_PARENT_DIR}" ] || mkdir "${__SALT_GIT_CHECKOUT_PARENT_DIR}" [ -d "${__SALT_GIT_CHECKOUT_PARENT_DIR}" ] || mkdir "${__SALT_GIT_CHECKOUT_PARENT_DIR}"
cd "${__SALT_GIT_CHECKOUT_PARENT_DIR}" cd "${__SALT_GIT_CHECKOUT_PARENT_DIR}"
if [ -d "${__SALT_GIT_CHECKOUT_DIR}" ]; then if [ -d "${__SALT_GIT_CHECKOUT_DIR}" ]; then
@ -1170,7 +1184,7 @@ __git_clone_and_checkout() {
if [ "$(git clone --help | grep 'single-branch')" != "" ]; then if [ "$(git clone --help | grep 'single-branch')" != "" ]; then
# The "--single-branch" option is supported, attempt shallow cloning # The "--single-branch" option is supported, attempt shallow cloning
echoinfo "Attempting to shallow clone $GIT_REV from Salt's repository ${_SALT_REPO_URL}" echoinfo "Attempting to shallow clone $GIT_REV from Salt's repository ${_SALT_REPO_URL}"
git clone --depth 1 --branch "$GIT_REV" "$_SALT_REPO_URL" git clone --depth 1 --branch "$GIT_REV" "$_SALT_REPO_URL" "$__SALT_CHECKOUT_REPONAME"
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
cd "${__SALT_GIT_CHECKOUT_DIR}" cd "${__SALT_GIT_CHECKOUT_DIR}"
__SHALLOW_CLONE="${BS_TRUE}" __SHALLOW_CLONE="${BS_TRUE}"
@ -1178,17 +1192,17 @@ __git_clone_and_checkout() {
# Shallow clone above failed(missing upstream tags???), let's resume the old behaviour. # Shallow clone above failed(missing upstream tags???), let's resume the old behaviour.
echowarn "Failed to shallow clone." echowarn "Failed to shallow clone."
echoinfo "Resuming regular git clone and remote SaltStack repository addition procedure" echoinfo "Resuming regular git clone and remote SaltStack repository addition procedure"
git clone "$_SALT_REPO_URL" || return 1 git clone "$_SALT_REPO_URL" "$__SALT_CHECKOUT_REPONAME" || return 1
cd "${__SALT_GIT_CHECKOUT_DIR}" cd "${__SALT_GIT_CHECKOUT_DIR}"
fi fi
else else
echodebug "Shallow cloning not possible. Required git version not met." echodebug "Shallow cloning not possible. Required git version not met."
git clone "$_SALT_REPO_URL" || return 1 git clone "$_SALT_REPO_URL" "$__SALT_CHECKOUT_REPONAME" || return 1
cd "${__SALT_GIT_CHECKOUT_DIR}" cd "${__SALT_GIT_CHECKOUT_DIR}"
fi fi
else else
echowarn "The git revision being installed does not match a Salt version tag. Shallow cloning disabled" echowarn "The git revision being installed does not match a Salt version tag. Shallow cloning disabled"
git clone "$_SALT_REPO_URL" || return 1 git clone "$_SALT_REPO_URL" "$__SALT_CHECKOUT_REPONAME" || return 1
cd "${__SALT_GIT_CHECKOUT_DIR}" cd "${__SALT_GIT_CHECKOUT_DIR}"
fi fi
@ -1540,7 +1554,7 @@ __check_services_debian() {
servicename=$1 servicename=$1
echodebug "Checking if service ${servicename} is enabled" echodebug "Checking if service ${servicename} is enabled"
# shellcheck disable=SC2086,SC2046 # shellcheck disable=SC2086,SC2046,SC2144
if [ -f /etc/rc$(runlevel | awk '{ print $2 }').d/S*${servicename} ]; then if [ -f /etc/rc$(runlevel | awk '{ print $2 }').d/S*${servicename} ]; then
echodebug "Service ${servicename} is enabled" echodebug "Service ${servicename} is enabled"
return 0 return 0
@ -1695,6 +1709,10 @@ install_ubuntu_deps() {
__apt_get_install_noinput python-apt __apt_get_install_noinput python-apt
if [ "$DISTRO_MAJOR_VERSION" -gt 12 ] || ([ "$DISTRO_MAJOR_VERSION" -eq 12 ] && [ "$DISTRO_MINOR_VERSION" -gt 03 ]); then if [ "$DISTRO_MAJOR_VERSION" -gt 12 ] || ([ "$DISTRO_MAJOR_VERSION" -eq 12 ] && [ "$DISTRO_MINOR_VERSION" -gt 03 ]); then
if [ "$_ENABLE_EXTERNAL_ZMQ_REPOS" -eq $BS_TRUE ]; then
echoinfo "Installing ZMQ>=4/PyZMQ>=14 from Chris Lea's PPA repository"
add-apt-repository -y ppa:chris-lea/zeromq || return 1
fi
__apt_get_install_noinput python-requests __apt_get_install_noinput python-requests
__PIP_PACKAGES="" __PIP_PACKAGES=""
else else
@ -2360,6 +2378,10 @@ install_debian_check_services() {
# Fedora Install Functions # Fedora Install Functions
# #
install_fedora_deps() { install_fedora_deps() {
if [ "$_ENABLE_EXTERNAL_ZMQ_REPOS" -eq $BS_TRUE ]; then
__install_saltstack_copr_zeromq_repository || return 1
fi
__PACKAGES="yum-utils PyYAML libyaml m2crypto python-crypto python-jinja2 python-msgpack python-zmq python-requests" __PACKAGES="yum-utils PyYAML libyaml m2crypto python-crypto python-jinja2 python-msgpack python-zmq python-requests"
if [ "$_INSTALL_CLOUD" -eq $BS_TRUE ]; then if [ "$_INSTALL_CLOUD" -eq $BS_TRUE ]; then
@ -2415,7 +2437,7 @@ install_fedora_stable_post() {
install_fedora_git_deps() { install_fedora_git_deps() {
install_fedora_deps || return 1 install_fedora_deps || return 1
yum install -y git || return 1 yum install -y git systemd-python || return 1
__git_clone_and_checkout || return 1 __git_clone_and_checkout || return 1
@ -2531,9 +2553,28 @@ __install_epel_repository() {
return 0 return 0
} }
__install_saltstack_copr_zeromq_repository() {
echoinfo "Installing Zeromq >=4 and PyZMQ>=14 from SaltStack's COPR repository"
if [ ! -f /etc/yum.repos.d/saltstack-zeromq4.repo ]; then
if [ "${DISTRO_NAME_L}" = "fedora" ]; then
__REPOTYPE="${DISTRO_NAME_L}"
else
__REPOTYPE="epel"
fi
wget -O /etc/yum.repos.d/saltstack-zeromq4.repo \
"https://copr.fedoraproject.org/coprs/saltstack/zeromq4/repo/${__REPOTYPE}-${DISTRO_MAJOR_VERSION}/saltstack-zeromq4-${__REPOTYPE}-${DISTRO_MAJOR_VERSION}.repo" || return 1
fi
return 0
}
install_centos_stable_deps() { install_centos_stable_deps() {
__install_epel_repository || return 1 __install_epel_repository || return 1
if [ "$_ENABLE_EXTERNAL_ZMQ_REPOS" -eq $BS_TRUE ]; then
__install_saltstack_copr_zeromq_repository || return 1
fi
if [ "$_UPGRADE_SYS" -eq $BS_TRUE ]; then if [ "$_UPGRADE_SYS" -eq $BS_TRUE ]; then
yum -y update || return 1 yum -y update || return 1
fi fi
@ -2674,7 +2715,7 @@ install_centos_git() {
} }
install_centos_git_post() { install_centos_git_post() {
for fname in minion master minion api; do for fname in minion master syndic api; do
# Skip if not meant to be installed # Skip if not meant to be installed
[ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue [ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
@ -3344,7 +3385,7 @@ install_arch_linux_git_deps() {
pacman -R --noconfirm --needed python2-distribute pacman -R --noconfirm --needed python2-distribute
pacman -Sy --noconfirm --needed git python2-crypto python2-setuptools python2-jinja \ pacman -Sy --noconfirm --needed git python2-crypto python2-setuptools python2-jinja \
python2-m2crypto python2-markupsafe python2-msgpack python2-psutil python2-yaml \ python2-m2crypto python2-markupsafe python2-msgpack python2-psutil python2-yaml \
python2-pyzmq zeromq python2-requests || return 1 python2-pyzmq zeromq python2-requests python2-systemd || return 1
__git_clone_and_checkout || return 1 __git_clone_and_checkout || return 1
@ -3656,9 +3697,9 @@ install_freebsd_git() {
# Install from git # Install from git
if [ ! -f salt/syspaths.py ]; then if [ ! -f salt/syspaths.py ]; then
# We still can't provide the system paths, salt 0.16.x # We still can't provide the system paths, salt 0.16.x
/usr/local/bin/python setup.py install || return 1 /usr/local/bin/python2 setup.py install || return 1
else else
/usr/local/bin/python setup.py install \ /usr/local/bin/python2 setup.py install \
--salt-root-dir=/usr/local \ --salt-root-dir=/usr/local \
--salt-config-dir="${_SALT_ETC_DIR}" \ --salt-config-dir="${_SALT_ETC_DIR}" \
--salt-cache-dir=/var/cache/salt \ --salt-cache-dir=/var/cache/salt \

View File

@ -294,7 +294,7 @@ DEFAULT_MINION_OPTS = {
'failhard': False, 'failhard': False,
'autoload_dynamic_modules': True, 'autoload_dynamic_modules': True,
'environment': None, 'environment': None,
'extension_modules': os.path.join(salt.syspaths.CACHE_DIR, 'extmods'), 'extension_modules': '',
'state_top': 'top.sls', 'state_top': 'top.sls',
'startup_states': '', 'startup_states': '',
'sls_list': [], 'sls_list': [],

View File

@ -21,6 +21,7 @@ import salt.crypt
import salt.loader import salt.loader
import salt.payload import salt.payload
import salt.transport import salt.transport
import salt.fileserver
import salt.utils import salt.utils
import salt.utils.templates import salt.utils.templates
import salt.utils.gzip_util import salt.utils.gzip_util

View File

@ -1489,7 +1489,8 @@ class ClearFuncs(object):
pass pass
elif os.path.isfile(pubfn_rejected): elif os.path.isfile(pubfn_rejected):
# The key has been rejected, don't place it in pending # The key has been rejected, don't place it in pending
log.info('Public key rejected for {id}'.format(**load)) log.info('Public key rejected for {0}. Key is present in '
'rejection key dir.'.format(load['id']))
eload = {'result': False, eload = {'result': False,
'id': load['id'], 'id': load['id'],
'pub': load['pub']} 'pub': load['pub']}
@ -2254,14 +2255,17 @@ class ClearFuncs(object):
} }
} }
# Retrieve the jid # Retrieve the jid
if not clear_load['jid']:
fstr = '{0}.prep_jid'.format(self.opts['master_job_cache']) fstr = '{0}.prep_jid'.format(self.opts['master_job_cache'])
try: try:
clear_load['jid'] = self.mminion.returners[fstr](nocache=extra.get('nocache', False)) clear_load['jid'] = self.mminion.returners[fstr](nocache=extra.get('nocache', False),
# the jid in clear_load can be None, '', or something else.
# this is an attempt to clean up the value before passing to plugins
passed_jid=clear_load['jid'] if clear_load.get('jid') else None)
except TypeError: # The returner is not present except TypeError: # The returner is not present
log.error('The requested returner {0} could not be loaded. Publication not sent.'.format(fstr.split('.')[0])) log.error('The requested returner {0} could not be loaded. Publication not sent.'.format(fstr.split('.')[0]))
return {} return {}
# TODO Error reporting over the master event bus # TODO Error reporting over the master event bus
self.event.fire_event({'minions': minions}, clear_load['jid']) self.event.fire_event({'minions': minions}, clear_load['jid'])
new_job_load = { new_job_load = {

View File

@ -105,10 +105,10 @@ def resolve_dns(opts):
if opts['retry_dns']: if opts['retry_dns']:
while True: while True:
import salt.log import salt.log
msg = ('Master hostname: {0} not found. Retrying in {1} ' msg = ('Master hostname: \'{0}\' not found. Retrying in {1} '
'seconds').format(opts['master'], opts['retry_dns']) 'seconds').format(opts['master'], opts['retry_dns'])
if salt.log.is_console_configured(): if salt.log.is_console_configured():
log.warn(msg) log.error(msg)
else: else:
print('WARNING: {0}'.format(msg)) print('WARNING: {0}'.format(msg))
time.sleep(opts['retry_dns']) time.sleep(opts['retry_dns'])
@ -711,6 +711,8 @@ class Minion(MinionBase):
' {0}'.format(opts['master'])) ' {0}'.format(opts['master']))
if opts['master_shuffle']: if opts['master_shuffle']:
shuffle(opts['master']) shuffle(opts['master'])
elif opts['__role'] == 'syndic':
log.info('Syndic setting master_syndic to \'{0}\''.format(opts['master']))
# if failed=True, the minion was previously connected # if failed=True, the minion was previously connected
# we're probably called from the minions main-event-loop # we're probably called from the minions main-event-loop
@ -1971,16 +1973,18 @@ class Syndic(Minion):
''' '''
Lock onto the publisher. This is the main event loop for the syndic Lock onto the publisher. This is the main event loop for the syndic
''' '''
# Instantiate the local client
self.local = salt.client.get_local_client(self.opts['_minion_conf_file'])
self.local.event.subscribe('')
self.local.opts['interface'] = self._syndic_interface
signal.signal(signal.SIGTERM, self.clean_die) signal.signal(signal.SIGTERM, self.clean_die)
log.debug('Syndic {0!r} trying to tune in'.format(self.opts['id'])) log.debug('Syndic {0!r} trying to tune in'.format(self.opts['id']))
self._init_context_and_poller() self._init_context_and_poller()
# Instantiate the local client
self.local = salt.client.get_local_client(self.opts['_minion_conf_file'])
self.local.event.subscribe('')
self.local.opts['interface'] = self._syndic_interface
# register the event sub to the poller
self.poller.register(self.local.event.sub)
# Start with the publish socket # Start with the publish socket
# Share the poller with the event object # Share the poller with the event object
self.socket = self.context.socket(zmq.SUB) self.socket = self.context.socket(zmq.SUB)

469
salt/modules/drac.py Normal file
View File

@ -0,0 +1,469 @@
# -*- coding: utf-8 -*-
'''
Manage Dell DRAC
'''
import salt.utils
import logging
log = logging.getLogger(__name__)
def __virtual__():
'''
'''
if salt.utils.which('racadm'):
return True
return False
def __parse_drac(output):
'''
Parse Dell DRAC output
'''
drac = {}
section = ''
for i in output.splitlines():
if len(i.rstrip()) > 0 and '=' in i:
if section in drac:
drac[section].update(dict(
[[prop.strip() for prop in i.split('=')]]
))
else:
section = i.strip()[:-1]
if section not in drac and section:
drac[section] = {}
return drac
def __execute_cmd(command):
'''
Execute rac commands
'''
cmd = __salt__['cmd.run_all']('racadm {0}'.format(command))
if cmd['retcode'] != 0:
log.warn('racadm return an exit code \'{0}\'.'.format(cmd['retcode']))
return False
return True
def system_info():
'''
Return System information
CLI Example:
.. code-block:: bash
salt dell drac.getsysinfo
'''
drac = {}
section = ''
cmd = __salt__['cmd.run_all']('racadm getsysinfo')
if cmd['retcode'] != 0:
log.warn('racadm return an exit code \'{0}\'.'.format(cmd['retcode']))
return __parse_drac(cmd['stdout'])
def network_info():
'''
Return Network Configuration
CLI Example:
.. code-block:: bash
salt dell drac.getniccfg
'''
cmd = __salt__['cmd.run_all']('racadm getniccfg')
if cmd['retcode'] != 0:
log.warn('racadm return an exit code \'{0}\'.'.format(cmd['retcode']))
return __parse_drac(cmd['stdout'])
def nameservers(*ns):
'''
Configure the nameservers on the DRAC
CLI Example:
.. code-block:: bash
salt dell drac.nameservers [NAMESERVERS]
salt dell drac.nameservers ns1.example.com ns2.example.com
'''
if len(ns) > 2:
log.warn('racadm only supports two nameservers')
return False
for i in range(1, len(ns) + 1):
if not __execute_cmd('config -g cfgLanNetworking -o \
cfgDNSServer{0} {1}'.format(i, ns[i - 1])):
return False
return True
def syslog(server, enable=True):
'''
Configure syslog remote logging, by default syslog will automatically be
enabled if a server is specified. However, if you want to disable syslog
you will need to specify a server followed by False
CLI Example:
.. code-block:: bash
salt dell drac.syslog [SYSLOG IP] [ENABLE/DISABLE]
salt dell drac.syslog 0.0.0.0 False
'''
if enable:
if __execute_cmd('config -g cfgRemoteHosts -o \
cfgRhostsSyslogEnable 1'):
return __execute_cmd('config -g cfgRemoteHosts -o \
cfgRhostsSyslogServer1 {0}'.format(server))
return __execute_cmd('config -g cfgRemoteHosts -o cfgRhostsSyslogEnable 0')
def email_alerts(action):
'''
Enable/Disable email alerts
CLI Example:
.. code-block:: bash
salt dell drac.email_alerts True
salt dell drac.email_alerts False
'''
if action:
return __execute_cmd('config -g cfgEmailAlert -o \
cfgEmailAlertEnable -i 1 1')
else:
return __execute_cmd('config -g cfgEmailAlert -o \
cfgEmailAlertEnable -i 1 0')
def list_users():
'''
List all DRAC users
CLI Example:
.. code-block:: bash
salt dell drac.list_users
'''
users = {}
_username = ''
for i in range(1, 12):
cmd = __salt__['cmd.run_all']('racadm getconfig -g \
cfgUserAdmin -i {0}'.format(i))
if cmd['retcode'] != 0:
log.warn('racadm return an exit \
code \'{0}\'.'.format(cmd['retcode']))
for user in cmd['stdout'].splitlines():
if 'cfgUserAdminIndex' in user or user.startswith('#'):
continue
(k, v) = user.split('=')
if k.startswith('cfgUserAdminUserName'):
_username = v.strip()
if v:
users[_username] = {'index': i}
else:
break
else:
users[_username].update({k: v})
return users
def delete_user(username, uid=None):
'''
Delete a user
CLI Example:
.. code-block:: bash
salt dell drac.delete_user [USERNAME] [UID - optional]
salt dell drac.delete_user diana 4
'''
if uid is None:
user = list_users()
uid = user[username]['index']
if uid:
return __execute_cmd('config -g cfgUserAdmin -o \
cfgUserAdminUserName -i {0} ""'.format(uid))
else:
log.warn('\'{0}\' does not exist'.format(username))
return False
return True
def change_password(username, password, uid=None):
'''
Change users password
CLI Example:
.. code-block:: bash
salt dell drac.change_password [USERNAME] [PASSWORD] [UID - optional]
salt dell drac.change_password diana secret
'''
if uid is None:
user = list_users()
uid = user[username]['index']
if uid:
return __execute_cmd('config -g cfgUserAdmin -o \
cfgUserAdminPassword -i {0} {1}'.format(uid, password))
else:
log.warn('\'{0}\' does not exist'.format(username))
return False
return True
def create_user(username, password, permissions):
'''
Create user accounts
CLI Example:
.. code-block:: bash
salt dell drac.create_user [USERNAME] [PASSWORD] [PRIVELEGES]
salt dell drac.create_user diana secret login,test_alerts,clear_logs
DRAC Priveleges
* login : Login to iDRAC
* drac : Configure iDRAC
* user_management : Configure Users
* clear_logs : Clear Logs
* server_control_commands : Execute Server Control Commands
* console_redirection : Access Console Redirection
* virtual_media : Access Virtual Media
* test_alerts : Test Alerts
* debug_commands : Execute Debug Commands
'''
_uids = set()
user = list_users()
if username in user:
log.warn('\'{0}\' already exists'.format(username))
return False
for i in user.keys():
_uids.add(user[i]['index'])
uid = sorted(list(set(xrange(2, 12)) - _uids), reverse=True).pop()
# Create user accountvfirst
if not __execute_cmd('config -g cfgUserAdmin -o \
cfgUserAdminUserName -i {0} {1}'.format(uid, username)):
delete_user(username, uid)
return False
# Configure users permissions
if not set_permissions(username, permissions, uid):
log.warn('unable to set user permissions')
delete_user(username, uid)
return False
# Configure users password
if not change_password(username, password, uid):
log.warn('unable to set user password')
delete_user(username, uid)
return False
# Enable users admin
if not __execute_cmd('config -g cfgUserAdmin -o \
cfgUserAdminEnable -i {0} 1'.format(uid)):
delete_user(username, uid)
return False
return True
def set_permissions(username, permissions, uid=None):
'''
Configure users permissions
CLI Example:
.. code-block:: bash
salt dell drac.set_permissions [USERNAME] [PRIVELEGES] [USER INDEX - optional]
salt dell drac.set_permissions diana login,test_alerts,clear_logs 4
DRAC Priveleges
* login : Login to iDRAC
* drac : Configure iDRAC
* user_management : Configure Users
* clear_logs : Clear Logs
* server_control_commands : Execute Server Control Commands
* console_redirection : Access Console Redirection
* virtual_media : Access Virtual Media
* test_alerts : Test Alerts
* debug_commands : Execute Debug Commands
'''
privileges = {'login': '0x0000001',
'drac': '0x0000002',
'user_management': '0x0000004',
'clear_logs': '0x0000008',
'server_control_commands': '0x0000010',
'console_redirection': '0x0000020',
'virtual_media': '0x0000040',
'test_alerts': '0x0000080',
'debug_commands': '0x0000100'}
permission = 0
# When users don't provide a user ID we need to search for this
if uid is None:
user = list_users()
uid = user[username]['index']
# Generate privilege bit mask
for i in permissions.split(','):
perm = i.strip()
if perm in privileges:
permission += int(privileges[perm], 16)
return __execute_cmd('config -g cfgUserAdmin -o \
cfgUserAdminPrivilege -i {0} 0x{1:08X}'.format(uid, permission))
def set_snmp(community):
'''
Configure SNMP community string
CLI Example:
.. code-block:: bash
salt dell drac.set_snmp [COMMUNITY]
salt dell drac.set_snmp public
'''
return __execute_cmd('config -g cfgOobSnmp -o \
cfgOobSnmpAgentCommunity {0}'.format(community))
def set_network(ip, netmask, gateway):
'''
Configure Network
CLI Example:
.. code-block:: bash
salt dell drac.set_network [DRAC IP] [NETMASK] [GATEWAY]
salt dell drac.set_network 192.168.0.2 255.255.255.0 192.168.0.1
'''
return __execute_cmd('setniccfg -s {0} {1} {2}'.format(
ip, netmask, gateway
))
def server_reboot():
'''
Issues a power-cycle operation on the managed server. This action is
similar to pressing the power button on the system's front panel to
power down and then power up the system.
CLI Example:
.. code-block:: bash
salt dell drac.server_reboot
'''
return __execute_cmd('serveraction powercycle')
def server_poweroff():
'''
Powers down the managed server.
CLI Example:
.. code-block:: bash
salt dell drac.server_poweroff
'''
return __execute_cmd('serveraction powerdown')
def server_poweron():
'''
Powers up the managed server.
CLI Example:
.. code-block:: bash
salt dell drac.server_poweron
'''
return __execute_cmd('serveraction powerup')
def server_hardreset():
'''
Performs a reset (reboot) operation on the managed server.
CLI Example:
.. code-block:: bash
salt dell drac.server_hardreset
'''
return __execute_cmd('serveraction hardreset')
def server_pxe():
'''
Configure server to PXE perform a one off PXE boot
CLI Example:
.. code-block:: bash
salt dell drac.server_pxe
'''
if __execute_cmd('config -g cfgServerInfo -o \
cfgServerFirstBootDevice PXE'):
if __execute_cmd('config -g cfgServerInfo -o cfgServerBootOnce 1'):
return server_reboot
else:
log.warn('failed to set boot order')
return False
log.warn('failed to to configure PXE boot')
return False

View File

@ -98,8 +98,9 @@ def list_pkgs(versions_as_list=False, **kwargs):
salt '*' pkg.list_pkgs salt '*' pkg.list_pkgs
''' '''
versions_as_list = salt.utils.is_true(versions_as_list) versions_as_list = salt.utils.is_true(versions_as_list)
# 'removed' not yet implemented or not applicable # 'removed', 'purge_desired' not yet implemented or not applicable
if salt.utils.is_true(kwargs.get('removed')): if any([salt.utils.is_true(kwargs.get(x))
for x in ('removed', 'purge_desired')]):
return {} return {}
if 'pkg.list_pkgs' in __context__: if 'pkg.list_pkgs' in __context__:

View File

@ -197,6 +197,7 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914
process_dependency_links=False, process_dependency_links=False,
__env__=None, __env__=None,
saltenv='base', saltenv='base',
env_vars=None,
use_vt=False): use_vt=False):
''' '''
Install packages with pip Install packages with pip
@ -311,6 +312,11 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914
Enable the processing of dependency links Enable the processing of dependency links
use_vt use_vt
Use VT terminal emulation (see ouptut while installing) Use VT terminal emulation (see ouptut while installing)
env_vars
Set environment variables that some builds will depend on. For example,
a Python C-module may have a Makefile that needs INCLUDE_PATH set to
pick up a header file while compiling.
CLI Example: CLI Example:
@ -576,6 +582,9 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914
if process_dependency_links: if process_dependency_links:
cmd.append('--process-dependency-links') cmd.append('--process-dependency-links')
if env_vars:
os.environ.update(env_vars)
try: try:
cmd_kwargs = dict(runas=user, cwd=cwd, saltenv=saltenv, use_vt=use_vt) cmd_kwargs = dict(runas=user, cwd=cwd, saltenv=saltenv, use_vt=use_vt)
if bin_env and os.path.isdir(bin_env): if bin_env and os.path.isdir(bin_env):

View File

@ -29,7 +29,7 @@ def __virtual__():
enabled = ('amazon', 'xcp', 'xenserver') enabled = ('amazon', 'xcp', 'xenserver')
if os_family == 'redhat' or os_grain in enabled: if os_family in ['redhat', 'suse'] or os_grain in enabled:
return __virtualname__ return __virtualname__
return False return False
@ -183,3 +183,34 @@ def file_dict(*packages):
files.append(line) files.append(line)
ret[pkg] = files ret[pkg] = files
return {'errors': errors, 'packages': ret} return {'errors': errors, 'packages': ret}
def owner(*paths):
'''
Return the name of the package that owns the file. Multiple file paths can
be passed. If a single path is passed, a string will be returned,
and if multiple paths are passed, a dictionary of file/package name pairs
will be returned.
If the file is not owned by a package, or is not present on the minion,
then an empty string will be returned for that path.
CLI Examples:
.. code-block:: bash
salt '*' lowpkg.owner /usr/bin/apachectl
salt '*' lowpkg.owner /usr/bin/apachectl /etc/httpd/conf/httpd.conf
'''
if not paths:
return ''
ret = {}
cmd = 'rpm -qf --queryformat "%{{NAME}}" {0!r}'
for path in paths:
ret[path] = __salt__['cmd.run_stdout'](cmd.format(path),
output_loglevel='trace')
if 'not owned' in ret[path].lower():
ret[path] = ''
if len(ret) == 1:
return ret.values()[0]
return ret

View File

@ -1,77 +1,265 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
''' '''
Module for notifications via Slack. Module for sending messages to Slack
See https://slack.com for more info.
.. versionadded:: Lithium .. versionadded:: Lithium
:depends: - pyslack python module :configuration: This module can be used by either passing an api key and version
:configuration: Configure this module by specifying the name of a configuration directly or by specifying both in a configuration profile in the salt
profile in the minion config, minion pillar, or master config. master/minion config.
For example: For example:
.. code-block:: yaml .. code-block:: yaml
slack.api_token: <api token> slack:
slack.username: salt-bot api_key: peWcBiMOS9HrZG15peWcBiMOS9HrZG15
''' '''
import requests
import logging import logging
from salt.exceptions import CommandExecutionError from urlparse import urljoin as _urljoin
from requests.exceptions import ConnectionError
HAS_LIBS = False
try:
import slack
import slack.chat
from slack.exception import ChannelNotFoundError
from slack.exception import NotAuthedError
HAS_LIBS = True
except ImportError:
pass
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
__virtualname__ = 'slack' __virtualname__ = 'slack'
def __virtual__(): def __virtual__():
''' '''
Only load this module if slack is installed on this minion. Return virtual name of the module.
:return: The virtual name of the module.
''' '''
if HAS_LIBS:
return __virtualname__ return __virtualname__
return False
def _setup(): def _query(function, api_key=None, method='GET', data=None):
''' '''
Return the slack connection Slack object method function to construct and execute on the API URL.
:param api_key: The Slack api key.
:param function: The Slack api function to perform.
:param method: The HTTP method, e.g. GET or POST.
:param data: The data to be sent for POST method.
:return: The json response from the API call or False.
''' '''
creds = {} headers = {}
creds['api_token'] = __salt__['config.option']('slack.api_token') query_params = {}
creds['username'] = __salt__['config.option']('slack.username')
slack.api_token = creds.get('api_token') if data is None:
return creds data = {}
ret = {'message': '',
'res': True}
slack_functions = {
'rooms': {
'request': 'channels.list',
'response': 'channels',
},
'users': {
'request': 'users.list',
'response': 'members',
},
'message': {
'request': 'chat.postMessage',
'response': 'channel',
},
}
if not api_key:
try:
options = __salt__['config.option']('slack')
if not api_key:
api_key = options.get('api_key')
except (NameError, KeyError, AttributeError):
log.error('No Slack api key found.')
ret['message'] = 'No Slack api key found.'
ret['res'] = False
return ret
api_url = 'https://slack.com'
base_url = _urljoin(api_url, '/api/')
path = slack_functions.get(function).get('request')
url = _urljoin(base_url, path, False)
query_params['token'] = api_key
try:
result = requests.request(
method=method,
url=url,
headers=headers,
params=query_params,
data=data,
verify=True,
)
except ConnectionError as e:
ret['message'] = e
ret['res'] = False
return ret
if result.status_code == 200:
result = result.json()
response = slack_functions.get(function).get('response')
if 'error' in result:
ret['message'] = result['error']
ret['res'] = False
return ret
ret['message'] = result.get(response)
return ret
elif result.status_code == 204:
return True
else:
log.debug(url)
log.debug(query_params)
log.debug(data)
log.debug(result)
if 'error' in result:
ret['message'] = result['error']
ret['res'] = False
return ret
ret['message'] = result
return ret
def post_message(message, channel='#general', username=None): def list_rooms(api_key=None):
''' '''
Post a message to a channel List all Slack rooms.
:param api_key: The Slack admin api key.
:return: The room list.
CLI Example: CLI Example:
.. code-block:: yaml .. code-block:: bash
salt '*' slack.post_message 'Test message' salt '*' slack.list_rooms
salt '*' slack.list_rooms api_key=peWcBiMOS9HrZG15peWcBiMOS9HrZG15
''' '''
ret = {} return _query(function='rooms', api_key=api_key)
creds = _setup()
if username is None:
username = creds['username'] def list_users(api_key=None):
try: '''
ret = slack.chat.post_message(channel, message, username=username) List all Slack users.
except ChannelNotFoundError as exc: :param api_key: The Slack admin api key.
raise CommandExecutionError('Channel "{0}" does not exist. {1}'.format(channel, exc)) :return: The user list.
except NotAuthedError as exc:
raise CommandExecutionError('Authentication Failed. {0}'.format(exc)) CLI Example:
return ret
.. code-block:: bash
salt '*' slack.list_users
salt '*' slack.list_users api_key=peWcBiMOS9HrZG15peWcBiMOS9HrZG15
'''
return _query(function='users', api_key=api_key)
def find_room(name, api_key=None):
'''
Find a room by name and return it.
:param name: The room name.
:param api_key: The Slack admin api key.
:return: The room object.
CLI Example:
.. code-block:: bash
salt '*' slack.find_room name="random"
salt '*' slack.find_room name="random" api_key=peWcBiMOS9HrZG15peWcBiMOS9HrZG15
'''
# search results don't include the name of the
# channel with a hash, if the passed channel name
# has a hash we remove it.
if name.startswith('#'):
name = name[1:]
ret = list_rooms(api_key)
if ret['res']:
rooms = ret['message']
if rooms:
for room in range(0, len(rooms)):
if rooms[room]['name'] == name:
return rooms[room]
return False
def find_user(name, api_key=None):
'''
Find a user by name and return it.
:param name: The user name.
:param api_key: The Slack admin api key.
:return: The user object.
CLI Example:
.. code-block:: bash
salt '*' slack.find_user name="ThomasHatch"
salt '*' slack.find_user name="ThomasHatch" api_key=peWcBiMOS9HrZG15peWcBiMOS9HrZG15
'''
ret = list_users(api_key)
if ret['res']:
users = ret['message']
if users:
for user in range(0, len(users)):
if users[user]['name'] == name:
return users[user]
return False
def post_message(channel,
message,
from_name,
api_key=None):
'''
Send a message to a Slack channel.
:param channel: The channel name, either will work.
:param message: The message to send to the HipChat room.
:param from_name: Specify who the message is from.
:param api_key: The Slack api key, if not specified in the configuration.
:return: Boolean if message was sent successfully.
CLI Example:
.. code-block:: bash
salt '*' slack.send_message channel="Development Room" message="Build is done" from_name="Build Server"
'''
if not channel:
log.error('channel is a required option.')
# channel must start with a hash
if not channel.startswith('#'):
channel = '#{0}'.format(channel)
if not from_name:
log.error('from_name is a required option.')
if not message:
log.error('message is a required option.')
if not from_name:
log.error('from_name is a required option.')
parameters = dict()
parameters['channel'] = channel
parameters['username'] = from_name
parameters['text'] = message
result = _query(function='message',
api_key=api_key,
method='POST',
data=parameters)
if result['res']:
return True
else:
return result

View File

@ -619,7 +619,7 @@ def fullversion():
continue continue
if ': ' in line: if ': ' in line:
comps = line.split(': ') comps = line.split(': ')
ret[comps[0]] = comps[1] ret[comps[0]] = comps[1].lstrip()
return ret return ret

View File

@ -98,8 +98,6 @@ def __get_conn():
- http://libvirt.org/uri.html#URI_config - http://libvirt.org/uri.html#URI_config
''' '''
connection = __salt__['config.get']('libvirt:connection', 'esx') connection = __salt__['config.get']('libvirt:connection', 'esx')
if connection.startswith('esx://'):
return connection
return connection return connection
def __esxi_auth(): def __esxi_auth():

View File

@ -1,6 +1,16 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
''' '''
Support for YUM Support for YUM
.. note::
This module makes heavy use of the **repoquery** utility, from the
yum-utils_ package. This package will be installed as a dependency if salt
is installed via EPEL. However, if salt has been installed using pip, or a
host is being managed using salt-ssh, then as of version 2014.7.0
yum-utils_ will be installed automatically to satisfy this dependency.
.. _yum-utils: http://yum.baseurl.org/wiki/YumUtils
''' '''
# Import python libs # Import python libs
@ -102,10 +112,27 @@ def _repoquery_pkginfo(repoquery_args):
return ret return ret
def _check_repoquery():
'''
Check for existence of repoquery and install yum-utils if it is not
present.
'''
if not salt.utils.which('repoquery'):
__salt__['cmd.run'](
['yum', '-y', 'install', 'yum-utils'],
python_shell=False,
output_loglevel='trace'
)
# Check again now that we've installed yum-utils
if not salt.utils.which('repoquery'):
raise CommandExecutionError('Unable to install yum-utils')
def _repoquery(repoquery_args, query_format=__QUERYFORMAT): def _repoquery(repoquery_args, query_format=__QUERYFORMAT):
''' '''
Runs a repoquery command and returns a list of namedtuples Runs a repoquery command and returns a list of namedtuples
''' '''
_check_repoquery()
cmd = 'repoquery --plugins --queryformat="{0}" {1}'.format( cmd = 'repoquery --plugins --queryformat="{0}" {1}'.format(
query_format, repoquery_args query_format, repoquery_args
) )

View File

@ -5,6 +5,7 @@ Module for running ZFS zpool command
# Import Python libs # Import Python libs
import os import os
import stat
import logging import logging
# Import Salt libs # Import Salt libs
@ -150,15 +151,18 @@ def scrub(pool_name=None):
ret['Error'] = 'Storage pool {0} does not exist'.format(pool_name) ret['Error'] = 'Storage pool {0} does not exist'.format(pool_name)
def create(pool_name, *vdevs): def create(pool_name, *vdevs, **kwargs):
''' '''
Create a new storage pool Create a simple zpool, a mirrored zpool, a zpool having nested VDEVs and a hybrid zpool with cache and log drives
CLI Example: CLI Example:
.. code-block:: bash .. code-block:: bash
salt '*' zpool.create myzpool /path/to/vdev1 [/path/to/vdev2] [...] salt '*' zpool.create myzpool /path/to/vdev1 [...] [force=True|False]
salt '*' zpool.create myzpool mirror /path/to/vdev1 /path/to/vdev2 [...] [force=True|False]
salt '*' zpool.create myzpool mirror /path/to/vdev1 [...] mirror /path/to/vdev2 /path/to/vdev3 [...] [force=True|False]
salt '*' zpool.create myhybridzpool mirror /tmp/file1 [...] log mirror /path/to/vdev1 [...] cache /path/to/vdev2 [...] [force=True|False]
''' '''
ret = {} ret = {}
dlist = [] dlist = []
@ -170,26 +174,37 @@ def create(pool_name, *vdevs):
# make sure files are present on filesystem # make sure files are present on filesystem
for vdev in vdevs: for vdev in vdevs:
if not os.path.isfile(vdev): if vdev not in ['mirror', 'log', 'cache']:
# File is not there error and return if not os.path.exists(vdev):
# Path doesn't exist so error and return
ret[vdev] = '{0} not present on filesystem'.format(vdev) ret[vdev] = '{0} not present on filesystem'.format(vdev)
return ret return ret
else: mode = os.stat(vdev).st_mode
if not stat.S_ISBLK(mode) and not stat.S_ISREG(mode):
# Not a block device or file vdev so error and return
ret[vdev] = '{0} is not a block device or a file vdev'.format(vdev)
return ret
dlist.append(vdev) dlist.append(vdev)
devs = ' '.join(dlist) devs = ' '.join(dlist)
zpool = _check_zpool() zpool = _check_zpool()
force = kwargs.get('force', False)
if force is True:
cmd = '{0} create -f {1} {2}'.format(zpool, pool_name, devs)
else:
cmd = '{0} create {1} {2}'.format(zpool, pool_name, devs) cmd = '{0} create {1} {2}'.format(zpool, pool_name, devs)
# Create storage pool # Create storage pool
__salt__['cmd.run'](cmd) res = __salt__['cmd.run'](cmd)
# Check and see if the pools is available # Check and see if the pools is available
if exists(pool_name): if exists(pool_name):
ret[pool_name] = 'created' ret[pool_name] = 'created'
return ret return ret
else: else:
ret['Error'] = 'Unable to create storage pool {0}'.format(pool_name) ret['Error'] = {}
ret['Error']['Messsage'] = 'Unable to create storage pool {0}'.format(pool_name)
ret['Error']['Reason'] = res
return ret return ret

View File

@ -7,6 +7,8 @@ Package support for openSUSE via the zypper package manager
import copy import copy
import logging import logging
import re import re
import os
from xml.dom import minidom as dom
from contextlib import contextmanager as _contextmanager from contextlib import contextmanager as _contextmanager
# Import salt libs # Import salt libs
@ -18,6 +20,7 @@ from salt.exceptions import (
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
HAS_ZYPP = False HAS_ZYPP = False
LOCKS = "/etc/zypp/locks"
try: try:
import zypp import zypp
@ -847,3 +850,238 @@ def purge(name=None, pkgs=None, **kwargs):
salt '*' pkg.purge pkgs='["foo", "bar"]' salt '*' pkg.purge pkgs='["foo", "bar"]'
''' '''
return _uninstall(action='purge', name=name, pkgs=pkgs) return _uninstall(action='purge', name=name, pkgs=pkgs)
def list_locks():
'''
List current package locks.
Return a dict containing the locked package with attributes::
{'<package>': {'case_sensitive': '<case_sensitive>',
'match_type': '<match_type>'
'type': '<type>'}}
CLI Example:
.. code-block:: bash
salt '*' pkg.list_locks
'''
if not os.path.exists(LOCKS):
return False
locks = {}
for meta in map(lambda item: item.split("\n"),
open(LOCKS).read().split("\n\n")):
lock = {}
for element in [el for el in meta if el]:
if ":" in element:
lock.update(dict([tuple(map(lambda i: i.strip(),
element.split(":", 1))), ]))
if lock.get('solvable_name'):
locks[lock.pop('solvable_name')] = lock
return locks
def clean_locks():
'''
Remove unused locks that do not currently (with regard to repositories used) lock any package.
CLI Example:
.. code-block:: bash
salt '*' pkg.clean_locks
'''
if not os.path.exists(LOCKS):
return False
cmd = ('zypper --non-interactive cl')
__salt__['cmd.run'](cmd, output_loglevel='trace')
return True
def remove_lock(name=None, pkgs=None, **kwargs):
'''
Remove specified package lock.
CLI Example:
.. code-block:: bash
salt '*' pkg.remove_lock <package name>
salt '*' pkg.remove_lock <package1>,<package2>,<package3>
salt '*' pkg.remove_lock pkgs='["foo", "bar"]'
'''
locks = list_locks()
packages = []
try:
packages = __salt__['pkg_resource.parse_targets'](name, pkgs)[0].keys()
except MinionError as exc:
raise CommandExecutionError(exc)
removed = []
missing = []
for pkg in packages:
if locks.get(pkg):
removed.append(pkg)
else:
missing.append(pkg)
if removed:
__salt__['cmd.run'](('zypper --non-interactive rl {0}'.format(' '.join(removed))),
output_loglevel='trace')
return {'removed': len(removed), 'not_found': missing}
def add_lock(name=None, pkgs=None, **kwargs):
'''
Add a package lock. Specify packages to lock by exact name.
CLI Example:
.. code-block:: bash
salt '*' pkg.add_lock <package name>
salt '*' pkg.add_lock <package1>,<package2>,<package3>
salt '*' pkg.add_lock pkgs='["foo", "bar"]'
'''
locks = list_locks()
packages = []
added = []
try:
packages = __salt__['pkg_resource.parse_targets'](name, pkgs)[0].keys()
except MinionError as exc:
raise CommandExecutionError(exc)
for pkg in packages:
if not locks.get(pkg):
added.append(pkg)
if added:
__salt__['cmd.run'](('zypper --non-interactive al {0}'.format(' '.join(added))),
output_loglevel='trace')
return {'added': len(added), 'packages': added}
def verify(*names, **kwargs):
'''
Runs an rpm -Va on a system, and returns the results in a dict
Files with an attribute of config, doc, ghost, license or readme in the
package header can be ignored using the ``ignore_types`` keyword argument
CLI Example:
.. code-block:: bash
salt '*' pkg.verify
salt '*' pkg.verify httpd
salt '*' pkg.verify 'httpd postfix'
salt '*' pkg.verify 'httpd postfix' ignore_types=['config','doc']
'''
return __salt__['lowpkg.verify'](*names, **kwargs)
def file_list(*packages):
'''
List the files that belong to a package. Not specifying any packages will
return a list of *every* file on the system's rpm database (not generally
recommended).
CLI Examples:
.. code-block:: bash
salt '*' pkg.file_list httpd
salt '*' pkg.file_list httpd postfix
salt '*' pkg.file_list
'''
return __salt__['lowpkg.file_list'](*packages)
def file_dict(*packages):
'''
List the files that belong to a package, grouped by package. Not
specifying any packages will return a list of *every* file on the system's
rpm database (not generally recommended).
CLI Examples:
.. code-block:: bash
salt '*' pkg.file_list httpd
salt '*' pkg.file_list httpd postfix
salt '*' pkg.file_list
'''
return __salt__['lowpkg.file_dict'](*packages)
def owner(*paths):
'''
Return the name of the package that owns the file. Multiple file paths can
be passed. If a single path is passed, a string will be returned,
and if multiple paths are passed, a dictionary of file/package name
pairs will be returned.
If the file is not owned by a package, or is not present on the minion,
then an empty string will be returned for that path.
CLI Examples:
.. code-block:: bash
salt '*' pkg.owner /usr/bin/apachectl
salt '*' pkg.owner /usr/bin/apachectl /etc/httpd/conf/httpd.conf
'''
return __salt__['lowpkg.owner'](*paths)
def _get_patterns(installed_only=None):
'''
List all known patterns in repos.
'''
patterns = {}
doc = dom.parseString(__salt__['cmd.run'](('zypper --xmlout se -t pattern'),
output_loglevel='trace'))
for element in doc.getElementsByTagName("solvable"):
installed = element.getAttribute("status") == "installed"
if (installed_only and installed) or not installed_only:
patterns[element.getAttribute("name")] = {
'installed': installed,
'summary': element.getAttribute("summary"),
}
return patterns
def list_patterns():
'''
List all known patterns from available repos.
CLI Examples:
.. code-block:: bash
salt '*' pkg.list_patterns
'''
return _get_patterns()
def list_installed_patterns():
'''
List installed patterns on the system.
CLI Examples:
.. code-block:: bash
salt '*' pkg.list_installed_patterns
'''
return _get_patterns(installed_only=True)

View File

@ -232,8 +232,8 @@ def returner(ret):
total_sent_bytes += sent_bytes total_sent_bytes += sent_bytes
def prep_jid(nocache): # pylint: disable=unused-argument def prep_jid(nocache, passed_jid=None): # pylint: disable=unused-argument
''' '''
Do any work necessary to prepare a JID, including sending a custom id Do any work necessary to prepare a JID, including sending a custom id
''' '''
return salt.utils.gen_jid() return passed_jid if passed_jid is not None else salt.utils.gen_jid()

View File

@ -74,9 +74,8 @@ def returner(ret):
ccf.insert(ret['jid'], columns) ccf.insert(ret['jid'], columns)
def prep_jid(nocache): # pylint: disable=unused-argument def prep_jid(nocache, passed_jid=None): # pylint: disable=unused-argument
''' '''
Do any work necessary to prepare the jid for storage, Do any work necessary to prepare a JID, including sending a custom id
including returning a custom jid
''' '''
return salt.utils.gen_jid() return passed_jid if passed_jid is not None else salt.utils.gen_jid()

View File

@ -119,21 +119,27 @@ def _get_ttl():
#TODO: add to returner docs-- this is a new one #TODO: add to returner docs-- this is a new one
def prep_jid(nocache=False): def prep_jid(nocache=False, passed_jid=None):
''' '''
Return a job id and prepare the job id directory Return a job id and prepare the job id directory
This is the function responsible for making sure jids don't collide (unless its passed a jid) This is the function responsible for making sure jids don't collide (unless its passed a jid)
So do what you have to do to make sure that stays the case So do what you have to do to make sure that stays the case
''' '''
if passed_jid is None:
jid = salt.utils.gen_jid()
else:
jid = passed_jid
cb_ = _get_connection() cb_ = _get_connection()
jid = salt.utils.gen_jid()
try: try:
cb_.add(str(jid), cb_.add(str(jid),
{'nocache': nocache}, {'nocache': nocache},
ttl=_get_ttl(), ttl=_get_ttl(),
) )
except couchbase.exceptions.KeyExistsError: except couchbase.exceptions.KeyExistsError:
# TODO: some sort of sleep or something? Spinning is generally bad practice
if passed_jid is None:
return prep_jid(nocache=nocache) return prep_jid(nocache=nocache)
return jid return jid

View File

@ -349,8 +349,8 @@ def set_salt_view():
return True return True
def prep_jid(nocache): # pylint: disable=unused-argument def prep_jid(nocache, passed_jid=None): # pylint: disable=unused-argument
''' '''
Do any necessary pre-processing and return the jid to use Do any work necessary to prepare a JID, including sending a custom id
''' '''
return salt.utils.gen_jid() return passed_jid if passed_jid is not None else salt.utils.gen_jid()

View File

@ -148,9 +148,8 @@ def returner(ret):
) )
def prep_jid(nocache): # pylint: disable=unused-argument def prep_jid(nocache, passed_jid=None): # pylint: disable=unused-argument
''' '''
Prepare the jid, including doing any pre-processing and Do any work necessary to prepare a JID, including sending a custom id
returning the jid to use
''' '''
return salt.utils.gen_jid() return passed_jid if passed_jid is not None else salt.utils.gen_jid()

View File

@ -168,8 +168,8 @@ def get_minions():
return ret return ret
def prep_jid(nocache): # pylint: disable=unused-argument def prep_jid(nocache, passed_jid=None): # pylint: disable=unused-argument
''' '''
Pre-process the JID and return the JID to use Do any work necessary to prepare a JID, including sending a custom id
''' '''
return salt.utils.gen_jid() return passed_jid if passed_jid is not None else salt.utils.gen_jid()

View File

@ -97,13 +97,16 @@ def _format_jid_instance(jid, job):
#TODO: add to returner docs-- this is a new one #TODO: add to returner docs-- this is a new one
def prep_jid(nocache=False): def prep_jid(nocache=False, passed_jid=None):
''' '''
Return a job id and prepare the job id directory Return a job id and prepare the job id directory
This is the function responsible for making sure jids don't collide (unless its passed a jid) This is the function responsible for making sure jids don't collide (unless its passed a jid)
So do what you have to do to make sure that stays the case So do what you have to do to make sure that stays the case
''' '''
if passed_jid is None: # this can be a None of an empty string
jid = salt.utils.gen_jid() jid = salt.utils.gen_jid()
else:
jid = passed_jid
jid_dir_ = _jid_dir(jid) jid_dir_ = _jid_dir(jid)
@ -113,6 +116,7 @@ def prep_jid(nocache=False):
os.makedirs(jid_dir_) os.makedirs(jid_dir_)
except OSError: except OSError:
# TODO: some sort of sleep or something? Spinning is generally bad practice # TODO: some sort of sleep or something? Spinning is generally bad practice
if passed_jid is None:
return prep_jid(nocache=nocache) return prep_jid(nocache=nocache)
with salt.utils.fopen(os.path.join(jid_dir_, 'jid'), 'w+') as fn_: with salt.utils.fopen(os.path.join(jid_dir_, 'jid'), 'w+') as fn_:

View File

@ -93,11 +93,11 @@ def _get_serv(ret):
# an integer weight value. # an integer weight value.
def prep_jid(nocache): # pylint: disable=unused-argument def prep_jid(nocache, passed_jid=None): # pylint: disable=unused-argument
''' '''
Pre-process the jid and return the jid to use Do any work necessary to prepare a JID, including sending a custom id
''' '''
return salt.utils.gen_jid() return passed_jid if passed_jid is not None else salt.utils.gen_jid()
def returner(ret): def returner(ret):

View File

@ -209,8 +209,8 @@ def get_jids():
return ret return ret
def prep_jid(nocache): # pylint: disable=unused-argument def prep_jid(nocache, passed_jid=None): # pylint: disable=unused-argument
''' '''
Pre-process the jid and return the jid to use Do any work necessary to prepare a JID, including sending a custom id
''' '''
return salt.utils.gen_jid() return passed_jid if passed_jid is not None else salt.utils.gen_jid()

View File

@ -157,8 +157,8 @@ def get_fun(fun):
return ret return ret
def prep_jid(nocache): # pylint: disable=unused-argument def prep_jid(nocache, passed_jid=None): # pylint: disable=unused-argument
''' '''
Pre-process the jid and return the jid to use Do any work necessary to prepare a JID, including sending a custom id
''' '''
return salt.utils.gen_jid() return passed_jid if passed_jid is not None else salt.utils.gen_jid()

View File

@ -30,7 +30,7 @@ def _mminion():
return MMINION return MMINION
def prep_jid(nocache=False): def prep_jid(nocache=False, passed_jid=None):
''' '''
Call both with prep_jid on all returners in multi_returner Call both with prep_jid on all returners in multi_returner
@ -41,7 +41,7 @@ def prep_jid(nocache=False):
returners is non-trivial returners is non-trivial
''' '''
jid = None jid = passed_jid
for returner in __opts__[CONFIG_KEY]: for returner in __opts__[CONFIG_KEY]:
if jid is None: if jid is None:
jid = _mminion().returners['{0}.prep_jid'.format(returner)](nocache=nocache) jid = _mminion().returners['{0}.prep_jid'.format(returner)](nocache=nocache)

View File

@ -85,6 +85,7 @@ import logging
# Import salt libs # Import salt libs
import salt.returners import salt.returners
import salt.utils
# Import third party libs # Import third party libs
try: try:
@ -148,7 +149,7 @@ def _get_serv(ret=None, commit=False):
try: try:
yield cursor yield cursor
except MySQLdb.DatabaseError as err: except MySQLdb.DatabaseError as err:
error, = err.args error = err.args
sys.stderr.write(str(error)) sys.stderr.write(str(error))
cursor.execute("ROLLBACK") cursor.execute("ROLLBACK")
raise err raise err
@ -196,13 +197,11 @@ def get_load(jid):
''' '''
with _get_serv(ret=None, commit=True) as cur: with _get_serv(ret=None, commit=True) as cur:
sql = '''SELECT load FROM `jids` sql = '''SELECT `load` FROM `jids` WHERE `jid` = %s;'''
WHERE `jid` = '%s';'''
cur.execute(sql, (jid,)) cur.execute(sql, (jid,))
data = cur.fetchone() data = cur.fetchone()
if data: if data:
return json.loads(data) return json.loads(data[0])
return {} return {}
@ -280,3 +279,10 @@ def get_minions():
for minion in data: for minion in data:
ret.append(minion[0]) ret.append(minion[0])
return ret return ret
def prep_jid(nocache, passed_jid=None): # pylint: disable=unused-argument
'''
Do any work necessary to prepare a JID, including sending a custom id
'''
return passed_jid if passed_jid is not None else salt.utils.gen_jid()

View File

@ -300,8 +300,8 @@ def get_minions():
return ret return ret
def prep_jid(nocache): # pylint: disable=unused-argument def prep_jid(nocache, passed_jid=None): # pylint: disable=unused-argument
''' '''
Do any jid pre-processing and return the jid to use Do any work necessary to prepare a JID, including sending a custom id
''' '''
return salt.utils.gen_jid() return passed_jid if passed_jid is not None else salt.utils.gen_jid()

View File

@ -272,8 +272,8 @@ def get_minions():
return ret return ret
def prep_jid(nocache): # pylint: disable=unused-argument def prep_jid(nocache, passed_jid=None): # pylint: disable=unused-argument
''' '''
Do any pre-processing necessary and return the jid to use Do any work necessary to prepare a JID, including sending a custom id
''' '''
return salt.utils.gen_jid() return passed_jid if passed_jid is not None else salt.utils.gen_jid()

View File

@ -162,8 +162,8 @@ def get_minions():
return list(serv.smembers('minions')) return list(serv.smembers('minions'))
def prep_jid(nocache): # pylint: disable=unused-argument def prep_jid(nocache, passed_jid=None): # pylint: disable=unused-argument
''' '''
Do any pre-processing necessary and return the jid to use Do any work necessary to prepare a JID, including sending a custom id
''' '''
return salt.utils.gen_jid() return passed_jid if passed_jid is not None else salt.utils.gen_jid()

View File

@ -111,8 +111,8 @@ def returner(ret):
) )
def prep_jid(nocache): # pylint: disable=unused-argument def prep_jid(nocache, passed_jid=None): # pylint: disable=unused-argument
''' '''
Do any necessary pre-processing and then return the jid to use Do any work necessary to prepare a JID, including sending a custom id
''' '''
return salt.utils.gen_jid() return passed_jid if passed_jid is not None else salt.utils.gen_jid()

View File

@ -0,0 +1,269 @@
# -*- coding: utf-8 -*-
'''
Return salt data via slack
.. versionadded:: Lithium
The following fields can be set in the minion conf file::
slack.channel (required)
slack.api_key (required)
slack.from_name (required)
slack.profile (optional)
Alternative configuration values can be used by prefacing the configuration.
Any values not found in the alternative configuration will be pulled from
the default location::
slack.channel
slack.api_key
slack.from_name
Hipchat settings may also be configured as::
slack:
channel: RoomName
api_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
from_name: user@email.com
alternative.slack:
room_id: RoomName
api_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
from_name: user@email.com
slack_profile:
api_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
from_name: user@email.com
slack:
profile: slack_profile
channel: RoomName
alternative.slack:
profile: slack_profile
channel: RoomName
To use the HipChat returner, append '--return slack' to the salt command. ex:
.. code-block:: bash
salt '*' test.ping --return slack
To use the alternative configuration, append '--return_config alternative' to the salt command. ex:
salt '*' test.ping --return slack --return_config alternative
'''
import salt.returners
import pprint
import requests
import logging
from urlparse import urljoin as _urljoin
from requests.exceptions import ConnectionError
log = logging.getLogger(__name__)
__virtualname__ = 'slack'
def _get_options(ret=None):
'''
Get the slack options from salt.
'''
defaults = {'channel': '#general'}
attrs = {'slack_profile': 'profile',
'channel': 'channel',
'from_name': 'from_name',
'api_key': 'api_key',
}
profile_attr = 'slack_profile'
profile_attrs = {'from_jid': 'from_jid',
'api_key': 'api_key',
'api_version': 'api_key'
}
_options = salt.returners.get_returner_options(__virtualname__,
ret,
attrs,
profile_attr=profile_attr,
profile_attrs=profile_attrs,
__salt__=__salt__,
__opts__=__opts__,
defaults=defaults)
return _options
def __virtual__():
'''
Return virtual name of the module.
:return: The virtual name of the module.
'''
return __virtualname__
def _query(function, api_key=None, method='GET', data=None):
'''
Slack object method function to construct and execute on the API URL.
:param api_key: The Slack api key.
:param function: The Slack api function to perform.
:param method: The HTTP method, e.g. GET or POST.
:param data: The data to be sent for POST method.
:return: The json response from the API call or False.
'''
headers = {}
query_params = {}
if data is None:
data = {}
ret = {'message': '',
'res': True}
slack_functions = {
'rooms': {
'request': 'channels.list',
'response': 'channels',
},
'users': {
'request': 'users.list',
'response': 'members',
},
'message': {
'request': 'chat.postMessage',
'response': 'channel',
},
}
if not api_key:
try:
options = __salt__['config.option']('slack')
if not api_key:
api_key = options.get('api_key')
except (NameError, KeyError, AttributeError):
log.error('No Slack api key found.')
ret['message'] = 'No Slack api key found.'
ret['res'] = False
return ret
api_url = 'https://slack.com'
base_url = _urljoin(api_url, '/api/')
path = slack_functions.get(function).get('request')
url = _urljoin(base_url, path, False)
query_params['token'] = api_key
try:
result = requests.request(
method=method,
url=url,
headers=headers,
params=query_params,
data=data,
verify=True,
)
except ConnectionError as e:
ret['message'] = e
ret['res'] = False
return ret
if result.status_code == 200:
result = result.json()
response = slack_functions.get(function).get('response')
if 'error' in result:
ret['message'] = result['error']
ret['res'] = False
return ret
ret['message'] = result.get(response)
return ret
elif result.status_code == 204:
return True
else:
log.debug(url)
log.debug(query_params)
log.debug(data)
log.debug(result)
if 'error' in result:
ret['message'] = result['error']
ret['res'] = False
return ret
ret['message'] = result
return ret
def _post_message(channel,
message,
from_name,
api_key=None):
'''
Send a message to a HipChat room.
:param room_id: The room id or room name, either will work.
:param message: The message to send to the HipChat room.
:param from_name: Specify who the message is from.
:param api_key: The HipChat api key, if not specified in the configuration.
:param api_version: The HipChat api version, if not specified in the configuration.
:param color: The color for the message, default: yellow.
:param notify: Whether to notify the room, default: False.
:return: Boolean if message was sent successfully.
'''
parameters = dict()
parameters['channel'] = channel
parameters['from'] = from_name
parameters['text'] = message
result = _query(function='message',
api_key=api_key,
method='POST',
data=parameters)
log.debug('result {0}'.format(result))
if result:
return True
else:
return False
def returner(ret):
'''
Send an slack message with the data
'''
_options = _get_options(ret)
channel = _options.get('channel')
from_name = _options.get('from_name')
api_key = _options.get('api_key')
if not channel:
log.error('slack.channel not defined in salt config')
return
if not from_name:
log.error('slack.from_name not defined in salt config')
return
if not api_key:
log.error('slack.api_key not defined in salt config')
return
message = ('id: {0}\r\n'
'function: {1}\r\n'
'function args: {2}\r\n'
'jid: {3}\r\n'
'return: {4}\r\n').format(
ret.get('id'),
ret.get('fun'),
ret.get('fun_args'),
ret.get('jid'),
pprint.pformat(ret.get('return')))
slack = _post_message(channel,
message,
channel,
api_key)
return slack

View File

@ -183,8 +183,8 @@ def returner(ret):
server.quit() server.quit()
def prep_jid(nocache): # pylint: disable=unused-argument def prep_jid(nocache, passed_jid=None): # pylint: disable=unused-argument
''' '''
Do any necessary pre-processing and return the jid to use Do any work necessary to prepare a JID, including sending a custom id
''' '''
return salt.utils.gen_jid() return passed_jid if passed_jid is not None else salt.utils.gen_jid()

View File

@ -271,8 +271,8 @@ def get_minions():
return ret return ret
def prep_jid(nocache): # pylint: disable=unused-argument def prep_jid(nocache, passed_jid=None): # pylint: disable=unused-argument
''' '''
Do any necessary pre-processing and then return the jid to use Do any work necessary to prepare a JID, including sending a custom id
''' '''
return salt.utils.gen_jid() return passed_jid if passed_jid is not None else salt.utils.gen_jid()

View File

@ -41,8 +41,8 @@ def returner(ret):
syslog.syslog(syslog.LOG_INFO, 'salt-minion: {0}'.format(json.dumps(ret))) syslog.syslog(syslog.LOG_INFO, 'salt-minion: {0}'.format(json.dumps(ret)))
def prep_jid(nocache): # pylint: disable=unused-argument def prep_jid(nocache, passed_jid=None): # pylint: disable=unused-argument
''' '''
Do any necessary pre-preocessing and then return the jid to use Do any work necessary to prepare a JID, including sending a custom id
''' '''
return salt.utils.gen_jid() return passed_jid if passed_jid is not None else salt.utils.gen_jid()

View File

@ -74,7 +74,7 @@ def lookup_jid(jid, ext_source=None, missing=False, outputter=None):
try: try:
data = mminion.returners['{0}.get_jid'.format(returner)](jid) data = mminion.returners['{0}.get_jid'.format(returner)](jid)
except TypeError: except TypeError:
print 'Requested returner could not be loaded. No JIDs could be retreived.' print 'Requested returner could not be loaded. No JIDs could be retrieved.'
return return
for minion in data: for minion in data:
if u'return' in data[minion]: if u'return' in data[minion]:
@ -132,7 +132,7 @@ def list_jobs(ext_source=None,
try: try:
ret = mminion.returners['{0}.get_jids'.format(returner)]() ret = mminion.returners['{0}.get_jids'.format(returner)]()
except TypeError: except TypeError:
print 'Error: Requested returner could not be loaded. No jobs could be retreived.' print 'Error: Requested returner could not be loaded. No jobs could be retrieved.'
return return
if search_metadata: if search_metadata:
@ -200,8 +200,8 @@ def print_job(jid, ext_source=None, outputter=None):
job = mminion.returners['{0}.get_load'.format(returner)](jid) job = mminion.returners['{0}.get_load'.format(returner)](jid)
ret[jid] = _format_jid_instance(jid, job) ret[jid] = _format_jid_instance(jid, job)
except TypeError: except TypeError:
ret[jid]['Result'] = 'Requested returner {0} is not available. Jobs cannot be retreived. ' ret[jid]['Result'] = ('Requested returner {0} is not available. Jobs cannot be retrieved. '
'Check master log for details.'.format(returner) 'Check master log for details.'.format(returner))
return ret return ret
ret[jid]['Result'] = mminion.returners['{0}.get_jid'.format(returner)](jid) ret[jid]['Result'] = mminion.returners['{0}.get_jid'.format(returner)](jid)
salt.output.display_output(ret, outputter, opts=__opts__) salt.output.display_output(ret, outputter, opts=__opts__)

View File

@ -20,7 +20,7 @@ def __virtual__():
return 'at.at' in __salt__ return 'at.at' in __salt__
def present(name, timespec, tag=None, runas=None, user=None, job=None): def present(name, timespec, tag=None, user=None, job=None):
''' '''
Add a job to queue. Add a job to queue.
@ -33,11 +33,6 @@ def present(name, timespec, tag=None, runas=None, user=None, job=None):
tag tag
Make a tag for the job. Make a tag for the job.
runas
Users run the job.
.. deprecated:: 2014.1.4
user user
The user to run the at job The user to run the at job
@ -48,7 +43,7 @@ def present(name, timespec, tag=None, runas=None, user=None, job=None):
rose: rose:
at.present: at.present:
- job: 'echo "I love saltstack" > love' - job: 'echo "I love saltstack" > love'
- timespec: '9:9 11/09/13' - timespec: '9:09 11/09/13'
- tag: love - tag: love
- user: jam - user: jam
@ -61,30 +56,6 @@ def present(name, timespec, tag=None, runas=None, user=None, job=None):
'comment': 'job {0} is add and will run on {1}'.format(name, 'comment': 'job {0} is add and will run on {1}'.format(name,
timespec)} timespec)}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 2014.1.4. Support will be removed in {version}.',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
binary = salt.utils.which('at') binary = salt.utils.which('at')
if __opts__['test']: if __opts__['test']:

View File

@ -202,49 +202,3 @@ def change(name, context=None, changes=None, lens=None, **kwargs):
ret['changes'] = changes ret['changes'] = changes
return ret return ret
def setvalue(name, prefix=None, changes=None, **kwargs):
'''
.. deprecated:: 2014.7.0
Use :py:func:`~salt.states.augeas.change` instead.
Set a value for a specific augeas path
'''
ret = {'name': name, 'result': False, 'comment': '', 'changes': {}}
args = []
if not changes:
ret['comment'] = '\'changes\' must be specified'
return ret
else:
if not isinstance(changes, list):
ret['comment'] = '\'changes\' must be formatted as a list'
return ret
for change_ in changes:
if not isinstance(change_, dict) or len(change_) > 1:
ret['comment'] = 'Invalidly-formatted change'
return ret
key = next(iter(change_))
args.extend([key, change_[key]])
if prefix is not None:
args.insert(0, 'prefix={0}'.format(prefix))
if __opts__['test']:
ret['result'] = None
ret['comment'] = 'Calling setvalue with {0}'.format(args)
return ret
call = __salt__['augeas.setvalue'](*args)
ret['result'] = call['retval']
if ret['result'] is False:
ret['comment'] = 'Error: {0}'.format(call['error'])
return ret
ret['comment'] = 'Success'
for change_ in changes:
ret['changes'].update(change_)
return ret

View File

@ -39,7 +39,6 @@ the location of composer in the state.
''' '''
# Import salt libs # Import salt libs
import salt.utils
from salt.exceptions import CommandExecutionError, CommandNotFoundError from salt.exceptions import CommandExecutionError, CommandNotFoundError
@ -53,7 +52,6 @@ def __virtual__():
def installed(name, def installed(name,
composer=None, composer=None,
php=None, php=None,
runas=None,
user=None, user=None,
prefer_source=None, prefer_source=None,
prefer_dist=None, prefer_dist=None,
@ -78,11 +76,6 @@ def installed(name,
Location of the php executable to use with composer. Location of the php executable to use with composer.
(i.e. /usr/bin/php) (i.e. /usr/bin/php)
runas
Which system user to run composer as.
.. deprecated:: 2014.1.4
user user
Which system user to run composer as. Which system user to run composer as.
@ -114,30 +107,6 @@ def installed(name,
''' '''
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}} ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 2014.1.4.',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
try: try:
call = __salt__['composer.install']( call = __salt__['composer.install'](
name, name,

View File

@ -2288,7 +2288,8 @@ def replace(name,
.. versionadded:: 0.17.0 .. versionadded:: 0.17.0
Params are identical to :py:func:`~salt.modules.file.replace`. Params are identical to the remote execution function :mod:`file.replace
<salt.modules.file.replace>`.
''' '''
name = os.path.expanduser(name) name = os.path.expanduser(name)
@ -2484,138 +2485,6 @@ def blockreplace(
return ret return ret
def sed(name,
before,
after,
limit='',
backup='.bak',
options='-r -e',
flags='g',
negate_match=False):
'''
.. deprecated:: 0.17.0
Use :py:func:`~salt.states.file.replace` instead.
Maintain a simple edit to a file
The file will be searched for the ``before`` pattern before making the
edit. In general the ``limit`` pattern should be as specific as possible
and ``before`` and ``after`` should contain the minimal text to be changed.
before
A pattern that should exist in the file before the edit.
after
A pattern that should exist in the file after the edit.
limit
An optional second pattern that can limit the scope of the before
pattern.
backup : '.bak'
The extension for the backed-up version of the file before the edit. If
no backups is desired, pass in the empty string: ''
options : ``-r -e``
Any options to pass to the ``sed`` command. ``-r`` uses extended
regular expression syntax and ``-e`` denotes that what follows is an
expression that sed will execute.
flags : ``g``
Any flags to append to the sed expression. ``g`` specifies the edit
should be made globally (and not stop after the first replacement).
negate_match : False
Negate the search command (``!``)
.. versionadded:: 0.17.0
Usage:
.. code-block:: yaml
# Disable the epel repo by default
/etc/yum.repos.d/epel.repo:
file.sed:
- before: 1
- after: 0
- limit: ^enabled=
# Remove ldap from nsswitch
/etc/nsswitch.conf:
file.sed:
- before: 'ldap'
- after: ''
- limit: '^passwd:'
.. versionadded:: 0.9.5
'''
name = os.path.expanduser(name)
ret = {'name': name, 'changes': {}, 'result': False, 'comment': ''}
check_res, check_msg = _check_file(name)
if not check_res:
return _error(ret, check_msg)
# Mandate that before and after are strings
before = str(before)
after = str(after)
# Look for the pattern before attempting the edit
if not __salt__['file.sed_contains'](name,
before,
limit=limit,
flags=flags):
# Pattern not found; don't try to guess why, just tell the user there
# were no changes made, as the changes should only be made once anyway.
# This makes it so users can use backreferences without the state
# coming back as failed all the time.
ret['comment'] = '"before" pattern not found, no changes made'
ret['result'] = True
return ret
if __opts__['test']:
ret['comment'] = 'File {0} is set to be updated'.format(name)
ret['result'] = None
return ret
with salt.utils.fopen(name, 'rb') as fp_:
slines = fp_.readlines()
# should be ok now; perform the edit
retcode = __salt__['file.sed'](path=name,
before=before,
after=after,
limit=limit,
backup=backup,
options=options,
flags=flags,
negate_match=negate_match)['retcode']
if retcode != 0:
ret['result'] = False
ret['comment'] = ('There was an error running sed. '
'Return code {0}').format(retcode)
return ret
with salt.utils.fopen(name, 'rb') as fp_:
nlines = fp_.readlines()
if slines != nlines:
if not salt.utils.istextfile(name):
ret['changes']['diff'] = 'Replace binary file'
else:
# Changes happened, add them
ret['changes']['diff'] = ''.join(difflib.unified_diff(slines,
nlines))
# Don't check the result -- sed is not designed to be able to check
# the result, because of backreferences and so forth. Just report
# that sed was run, and assume it was successful (no error!)
ret['result'] = True
ret['comment'] = 'sed ran without error'
else:
ret['result'] = True
ret['comment'] = 'sed ran without error, but no changes were made'
return ret
def comment(name, regex, char='#', backup='.bak'): def comment(name, regex, char='#', backup='.bak'):
''' '''
Comment out specified lines in a file. Comment out specified lines in a file.

View File

@ -15,9 +15,6 @@ you can specify what ruby version and gemset to target.
- ruby: jruby@jgemset - ruby: jruby@jgemset
''' '''
# Import salt libs
import salt.utils
def __virtual__(): def __virtual__():
''' '''
@ -28,7 +25,6 @@ def __virtual__():
def installed(name, # pylint: disable=C0103 def installed(name, # pylint: disable=C0103
ruby=None, ruby=None,
runas=None,
user=None, user=None,
version=None, version=None,
rdoc=False, rdoc=False,
@ -44,11 +40,6 @@ def installed(name, # pylint: disable=C0103
ruby: None ruby: None
For RVM or rbenv installations: the ruby version and gemset to target. For RVM or rbenv installations: the ruby version and gemset to target.
runas: None
The user under which to run the ``gem`` command
.. deprecated:: 0.17.0
user: None user: None
The user under which to run the ``gem`` command The user under which to run the ``gem`` command
@ -72,31 +63,6 @@ def installed(name, # pylint: disable=C0103
Format: http://hostname[:port] Format: http://hostname[:port]
''' '''
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}} ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
gems = __salt__['gem.list'](name, ruby, runas=user) gems = __salt__['gem.list'](name, ruby, runas=user)
if name in gems and version is not None and version in gems[name]: if name in gems and version is not None and version in gems[name]:
ret['result'] = True ret['result'] = True
@ -128,7 +94,7 @@ def installed(name, # pylint: disable=C0103
return ret return ret
def removed(name, ruby=None, runas=None, user=None): def removed(name, ruby=None, user=None):
''' '''
Make sure that a gem is not installed. Make sure that a gem is not installed.
@ -138,11 +104,6 @@ def removed(name, ruby=None, runas=None, user=None):
ruby: None ruby: None
For RVM or rbenv installations: the ruby version and gemset to target. For RVM or rbenv installations: the ruby version and gemset to target.
runas: None
The user under which to run the ``gem`` command
.. deprecated:: 0.17.0
user: None user: None
The user under which to run the ``gem`` command The user under which to run the ``gem`` command
@ -150,30 +111,6 @@ def removed(name, ruby=None, runas=None, user=None):
''' '''
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}} ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
if name not in __salt__['gem.list'](name, ruby, runas=user): if name not in __salt__['gem.list'](name, ruby, runas=user):
ret['result'] = True ret['result'] = True
ret['comment'] = 'Gem is not installed.' ret['comment'] = 'Gem is not installed.'

View File

@ -22,7 +22,6 @@ import os.path
import shutil import shutil
# Import salt libs # Import salt libs
import salt.utils
from salt.exceptions import CommandExecutionError from salt.exceptions import CommandExecutionError
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -38,7 +37,6 @@ def __virtual__():
def latest(name, def latest(name,
rev=None, rev=None,
target=None, target=None,
runas=None,
user=None, user=None,
force=None, force=None,
force_checkout=False, force_checkout=False,
@ -64,11 +62,6 @@ def latest(name,
target target
Name of the target directory where repository is about to be cloned Name of the target directory where repository is about to be cloned
runas
Name of the user performing repository management operations
.. deprecated:: 0.17.0
user user
Name of the user performing repository management operations Name of the user performing repository management operations
@ -162,30 +155,6 @@ def latest(name,
return _fail(ret, '"target" option is required') return _fail(ret, '"target" option is required')
target = os.path.expanduser(target) target = os.path.expanduser(target)
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
run_check_cmd_kwargs = {'runas': user} run_check_cmd_kwargs = {'runas': user}
if 'shell' in __grains__: if 'shell' in __grains__:
run_check_cmd_kwargs['shell'] = __grains__['shell'] run_check_cmd_kwargs['shell'] = __grains__['shell']
@ -405,7 +374,7 @@ def latest(name,
return ret return ret
def present(name, bare=True, runas=None, user=None, force=False): def present(name, bare=True, user=None, force=False):
''' '''
Make sure the repository is present in the given directory Make sure the repository is present in the given directory
@ -415,11 +384,6 @@ def present(name, bare=True, runas=None, user=None, force=False):
bare bare
Create a bare repository (Default: True) Create a bare repository (Default: True)
runas
Name of the user performing repository management operations
.. deprecated:: 0.17.0
user user
Name of the user performing repository management operations Name of the user performing repository management operations
@ -432,30 +396,6 @@ def present(name, bare=True, runas=None, user=None, force=False):
name = os.path.expanduser(name) name = os.path.expanduser(name)
ret = {'name': name, 'result': True, 'comment': '', 'changes': {}} ret = {'name': name, 'result': True, 'comment': '', 'changes': {}}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
# If the named directory is a git repo return True # If the named directory is a git repo return True
if os.path.isdir(name): if os.path.isdir(name):
if bare and os.path.isfile(os.path.join(name, 'HEAD')): if bare and os.path.isfile(os.path.join(name, 'HEAD')):

View File

@ -42,7 +42,6 @@ def latest(name,
rev=None, rev=None,
target=None, target=None,
clean=False, clean=False,
runas=None,
user=None, user=None,
force=False, force=False,
opts=False): opts=False):
@ -61,11 +60,6 @@ def latest(name,
clean clean
Force a clean update with -C (Default: False) Force a clean update with -C (Default: False)
runas
Name of the user performing repository management operations
.. deprecated:: 0.17.0
user user
Name of the user performing repository management operations Name of the user performing repository management operations
@ -79,30 +73,6 @@ def latest(name,
''' '''
ret = {'name': name, 'result': True, 'comment': '', 'changes': {}} ret = {'name': name, 'result': True, 'comment': '', 'changes': {}}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
if not target: if not target:
return _fail(ret, '"target option is required') return _fail(ret, '"target option is required')

View File

@ -338,6 +338,14 @@ def append(name, family='ipv4', **kwargs):
name, name,
command.strip(), command.strip(),
family) family)
if kwargs['save']:
if kwargs['save'] is not True:
filename = kwargs['save']
else:
filename = None
__salt__['iptables.save'](filename, family=family)
ret['comment'] += ('\nSaved iptables rule for {0} to: '
'{1} for {2}'.format(name, command.strip(), family))
return ret return ret
if __opts__['test']: if __opts__['test']:
ret['comment'] = 'iptables rule for {0} needs to be set ({1}) for {2}'.format( ret['comment'] = 'iptables rule for {0} needs to be set ({1}) for {2}'.format(
@ -409,6 +417,11 @@ def insert(name, family='ipv4', **kwargs):
name, name,
family, family,
command.strip()) command.strip())
if 'save' in kwargs:
if kwargs['save']:
__salt__['iptables.save'](filename=None, family=family)
ret['comment'] += ('\nSaved iptables rule for {0} to: '
'{1} for {2}').format(name, command.strip(), family)
return ret return ret
if __opts__['test']: if __opts__['test']:
ret['comment'] = 'iptables rule for {0} needs to be set for {1} ({2})'.format( ret['comment'] = 'iptables rule for {0} needs to be set for {1} ({2})'.format(

View File

@ -129,7 +129,6 @@ def run(name, **kwargs):
return ret return ret
aspec = salt.utils.get_function_argspec(__salt__[name]) aspec = salt.utils.get_function_argspec(__salt__[name])
args = [] args = []
defaults = {} defaults = {}

View File

@ -20,7 +20,6 @@ for the package which provides npm (simply ``npm`` in most cases). Example:
''' '''
# Import salt libs # Import salt libs
import salt.utils
from salt.exceptions import CommandExecutionError, CommandNotFoundError from salt.exceptions import CommandExecutionError, CommandNotFoundError
@ -34,7 +33,6 @@ def __virtual__():
def installed(name, def installed(name,
pkgs=None, pkgs=None,
dir=None, dir=None,
runas=None,
user=None, user=None,
force_reinstall=False, force_reinstall=False,
registry=None, registry=None,
@ -67,11 +65,6 @@ def installed(name,
The target directory in which to install the package, or None for The target directory in which to install the package, or None for
global installation global installation
runas
The user to run NPM with
.. deprecated:: 0.17.0
user user
The user to run NPM with The user to run NPM with
@ -94,37 +87,13 @@ def installed(name,
''' '''
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}} ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
if pkgs is not None: if pkgs is not None:
pkg_list = pkgs pkg_list = pkgs
else: else:
pkg_list = [name] pkg_list = [name]
try: try:
installed_pkgs = __salt__['npm.list'](dir=dir, runas=runas, env=env) installed_pkgs = __salt__['npm.list'](dir=dir, runas=user, env=env)
except (CommandNotFoundError, CommandExecutionError) as err: except (CommandNotFoundError, CommandExecutionError) as err:
ret['result'] = False ret['result'] = False
ret['comment'] = 'Error looking up {0!r}: {1}'.format(name, err) ret['comment'] = 'Error looking up {0!r}: {1}'.format(name, err)
@ -221,7 +190,6 @@ def installed(name,
def removed(name, def removed(name,
dir=None, dir=None,
runas=None,
user=None): user=None):
''' '''
Verify that the given package is not installed. Verify that the given package is not installed.
@ -230,11 +198,6 @@ def removed(name,
The target directory in which to install the package, or None for The target directory in which to install the package, or None for
global installation global installation
runas
The user to run NPM with
.. deprecated:: 0.17.0
user user
The user to run NPM with The user to run NPM with
@ -242,30 +205,6 @@ def removed(name,
''' '''
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}} ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
try: try:
installed_pkgs = __salt__['npm.list'](dir=dir) installed_pkgs = __salt__['npm.list'](dir=dir)
except (CommandExecutionError, CommandNotFoundError) as err: except (CommandExecutionError, CommandNotFoundError) as err:
@ -295,50 +234,18 @@ def removed(name,
def bootstrap(name, def bootstrap(name,
runas=None,
user=None): user=None):
''' '''
Bootstraps a node.js application. Bootstraps a node.js application.
will execute npm install --json on the specified directory Will execute 'npm install --json' on the specified directory.
runas
The user to run NPM with
.. deprecated:: 0.17.0
user user
The user to run NPM with The user to run NPM with
.. versionadded:: 0.17.0 .. versionadded:: 0.17.0
''' '''
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}} ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
try: try:
call = __salt__['npm.install'](dir=name, runas=user, pkg=None) call = __salt__['npm.install'](dir=name, runas=user, pkg=None)

View File

@ -130,6 +130,7 @@ def installed(name,
allow_external=None, allow_external=None,
allow_unverified=None, allow_unverified=None,
process_dependency_links=False, process_dependency_links=False,
env_vars=None,
use_vt=False): use_vt=False):
''' '''
Make sure the package is installed Make sure the package is installed
@ -267,6 +268,11 @@ def installed(name,
a pip executable. The example below assumes a virtual environment a pip executable. The example below assumes a virtual environment
has been created at ``/foo/.virtualenvs/bar``. has been created at ``/foo/.virtualenvs/bar``.
env_vars
Add or modify environment variables. Useful for tweaking build steps,
such as specifying INCLUDE or LIBRARY paths in Makefiles, build scripts or
compiler calls.
use_vt use_vt
Use VT terminal emulation (see ouptut while installing) Use VT terminal emulation (see ouptut while installing)
@ -554,6 +560,7 @@ def installed(name,
allow_unverified=allow_unverified, allow_unverified=allow_unverified,
process_dependency_links=process_dependency_links, process_dependency_links=process_dependency_links,
saltenv=__env__, saltenv=__env__,
env_vars=env_vars,
use_vt=use_vt use_vt=use_vt
) )

View File

@ -30,7 +30,6 @@ def present(name,
lc_ctype=None, lc_ctype=None,
owner=None, owner=None,
template=None, template=None,
runas=None,
user=None, user=None,
maintenance_db=None, maintenance_db=None,
db_password=None, db_password=None,
@ -62,11 +61,6 @@ def present(name,
template template
The template database from which to build this database The template database from which to build this database
runas
System user all operations should be performed on behalf of
.. deprecated:: 0.17.0
user user
System user all operations should be performed on behalf of System user all operations should be performed on behalf of
@ -95,23 +89,6 @@ def present(name,
'added in 0.17.0', 'added in 0.17.0',
_dont_call_warnings=True _dont_call_warnings=True
) )
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
db_args = { db_args = {
'maintenance_db': maintenance_db, 'maintenance_db': maintenance_db,
@ -188,7 +165,6 @@ def present(name,
def absent(name, def absent(name,
runas=None,
user=None, user=None,
maintenance_db=None, maintenance_db=None,
db_password=None, db_password=None,
@ -213,11 +189,6 @@ def absent(name,
db_port db_port
Database port if different from config or default Database port if different from config or default
runas
System user all operations should be performed on behalf of
.. deprecated:: 0.17.0
user user
System user all operations should be performed on behalf of System user all operations should be performed on behalf of
@ -227,29 +198,6 @@ def absent(name,
'changes': {}, 'changes': {},
'result': True, 'result': True,
'comment': ''} 'comment': ''}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
db_args = { db_args = {
'maintenance_db': maintenance_db, 'maintenance_db': maintenance_db,

View File

@ -14,7 +14,6 @@ The postgres_group module is used to create and manage Postgres groups.
# Import Python libs # Import Python libs
# Import salt libs # Import salt libs
import salt.utils
import logging import logging
# Salt imports # Salt imports
@ -43,7 +42,6 @@ def present(name,
password=None, password=None,
refresh_password=None, refresh_password=None,
groups=None, groups=None,
runas=None,
user=None, user=None,
maintenance_db=None, maintenance_db=None,
db_password=None, db_password=None,
@ -109,11 +107,6 @@ def present(name,
groups groups
A string of comma separated groups the group should be in A string of comma separated groups the group should be in
runas
System user all operations should be performed on behalf of
.. deprecated:: 0.17.0
user user
System user all operations should be performed on behalf of System user all operations should be performed on behalf of
@ -136,12 +129,6 @@ def present(name,
'result': True, 'result': True,
'comment': 'Group {0} is already present'.format(name)} 'comment': 'Group {0} is already present'.format(name)}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if createuser: if createuser:
createroles = True createroles = True
# default to encrypted passwords # default to encrypted passwords
@ -151,24 +138,6 @@ def present(name,
password = postgres._maybe_encrypt_password(name, password = postgres._maybe_encrypt_password(name,
password, password,
encrypted=encrypted) encrypted=encrypted)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
db_args = { db_args = {
'maintenance_db': maintenance_db, 'maintenance_db': maintenance_db,
'runas': user, 'runas': user,
@ -250,7 +219,6 @@ def present(name,
def absent(name, def absent(name,
runas=None,
user=None, user=None,
maintenance_db=None, maintenance_db=None,
db_password=None, db_password=None,
@ -263,11 +231,6 @@ def absent(name,
name name
The groupname of the group to remove The groupname of the group to remove
runas
System user all operations should be performed on behalf of
.. deprecated:: 0.17.0
user user
System user all operations should be performed on behalf of System user all operations should be performed on behalf of
@ -290,30 +253,6 @@ def absent(name,
'result': True, 'result': True,
'comment': ''} 'comment': ''}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
db_args = { db_args = {
'maintenance_db': maintenance_db, 'maintenance_db': maintenance_db,
'runas': user, 'runas': user,

View File

@ -14,7 +14,6 @@ The postgres_users module is used to create and manage Postgres users.
# Import Python libs # Import Python libs
# Import salt libs # Import salt libs
import salt.utils
import logging import logging
# Salt imports # Salt imports
@ -43,7 +42,6 @@ def present(name,
password=None, password=None,
refresh_password=None, refresh_password=None,
groups=None, groups=None,
runas=None,
user=None, user=None,
maintenance_db=None, maintenance_db=None,
db_password=None, db_password=None,
@ -108,11 +106,6 @@ def present(name,
groups groups
A string of comma separated groups the user should be in A string of comma separated groups the user should be in
runas
System user all operations should be performed on behalf of
.. deprecated:: 0.17.0
user user
System user all operations should be performed on behalf of System user all operations should be performed on behalf of
@ -135,12 +128,6 @@ def present(name,
'result': True, 'result': True,
'comment': 'User {0} is already present'.format(name)} 'comment': 'User {0} is already present'.format(name)}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if createuser: if createuser:
createroles = True createroles = True
# default to encrypted passwords # default to encrypted passwords
@ -151,24 +138,6 @@ def present(name,
password, password,
encrypted=encrypted) encrypted=encrypted)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
db_args = { db_args = {
'maintenance_db': maintenance_db, 'maintenance_db': maintenance_db,
'runas': user, 'runas': user,
@ -254,7 +223,6 @@ def present(name,
def absent(name, def absent(name,
runas=None,
user=None, user=None,
maintenance_db=None, maintenance_db=None,
db_password=None, db_password=None,
@ -267,11 +235,6 @@ def absent(name,
name name
The username of the user to remove The username of the user to remove
runas
System user all operations should be performed on behalf of
.. deprecated:: 0.17.0
user user
System user all operations should be performed on behalf of System user all operations should be performed on behalf of
@ -294,30 +257,6 @@ def absent(name,
'result': True, 'result': True,
'comment': ''} 'comment': ''}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
db_args = { db_args = {
'maintenance_db': maintenance_db, 'maintenance_db': maintenance_db,
'runas': user, 'runas': user,

View File

@ -48,9 +48,6 @@ This is how a state configuration could look like:
# Import python libs # Import python libs
import re import re
# Import salt libs
import salt.utils
def _check_pyenv(ret, user=None): def _check_pyenv(ret, user=None):
''' '''
@ -99,7 +96,7 @@ def _check_and_install_python(ret, python, default=False, user=None):
return ret return ret
def installed(name, default=False, runas=None, user=None): def installed(name, default=False, user=None):
''' '''
Verify that the specified python is installed with pyenv. pyenv is Verify that the specified python is installed with pyenv. pyenv is
installed if necessary. installed if necessary.
@ -110,11 +107,6 @@ def installed(name, default=False, runas=None, user=None):
default : False default : False
Whether to make this python the default. Whether to make this python the default.
runas: None
The user to run pyenv as.
.. deprecated:: 0.17.0
user: None user: None
The user to run pyenv as. The user to run pyenv as.
@ -124,18 +116,6 @@ def installed(name, default=False, runas=None, user=None):
''' '''
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}} ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
if name.startswith('python-'): if name.startswith('python-'):
name = re.sub(r'^python-', '', name) name = re.sub(r'^python-', '', name)
@ -179,7 +159,7 @@ def _check_and_uninstall_python(ret, python, user=None):
return ret return ret
def absent(name, runas=None, user=None): def absent(name, user=None):
''' '''
Verify that the specified python is not installed with pyenv. pyenv Verify that the specified python is not installed with pyenv. pyenv
is installed if necessary. is installed if necessary.
@ -187,11 +167,6 @@ def absent(name, runas=None, user=None):
name name
The version of python to uninstall The version of python to uninstall
runas: None
The user to run pyenv as.
.. deprecated:: 0.17.0
user: None user: None
The user to run pyenv as. The user to run pyenv as.
@ -201,30 +176,6 @@ def absent(name, runas=None, user=None):
''' '''
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}} ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
salt.utils.warn_until(
'Hydrogen',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
if name.startswith('python-'): if name.startswith('python-'):
name = re.sub(r'^python-', '', name) name = re.sub(r'^python-', '', name)

View File

@ -45,9 +45,6 @@ This is how a state configuration could look like:
import re import re
import copy import copy
# Import salt libs
import salt.utils
def _check_rbenv(ret, user=None): def _check_rbenv(ret, user=None):
''' '''
@ -96,7 +93,7 @@ def _check_and_install_ruby(ret, ruby, default=False, user=None):
return ret return ret
def installed(name, default=False, runas=None, user=None): def installed(name, default=False, user=None):
''' '''
Verify that the specified ruby is installed with rbenv. Rbenv is Verify that the specified ruby is installed with rbenv. Rbenv is
installed if necessary. installed if necessary.
@ -107,11 +104,6 @@ def installed(name, default=False, runas=None, user=None):
default : False default : False
Whether to make this ruby the default. Whether to make this ruby the default.
runas: None
The user to run rbenv as.
.. deprecated:: 0.17.0
user: None user: None
The user to run rbenv as. The user to run rbenv as.
@ -122,30 +114,6 @@ def installed(name, default=False, runas=None, user=None):
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}} ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
rbenv_installed_ret = copy.deepcopy(ret) rbenv_installed_ret = copy.deepcopy(ret)
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
if name.startswith('ruby-'): if name.startswith('ruby-'):
name = re.sub(r'^ruby-', '', name) name = re.sub(r'^ruby-', '', name)
@ -187,7 +155,7 @@ def _check_and_uninstall_ruby(ret, ruby, user=None):
return ret return ret
def absent(name, runas=None, user=None): def absent(name, user=None):
''' '''
Verify that the specified ruby is not installed with rbenv. Rbenv Verify that the specified ruby is not installed with rbenv. Rbenv
is installed if necessary. is installed if necessary.
@ -195,11 +163,6 @@ def absent(name, runas=None, user=None):
name name
The version of ruby to uninstall The version of ruby to uninstall
runas: None
The user to run rbenv as.
.. deprecated:: 0.17.0
user: None user: None
The user to run rbenv as. The user to run rbenv as.
@ -209,30 +172,6 @@ def absent(name, runas=None, user=None):
''' '''
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}} ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
if name.startswith('ruby-'): if name.startswith('ruby-'):
name = re.sub(r'^ruby-', '', name) name = re.sub(r'^ruby-', '', name)

View File

@ -105,9 +105,6 @@ configuration could look like:
# Import python libs # Import python libs
import re import re
# Import salt libs
import salt.utils
def _check_rvm(ret, user=None): def _check_rvm(ret, user=None):
''' '''
@ -169,7 +166,7 @@ def _check_ruby(ret, ruby, user=None):
return ret return ret
def installed(name, default=False, runas=None, user=None): def installed(name, default=False, user=None):
''' '''
Verify that the specified ruby is installed with RVM. RVM is Verify that the specified ruby is installed with RVM. RVM is
installed when necessary. installed when necessary.
@ -180,11 +177,6 @@ def installed(name, default=False, runas=None, user=None):
default : False default : False
Whether to make this ruby the default. Whether to make this ruby the default.
runas: None
The user to run rvm as.
.. deprecated:: 0.17.0
user: None user: None
The user to run rvm as. The user to run rvm as.
@ -192,30 +184,6 @@ def installed(name, default=False, runas=None, user=None):
''' '''
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}} ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
if __opts__['test']: if __opts__['test']:
ret['comment'] = 'Ruby {0} is set to be installed'.format(name) ret['comment'] = 'Ruby {0} is set to be installed'.format(name)
return ret return ret
@ -231,7 +199,7 @@ def installed(name, default=False, runas=None, user=None):
return _check_and_install_ruby(ret, name, default, user=user) return _check_and_install_ruby(ret, name, default, user=user)
def gemset_present(name, ruby='default', runas=None, user=None): def gemset_present(name, ruby='default', user=None):
''' '''
Verify that the gemset is present. Verify that the gemset is present.
@ -241,11 +209,6 @@ def gemset_present(name, ruby='default', runas=None, user=None):
ruby: default ruby: default
The ruby version this gemset belongs to. The ruby version this gemset belongs to.
runas: None
The user to run rvm as.
.. deprecated:: 0.17.0
user: None user: None
The user to run rvm as. The user to run rvm as.
@ -253,30 +216,6 @@ def gemset_present(name, ruby='default', runas=None, user=None):
''' '''
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}} ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
ret = _check_rvm(ret, user) ret = _check_rvm(ret, user)
if ret['result'] is False: if ret['result'] is False:
return ret return ret

108
salt/states/slack.py Normal file
View File

@ -0,0 +1,108 @@
# -*- coding: utf-8 -*-
'''
Send a message to Slack
=========================
This state is useful for sending messages to Slack during state runs.
.. versionadded:: Lithium
.. code-block:: yaml
slack-message:
slack.send_message:
- channel: '#general'
- from_name: SuperAdmin
- message: 'This state was executed successfully.'
- api_key: peWcBiMOS9HrZG15peWcBiMOS9HrZG15
The api key can be specified in the master or minion configuration like below:
.. code-block:: yaml
slack:
api_key: peWcBiMOS9HrZG15peWcBiMOS9HrZG15
'''
def __virtual__():
'''
Only load if the slack module is available in __salt__
'''
return 'slack' if 'slack.post_message' in __salt__ else False
def post_message(name,
channel,
from_name,
message,
api_key=None):
'''
Send a message to a Slack room.
.. code-block:: yaml
slack-message:
slack.send_message:
- channel: '#general'
- from_name: SuperAdmin
- message: 'This state was executed successfully.'
- api_key: peWcBiMOS9HrZG15peWcBiMOS9HrZG15
The following parameters are required:
name
The unique name for this event.
channel
The room to send the message to. Can either be the ID or the name.
from_name
The name of that is to be shown in the "from" field.
If not specified, defaults to.
message
The message that is to be sent to the Hipchat room.
The following parameters are optional:
api_key
The api key for Slack to use for authentication,
if not specified in the configuration options of master or minion.
'''
ret = {'name': name,
'changes': {},
'result': False,
'comment': ''}
if __opts__['test']:
ret['comment'] = 'The following message is to be sent to Slack: {0}'.format(message)
ret['result'] = None
return ret
if not channel:
ret['comment'] = 'Slack channel is missing: {0}'.format(channel)
return ret
if not from_name:
ret['comment'] = 'Slack from name is missing: {0}'.format(from_name)
return ret
if not message:
ret['comment'] = 'Slack message is missing: {0}'.format(message)
return ret
result = __salt__['slack.post_message'](
channel=channel,
message=message,
from_name=from_name,
api_key=api_key,
)
if result:
ret['result'] = True
ret['comment'] = 'Sent message: {0}'.format(name)
else:
ret['comment'] = 'Failed to send message: {0}'.format(name)
return ret

View File

@ -17,8 +17,6 @@ Interaction with the Supervisor daemon
# Import python libs # Import python libs
import logging import logging
# Import salt libs
import salt.utils
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -48,7 +46,6 @@ def running(name,
restart=False, restart=False,
update=False, update=False,
user=None, user=None,
runas=None,
conf_file=None, conf_file=None,
bin_env=None): bin_env=None):
''' '''
@ -63,11 +60,6 @@ def running(name,
update update
Whether to update the supervisor configuration. Whether to update the supervisor configuration.
runas
Name of the user to run the supervisorctl command
.. deprecated:: 0.17.0
user user
Name of the user to run the supervisorctl command Name of the user to run the supervisorctl command
@ -83,30 +75,6 @@ def running(name,
''' '''
ret = {'name': name, 'result': True, 'comment': '', 'changes': {}} ret = {'name': name, 'result': True, 'comment': '', 'changes': {}}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
if 'supervisord.status' not in __salt__: if 'supervisord.status' not in __salt__:
ret['result'] = False ret['result'] = False
ret['comment'] = 'Supervisord module not activated. Do you need to install supervisord?' ret['comment'] = 'Supervisord module not activated. Do you need to install supervisord?'
@ -270,7 +238,7 @@ def running(name,
log.debug(comment) log.debug(comment)
result = __salt__['supervisord.start']( result = __salt__['supervisord.start'](
name, name,
user=runas, user=user,
conf_file=conf_file, conf_file=conf_file,
bin_env=bin_env bin_env=bin_env
) )
@ -285,7 +253,6 @@ def running(name,
def dead(name, def dead(name,
user=None, user=None,
runas=None,
conf_file=None, conf_file=None,
bin_env=None): bin_env=None):
''' '''
@ -294,11 +261,6 @@ def dead(name,
name name
Service name as defined in the supervisor configuration file Service name as defined in the supervisor configuration file
runas
Name of the user to run the supervisorctl command
.. deprecated:: 0.17.0
user user
Name of the user to run the supervisorctl command Name of the user to run the supervisorctl command
@ -314,30 +276,6 @@ def dead(name,
''' '''
ret = {'name': name, 'result': True, 'comment': '', 'changes': {}} ret = {'name': name, 'result': True, 'comment': '', 'changes': {}}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 0.17.0',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
if __opts__['test']: if __opts__['test']:
ret['result'] = None ret['result'] = None
ret['comment'] = ( ret['comment'] = (
@ -347,7 +285,7 @@ def dead(name,
log.debug(comment) log.debug(comment)
all_processes = __salt__['supervisord.status']( all_processes = __salt__['supervisord.status'](
user=runas, user=user,
conf_file=conf_file, conf_file=conf_file,
bin_env=bin_env bin_env=bin_env
) )
@ -397,7 +335,6 @@ def mod_watch(name,
restart=True, restart=True,
update=False, update=False,
user=None, user=None,
runas=None,
conf_file=None, conf_file=None,
bin_env=None): bin_env=None):
# Always restart on watch # Always restart on watch
@ -406,7 +343,6 @@ def mod_watch(name,
restart=restart, restart=restart,
update=update, update=update,
user=user, user=user,
runas=runas,
conf_file=conf_file, conf_file=conf_file,
bin_env=bin_env bin_env=bin_env
) )

View File

@ -35,7 +35,6 @@ def managed(name,
never_download=None, never_download=None,
prompt=None, prompt=None,
user=None, user=None,
runas=None,
no_chown=False, no_chown=False,
cwd=None, cwd=None,
index_url=None, index_url=None,
@ -83,29 +82,6 @@ def managed(name,
ret['comment'] = 'Virtualenv was not detected on this system' ret['comment'] = 'Virtualenv was not detected on this system'
return ret return ret
if runas:
# Warn users about the deprecation
salt.utils.warn_until(
'Lithium',
'The support for \'runas\' is being deprecated in favor of '
'\'user\' and will be removed in Salt Beryllium. Please update '
'your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
salt.utils.warn_until(
'Lithium',
'Passed both the \'runas\' and \'user\' arguments. \'runas\' is '
'being ignored in favor of \'user\' as the support for \'runas\' '
'is being deprecated in favor of \'user\' and will be removed in '
'Salt Beryllium. Please update your state files.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
if salt.utils.is_windows(): if salt.utils.is_windows():
venv_py = os.path.join(name, 'Scripts', 'python.exe') venv_py = os.path.join(name, 'Scripts', 'python.exe')
else: else:

View File

@ -40,7 +40,6 @@ Available Functions
import sys import sys
# Import salt libs # Import salt libs
import salt.utils
from salt._compat import string_types from salt._compat import string_types
# Define the module's virtual name # Define the module's virtual name
@ -120,7 +119,6 @@ def installed(name,
config='buildout.cfg', config='buildout.cfg',
quiet=False, quiet=False,
parts=None, parts=None,
runas=None,
user=None, user=None,
env=(), env=(),
buildout_ver=None, buildout_ver=None,
@ -154,11 +152,6 @@ def installed(name,
parts parts
specific buildout parts to run specific buildout parts to run
runas
user used to run buildout as
.. deprecated:: 2014.1.4
user user
user used to run buildout as user used to run buildout as
@ -209,30 +202,6 @@ def installed(name,
''' '''
ret = {} ret = {}
salt.utils.warn_until(
'Lithium',
'Please remove \'runas\' support at this stage. \'user\' support was '
'added in 2014.1.4.',
_dont_call_warnings=True
)
if runas:
# Warn users about the deprecation
ret.setdefault('warnings', []).append(
'The \'runas\' argument is being deprecated in favor of \'user\', '
'please update your state files.'
)
if user is not None and runas is not None:
# user wins over runas but let warn about the deprecation.
ret.setdefault('warnings', []).append(
'Passed both the \'runas\' and \'user\' arguments. Please don\'t. '
'\'runas\' is being ignored in favor of \'user\'.'
)
runas = None
elif runas is not None:
# Support old runas usage
user = runas
runas = None
try: try:
test_release = int(test_release) test_release = int(test_release)
except ValueError: except ValueError:

View File

@ -526,15 +526,13 @@ def dns_check(addr, safe=False, ipv6=False):
if not addr: if not addr:
error = True error = True
except TypeError: except TypeError:
err = ('Attempt to resolve address failed. Invalid or unresolveable address') err = ('Attempt to resolve address \'{0}\' failed. Invalid or unresolveable address').format(addr)
raise SaltSystemExit(code=42, msg=err) raise SaltSystemExit(code=42, msg=err)
except socket.error: except socket.error:
error = True error = True
if error: if error:
err = ('This master address: \'{0}\' was previously resolvable ' err = ('DNS lookup of \'{0}\' failed.').format(addr)
'but now fails to resolve! The previously resolved ip addr '
'will continue to be used').format(addr)
if safe: if safe:
if salt.log.is_console_configured(): if salt.log.is_console_configured():
# If logging is not configured it also means that either # If logging is not configured it also means that either
@ -842,13 +840,6 @@ def build_whitespace_split_regex(text):
return r'(?m)^{0}$'.format(regex) return r'(?m)^{0}$'.format(regex)
def build_whitepace_splited_regex(text):
warnings.warn('The build_whitepace_splited_regex function is deprecated,'
' please use build_whitespace_split_regex instead.',
DeprecationWarning)
build_whitespace_split_regex(text)
def format_call(fun, def format_call(fun,
data, data,
initial_ret=None, initial_ret=None,

View File

@ -367,6 +367,9 @@ def bootstrap(vm_, opts):
'known_hosts_file': salt.config.get_cloud_config_value( 'known_hosts_file': salt.config.get_cloud_config_value(
'known_hosts_file', vm_, opts, default='/dev/null' 'known_hosts_file', vm_, opts, default='/dev/null'
), ),
'file_map': salt.config.get_cloud_config_value(
'file_map', vm_, opts, default=None
),
} }
# forward any info about possible ssh gateway to deploy script # forward any info about possible ssh gateway to deploy script
# as some providers need also a 'gateway' configuration # as some providers need also a 'gateway' configuration
@ -428,8 +431,10 @@ def bootstrap(vm_, opts):
else: else:
deployed = deploy_script(**deploy_kwargs) deployed = deploy_script(**deploy_kwargs)
if deployed: if deployed is not False:
ret['deployed'] = deployed ret['deployed'] = True
if deployed is not True:
ret.update(deployed)
log.info('Salt installed on {0}'.format(vm_['name'])) log.info('Salt installed on {0}'.format(vm_['name']))
return ret return ret
@ -938,6 +943,7 @@ def deploy_script(host,
deploy_command='/tmp/.saltcloud/deploy.sh', deploy_command='/tmp/.saltcloud/deploy.sh',
opts=None, opts=None,
tmp_dir='/tmp/.saltcloud', tmp_dir='/tmp/.saltcloud',
file_map=None,
**kwargs): **kwargs):
''' '''
Copy a deploy script to a remote server, execute it, and remove it Copy a deploy script to a remote server, execute it, and remove it
@ -1021,6 +1027,34 @@ def deploy_script(host,
'Cant set {0} ownership on {1}'.format( 'Cant set {0} ownership on {1}'.format(
username, tmp_dir)) username, tmp_dir))
if not isinstance(file_map, dict):
file_map = {}
# Copy an arbitrary group of files to the target system
remote_dirs = []
file_map_success = []
file_map_fail = []
for map_item in file_map:
local_file = map_item
remote_file = file_map[map_item]
if not os.path.exists(map_item):
log.error(
'The local file "{0}" does not exist, and will not be '
'copied to "{1}" on the target system'.format(
local_file, remote_file
)
)
file_map_fail.append({local_file: remote_file})
continue
remote_dir = os.path.dirname(remote_file)
if remote_dir not in remote_dirs:
root_cmd('mkdir -p {0}'.format(remote_dir), tty, sudo, **ssh_kwargs)
remote_dirs.append(remote_dir)
sftp_file(
remote_file, kwargs=ssh_kwargs, local_file=local_file
)
file_map_success.append({local_file: remote_file})
# Minion configuration # Minion configuration
if minion_pem: if minion_pem:
sftp_file('{0}/minion.pem'.format(tmp_dir), minion_pem, ssh_kwargs) sftp_file('{0}/minion.pem'.format(tmp_dir), minion_pem, ssh_kwargs)
@ -1316,6 +1350,11 @@ def deploy_script(host,
}, },
transport=opts.get('transport', 'zeromq') transport=opts.get('transport', 'zeromq')
) )
if file_map_fail or file_map_success:
return {
'File Upload Success': file_map_success,
'File Upload Failure': file_map_fail,
}
return True return True
return False return False
@ -1500,14 +1539,18 @@ def smb_file(dest_path, contents, kwargs):
win_cmd(cmd) win_cmd(cmd)
def sftp_file(dest_path, contents, kwargs): def sftp_file(dest_path, contents=None, kwargs=None, local_file=None):
''' '''
Use sftp to upload a file to a server Use sftp to upload a file to a server
''' '''
if contents is not None:
tmpfh, tmppath = tempfile.mkstemp() tmpfh, tmppath = tempfile.mkstemp()
with salt.utils.fopen(tmppath, 'w') as tmpfile: with salt.utils.fopen(tmppath, 'w') as tmpfile:
tmpfile.write(contents) tmpfile.write(contents)
if local_file is not None:
tmppath = local_file
log.debug('Uploading {0} to {1} (sfcp)'.format(dest_path, kwargs['hostname'])) log.debug('Uploading {0} to {1} (sfcp)'.format(dest_path, kwargs['hostname']))
ssh_args = [ ssh_args = [

View File

@ -183,15 +183,12 @@ class CkMinions(object):
if not greedy and id_ in minions: if not greedy and id_ in minions:
minions.remove(id_) minions.remove(id_)
continue continue
try: search_results = self.serial.load(
with salt.utils.fopen(datap, 'rb') as fp_: salt.utils.fopen(datap, 'rb')
search_results = self.serial.load(fp_).get(search_type) ).get(search_type)
except (IOError, OSError):
continue
if not salt.utils.subdict_match(search_results, if not salt.utils.subdict_match(search_results,
expr, expr,
delimiter, regex_match=regex_match) and id_ in minions:
regex_match=regex_match):
minions.remove(id_) minions.remove(id_)
return list(minions) return list(minions)
@ -205,36 +202,11 @@ class CkMinions(object):
''' '''
Return the minions found by looking via grains with PCRE Return the minions found by looking via grains with PCRE
''' '''
cache_enabled = self.opts.get('minion_data_cache', False) return self._check_cache_minions(expr,
delimiter,
if greedy: greedy,
minions = set( 'grains',
os.listdir(os.path.join(self.opts['pki_dir'], self.acc)) regex_match=True)
)
elif cache_enabled:
minions = os.listdir(os.path.join(self.opts['cachedir'], 'minions'))
else:
return list()
if cache_enabled:
cdir = os.path.join(self.opts['cachedir'], 'minions')
if not os.path.isdir(cdir):
return list(minions)
for id_ in os.listdir(cdir):
if not greedy and id_ not in minions:
continue
datap = os.path.join(cdir, id_, 'data.p')
if not os.path.isfile(datap):
if not greedy and id_ in minions:
minions.remove(id_)
continue
grains = self.serial.load(
salt.utils.fopen(datap, 'rb')
).get('grains')
if not salt.utils.subdict_match(grains, expr,
delimiter=':', regex_match=True) and id_ in minions:
minions.remove(id_)
return list(minions)
def _check_pillar_minions(self, expr, delimiter, greedy): def _check_pillar_minions(self, expr, delimiter, greedy):
''' '''

23
salt/wheel/minions.py Normal file
View File

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
'''
Wheel system wrapper for connected minions
'''
from salt.utils.cache import CacheCli
import salt.config
import salt.utils.minion
def connected():
'''
List all connected minions on a salt-master
'''
opts = salt.config.master_config(__opts__['conf_file'])
minions = []
if opts.get('con_cache'):
cache_cli = CacheCli(opts)
minions = cache_cli.get_cached()
else:
minions = list(salt.utils.minions.CkMinions(opts).connected_ids())
return minions

View File

@ -651,6 +651,7 @@ SETUP_KWARGS = {'name': NAME,
'salt.utils', 'salt.utils',
'salt.utils.decorators', 'salt.utils.decorators',
'salt.utils.openstack', 'salt.utils.openstack',
'salt.utils.openstack.pyrax',
'salt.utils.validate', 'salt.utils.validate',
'salt.utils.serializers', 'salt.utils.serializers',
'salt.wheel', 'salt.wheel',

View File

@ -1,4 +1,4 @@
digitalocean-test: digitalocean-test:
provider: digitalocean-config provider: digitalocean-config
image: Ubuntu 14.04 x64 image: 14.04 x64
size: 2GB size: 2GB

View File

@ -518,40 +518,6 @@ class FileTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
finally: finally:
os.remove(name) os.remove(name)
def test_sed(self):
'''
file.sed
'''
name = os.path.join(integration.TMP, 'sed_test')
with salt.utils.fopen(name, 'w+') as fp_:
fp_.write('change_me')
ret = self.run_state(
'file.sed', name=name, before='change', after='salt'
)
try:
with salt.utils.fopen(name, 'r') as fp_:
self.assertIn('salt', fp_.read())
self.assertSaltTrueReturn(ret)
finally:
os.remove(name)
def test_test_sed(self):
'''
file.sed test integration
'''
name = os.path.join(integration.TMP, 'sed_test_test')
with salt.utils.fopen(name, 'w+') as fp_:
fp_.write('change_me')
ret = self.run_state(
'file.sed', test=True, name=name, before='change', after='salt'
)
try:
with salt.utils.fopen(name, 'r') as fp_:
self.assertIn('change', fp_.read())
self.assertSaltNoneReturn(ret)
finally:
os.remove(name)
def test_comment(self): def test_comment(self):
''' '''
file.comment file.comment

View File

@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Nicole Thomas (nicole@saltstack.com)`
'''
# Import Pyhton Libs
from inspect import ArgSpec
# Import Salt Libs
from salt.states import module
# Import Salt Testing Libs
from salttesting import skipIf, TestCase
from salttesting.helpers import ensure_in_syspath
from salttesting.mock import (
NO_MOCK,
NO_MOCK_REASON,
MagicMock,
patch
)
ensure_in_syspath('../../')
CMD = 'foo.bar'
MOCK = MagicMock()
module.__salt__ = {CMD: MOCK}
module.__opts__ = {'test': False}
@skipIf(NO_MOCK, NO_MOCK_REASON)
class ModuleStateTest(TestCase):
'''
Tests module state (salt/states/module.py)
'''
aspec = ArgSpec(args=['hello', 'world'],
varargs=None,
keywords=None,
defaults=False)
def test_module_run_module_not_available(self):
'''
Tests the return of module.run state when the module function
name isn't available
'''
with patch.dict(module.__salt__, {}):
cmd = 'hello.world'
ret = module.run(cmd)
comment = 'Module function {0} is not available'.format(cmd)
self.assertEqual(ret['comment'], comment)
self.assertFalse(ret['result'])
def test_module_run_test_true(self):
'''
Tests the return of module.run state when test=True is passed in
'''
with patch.dict(module.__opts__, {'test': True}):
ret = module.run(CMD)
comment = 'Module function {0} is set to execute'.format(CMD)
self.assertEqual(ret['comment'], comment)
@patch('salt.utils.get_function_argspec', MagicMock(return_value=aspec))
def test_module_run_missing_arg(self):
'''
Tests the return of module.run state when arguments are missing
'''
ret = module.run(CMD)
comment = 'The following arguments are missing: world hello'
self.assertEqual(ret['comment'], comment)
if __name__ == '__main__':
from integration import run_tests
run_tests(ModuleStateTest, needs_daemon=False)

View File

@ -108,13 +108,6 @@ class UtilsTestCase(TestCase):
ret = utils.build_whitespace_split_regex(' '.join(LORUM_IPSUM.split()[:5])) ret = utils.build_whitespace_split_regex(' '.join(LORUM_IPSUM.split()[:5]))
self.assertEqual(ret, expected_regex) self.assertEqual(ret, expected_regex)
@skipIf(NO_MOCK, NO_MOCK_REASON)
@patch('warnings.warn')
def test_build_whitepace_splited_regex(self, warnings_mock):
# noinspection PyDeprecation
utils.build_whitepace_splited_regex('foo')
self.assertTrue(warnings_mock.called)
def test_get_function_argspec(self): def test_get_function_argspec(self):
def dummy_func(first, second, third, fourth='fifth'): def dummy_func(first, second, third, fourth='fifth'):
pass pass