Merge branch '2016.11' into 'develop'

Conflicts:
  - salt/config/__init__.py
  - salt/modules/win_lgpo.py
  - salt/utils/aws.py
  - tests/unit/utils/schema_test.py
This commit is contained in:
rallytime 2017-02-09 10:29:40 -07:00
commit 609e6e4b23
78 changed files with 806 additions and 282 deletions

View file

@ -1,3 +1,6 @@
.. _glossary:
========
Glossary
========

View file

@ -1,6 +1,6 @@
========================
============================
salt.cloud.clouds.virtualbox
========================
============================
.. automodule:: salt.cloud.clouds.virtualbox
:members:

View file

@ -1,3 +1,5 @@
.. _configuration-file-examples:
===========================
Configuration file examples
===========================

View file

@ -794,7 +794,7 @@ Pass in an alternative location for the salt-ssh roster file.
.. conf_master:: ssh_log_file
``ssh_log_file``
-------------------
----------------
.. versionadded:: 2016.3.5

View file

@ -1,4 +1,4 @@
.. _all-salt_modules:
.. _all-salt.modules:
=================
execution modules

View file

@ -3,4 +3,3 @@ salt.modules.cytest module
.. automodule:: salt.modules.cytest
:members:

View file

@ -47,7 +47,7 @@ Writing a Returner
A returner is a Python module containing at minimum a ``returner`` function.
Other optional functions can be included to add support for
:ref:`master_job_cache`, :ref:`external_job_cache`, and `Event Returners`_.
:conf_master:`master_job_cache`, :ref:`external-job-cache`, and `Event Returners`_.
``returner``
The ``returner`` function must accept a single argument. The argument
@ -85,8 +85,8 @@ serializes the data as JSON and sets it in redis.
Master Job Cache Support
------------------------
:ref:`master_job_cache`, :ref:`external_job_cache`, and `Event Returners`_.
Salt's :ref:`master_job_cache` allows returners to be used as a pluggable
:conf_master:`master_job_cache`, :ref:`external-job-cache`, and `Event Returners`_.
Salt's :conf_master:`master_job_cache` allows returners to be used as a pluggable
replacement for the :ref:`default_job_cache`. In order to do so, a returner
must implement the following functions:
@ -176,7 +176,7 @@ must implement the following functions:
External Job Cache Support
--------------------------
Salt's :ref:`external_job_cache` extends the :ref:`master_job_cache`. External
Salt's :ref:`external-job-cache` extends the :conf_master:`master_job_cache`. External
Job Cache support requires the following functions in addition to what is
required for Master Job Cache support:
@ -328,7 +328,7 @@ Testing the Returner
The ``returner``, ``prep_jid``, ``save_load``, ``get_load``, and
``event_return`` functions can be tested by configuring the
:ref:`master_job_cache` and `Event Returners`_ in the master config
:conf_master:`master_job_cache` and `Event Returners`_ in the master config
file and submitting a job to ``test.ping`` each minion from the master.
Once you have successfully exercised the Master Job Cache functions, test the

View file

@ -94,7 +94,7 @@ profile or map:
Setting Up a Salt Syndic with Salt Cloud
========================================
In addition to `setting up new Salt Masters`_, :ref:`syndic`s can also be
In addition to `setting up new Salt Masters`_, :ref:`syndics <syndic>` can also be
provisioned using Salt Cloud. In order to set up a Salt Syndic via Salt Cloud,
a Salt Master needs to be installed on the new machine and a master configuration
file needs to be set up using the ``make_master`` setting. This setting can be

View file

@ -418,3 +418,4 @@ and bug resolution. See the :ref:`Labels and Milestones
.. _'Git resources`: https://help.github.com/articles/good-resources-for-learning-git-and-github/
.. _`Closing issues via commit message`: https://help.github.com/articles/closing-issues-via-commit-messages
.. _`git format-patch`: https://www.kernel.org/pub/software/scm/git/docs/git-format-patch.html
.. _salt-users: https://groups.google.com/forum/#!forum/salt-users

View file

@ -25,7 +25,7 @@ modules is that the defined functions always return a JSON serializable
object.
For a list of all built in execution modules, click :ref:`here
<all-salt_modules>`
<all-salt.modules>`
For information on writing execution modules, see :ref:`this page
<writing-execution-modules>`.

View file

@ -15,7 +15,7 @@ a wide variety of tasks. These modules provide functionality such as installing
packages, restarting a service, running a remote command, transferring files,
and so on.
:ref:`Full list of execution modules <all-salt_modules>`
:ref:`Full list of execution modules <all-salt.modules>`
Contains: a list of core modules that ship with Salt.
:ref:`Writing execution modules <writing-execution-modules>`

View file

@ -6,7 +6,7 @@ High Availability Features in Salt
Salt supports several features for high availability and fault tolerance.
Brief documentation for these features is listed alongside their configuration
parameters in :ref:`Configuration file examples <configuration/examples>`.
parameters in :ref:`Configuration file examples <configuration-file-examples>`.
Multimaster
===========

View file

@ -6,6 +6,7 @@ Introduction to Salt
The 30 second summary
=====================
Salt is:
* a configuration management system, capable of maintaining remote nodes
@ -89,3 +90,101 @@ the Salt project so that we can all benefit together as Salt grows.
Please feel free to sprinkle Salt around your systems and let the
deliciousness come forth.
.. _salt-community:
Salt Community
==============
Join the Salt!
There are many ways to participate in and communicate with the Salt community.
Salt has an active IRC channel and a mailing list.
Mailing List
============
Join the `salt-users mailing list`_. It is the best place to ask questions
about Salt and see whats going on with Salt development! The Salt mailing list
is hosted by Google Groups. It is open to new members.
.. _`salt-users mailing list`: https://groups.google.com/forum/#!forum/salt-users
IRC
===
The ``#salt`` IRC channel is hosted on the popular `Freenode`_ network. You
can use the `Freenode webchat client`_ right from your browser.
`Logs of the IRC channel activity`_ are being collected courtesy of Moritz Lenz.
.. _Freenode:: http://freenode.net/irc_servers.shtml
.. _Freenode webchat client:: http://webchat.freenode.net/?channels=salt&uio=Mj10cnVlJjk9dHJ1ZSYxMD10cnVl83
.. _Logs of the IRC channel activity:: http://irclog.perlgeek.de/salt/
If you wish to discuss the development of Salt itself join us in
``#salt-devel``.
Follow on Github
================
The Salt code is developed via Github. Follow Salt for constant updates on what
is happening in Salt development:
|saltrepo|
Blogs
=====
SaltStack Inc. keeps a `blog`_ with recent news and advancements:
http://www.saltstack.com/blog/
.. _`blog`: http://www.saltstack.com/blog/
Example Salt States
===================
The official ``salt-states`` repository is:
https://github.com/saltstack/salt-states
A few examples of salt states from the community:
* https://github.com/blast-hardcheese/blast-salt-states
* https://github.com/kevingranade/kevingranade-salt-state
* https://github.com/uggedal/states
* https://github.com/mattmcclean/salt-openstack/tree/master/salt
* https://github.com/rentalita/ubuntu-setup/
* https://github.com/brutasse/states
* https://github.com/bclermont/states
* https://github.com/pcrews/salt-data
Follow on ohloh
===============
https://www.ohloh.net/p/salt
Other community links
=====================
- `Salt Stack Inc. <http://www.saltstack.com>`_
- `Subreddit <http://www.reddit.com/r/saltstack>`_
- `Google+ <https://plus.google.com/114449193225626631691/posts>`_
- `YouTube <http://www.youtube.com/user/SaltStack>`_
- `Facebook <https://www.facebook.com/SaltStack>`_
- `Twitter <https://twitter.com/SaltStackInc>`_
- `Wikipedia page <http://en.wikipedia.org/wiki/Salt_(software)>`_
Hack the Source
===============
If you want to get involved with the development of source code or the
documentation efforts, please review the :ref:`contributing documentation
<contributing>`!
.. _`Apache 2.0 license`: http://www.apache.org/licenses/LICENSE-2.0.html

View file

@ -1,4 +1,4 @@
.. _jinja:
.. _understanding-jinja:
===================
Understanding Jinja

View file

@ -1,4 +1,4 @@
.. _external-master-cache:
.. _external-job-cache:
=========================================
Storing Job Results in an External System

View file

@ -67,6 +67,6 @@ Many deployments may wish to use an external database to maintain a long term
register of executed jobs. Salt comes with two main mechanisms to do this, the
master job cache and the external job cache.
See :ref:`Storing Job Results in an External System <external-master-cache>`.
See :ref:`Storing Job Results in an External System <external-job-cache>`.

View file

@ -22,7 +22,7 @@ refreshed on a very limited basis and are largely static data. Mines are
designed to replace slow peer publishing calls when Minions need data from
other Minions. Rather than having a Minion reach out to all the other Minions
for a piece of data, the Salt Mine, running on the Master, can collect it from
all the Minions every :ref:`mine-interval`, resulting in
all the Minions every :ref:`mine_interval`, resulting in
almost fresh data at any given time, with much less overhead.
Mine Functions

View file

@ -410,7 +410,7 @@ sets up and listens to the minions event bus, instead of to the masters.
The biggest difference is that you have to use the caller method on the
Reactor, which is the equivalent of salt-call, to run your commands.
:ref:`Reactor Engine setup<salt.engines.reactor>`
:mod:`Reactor Engine setup <salt.engines.reactor>`
.. code-block:: yaml

View file

@ -9,7 +9,7 @@ Salt 2014.1.0 Release Notes - Codename Hydrogen
Due to a change in master to minion communication, 2014.1.0 minions are not
compatible with older-version masters. Please upgrade masters first.
More info on backwards-compatibility policy :ref:`here
<installation`, under the "Upgrading Salt" subheading.
<installation>`, under the "Upgrading Salt" subheading.
.. note::
@ -248,7 +248,7 @@ Proxy Minions
-------------
Initial basic support for Proxy Minions is in this release. Documentation can
be found :ref:`here <proxy>`.
be found :ref:`here <proxy-minion>`.
Proxy minions are a developing feature in Salt that enables control of devices
that cannot run a minion. Examples include network gear like switches and

View file

@ -17,7 +17,7 @@ New Configuration Parameter: ``rotate_aes_key``
- ``Rotate_aes_key`` causes Salt to generate a new AES key whenever a minion key
is deleted. This eliminates the chance that a deleted minion could continue
to eavesdrop on communications with the master if it continues to run after its
key is deleted. See the entry in the documentation for `rotate_aes_key`_.
key is deleted. See the entry in the documentation for :conf_master:`rotate_aes_key`.
Ubuntu 16.04 Packages
=====================
@ -404,11 +404,13 @@ Changes:
.. _`#20226`: https://github.com/saltstack/salt/pull/20226
.. _`#22480`: https://github.com/saltstack/salt/pull/22480
.. _`#23643`: https://github.com/saltstack/salt/issues/23643
.. _`#25089`: https://github.com/saltstack/salt/pull/25089
.. _`#28325`: https://github.com/saltstack/salt/pull/28325
.. _`#28467`: https://github.com/saltstack/salt/pull/28467
.. _`#32484`: https://github.com/saltstack/salt/pull/32484
.. _`#32857`: https://github.com/saltstack/salt/pull/32857
.. _`#33266`: https://github.com/saltstack/salt/issues/33266
.. _`#33282`: https://github.com/saltstack/salt/pull/33282
.. _`#33286`: https://github.com/saltstack/salt/pull/33286
.. _`#33287`: https://github.com/saltstack/salt/pull/33287
@ -491,6 +493,7 @@ Changes:
.. _`#33555`: https://github.com/saltstack/salt/pull/33555
.. _`#33558`: https://github.com/saltstack/salt/pull/33558
.. _`#33581`: https://github.com/saltstack/salt/pull/33581
.. _`#33582`: https://github.com/saltstack/salt/issues/33582
.. _`#33599`: https://github.com/saltstack/salt/pull/33599
.. _`#33611`: https://github.com/saltstack/salt/pull/33611
.. _`#33615`: https://github.com/saltstack/salt/pull/33615
@ -647,4 +650,3 @@ Changes:
.. _`#34647`: https://github.com/saltstack/salt/pull/34647
.. _`#34651`: https://github.com/saltstack/salt/pull/34651
.. _`#34676`: https://github.com/saltstack/salt/pull/34676
.. _ `rotate_aes_key`: https://docs.saltstack.com/en/2015.8/ref/configuration/master.html#rotate-aes-key

