mirror of
https://github.com/saltstack/salt.git
synced 2025-04-16 17:50:20 +00:00
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:
commit
609e6e4b23
78 changed files with 806 additions and 282 deletions
|
@ -1,3 +1,6 @@
|
|||
.. _glossary:
|
||||
|
||||
========
|
||||
Glossary
|
||||
========
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
========================
|
||||
============================
|
||||
salt.cloud.clouds.virtualbox
|
||||
========================
|
||||
============================
|
||||
|
||||
.. automodule:: salt.cloud.clouds.virtualbox
|
||||
:members:
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
.. _configuration-file-examples:
|
||||
|
||||
===========================
|
||||
Configuration file examples
|
||||
===========================
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.. _all-salt_modules:
|
||||
.. _all-salt.modules:
|
||||
|
||||
=================
|
||||
execution modules
|
||||
|
|
|
@ -3,4 +3,3 @@ salt.modules.cytest module
|
|||
|
||||
.. automodule:: salt.modules.cytest
|
||||
:members:
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>`.
|
||||
|
|
|
@ -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>`
|
||||
|
|
|
@ -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
|
||||
===========
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.. _jinja:
|
||||
.. _understanding-jinja:
|
||||
|
||||
===================
|
||||
Understanding Jinja
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.. _external-master-cache:
|
||||
.. _external-job-cache:
|
||||
|
||||
=========================================
|
||||
Storing Job Results in an External System
|
||||
|
|
|
@ -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>`.
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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``.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
======================================
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
---------
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
====================================================
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>`.
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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'] \
|
||||
|
|
|
@ -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': '',
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 ''
|
||||
|
|
|
@ -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'
|
||||
|
||||
'''
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 ''
|
||||
|
||||
|
|
|
@ -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'],
|
||||
)
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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':
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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.")
|
||||
|
|
|
@ -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:')
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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*
|
||||
|
|
|
@ -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
|
||||
|
||||
'''
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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':
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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]:
|
||||
|
|
25
setup.py
25
setup.py
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'}]}
|
||||
|
|
|
@ -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': {}}
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Add table
Reference in a new issue