View file

@ -48,8 +48,6 @@ Core Changes
salt '*' state.highstate mock=True
salt '*' state.apply edit.vim mock=True
.. _`#28994`: https://github.com/saltstack/salt/pull/28994
Changes for v2015.8.3..v2015.8.4
--------------------------------
@ -515,7 +513,7 @@ Changes:
- **PR** `#29317`_: (*basepi*) [2015.8] Merge forward from 2015.5 to 2015.8
- **PR** `#29240`_: (*clan*) handle acl_type [[d]efault:][user|group|mask|other]
- **PR** `#29240`_: (*clan*) handle acl_type ``[[d]efault:][user|group|mask|other]``
- **PR** `#29305`_: (*lorengordon*) Add 'file' as a source_hash proto
@ -578,11 +576,13 @@ Changes:
- **PR** `#29178`_: (*whytewolf*) Profile not being passed to keystone.endpoint_get in _auth. so if a p…
.. _`#19332`: https://github.com/saltstack/salt/issues/19332
.. _`#24237`: https://github.com/saltstack/salt/issues/24237
.. _`#29116`: https://github.com/saltstack/salt/issues/29116
.. _`#29187`: https://github.com/saltstack/salt/issues/29187
.. _`#23825`: https://github.com/saltstack/salt/pull/23825
.. _`#26511`: https://github.com/saltstack/salt/pull/26511
.. _`#26853`: https://github.com/saltstack/salt/pull/26853
.. _`#26845`: https://github.com/saltstack/salt/issues/26845
.. _`#26962`: https://github.com/saltstack/salt/pull/26962
.. _`#27104`: https://github.com/saltstack/salt/pull/27104
.. _`#27606`: https://github.com/saltstack/salt/pull/27606

View file

@ -599,13 +599,16 @@ Changes:
- **PR** `#30625`_: (*jfindlay*) doc.topics.eauth: clarify client_acl vs eauth
.. _`#27796`: https://github.com/saltstack/salt/issues/27796
.. _`#29650`: https://github.com/saltstack/salt/pull/29650
.. _`#29718`: https://github.com/saltstack/salt/pull/29718
.. _`#30062`: https://github.com/saltstack/salt/pull/30062
.. _`#30217`: https://github.com/saltstack/salt/pull/30217
.. _`#30279`: https://github.com/saltstack/salt/pull/30279
.. _`#30300`: https://github.com/saltstack/salt/issues/30300
.. _`#30378`: https://github.com/saltstack/salt/pull/30378
.. _`#30458`: https://github.com/saltstack/salt/pull/30458
.. _`#30461`: https://github.com/saltstack/salt/issues/30461
.. _`#30542`: https://github.com/saltstack/salt/pull/30542
.. _`#30586`: https://github.com/saltstack/salt/pull/30586
.. _`#30591`: https://github.com/saltstack/salt/pull/30591
@ -664,6 +667,7 @@ Changes:
.. _`#30813`: https://github.com/saltstack/salt/pull/30813
.. _`#30815`: https://github.com/saltstack/salt/pull/30815
.. _`#30818`: https://github.com/saltstack/salt/pull/30818
.. _`#30820`: https://github.com/saltstack/salt/issues/30820
.. _`#30822`: https://github.com/saltstack/salt/pull/30822
.. _`#30823`: https://github.com/saltstack/salt/pull/30823
.. _`#30826`: https://github.com/saltstack/salt/pull/30826
@ -700,6 +704,7 @@ Changes:
.. _`#30920`: https://github.com/saltstack/salt/pull/30920
.. _`#30922`: https://github.com/saltstack/salt/pull/30922
.. _`#30924`: https://github.com/saltstack/salt/pull/30924
.. _`#30934`: https://github.com/saltstack/salt/issues/30934
.. _`#30940`: https://github.com/saltstack/salt/pull/30940
.. _`#30941`: https://github.com/saltstack/salt/pull/30941
.. _`#30942`: https://github.com/saltstack/salt/pull/30942
@ -713,10 +718,12 @@ Changes:
.. _`#30978`: https://github.com/saltstack/salt/pull/30978
.. _`#30987`: https://github.com/saltstack/salt/pull/30987
.. _`#30998`: https://github.com/saltstack/salt/pull/30998
.. _`#30999`: https://github.com/saltstack/salt/issues/30999
.. _`#31002`: https://github.com/saltstack/salt/pull/31002
.. _`#31004`: https://github.com/saltstack/salt/pull/31004
.. _`#31007`: https://github.com/saltstack/salt/pull/31007
.. _`#31012`: https://github.com/saltstack/salt/pull/31012
.. _`#31014`: https://github.com/saltstack/salt/issues/31014
.. _`#31015`: https://github.com/saltstack/salt/pull/31015
.. _`#31024`: https://github.com/saltstack/salt/pull/31024
.. _`#31026`: https://github.com/saltstack/salt/pull/31026
@ -737,6 +744,7 @@ Changes:
.. _`#31100`: https://github.com/saltstack/salt/pull/31100
.. _`#31103`: https://github.com/saltstack/salt/pull/31103
.. _`#31105`: https://github.com/saltstack/salt/pull/31105
.. _`#31106`: https://github.com/saltstack/salt/issues/31106
.. _`#31107`: https://github.com/saltstack/salt/pull/31107
.. _`#31108`: https://github.com/saltstack/salt/pull/31108
.. _`#31110`: https://github.com/saltstack/salt/pull/31110
@ -769,6 +777,7 @@ Changes:
.. _`#31191`: https://github.com/saltstack/salt/pull/31191
.. _`#31196`: https://github.com/saltstack/salt/pull/31196
.. _`#31201`: https://github.com/saltstack/salt/pull/31201
.. _`#31223`: https://github.com/saltstack/salt/issues/31223
.. _`#31225`: https://github.com/saltstack/salt/pull/31225
.. _`#31226`: https://github.com/saltstack/salt/pull/31226
.. _`#31233`: https://github.com/saltstack/salt/pull/31233
@ -868,6 +877,7 @@ Changes:
.. _`#31598`: https://github.com/saltstack/salt/pull/31598
.. _`#31601`: https://github.com/saltstack/salt/pull/31601
.. _`#31604`: https://github.com/saltstack/salt/pull/31604
.. _`#31617`: https://github.com/saltstack/salt/issues/31617
.. _`#31622`: https://github.com/saltstack/salt/pull/31622
.. _`#31627`: https://github.com/saltstack/salt/pull/31627
.. _`#31629`: https://github.com/saltstack/salt/pull/31629

View file

@ -297,7 +297,7 @@ Changes:
- **PR** `#32425`_: (*cachedout*) Fix salt-cloud parallel provisioning
* 51fb2ac FreeBSD supports packages in format java/openjdk7 so the prior commit broke that functionality. Check freebsd/pkg`#1409`_ for more info.
* 51fb2ac FreeBSD supports packages in format java/openjdk7 so the prior commit broke that functionality. Check freebsd/pkg #1409 for more info.
* 709410a Improve git_pillar documentation/logging
@ -325,7 +325,7 @@ Changes:
- **PR** `#32321`_: (*abednarik*) Better message when minion fail to start
- **PR** `#32345`_: (*nmadhok*) [2015.8] Check if profile key exists in vm_ dict
- **PR** `#32345`_: (*nmadhok*) [2015.8] Check if profile key exists in ``vm_`` dict
- **PR** `#32343`_: (*Ferbla*) Fixed win_wua example documentation
@ -467,15 +467,21 @@ Changes:
- **PR** `#31912`_: (*jfindlay*) log.mixins: remove extermporaneous .record
.. _`#14277`: https://github.com/saltstack/salt/issues/14277
.. _`#23714`: https://github.com/saltstack/salt/issues/23714
.. _`#24237`: https://github.com/saltstack/salt/issues/24237
.. _`#26518`: https://github.com/saltstack/salt/pull/26518
.. _`#26648`: https://github.com/saltstack/salt/pull/26648
.. _`#26676`: https://github.com/saltstack/salt/pull/26676
.. _`#28262`: https://github.com/saltstack/salt/issues/28262
.. _`#28639`: https://github.com/saltstack/salt/pull/28639
.. _`#28706`: https://github.com/saltstack/salt/issues/28706
.. _`#29322`: https://github.com/saltstack/salt/pull/29322
.. _`#30824`: https://github.com/saltstack/salt/pull/30824
.. _`#31139`: https://github.com/saltstack/salt/pull/31139
.. _`#31162`: https://github.com/saltstack/salt/pull/31162
.. _`#31164`: https://github.com/saltstack/salt/pull/31164
.. _`#31270`: https://github.com/saltstack/salt/issues/31270
.. _`#31364`: https://github.com/saltstack/salt/pull/31364
.. _`#31382`: https://github.com/saltstack/salt/pull/31382
.. _`#31598`: https://github.com/saltstack/salt/pull/31598
@ -778,6 +784,7 @@ Changes:
.. _`#33224`: https://github.com/saltstack/salt/pull/33224
.. _`#33236`: https://github.com/saltstack/salt/pull/33236
.. _`#33237`: https://github.com/saltstack/salt/pull/33237
.. _`#33238`: https://github.com/saltstack/salt/issues/33238
.. _`#33239`: https://github.com/saltstack/salt/pull/33239
.. _`#33244`: https://github.com/saltstack/salt/pull/33244
.. _`#33245`: https://github.com/saltstack/salt/pull/33245
@ -789,5 +796,6 @@ Changes:
.. _`#33274`: https://github.com/saltstack/salt/pull/33274
.. _`#33293`: https://github.com/saltstack/salt/pull/33293
.. _`#33294`: https://github.com/saltstack/salt/pull/33294
.. _`#33299`: https://github.com/saltstack/salt/issues/33299
.. _`#33300`: https://github.com/saltstack/salt/pull/33300
.. _`#33305`: https://github.com/saltstack/salt/pull/33305

View file

@ -351,7 +351,7 @@ Documentation of the Dimension Data SaltStack integration is found on `developer
Minion Blackout
---------------
During a blackout, minions will not execute any remote execution commands,
except for :ref:`saltutil.refresh_pillar
except for :mod:`saltutil.refresh_pillar
<salt.modules.saltutil.refresh_pillar>`. Blackouts are enabled using a special
pillar key, ``minion_blackout`` set to ``True``.

View file

@ -155,14 +155,18 @@ Changes:
.. _`#33519`: https://github.com/saltstack/salt/pull/33519
.. _`#33520`: https://github.com/saltstack/salt/pull/33520
.. _`#33522`: https://github.com/saltstack/salt/pull/33522
.. _`#33530`: https://github.com/saltstack/salt/issues/33530
.. _`#33538`: https://github.com/saltstack/salt/pull/33538
.. _`#33549`: https://github.com/saltstack/salt/pull/33549
.. _`#33550`: https://github.com/saltstack/salt/pull/33550
.. _`#33555`: https://github.com/saltstack/salt/pull/33555
.. _`#33558`: https://github.com/saltstack/salt/pull/33558
.. _`#33562`: https://github.com/saltstack/salt/pull/33562
.. _`#33565`: https://github.com/saltstack/salt/issues/33565
.. _`#33576`: https://github.com/saltstack/salt/pull/33576
.. _`#33578`: https://github.com/saltstack/salt/issues/33578
.. _`#33581`: https://github.com/saltstack/salt/pull/33581
.. _`#33590`: https://github.com/saltstack/salt/issues/33590
.. _`#33599`: https://github.com/saltstack/salt/pull/33599
.. _`#33603`: https://github.com/saltstack/salt/pull/33603
.. _`#33604`: https://github.com/saltstack/salt/pull/33604
@ -170,6 +174,7 @@ Changes:
.. _`#33613`: https://github.com/saltstack/salt/pull/33613
.. _`#33615`: https://github.com/saltstack/salt/pull/33615
.. _`#33631`: https://github.com/saltstack/salt/pull/33631
.. _`#33632`: https://github.com/saltstack/salt/issues/33632
.. _`#33637`: https://github.com/saltstack/salt/pull/33637
.. _`#33638`: https://github.com/saltstack/salt/pull/33638
.. _`#33641`: https://github.com/saltstack/salt/pull/33641
@ -205,6 +210,7 @@ Changes:
.. _`#33743`: https://github.com/saltstack/salt/pull/33743
.. _`#33745`: https://github.com/saltstack/salt/pull/33745
.. _`#33748`: https://github.com/saltstack/salt/pull/33748
.. _`#33754`: https://github.com/saltstack/salt/issues/33754
.. _`#33757`: https://github.com/saltstack/salt/pull/33757
.. _`#33759`: https://github.com/saltstack/salt/pull/33759
.. _`#33763`: https://github.com/saltstack/salt/pull/33763

View file

@ -423,6 +423,7 @@ Changes:
.. _`#36016`: https://github.com/saltstack/salt/pull/36016
.. _`#36018`: https://github.com/saltstack/salt/pull/36018
.. _`#36019`: https://github.com/saltstack/salt/pull/36019
.. _`#36021`: https://github.com/saltstack/salt/issues/36021
.. _`#36022`: https://github.com/saltstack/salt/pull/36022
.. _`#36023`: https://github.com/saltstack/salt/pull/36023
.. _`#36024`: https://github.com/saltstack/salt/pull/36024
@ -434,6 +435,7 @@ Changes:
.. _`#36039`: https://github.com/saltstack/salt/pull/36039
.. _`#36040`: https://github.com/saltstack/salt/pull/36040
.. _`#36047`: https://github.com/saltstack/salt/pull/36047
.. _`#36055`: https://github.com/saltstack/salt/issues/36055
.. _`#36061`: https://github.com/saltstack/salt/pull/36061
.. _`#36062`: https://github.com/saltstack/salt/pull/36062
.. _`#36068`: https://github.com/saltstack/salt/pull/36068
@ -474,6 +476,7 @@ Changes:
.. _`#36227`: https://github.com/saltstack/salt/pull/36227
.. _`#36235`: https://github.com/saltstack/salt/pull/36235
.. _`#36238`: https://github.com/saltstack/salt/pull/36238
.. _`#36240`: https://github.com/saltstack/salt/issues/36240
.. _`#36241`: https://github.com/saltstack/salt/pull/36241
.. _`#36244`: https://github.com/saltstack/salt/pull/36244
.. _`#36245`: https://github.com/saltstack/salt/pull/36245
@ -731,6 +734,7 @@ Changes:
.. _`#37179`: https://github.com/saltstack/salt/pull/37179
.. _`#37183`: https://github.com/saltstack/salt/pull/37183
.. _`#37186`: https://github.com/saltstack/salt/pull/37186
.. _`#37187`: https://github.com/saltstack/salt/issues/37187
.. _`#37188`: https://github.com/saltstack/salt/pull/37188
.. _`#37206`: https://github.com/saltstack/salt/pull/37206
.. _`#37207`: https://github.com/saltstack/salt/pull/37207

View file

@ -63,7 +63,8 @@ be used to install it:
If pygit2_ is not packaged for the platform on which the Master is running, the
pygit2_ website has installation instructions here__. Keep in mind however that
pygit2_ website has installation instructions
`here <pygit2-install-instructions>`_. Keep in mind however that
following these instructions will install libgit2_ and pygit2_ without system
packages. Additionally, keep in mind that :ref:`SSH authentication in pygit2
<pygit2-authentication-ssh>` requires libssh2_ (*not* libssh) development
@ -80,26 +81,26 @@ advisable as several other applications depend on it, so on older LTS linux
releases pygit2_ 0.20.3 and libgit2_ 0.20.0 is the recommended combination.
While these are not packaged in the official repositories for Debian and
Ubuntu, SaltStack is actively working on adding packages for these to our
repositories_. The progress of this effort can be tracked here__.
repositories_. The progress of this effort can be tracked `here <salt-pack-70>`_.
.. warning::
pygit2_ is actively developed and :ref:`frequently makes
non-backwards-compatible API changes <pygit2-version-policy>`, even in
pygit2_ is actively developed and `frequently makes
non-backwards-compatible API changes <pygit2-version-policy>`_, even in
minor releases. It is not uncommon for pygit2_ upgrades to result in errors
in Salt. Please take care when upgrading pygit2_, and pay close attention
to the changelog_, keeping an eye out for API changes. Errors can be
reported on the :ref:`SaltStack issue tracker <saltstack-issue-tracker>`.
reported on the `SaltStack issue tracker <saltstack-issue-tracker>`_.
.. _pygit2-version-policy: http://www.pygit2.org/install.html#version-numbers
.. _changelog: https://github.com/libgit2/pygit2#changelog
.. _saltstack-issue-tracker: https://github.com/saltstack/salt/issues
.. __: http://www.pygit2.org/install.html
.. _pygit2-install-instructions: http://www.pygit2.org/install.html
.. _libgit2: https://libgit2.github.com/
.. _libssh2: http://www.libssh2.org/
.. _python-cffi: https://pypi.python.org/pypi/cffi
.. _libffi: http://sourceware.org/libffi/
.. _repositories: https://repo.saltstack.com
.. __: https://github.com/saltstack/salt-pack/issues/70
.. _salt-pack-70: https://github.com/saltstack/salt-pack/issues/70
GitPython
---------
@ -934,7 +935,7 @@ match the user under which the minion is running.
.. _`post-receive hook`: http://www.git-scm.com/book/en/Customizing-Git-Git-Hooks#Server-Side-Hooks
.. _git-as-ext_pillar
.. _git-as-ext_pillar:
Using Git as an External Pillar Source
======================================

View file

@ -377,7 +377,8 @@ using the ``ca_bundle`` variable.
)
Updating CA Bundles
'''''''''''''''''''
```````````````````
The ``update_ca_bundle()`` function can be used to update the bundle file at a
specified location. If the target location is not specified, then it will
attempt to auto-detect the location of the bundle file. If the URL to download

View file

@ -82,7 +82,7 @@ Run an arbitrary shell command:
salt '*' cmd.run 'uname -a'
.. seealso:: :ref:`the full list of modules <all-salt_modules>`
.. seealso:: :ref:`the full list of modules <all-salt.modules>`
arguments
---------

View file

@ -348,7 +348,7 @@ gives you a `"Pythonic"`_ interface to building state data.
They can also be used in :mod:`file.managed <salt.states.file.managed>`
states, making file management much more dynamic and flexible. Some
examples for using templates in managed files can be found in the
documentation for the :ref:`file state <salt.states.file>`, as well as the
documentation for the :mod:`file state <salt.states.file>`, as well as the
:ref:`MooseFS example<jinja-example-moosefs>` below.

View file

@ -294,7 +294,7 @@ This will display a very large list of available functions and documentation on
them.
.. note::
Module documentation is also available :ref:`on the web <all-salt_modules>`.
Module documentation is also available :ref:`on the web <all-salt.modules>`.
These functions cover everything from shelling out to package management to
manipulating database servers. They comprise a powerful system management API
@ -304,7 +304,7 @@ of Salt.
.. note::
Salt comes with many plugin systems. The functions that are available via
the ``salt`` command are called :ref:`Execution Modules <all-salt_modules>`.
the ``salt`` command are called :ref:`Execution Modules <all-salt.modules>`.
Helpful Functions to Know

View file

@ -7,14 +7,11 @@ The macOS (Maverick) Developer Step By Step Guide To Salt Installation
This document provides a step-by-step guide to installing a Salt cluster
consisting of one master, and one minion running on a local VM hosted on macOS.
.. note::
This guide is aimed at developers who wish to run Salt in a virtual machine.
The official (Linux) walkthrough can be found
`here <http://docs.saltstack.com/topics/tutorials/walkthrough.html>`_.
The 5 Cent Salt Intro
---------------------
@ -63,18 +60,19 @@ Here's a brief overview of a Salt cluster:
that.
Before Digging In, The Architecture Of The Salt Cluster
-------------------------------------------------------
Salt Master
+++++++++++
The "Salt master" server is going to be the Mac OS machine, directly. Commands
will be run from a terminal app, so Salt will need to be installed on the Mac.
This is going to be more convenient for toying around with configuration files.
Salt Minion
+++++++++++
We'll only have one "Salt minion" server. It is going to be running on a
Virtual Machine running on the Mac, using VirtualBox. It will run an Ubuntu
distribution.
@ -194,6 +192,7 @@ There should be no errors when running the above command.
Now that the master is set, let's configure a minion on a VM.
Step 2 - Configuring The Minion VM
==================================
@ -324,6 +323,7 @@ following:
It's now time to connect the VM to the salt master
Step 3 - Connecting Master and Minion
=====================================
@ -369,7 +369,6 @@ Then copy the .pub file into the list of accepted minions:
sudo cp minion1.pub /etc/salt/pki/master/minions/minion1
Modify Vagrantfile to Use Salt Provisioner
------------------------------------------
@ -415,6 +414,7 @@ following:
You should see your minion answering the ping. It's now time to do some
configuration.
Step 4 - Configure Services to Install On the Minion
====================================================

View file

@ -8,7 +8,7 @@ Salt's Test Suite: An Introduction
This tutorial makes a couple of assumptions. The first assumption is that
you have a basic knowledge of Salt. To get up to speed, check out the
:ref:`Salt Walkthrough </topics/tutorials/walkthrough>`.
:ref:`Salt Walkthrough <tutorial-salt-walk-through>`.
The second assumption is that your Salt development environment is already
configured and that you have a basic understanding of contributing to the

View file

@ -78,7 +78,7 @@ And in Python:
}
Rule Three: Dashes
-------------------
------------------
To represent lists of items, a single dash followed by a space is used. Multiple
items are a part of the same list as a function of their having the same level of indentation.
@ -115,5 +115,4 @@ One excellent choice for experimenting with YAML parsing is: http://yaml-online-
Templating
----------
Jinja statements and expressions are allowed by default in SLS files. See
:ref:`Understanding Jinja <jinja>`.
:ref:`Understanding Jinja <understanding-jinja>`.

View file

@ -50,12 +50,16 @@ indicated above, though the model DOES NOT have to be named
# Import python libs
from __future__ import absolute_import
import logging
import os
import sys
# Import 3rd-party libs
import salt.ext.six as six
# pylint: disable=import-error
try:
import django
from django.db import connection
HAS_DJANGO = True
except Exception as exc:
# If Django is installed and is not detected, uncomment
@ -77,10 +81,22 @@ def __virtual__():
return False
def is_connection_usable():
try:
connection.connection.ping()
except Exception:
return False
else:
return True
def django_auth_setup():
'''
Prepare the connection to the Django authentication framework
'''
if django.VERSION >= (1, 7):
django.setup()
global DJANGO_AUTH_CLASS
if DJANGO_AUTH_CLASS is not None:
@ -95,21 +111,26 @@ def django_auth_setup():
django_model_name = django_model_fullname.split('.')[-1]
django_module_name = '.'.join(django_model_fullname.split('.')[0:-1])
__import__(django_module_name, globals(), locals(), 'SaltExternalAuthModel')
django_auth_module = __import__(django_module_name, globals(), locals(), 'SaltExternalAuthModel')
DJANGO_AUTH_CLASS_str = 'django_auth_module.{0}'.format(django_model_name)
DJANGO_AUTH_CLASS = eval(DJANGO_AUTH_CLASS_str) # pylint: disable=W0123
if django.VERSION >= (1, 7):
django.setup()
def auth(username, password):
'''
Simple Django auth
'''
import django.contrib.auth # pylint: disable=import-error
django_auth_path = __opts__['django_auth_path']
if django_auth_path not in sys.path:
sys.path.append(django_auth_path)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', __opts__['django_auth_settings'])
django_auth_setup()
if not is_connection_usable():
connection.close()
import django.contrib.auth # pylint: disable=import-error
user = django.contrib.auth.authenticate(username=username, password=password)
if user is not None:
if user.is_active:

View file

@ -672,6 +672,12 @@ def _manage_devices(devices, vm=None, container_ref=None, new_vm_name=None):
if device.capacityInKB < size_kb:
# expand the disk
disk_spec = _edit_existing_hard_disk_helper(device, size_kb)
elif device.capacityInKB > size_kb:
raise SaltCloudSystemExit(
'The specified disk size is smaller than the '
'size of the disk image. It must be equal to '
'or greater than the disk image'
)
if 'mode' in devices['disk'][device.deviceInfo.label]:
if devices['disk'][device.deviceInfo.label]['mode'] \

View file

@ -995,6 +995,10 @@ VALID_OPTS = {
# Whitelist specific modules to be synced
'extmod_whitelist': dict,
# django auth
'django_auth_path': str,
'django_auth_settings': str,
}
# default configurations
@ -1533,6 +1537,8 @@ DEFAULT_MASTER_OPTS = {
'ssl': None,
'extmod_whitelist': {},
'clean_dynamic_modules': True,
'django_auth_path': '',
'django_auth_settings': '',
}

View file

@ -1476,7 +1476,10 @@ class LazyLoader(salt.utils.lazy.LazyDict):
# It default's of course to the found callable attribute name
# if no alias is defined.
funcname = getattr(mod, '__func_alias__', {}).get(attr, attr)
full_funcname = '{0}.{1}'.format(module_name, funcname)
try:
full_funcname = '.'.join((module_name, funcname))
except TypeError:
full_funcname = '{0}.{1}'.format(module_name, funcname)
# Save many references for lookups
# Careful not to overwrite existing (higher priority) functions
if full_funcname not in self._dict:

View file

@ -1917,7 +1917,7 @@ class ClearFuncs(object):
name = self.loadauth.load_name(clear_load)
groups = self.loadauth.get_groups(clear_load)
eauth_config = self.opts['external_auth'][clear_load['eauth']]
if '*' not in eauth_config and name not in eauth_config:
if '^model' not in eauth_config and '*' not in eauth_config and name not in eauth_config:
found = False
for group in groups:
if "{0}%".format(group) in eauth_config:
@ -2017,7 +2017,7 @@ class ClearFuncs(object):
break
except KeyError:
pass
if '*' not in eauth_users and token['name'] not in eauth_users \
if '^model' not in eauth_users and '*' not in eauth_users and token['name'] not in eauth_users \
and not group_auth_match:
log.warning('Authentication failure of type "token" occurred.')
return ''

View file

@ -614,8 +614,8 @@ def create_image(ami_name, instance_id=None, instance_name=None, tags=None, regi
.. code-block:: bash
salt myminion boto_ec2.create_instance ami_name instance_name=myinstance
salt myminion boto_ec2.create_instance another_ami_name tags='{"mytag": "value"}' description='this is my ami'
salt myminion boto_ec2.create_image ami_name instance_name=myinstance
salt myminion boto_ec2.create_image another_ami_name tags='{"mytag": "value"}' description='this is my ami'
'''

View file

@ -220,7 +220,10 @@ def subnet_group_exists(name, tags=None, region=None, key=None, keyid=None,
rds = conn.describe_db_subnet_groups(DBSubnetGroupName=name)
return {'exists': bool(rds)}
except ClientError as e:
return {'error': salt.utils.boto3.get_error(e)}
if "DBSubnetGroupNotFoundFault" in e.message:
return {'exists': False}
else:
return {'error': salt.utils.boto3.get_error(e)}
def create(name, allocated_storage, db_instance_class, engine,

View file

@ -75,9 +75,7 @@ def usage(args=None):
return {}
if __grains__['kernel'] == 'Linux':
cmd = 'df -P'
elif __grains__['kernel'] == 'OpenBSD':
cmd = 'df -kP'
elif __grains__['kernel'] == 'AIX':
elif __grains__['kernel'] == 'OpenBSD' or __grains__['kernel'] == 'AIX':
cmd = 'df -kP'
else:
cmd = 'df'
@ -141,7 +139,10 @@ def inodeusage(args=None):
salt '*' disk.inodeusage
'''
flags = _clean_flags(args, 'disk.inodeusage')
cmd = 'df -iP'
if __grains__['kernel'] == 'AIX':
cmd = 'df -i'
else:
cmd = 'df -iP'
if flags:
cmd += ' -{0}'.format(flags)
ret = {}
@ -163,6 +164,14 @@ def inodeusage(args=None):
'use': comps[7],
'filesystem': comps[0],
}
elif __grains__['kernel'] == 'AIX':
ret[comps[6]] = {
'inodes': comps[4],
'used': comps[5],
'free': comps[2],
'use': comps[5],
'filesystem': comps[0],
}
else:
ret[comps[5]] = {
'inodes': comps[1],
@ -189,7 +198,7 @@ def percent(args=None):
'''
if __grains__['kernel'] == 'Linux':
cmd = 'df -P'
elif __grains__['kernel'] == 'OpenBSD':
elif __grains__['kernel'] == 'OpenBSD' or __grains__['kernel'] == 'AIX':
cmd = 'df -kP'
else:
cmd = 'df'
@ -201,9 +210,11 @@ def percent(args=None):
if line.startswith('Filesystem'):
continue
comps = line.split()
while not comps[1].isdigit():
while len(comps) >= 2 and not comps[1].isdigit():
comps[0] = '{0} {1}'.format(comps[0], comps[1])
comps.pop(1)
if len(comps) < 2:
continue
try:
if __grains__['kernel'] == 'Darwin':
ret[comps[8]] = comps[4]
@ -464,11 +475,18 @@ def fstype(device):
if salt.utils.which('df'):
# the fstype was not set on the block device, so inspect the filesystem
# itself for its type
df_out = __salt__['cmd.run']('df -T {0}'.format(device)).splitlines()
if len(df_out) > 1:
fs_type = df_out[1]
if fs_type:
return fs_type
if __grains__['kernel'] == 'AIX' and os.path.isfile('/usr/sysv/bin/df'):
df_out = __salt__['cmd.run']('/usr/sysv/bin/df -n {0}'.format(device)).split()
if len(df_out) > 2:
fs_type = df_out[2]
if fs_type:
return fs_type
else:
df_out = __salt__['cmd.run']('df -T {0}'.format(device)).splitlines()
if len(df_out) > 1:
fs_type = df_out[1]
if fs_type:
return fs_type
return ''

View file

@ -1214,7 +1214,7 @@ def _error_detail(data, item):
'''
err = item['errorDetail']
if 'code' in err:
msg = '{1}: {2}'.format(
msg = '{0}: {1}'.format(
item['errorDetail']['code'],
item['errorDetail']['message'],
)

View file

@ -6,6 +6,11 @@ Module for controlling Jenkins
.. versionadded:: 2016.3.0
:depends: python-jenkins_ Python module (not to be confused with jenkins_)
.. _python-jenkins: https://pypi.python.org/pypi/python-jenkins
.. _jenkins: https://pypi.python.org/pypi/jenkins
:configuration: This module can be used by either passing an api key and version
directly or by specifying both in a configuration profile in the salt
master/minion config.
@ -47,9 +52,15 @@ def __virtual__():
:return: The virtual name of the module.
'''
if HAS_JENKINS:
return __virtualname__
if hasattr(jenkins, 'Jenkins'):
return __virtualname__
else:
return (False,
'The wrong Python module appears to be installed. Please '
'make sure that \'python-jenkins\' is installed, not '
'\'jenkins\'.')
return (False, 'The jenkins execution module cannot be loaded: '
'python jenkins library is not installed.')
'python-jenkins is not installed.')
def _connect():

View file

@ -110,6 +110,27 @@ def _active_mounts(ret):
return ret
def _active_mounts_aix(ret):
'''
List active mounts on AIX systems
'''
for line in __salt__['cmd.run_stdout']('mount -p').split('\n'):
comps = re.sub(r"\s+", " ", line).split()
if comps and comps[0] == 'node' or comps[0] == '--------':
continue
if len(comps) < 8:
ret[comps[1]] = {'device': comps[0],
'fstype': comps[2],
'opts': _resolve_user_group_names(comps[6].split(','))}
else:
ret[comps[2]] = {'node': comps[0],
'device': comps[1],
'fstype': comps[3],
'opts': _resolve_user_group_names(comps[7].split(','))}
return ret
def _active_mounts_freebsd(ret):
'''
List active mounts on FreeBSD systems
@ -202,6 +223,8 @@ def active(extended=False):
ret = {}
if __grains__['os'] == 'FreeBSD':
_active_mounts_freebsd(ret)
elif __grains__['kernel'] == 'AIX':
_active_mounts_aix(ret)
elif __grains__['kernel'] == 'SunOS':
_active_mounts_solaris(ret)
elif __grains__['os'] == 'OpenBSD':

View file

@ -100,6 +100,27 @@ def getenforce():
return 'Disabled'
def getconfig():
'''
Return the selinux mode from the config file
CLI Example:
.. code-block:: bash
salt '*' selinux.getconfig
'''
try:
config = '/etc/selinux/config'
with salt.utils.fopen(config, 'r') as _fp:
for line in _fp:
if line.strip().startswith('SELINUX='):
return line.split('=')[1].capitalize().strip()
except (IOError, OSError, AttributeError):
return None
return None
def setenforce(mode):
'''
Set the SELinux enforcing mode

View file

@ -290,6 +290,60 @@ def get_config(name='root'):
)
def create_config(name=None,
subvolume=None,
fstype=None,
template=None,
extra_opts=None):
'''
Creates a new Snapper configuration
name
Name of the new Snapper configuration.
subvolume
Path to the related subvolume.
fstype
Filesystem type of the subvolume.
template
Configuration template to use. (Default: default)
extra_opts
Extra Snapper configuration opts dictionary. It will override the values provided
by the given template (if any).
CLI example:
.. code-block:: bash
salt '*' snapper.create_config name=myconfig subvolume=/foo/bar/ fstype=btrfs
salt '*' snapper.create_config name=myconfig subvolume=/foo/bar/ fstype=btrfs template="default"
salt '*' snapper.create_config name=myconfig subvolume=/foo/bar/ fstype=btrfs extra_opts='{"NUMBER_CLEANUP": False}'
'''
def raise_arg_error(argname):
raise CommandExecutionError(
'You must provide a "{0}" for the new configuration'.format(argname)
)
if not name:
raise_arg_error("name")
if not subvolume:
raise_arg_error("subvolume")
if not fstype:
raise_arg_error("fstype")
if not template:
template = ""
try:
snapper.CreateConfig(name, subvolume, fstype, template)
if extra_opts:
set_config(name, **extra_opts)
return get_config(name)
except dbus.DBusException as exc:
raise CommandExecutionError(
'Error encountered while creating the new configuration: {0}'
.format(_dbus_exception_to_reason(exc, locals()))
)
def create_snapshot(config='root', snapshot_type='single', pre_number=None,
description=None, cleanup_algorithm='number', userdata=None,
**kwargs):
@ -309,14 +363,14 @@ def create_snapshot(config='root', snapshot_type='single', pre_number=None,
cleanup_algorithm
Set the cleanup algorithm for the snapshot.
number
Deletes old snapshots when a certain number of snapshots
is reached.
timeline
Deletes old snapshots but keeps a number of hourly,
daily, weekly, monthly and yearly snapshots.
empty-pre-post
Deletes pre/post snapshot pairs with empty diffs.
number
Deletes old snapshots when a certain number of snapshots
is reached.
timeline
Deletes old snapshots but keeps a number of hourly,
daily, weekly, monthly and yearly snapshots.
empty-pre-post
Deletes pre/post snapshot pairs with empty diffs.
userdata
Set userdata for the snapshot (key-value pairs).
@ -364,6 +418,95 @@ def create_snapshot(config='root', snapshot_type='single', pre_number=None,
return new_nr
def delete_snapshot(snapshots_ids=None, config="root"):
'''
Deletes an snapshot
config
Configuration name. (Default: root)
snapshots_ids
List of the snapshots IDs to be deleted.
CLI example:
.. code-block:: bash
salt '*' snapper.delete_snapshot 54
salt '*' snapper.delete_snapshot config=root 54
salt '*' snapper.delete_snapshot config=root snapshots_ids=[54,55,56]
'''
if not snapshots_ids:
raise CommandExecutionError('Error: No snapshot ID has been provided')
try:
current_snapshots_ids = [x['id'] for x in list_snapshots(config)]
if not isinstance(snapshots_ids, list):
snapshots_ids = [snapshots_ids]
if not set(snapshots_ids).issubset(set(current_snapshots_ids)):
raise CommandExecutionError(
"Error: Snapshots '{0}' not found".format(", ".join(
[str(x) for x in set(snapshots_ids).difference(
set(current_snapshots_ids))]))
)
snapper.DeleteSnapshots(config, snapshots_ids)
return {config: {"ids": snapshots_ids, "status": "deleted"}}
except dbus.DBusException as exc:
raise CommandExecutionError(_dbus_exception_to_reason(exc, locals()))
def modify_snapshot(snapshot_id=None,
description=None,
userdata=None,
cleanup=None,
config="root"):
'''
Modify attributes of an existing snapshot.
config
Configuration name. (Default: root)
snapshot_id
ID of the snapshot to be modified.
cleanup
Change the cleanup method of the snapshot. (str)
description
Change the description of the snapshot. (str)
userdata
Change the userdata dictionary of the snapshot. (dict)
CLI example:
.. code-block:: bash
salt '*' snapper.modify_snapshot 54 description="my snapshot description"
salt '*' snapper.modify_snapshot 54 description="my snapshot description"
salt '*' snapper.modify_snapshot 54 userdata='{"foo": "bar"}'
salt '*' snapper.modify_snapshot snapshot_id=54 cleanup="number"
'''
if not snapshot_id:
raise CommandExecutionError('Error: No snapshot ID has been provided')
snapshot = get_snapshot(config=config, number=snapshot_id)
try:
# Updating only the explicitely provided attributes by the user
updated_opts = {
'description': description if description is not None else snapshot['description'],
'cleanup': cleanup if cleanup is not None else snapshot['cleanup'],
'userdata': userdata if userdata is not None else snapshot['userdata'],
}
snapper.SetSnapshot(config,
snapshot_id,
updated_opts['description'],
updated_opts['cleanup'],
updated_opts['userdata'])
return get_snapshot(config=config, number=snapshot_id)
except dbus.DBusException as exc:
raise CommandExecutionError(_dbus_exception_to_reason(exc, locals()))
def _get_num_interval(config, num_pre, num_post):
'''
Returns numerical interval based on optionals num_pre, num_post values

View file

@ -3,10 +3,12 @@
Manage users with the useradd command
.. important::
If you feel that Salt should be using this module to manage users on a
minion, and it is using a different module (or gives an error similar to
*'user.info' is not available*), see :ref:`here
<module-provider-override>`.
'''
# Import python libs

View file

@ -6,7 +6,6 @@ from __future__ import absolute_import
# Import python libs
import logging
import socket
import time
# Import salt libs
@ -41,62 +40,53 @@ def _interface_configs():
'''
cmd = ['netsh', 'interface', 'ip', 'show', 'config']
lines = __salt__['cmd.run'](cmd, python_shell=False).splitlines()
iface = ''
ip = 0
dns_flag = None
wins_flag = None
ret = {}
current_iface = None
current_ip_list = None
for line in lines:
if dns_flag:
try:
socket.inet_aton(line.strip())
ret[iface][dns_flag].append(line.strip())
dns_flag = None
continue
except socket.error as exc:
dns_flag = None
if wins_flag:
try:
socket.inet_aton(line.strip())
ret[iface][wins_flag].append(line.strip())
wins_flag = None
continue
except socket.error as exc:
wins_flag = None
line = line.strip()
if not line:
iface = ''
current_iface = None
current_ip_list = None
continue
if 'Configuration for interface' in line:
_, iface = line.rstrip('"').split('"', 1) # get iface name
ret[iface] = {}
ip = 0
current_iface = {}
ret[iface] = current_iface
continue
try:
key, val = line.split(':', 1)
except ValueError as exc:
log.debug('Could not split line. Error was {0}.'.format(exc))
continue
if 'DNS Servers' in line:
dns_flag = key.strip()
ret[iface][key.strip()] = [val.strip()]
continue
if 'WINS Servers' in line:
wins_flag = key.strip()
ret[iface][key.strip()] = [val.strip()]
continue
if 'IP Address' in key:
if 'ip_addrs' not in ret[iface]:
ret[iface]['ip_addrs'] = []
ret[iface]['ip_addrs'].append(dict([(key.strip(), val.strip())]))
continue
if 'Subnet Prefix' in key:
subnet, _, netmask = val.strip().split(' ', 2)
ret[iface]['ip_addrs'][ip]['Subnet'] = subnet.strip()
ret[iface]['ip_addrs'][ip]['Netmask'] = netmask.lstrip().rstrip(')')
ip = ip + 1
if ':' not in line:
if current_ip_list:
current_ip_list.append(line)
else:
log.warning('Cannot parse "{0}"'.format(line))
continue
key, val = line.split(':', 1)
key = key.strip()
val = val.strip()
lkey = key.lower()
if ('dns servers' in lkey) or ('wins servers' in lkey):
current_ip_list = []
current_iface[key] = current_ip_list
current_ip_list.append(val)
elif 'ip address' in lkey:
current_iface.setdefault('ip_addrs', []).append({key: val})
elif 'subnet prefix' in lkey:
subnet, _, netmask = val.split(' ', 2)
last_ip = current_iface['ip_addrs'][-1]
last_ip['Subnet'] = subnet.strip()
last_ip['Netmask'] = netmask.lstrip().rstrip(')')
else:
ret[iface][key.strip()] = val.strip()
current_iface[key] = val
return ret

View file

@ -1026,6 +1026,18 @@ class _policy_info(object):
'value_lookup': True,
},
},
'Transform': {
'Get': '_dict_lookup',
'Put': '_dict_lookup',
'GetArgs': {
'lookup': self.smb_server_name_hardening_levels,
'value_lookup': False,
},
'PutArgs': {
'lookup': self.smb_server_name_hardening_levels,
'value_lookup': True,
},
}
},
'EnableInstallerDetection': {
'Policy': 'User Account Control: Detect application '
@ -2478,6 +2490,7 @@ class _policy_info(object):
'''
minimum = 0
maximum = 1
if isinstance(val, string_types):
if val.lower() == 'not defined':
return True

View file

@ -850,6 +850,7 @@ def create_private_key(path=None,
def create_crl( # pylint: disable=too-many-arguments,too-many-locals
path=None, text=False, signing_private_key=None,
signing_private_key_passphrase=None,
signing_cert=None, revoked=None, include_expired=False,
days_valid=100, digest=''):
'''
@ -868,6 +869,9 @@ def create_crl( # pylint: disable=too-many-arguments,too-many-locals
A path or string of the private key in PEM format that will be used
to sign this crl. This is required.
signing_private_key_passphrase:
Passphrase to decrypt the private key.
signing_cert:
A certificate matching the private key that will be used to sign
this crl. This is required.
@ -971,7 +975,8 @@ def create_crl( # pylint: disable=too-many-arguments,too-many-locals
cert = OpenSSL.crypto.load_certificate(
OpenSSL.crypto.FILETYPE_PEM,
get_pem_entry(signing_cert, pem_type='CERTIFICATE'))
signing_private_key = _text_or_file(signing_private_key)
signing_private_key = _get_private_key_obj(signing_private_key,
passphrase=signing_private_key_passphrase).as_pem(cipher=None)
key = OpenSSL.crypto.load_privatekey(
OpenSSL.crypto.FILETYPE_PEM,
get_pem_entry(signing_private_key))
@ -1586,8 +1591,17 @@ def create_csr(path=None, text=False, **kwargs):
if 'public_key' not in kwargs:
kwargs['public_key'] = kwargs['private_key']
if 'private_key_passphrase' not in kwargs:
kwargs['private_key_passphrase'] = None
if 'public_key_passphrase' not in kwargs:
kwargs['public_key_passphrase'] = None
if kwargs['public_key_passphrase'] and not kwargs[
'private_key_passphrase']:
kwargs['private_key_passphrase'] = kwargs['public_key_passphrase']
if kwargs['private_key_passphrase'] and not kwargs[
'public_key_passphrase']:
kwargs['public_key_passphrase'] = kwargs['private_key_passphrase']
csr.set_pubkey(get_public_key(kwargs['public_key'],
passphrase=kwargs['public_key_passphrase'], asObj=True))
@ -1609,6 +1623,9 @@ def create_csr(path=None, text=False, **kwargs):
critical = True
extval = extval[9:]
if extname == 'subjectKeyIdentifier' and 'hash' in extval:
extval = extval.replace('hash', _get_pubkey_hash(csr))
if extname == 'subjectAltName':
extval = extval.replace('IP Address', 'IP')
@ -1628,7 +1645,7 @@ def create_csr(path=None, text=False, **kwargs):
csr.add_extensions(extstack)
csr.sign(_get_private_key_obj(kwargs['private_key'],
passphrase=kwargs['public_key_passphrase']), kwargs['algorithm'])
passphrase=kwargs['private_key_passphrase']), kwargs['algorithm'])
if path:
return write_pem(

View file

@ -2503,18 +2503,12 @@ def mod_repo(repo, basedir=None, **kwargs):
)
# Build a list of keys to be deleted
todelete = ['disabled']
todelete = []
for key in repo_opts:
if repo_opts[key] != 0 and not repo_opts[key]:
del repo_opts[key]
todelete.append(key)
# convert disabled to enabled respectively from pkgrepo state
if 'enabled' not in repo_opts:
repo_opts['enabled'] = int(str(repo_opts.pop('disabled', False)).lower() != 'true')
else:
repo_opts.pop('disabled', False)
# Add baseurl or mirrorlist to the 'todelete' list if the other was
# specified in the repo_opts
if 'mirrorlist' in repo_opts:
@ -2586,6 +2580,7 @@ def mod_repo(repo, basedir=None, **kwargs):
if key in six.iterkeys(filerepos[repo].copy()):
del filerepos[repo][key]
_bool_to_str = lambda x: '1' if x else '0'
# Old file or new, write out the repos(s)
filerepos[repo].update(repo_opts)
content = header
@ -2596,7 +2591,12 @@ def mod_repo(repo, basedir=None, **kwargs):
del filerepos[stanza]['comments']
content += '\n[{0}]'.format(stanza)
for line in six.iterkeys(filerepos[stanza]):
content += '\n{0}={1}'.format(line, filerepos[stanza][line])
content += '\n{0}={1}'.format(
line,
filerepos[stanza][line]
if not isinstance(filerepos[stanza][line], bool)
else _bool_to_str(filerepos[stanza][line])
)
content += '\n{0}\n'.format(comments)
with salt.utils.fopen(repofile, 'w') as fileout:
@ -2642,9 +2642,6 @@ def _parse_repo_file(filename):
'Failed to parse line in %s, offending line was '
'\'%s\'', filename, line.rstrip()
)
# YUM uses enabled field - create the disabled field so that comparisons works correctly in state
if comps[0].strip() == 'enabled':
repos[repo]['disabled'] = comps[1] != "1"
return (header, repos)

View file

@ -1686,16 +1686,19 @@ class Login(LowDataAdapter):
try:
eauth = self.opts.get('external_auth', {}).get(token['eauth'], {})
# Get sum of '*' perms, user-specific perms, and group-specific perms
perms = eauth.get(token['name'], [])
perms.extend(eauth.get('*', []))
if token['eauth'] == 'django' and '^model' in eauth:
perms = token['auth_list']
else:
# Get sum of '*' perms, user-specific perms, and group-specific perms
perms = eauth.get(token['name'], [])
perms.extend(eauth.get('*', []))
if 'groups' in token and token['groups']:
user_groups = set(token['groups'])
eauth_groups = set([i.rstrip('%') for i in eauth.keys() if i.endswith('%')])
if 'groups' in token and token['groups']:
user_groups = set(token['groups'])
eauth_groups = set([i.rstrip('%') for i in eauth.keys() if i.endswith('%')])
for group in user_groups & eauth_groups:
perms.extend(eauth['{0}%'.format(group)])
for group in user_groups & eauth_groups:
perms.extend(eauth['{0}%'.format(group)])
if not perms:
logger.debug("Eauth permission list not found.")

View file

@ -190,7 +190,7 @@ def _format_host(host, data):
# Verify that the needed data is present
data_tmp = {}
for tname, info in six.iteritems(data):
if isinstance(info, dict) and tname is not 'changes' and '__run_num__' not in info:
if isinstance(info, dict) and tname is not 'changes' and info and '__run_num__' not in info:
err = (u'The State execution failed to record the order '
'in which all states were executed. The state '
'return missing data is:')

View file

@ -56,6 +56,10 @@ the repo's URL. Configuration details can be found below.
Configuring git_pillar for Salt releases before 2015.8.0
========================================================
.. note::
This legacy configuration for git_pillar will no longer be supported as of
the **Oxygen** release of Salt.
For Salt releases earlier than :ref:`2015.8.0 <release-2015-8-0>`,
GitPython is the only supported provider for git_pillar. Individual
repositories can be configured under the :conf_master:`ext_pillar`
@ -540,6 +544,14 @@ def _legacy_git_pillar(minion_id, repo_string, pillar_dirs):
'''
Support pre-Beryllium config schema
'''
salt.utils.warn_until(
'Oxygen',
'The git ext_pillar configuration is deprecated. Please refer to the '
'documentation at '
'https://docs.saltstack.com/en/latest/ref/pillar/all/salt.pillar.git_pillar.html '
'for more information. This configuration will no longer be supported '
'as of the Oxygen release of Salt.'
)
if pillar_dirs is None:
return
# split the branch, repo name and optional extra (key=val) parameters.

View file

@ -184,7 +184,7 @@ def ext_pillar(minion_id,
pil = Pillar(opts, __grains__, minion_id, environment)
compiled_pillar = pil.compile_pillar()
compiled_pillar = pil.compile_pillar(ext=False)
return compiled_pillar

View file

@ -193,4 +193,4 @@ def ext_pillar(minion_id,
opts = deepcopy(__opts__)
opts['pillar_roots'][branch] = [pillar_dir]
pil = Pillar(opts, __grains__, minion_id, branch)
return pil.compile_pillar()
return pil.compile_pillar(ext=False)

View file

@ -2,7 +2,7 @@
'''
Jinja loading utils to enable a more powerful backend for jinja templates
For Jinja usage information see :ref:`Understanding Jinja <jinja>`.
For Jinja usage information see :ref:`Understanding Jinja <understanding-jinja>`.
'''
# Import python libs

View file

@ -5,7 +5,7 @@ Return data to a postgresql server
.. note::
:mod:`returners.postgres_local_cache <salt.returners.postgres_local_cache>`
is recommended instead of this module when using PostgreSQL as a
:ref:`master job cache <external-master-cache>`. These two modules
:ref:`master job cache <external-job-cache>`. These two modules
provide different functionality so you should compare each to see which
module best suits your particular needs.

View file

@ -6,7 +6,7 @@ cope with scale.
.. note::
:mod:`returners.postgres <salt.returners.postgres>` is also available if
you are not using PostgreSQL as a :ref:`master job cache
<external-master-cache>`. These two modules provide different
<external-job-cache>`. These two modules provide different
functionality so you should compare each to see which module best suits
your particular needs.

View file

@ -36,7 +36,7 @@ def envs(backend=None, sources=False):
salt-run fileserver.envs git
'''
fileserver = salt.fileserver.Fileserver(__opts__)
return fileserver.envs(back=backend, sources=sources)
return sorted(fileserver.envs(back=backend, sources=sources))
def clear_file_list_cache(saltenv=None, backend=None):

View file

@ -7,14 +7,14 @@ execution modules available
on the salt master.
.. _salt_salt_runner:
Salt's execution modules are normally available
on the salt minion. Use this runner to call
execution modules on the salt master.
Salt :ref:`execution modules <writing-execution-modules>`
are the functions called by the ``salt`` command.
Execution modules can be
called with ``salt-run``:
Execution modules can be called with ``salt-run``:
.. code-block:: bash
@ -45,7 +45,7 @@ log = logging.getLogger(__name__) # pylint: disable=invalid-name
def cmd(fun, *args, **kwargs):
'''
Execute ``fun`` with the given ``args`` and ``kwargs``.
Parameter ``fun`` should be the string :ref:`name <all-salt_modules>`
Parameter ``fun`` should be the string :ref:`name <all-salt.modules>`
of the execution module to call.
Note that execution modules will be *loaded every time*

View file

@ -31,18 +31,18 @@ config:
.. code-block:: yaml
myprofile:
keyid: GKTADJGHEIQSXMKKRBJ08H
key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
region: us-east-1
keyid: GKTADJGHEIQSXMKKRBJ08H
key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
region: us-east-1
.. code-block:: yaml
Ensure Apigateway API exists:
boto_apigateway.present:
- name: myfunction
- region: us-east-1
- keyid: GKTADJGHEIQSXMKKRBJ08H
- key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
boto_apigateway.present:
- name: myfunction
- region: us-east-1
- keyid: GKTADJGHEIQSXMKKRBJ08H
- key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
'''

View file

@ -485,21 +485,17 @@ def subnet_group_present(name, description, subnet_ids=None, subnet_names=None,
exists = __salt__['boto_rds.subnet_group_exists'](name=name, tags=tags, region=region, key=key,
keyid=keyid, profile=profile)
if not exists:
if not exists.get('exists'):
if __opts__['test']:
ret['comment'] = 'Subnet group {0} is set to be created.'.format(name)
ret['result'] = None
return ret
if not r.get('created'):
ret['result'] = False
ret['comment'] = 'Failed to create {0} subnet group.'.format(r['error']['message'])
return ret
created = __salt__['boto_rds.create_subnet_group'](name=name,
description=description,
subnet_ids=subnet_ids,
tags=tags, region=region,
key=key, keyid=keyid,
profile=profile)
description=description,
subnet_ids=subnet_ids,
tags=tags, region=region,
key=key, keyid=keyid,
profile=profile)
if not created:
ret['result'] = False
@ -508,6 +504,7 @@ def subnet_group_present(name, description, subnet_ids=None, subnet_names=None,
ret['changes']['old'] = None
ret['changes']['new'] = name
ret['comment'] = 'Subnet {0} created.'.format(name)
return ret
else:
ret['comment'] = 'Subnet {0} present.'.format(name)
@ -668,7 +665,7 @@ def parameter_present(name, db_parameter_group_family, description, parameters=N
'changes': {}
}
res = __salt__['boto_rds.parameter_group_exists'](name=name, tags=tags, region=region, key=key,
keyid=keyid, profile=profile)
keyid=keyid, profile=profile)
if not res.get('exists'):
if __opts__['test']:
ret['comment'] = 'Parameter group {0} is set to be created.'.format(name)

View file

@ -589,7 +589,7 @@ def wait_script(name,
**no**, **on**, **off**, **true**, and **false** are all loaded as
boolean ``True`` and ``False`` values, and must be enclosed in
quotes to be used as strings. More info on this (and other) PyYAML
idiosyncrasies can be found :ref:`here <yaml-idiosyncrasies.>`.
idiosyncrasies can be found :ref:`here <yaml-idiosyncrasies>`.
Variables as values are not evaluated. So $PATH in the following
example is a literal '$PATH':

View file

@ -427,18 +427,19 @@ def mounted(name,
opts.remove('remount')
if real_device not in device_list:
# name matches but device doesn't - need to umount
_device_mismatch_is_ignored = False
_device_mismatch_is_ignored = None
for regex in list(device_name_regex):
for _device in device_list:
if re.match(regex, _device):
_device_mismatch_is_ignored = _device
break
if __opts__['test']:
ret['result'] = None
ret['comment'] = "An umount would have been forced " \
+ "because devices do not match. Watched: " \
+ device
elif _device_mismatch_is_ignored is True:
ret['result'] = None
elif _device_mismatch_is_ignored:
ret['result'] = True
ret['comment'] = "An umount will not be forced " \
+ "because device matched device_name_regex: " \
+ _device_mismatch_is_ignored

View file

@ -110,7 +110,7 @@ def managed(name, ppa=None, **kwargs):
<salt.modules.yumpkg>`, :mod:`apt <salt.modules.aptpkg>`, and :mod:`zypper
<salt.modules.zypper>` repositories are supported.
**YUM OR ZYPPER-BASED SYSTEMS**
**YUM/DNF/ZYPPER-BASED SYSTEMS**
.. note::
One of ``baseurl`` or ``mirrorlist`` below is required. Additionally,
@ -124,6 +124,16 @@ def managed(name, ppa=None, **kwargs):
repo. Secondly, it will be the name of the file as stored in
/etc/yum.repos.d (e.g. ``/etc/yum.repos.d/foo.conf``).
enabled : True
Whether or not the repo is enabled. Can be specified as True/False or
1/0.
disabled : False
Included to reduce confusion due to APT's use of the ``disabled``
argument. If this is passed for a yum/dnf/zypper-based distro, then the
reverse will be passed as ``enabled``. For example passing
``disabled=True`` will assume ``enabled=False``.
humanname
This is used as the "name" value in the repo file in
``/etc/yum.repos.d/`` (or ``/etc/zypp/repos.d`` for SUSE distros).
@ -201,10 +211,16 @@ def managed(name, ppa=None, **kwargs):
'deb http://us.archive.ubuntu.com/ubuntu precise main':
pkgrepo.managed
disabled
disabled : False
Toggles whether or not the repo is used for resolving dependencies
and/or installing packages.
enabled : True
Included to reduce confusion due to yum/dnf/zypper's use of the
``enabled`` argument. If this is passed for an APT-based distro, then
the reverse will be passed as ``disabled``. For example, passing
``enabled=False`` will assume ``disabled=False``.
comps
On apt-based systems, comps dictate the types of packages to be
installed from the repository (e.g. main, nonfree, ...). For
@ -279,14 +295,19 @@ def managed(name, ppa=None, **kwargs):
'intended.')
return ret
if 'enabled' in kwargs:
salt.utils.warn_until(
'Nitrogen',
'The `enabled` argument has been deprecated in favor of '
'`disabled`.'
)
enabled = kwargs.pop('enabled', None)
disabled = kwargs.pop('disabled', None)
if enabled is not None and disabled is not None:
ret['result'] = False
ret['comment'] = 'Only one of enabled/disabled is allowed'
return ret
elif enabled is None and disabled is None:
# If neither argument was passed we assume the repo will be enabled
enabled = True
repo = name
os_family = __grains__['os_family'].lower()
if __grains__['os'] in ('Ubuntu', 'Mint'):
if ppa is not None:
# overload the name/repo value for PPAs cleanly
@ -296,26 +317,26 @@ def managed(name, ppa=None, **kwargs):
except TypeError:
repo = ':'.join(('ppa', str(ppa)))
elif __grains__['os_family'].lower() in ('redhat', 'suse'):
kwargs['disabled'] = not salt.utils.is_true(enabled) \
if enabled is not None \
else salt.utils.is_true(disabled)
elif os_family in ('redhat', 'suse'):
if 'humanname' in kwargs:
kwargs['name'] = kwargs.pop('humanname')
_val = lambda x: '1' if salt.utils.is_true(x) else '0'
if 'disabled' in kwargs:
if 'enabled' in kwargs:
ret['result'] = False
ret['comment'] = 'Only one of enabled/disabled is permitted'
return ret
_reverse = lambda x: '1' if x == '0' else '0'
kwargs['enabled'] = _reverse(_val(kwargs.pop('disabled')))
elif 'enabled' in kwargs:
kwargs['enabled'] = _val(kwargs['enabled'])
if 'name' not in kwargs:
# Fall back to the repo name if humanname not provided
kwargs['name'] = repo
# Replace 'enabled' from kwargs with 'disabled'
enabled = kwargs.pop('enabled', True)
kwargs['disabled'] = not salt.utils.is_true(enabled)
kwargs['enabled'] = not salt.utils.is_true(disabled) \
if disabled is not None \
else salt.utils.is_true(enabled)
elif os_family == 'nilinuxrt':
# opkg is the pkg virtual
kwargs['enabled'] = not salt.utils.is_true(disabled) \
if disabled is not None \
else salt.utils.is_true(enabled)
for kwarg in _STATE_INTERNAL_KEYWORDS:
kwargs.pop(kwarg, None)
@ -340,11 +361,10 @@ def managed(name, ppa=None, **kwargs):
else:
sanitizedkwargs = kwargs
if __grains__['os_family'] == 'Debian':
if os_family == 'debian':
repo = _strip_uri(repo)
if pre:
needs_update = False
for kwarg in sanitizedkwargs:
if kwarg not in pre:
if kwarg == 'enabled':
@ -352,33 +372,40 @@ def managed(name, ppa=None, **kwargs):
# not explicitly set, so we don't need to update the repo
# if it's desired to be enabled and the 'enabled' key is
# missing from the repo definition
if __grains__['os_family'] == 'RedHat':
if os_family == 'redhat':
if not salt.utils.is_true(sanitizedkwargs[kwarg]):
needs_update = True
break
else:
needs_update = True
break
else:
needs_update = True
break
elif kwarg == 'comps':
if sorted(sanitizedkwargs[kwarg]) != sorted(pre[kwarg]):
needs_update = True
elif kwarg == 'line' and __grains__['os_family'] == 'Debian':
break
elif kwarg == 'line' and os_family == 'debian':
# split the line and sort everything after the URL
sanitizedsplit = sanitizedkwargs[kwarg].split()
sanitizedsplit[3:] = sorted(sanitizedsplit[3:])
reposplit = pre[kwarg].split()
reposplit[3:] = sorted(reposplit[3:])
if sanitizedsplit != reposplit:
needs_update = True
break
if 'comments' in kwargs:
_line = pre[kwarg].split('#')
if str(kwargs['comments']) not in _line:
needs_update = True
break
else:
if str(sanitizedkwargs[kwarg]) != str(pre[kwarg]):
needs_update = True
if not needs_update:
if os_family in ('redhat', 'suse') \
and any(isinstance(x, bool) for x in
(sanitizedkwargs[kwarg], pre[kwarg])):
# This check disambiguates 1/0 from True/False
if salt.utils.is_true(sanitizedkwargs[kwarg]) != \
salt.utils.is_true(pre[kwarg]):
break
else:
if str(sanitizedkwargs[kwarg]) != str(pre[kwarg]):
break
else:
ret['result'] = True
ret['comment'] = ('Package repo \'{0}\' already configured'
.format(name))
@ -399,7 +426,7 @@ def managed(name, ppa=None, **kwargs):
pass
try:
if __grains__['os_family'] == 'Debian':
if os_family == 'debian':
__salt__['pkg.mod_repo'](repo, saltenv=__env__, **kwargs)
else:
__salt__['pkg.mod_repo'](repo, **kwargs)

View file

@ -94,7 +94,14 @@ def mode(name):
if tmode == 'unknown':
ret['comment'] = '{0} is not an accepted mode'.format(name)
return ret
# Either the current mode in memory or a non-matching config value
# will trigger setenforce
mode = __salt__['selinux.getenforce']()
config = __salt__['selinux.getconfig']()
# Just making sure the oldmode reflects the thing that didn't match tmode
if mode == tmode and mode != config and tmode != config:
mode = config
if mode == tmode:
ret['result'] = True
ret['comment'] = 'SELinux is already in {0} mode'.format(tmode)
@ -109,7 +116,7 @@ def mode(name):
return ret
oldmode, mode = mode, __salt__['selinux.setenforce'](tmode)
if mode == tmode:
if mode == tmode or (tmode == 'Disabled' and __salt__['selinux.getconfig']() == tmode):
ret['result'] = True
ret['comment'] = 'SELinux has been set to {0} mode'.format(tmode)
ret['changes'] = {'old': oldmode,

View file

@ -168,6 +168,11 @@ import salt.utils
# Import 3rd-party libs
import salt.ext.six as six
try:
from M2Crypto.RSA import RSAError
except ImportError:
pass
def __virtual__():
'''
@ -221,7 +226,8 @@ def _get_file_args(name, **kwargs):
return file_args, extra_args
def _check_private_key(name, bits=2048, passphrase=None, new=False):
def _check_private_key(name, bits=2048, passphrase=None,
new=False, overwrite=False):
current_bits = 0
if os.path.isfile(name):
try:
@ -229,6 +235,10 @@ def _check_private_key(name, bits=2048, passphrase=None, new=False):
private_key=name, passphrase=passphrase)
except salt.exceptions.SaltInvocationError:
pass
except RSAError:
if not overwrite:
raise salt.exceptions.CommandExecutionError(
'The provided passphrase cannot decrypt the private key.')
return current_bits == bits and not new
@ -238,6 +248,7 @@ def private_key_managed(name,
passphrase=None,
cipher='aes_128_cbc',
new=False,
overwrite=False,
verbose=True,
**kwargs):
'''
@ -259,6 +270,9 @@ def private_key_managed(name,
Always create a new key. Defaults to False.
Combining new with :mod:`prereq <salt.states.requsities.preqreq>`, or when used as part of a `managed_private_key` can allow key rotation whenever a new certificiate is generated.
overwrite:
Overwrite an existing private key if the provided passphrase cannot decrypt it.
verbose:
Provide visual feedback on stdout, dots while key is generated.
Default is True.
@ -286,7 +300,8 @@ def private_key_managed(name,
'''
file_args, kwargs = _get_file_args(name, **kwargs)
new_key = False
if _check_private_key(name, bits, passphrase, new):
if _check_private_key(
name, bits=bits, passphrase=passphrase, new=new, overwrite=overwrite):
file_args['contents'] = __salt__['x509.get_pem_entry'](
name, pem_type='RSA PRIVATE KEY')
else:
@ -329,7 +344,11 @@ def csr_managed(name,
- L: Salt Lake City
- keyUsage: 'critical dataEncipherment'
'''
old = __salt__['x509.read_csr'](name)
try:
old = __salt__['x509.read_csr'](name)
except salt.exceptions.SaltInvocationError:
old = '{0} is not a valid csr.'.format(name)
file_args, kwargs = _get_file_args(name, **kwargs)
file_args['contents'] = __salt__['x509.create_csr'](text=True, **kwargs)
@ -410,6 +429,7 @@ def certificate_managed(name,
private_key_args = {
'name': name,
'new': False,
'overwrite': False,
'bits': 2048,
'passphrase': None,
'cipher': 'aes_128_cbc',
@ -423,9 +443,10 @@ def certificate_managed(name,
private_key_args['new'] = False
if _check_private_key(private_key_args['name'],
private_key_args['bits'],
private_key_args['passphrase'],
private_key_args['new']):
bits=private_key_args['bits'],
passphrase=private_key_args['passphrase'],
new=private_key_args['new'],
overwrite=private_key_args['overwrite']):
private_key = __salt__['x509.get_pem_entry'](
private_key_args['name'], pem_type='RSA PRIVATE KEY')
else:
@ -551,6 +572,7 @@ def certificate_managed(name,
def crl_managed(name,
signing_private_key,
signing_private_key_passphrase=None,
signing_cert=None,
revoked=None,
days_valid=100,
@ -568,6 +590,9 @@ def crl_managed(name,
The private key that will be used to sign this crl. This is
usually your CA's private key.
signing_private_key_passphrase:
Passphrase to decrypt the private key.
signing_cert:
The certificate of the authority that will be used to sign this crl.
This is usually your CA's certificate.
@ -637,7 +662,7 @@ def crl_managed(name,
else:
current = '{0} does not exist.'.format(name)
new_crl = __salt__['x509.create_crl'](text=True, signing_private_key=signing_private_key,
new_crl = __salt__['x509.create_crl'](text=True, signing_private_key=signing_private_key, signing_private_key_passphrase=signing_private_key_passphrase,
signing_cert=signing_cert, revoked=revoked, days_valid=days_valid, digest=digest, include_expired=include_expired)
new = __salt__['x509.read_crl'](crl=new_crl)

View file

@ -121,7 +121,8 @@ class MasterPillarUtil(object):
log.debug('Skipping cached mine data minion_data_cache'
'and enfore_mine_cache are both disabled.')
return mine_data
minion_ids = self.cache.list('minions')
if not minion_ids:
minion_ids = self.cache.list('minions')
for minion_id in minion_ids:
if not salt.utils.verify.valid_id(self.opts, minion_id):
continue
@ -139,7 +140,8 @@ class MasterPillarUtil(object):
log.debug('Skipping cached data because minion_data_cache is not '
'enabled.')
return grains, pillars
minion_ids = self.cache.list('minions')
if not minion_ids:
minion_ids = self.cache.list('minions')
for minion_id in minion_ids:
if not salt.utils.verify.valid_id(self.opts, minion_id):
continue

View file

@ -101,7 +101,7 @@ def _read_proc_file(path, opts):
except IOError:
pass
return None
if opts['multiprocessing']:
if opts.get('multiprocessing'):
if data.get('pid') == pid:
return None
else:

View file

@ -1341,23 +1341,23 @@ def _netbsd_remotes_on(port, which_end):
Parses output of shell 'sockstat' (NetBSD)
to get connections
$ sudo sockstat -4
$ sudo sockstat -4 -n
USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS
root python2.7 1456 29 tcp4 *.4505 *.*
root python2.7 1445 17 tcp4 *.4506 *.*
root python2.7 1294 14 tcp4 127.0.0.1.11813 127.0.0.1.4505
root python2.7 1294 41 tcp4 127.0.0.1.61115 127.0.0.1.4506
root python2.7 1456 29 tcp *.4505 *.*
root python2.7 1445 17 tcp *.4506 *.*
root python2.7 1294 14 tcp 127.0.0.1.11813 127.0.0.1.4505
root python2.7 1294 41 tcp 127.0.0.1.61115 127.0.0.1.4506
$ sudo sockstat -4 -c -p 4506
$ sudo sockstat -4 -c -n -p 4506
USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS
root python2.7 1294 41 tcp4 127.0.0.1.61115 127.0.0.1.4506
root python2.7 1294 41 tcp 127.0.0.1.61115 127.0.0.1.4506
'''
port = int(port)
remotes = set()
try:
cmd = salt.utils.shlex_split('sockstat -4 -c -p {0}'.format(port))
cmd = salt.utils.shlex_split('sockstat -4 -c -n -p {0}'.format(port))
data = subprocess.check_output(cmd) # pylint: disable=minimum-python-version
except subprocess.CalledProcessError as ex:
log.error('Failed "sockstat" with returncode = {0}'.format(ex.returncode))
@ -1369,7 +1369,7 @@ def _netbsd_remotes_on(port, which_end):
chunks = line.split()
if not chunks:
continue
# ['root', 'python2.7', '1456', '37', 'tcp4',
# ['root', 'python2.7', '1456', '37', 'tcp',
# '127.0.0.1.4505-', '127.0.0.1.55703']
# print chunks
if 'COMMAND' in chunks[1]:

View file

@ -738,31 +738,6 @@ class Build(build):
class Install(install):
user_options = install.user_options + [
('salt-transport=', None, 'The transport to prepare salt for. Choices are \'zeromq\' '
'\'raet\' or \'both\'. Defaults to \'zeromq\'', 'zeromq'),
('salt-root-dir=', None,
'Salt\'s pre-configured root directory'),
('salt-config-dir=', None,
'Salt\'s pre-configured configuration directory'),
('salt-cache-dir=', None,
'Salt\'s pre-configured cache directory'),
('salt-sock-dir=', None,
'Salt\'s pre-configured socket directory'),
('salt-srv-root-dir=', None,
'Salt\'s pre-configured service directory'),
('salt-base-file-roots-dir=', None,
'Salt\'s pre-configured file roots directory'),
('salt-base-pillar-roots-dir=', None,
'Salt\'s pre-configured pillar roots directory'),
('salt-base-master-roots-dir=', None,
'Salt\'s pre-configured master roots directory'),
('salt-logs-dir=', None,
'Salt\'s pre-configured logs directory'),
('salt-pidfile-dir=', None,
'Salt\'s pre-configured pidfiles directory'),
]
def initialize_options(self):
install.initialize_options(self)

View file

@ -7,6 +7,7 @@
'''
# Import python libs
from __future__ import absolute_import, print_function
from distutils.version import LooseVersion as _LooseVersion
# Import Salt Testing Libs
from salttesting import TestCase, skipIf
@ -23,8 +24,10 @@ try:
import jsonschema
import jsonschema.exceptions
HAS_JSONSCHEMA = True
JSONSCHEMA_VERSION = _LooseVersion(jsonschema.__version__)
except ImportError:
HAS_JSONSCHEMA = False
JSONSCHEMA_VERSION = _LooseVersion('0')
class RoosterEntryConfigTest(TestCase):
@ -296,7 +299,13 @@ class RosterItemTest(TestCase):
ssh_schemas.RosterItem.serialize(),
format_checker=jsonschema.FormatChecker()
)
self.assertIn(
'Additional properties are not allowed (\'target-1:1\' was unexpected)',
excinfo.exception.message
)
if JSONSCHEMA_VERSION < _LooseVersion('2.6.0'):
self.assertIn(
'Additional properties are not allowed (\'target-1:1\' was unexpected)',
excinfo.exception.message
)
else:
self.assertIn(
'\'target-1:1\' does not match any of the regexes',
excinfo.exception.message
)

View file

@ -202,6 +202,26 @@ class SnapperTestCase(TestCase):
self.assertEqual(snapper.status_to_string(128), ["extended attributes changed"])
self.assertEqual(snapper.status_to_string(256), ["ACL info changed"])
@patch('salt.modules.snapper.snapper.CreateConfig', MagicMock())
@patch('salt.modules.snapper.snapper.GetConfig', MagicMock(return_value=DBUS_RET['ListConfigs'][0]))
def test_create_config(self):
opts = {
'name': 'testconfig',
'subvolume': '/foo/bar/',
'fstype': 'btrfs',
'template': 'mytemplate',
'extra_opts': {"NUMBER_CLEANUP": False},
}
with patch('salt.modules.snapper.set_config', MagicMock()) as set_config_mock:
self.assertEqual(snapper.create_config(**opts), DBUS_RET['ListConfigs'][0])
set_config_mock.assert_called_with("testconfig", **opts['extra_opts'])
with patch('salt.modules.snapper.set_config', MagicMock()) as set_config_mock:
del opts['extra_opts']
self.assertEqual(snapper.create_config(**opts), DBUS_RET['ListConfigs'][0])
assert not set_config_mock.called
self.assertRaises(CommandExecutionError, snapper.create_config)
@patch('salt.modules.snapper.snapper.CreateSingleSnapshot', MagicMock(return_value=1234))
@patch('salt.modules.snapper.snapper.CreatePreSnapshot', MagicMock(return_value=1234))
@patch('salt.modules.snapper.snapper.CreatePostSnapshot', MagicMock(return_value=1234))
@ -216,6 +236,36 @@ class SnapperTestCase(TestCase):
}
self.assertEqual(snapper.create_snapshot(**opts), 1234)
@patch('salt.modules.snapper.snapper.DeleteSnapshots', MagicMock())
@patch('salt.modules.snapper.snapper.ListSnapshots', MagicMock(return_value=DBUS_RET['ListSnapshots']))
def test_delete_snapshot_id_success(self):
self.assertEqual(snapper.delete_snapshot(snapshots_ids=43), {"root": {"ids": [43], "status": "deleted"}})
self.assertEqual(snapper.delete_snapshot(snapshots_ids=[42, 43]), {"root": {"ids": [42, 43], "status": "deleted"}})
@patch('salt.modules.snapper.snapper.DeleteSnapshots', MagicMock())
@patch('salt.modules.snapper.snapper.ListSnapshots', MagicMock(return_value=DBUS_RET['ListSnapshots']))
def test_delete_snapshot_id_fail(self):
self.assertRaises(CommandExecutionError, snapper.delete_snapshot)
self.assertRaises(CommandExecutionError, snapper.delete_snapshot, snapshots_ids=1)
self.assertRaises(CommandExecutionError, snapper.delete_snapshot, snapshots_ids=[1, 2])
@patch('salt.modules.snapper.snapper.SetSnapshot', MagicMock())
def test_modify_snapshot(self):
_ret = {
'userdata': {'userdata2': 'uservalue2'},
'description': 'UPDATED DESCRIPTION', 'timestamp': 1457006571,
'cleanup': 'number', 'user': 'root', 'type': 'pre', 'id': 42
}
_opts = {
'config': 'root',
'snapshot_id': 42,
'cleanup': 'number',
'description': 'UPDATED DESCRIPTION',
'userdata': {'userdata2': 'uservalue2'},
}
with patch('salt.modules.snapper.get_snapshot', MagicMock(side_effect=[DBUS_RET['ListSnapshots'][0], _ret])):
self.assertDictEqual(snapper.modify_snapshot(**_opts), _ret)
@patch('salt.modules.snapper._get_last_snapshot', MagicMock(return_value={'id': 42}))
def test__get_num_interval(self):
self.assertEqual(snapper._get_num_interval(config=None, num_pre=None, num_post=None), (42, 0)) # pylint: disable=protected-access

View file

@ -65,12 +65,12 @@ class WinShadowTestCase(TestCase):
Test if it return configs for all interfaces.
'''
ret = {'Ethernet': {'DHCP enabled': 'Yes',
'DNS servers configured through DHCP': '1.2.3.4',
'DNS servers configured through DHCP': ['1.2.3.4'],
'Default Gateway': '1.2.3.1',
'Gateway Metric': '0',
'InterfaceMetric': '20',
'Register with which suffix': 'Primary only',
'WINS servers configured through DHCP': 'None',
'WINS servers configured through DHCP': ['None'],
'ip_addrs': [{'IP Address': '1.2.3.74',
'Netmask': '255.255.255.0',
'Subnet': '1.2.3.0/24'}]}}
@ -86,11 +86,11 @@ class WinShadowTestCase(TestCase):
Test if it return the configuration of a network interface.
'''
ret = {'DHCP enabled': 'Yes',
'DNS servers configured through DHCP': '1.2.3.4',
'DNS servers configured through DHCP': ['1.2.3.4'],
'Default Gateway': '1.2.3.1', 'Gateway Metric': '0',
'InterfaceMetric': '20',
'Register with which suffix': 'Primary only',
'WINS servers configured through DHCP': 'None',
'WINS servers configured through DHCP': ['None'],
'ip_addrs': [{'IP Address': '1.2.3.74',
'Netmask': '255.255.255.0',
'Subnet': '1.2.3.0/24'}]}

View file

@ -47,6 +47,7 @@ class SelinuxTestCase(TestCase):
mock_pr = MagicMock(side_effect=['Permissive', 'Enforcing'])
with patch.dict(selinux.__salt__,
{'selinux.getenforce': mock_en,
'selinux.getconfig': mock_en,
'selinux.setenforce': mock_pr}):
comt = ('SELinux is already in Enforcing mode')
ret = {'name': 'Enforcing', 'comment': comt, 'result': True, 'changes': {}}

View file

@ -9,7 +9,7 @@ import copy
import json
import yaml
from distutils.version import LooseVersion
from distutils.version import LooseVersion as _LooseVersion
# Import Salt Testing Libs
from salttesting import TestCase, skipIf
@ -25,10 +25,10 @@ try:
import jsonschema
import jsonschema.exceptions
HAS_JSONSCHEMA = True
JSONSCHEMA_VERSION = jsonschema.__version__
JSONSCHEMA_VERSION = _LooseVersion(jsonschema.__version__)
except ImportError:
JSONSCHEMA_VERSION = ''
HAS_JSONSCHEMA = False
JSONSCHEMA_VERSION = _LooseVersion('0')
# pylint: disable=unused-import
@ -752,8 +752,7 @@ class ConfigTestCase(TestCase):
}
)
@skipIf(HAS_JSONSCHEMA is False, 'The \'jsonschema\' library is missing')
@skipIf(HAS_JSONSCHEMA and LooseVersion(jsonschema.__version__) <= LooseVersion('2.5.0'), 'Requires jsonschema 2.5.0 or greater')
@skipIf(JSONSCHEMA_VERSION <= _LooseVersion('2.5.0'), 'Requires jsonschema 2.5.0 or greater')
def test_ipv4_config_validation(self):
class TestConf(schema.Schema):
item = schema.IPv4Item(title='Item', description='Item description')
@ -1705,7 +1704,14 @@ class ConfigTestCase(TestCase):
with self.assertRaises(jsonschema.exceptions.ValidationError) as excinfo:
jsonschema.validate({'item': {'color': 'green', 'sides': 4, 'surfaces': 4}}, TestConf.serialize())
self.assertIn('Additional properties are not allowed', excinfo.exception.message)
if JSONSCHEMA_VERSION < _LooseVersion('2.6.0'):
self.assertIn(
'Additional properties are not allowed',
excinfo.exception.message)
else:
self.assertIn(
'\'surfaces\' does not match any of the regexes',
excinfo.exception.message)
class TestConf(schema.Schema):
item = schema.DictItem(