mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge branch '2018.3' into fix-broken-thing
This commit is contained in:
commit
298ad5c0aa
145 changed files with 8655 additions and 969 deletions
49
.codecov.yml
Normal file
49
.codecov.yml
Normal file
|
@ -0,0 +1,49 @@
|
|||
codecov:
|
||||
ci:
|
||||
- drone.saltstack.com
|
||||
- jenkinsci.saltstack.com
|
||||
|
||||
branch: 2018.3
|
||||
|
||||
notify:
|
||||
require_ci_to_pass: no
|
||||
|
||||
ignore:
|
||||
- ^*.py$
|
||||
- doc/.*
|
||||
- tests/.*
|
||||
|
||||
coverage:
|
||||
round: up
|
||||
range: 70..100
|
||||
precision: 2
|
||||
|
||||
status:
|
||||
project: # measuring the overall project coverage
|
||||
default:
|
||||
enabled: yes # must be yes|true to enable this status
|
||||
if_no_uploads: error # will post commit status of "error" if no coverage reports we uploaded
|
||||
# options: success, error, failure
|
||||
if_not_found: success # if parent is not found report status as success, error, or failure
|
||||
if_ci_failed: success # if ci fails report status as success, error, or failure
|
||||
|
||||
patch: # pull requests only: this commit status will measure the
|
||||
# entire pull requests Coverage Diff. Checking if the lines
|
||||
# adjusted are covered at least X%.
|
||||
default:
|
||||
enabled: no # must be yes|true to enable this status
|
||||
target: 80% # specify the target "X%" coverage to hit
|
||||
if_no_uploads: error # will post commit status of "error" if no coverage reports we uploaded
|
||||
# options: success, error, failure
|
||||
if_not_found: success
|
||||
if_ci_failed: success
|
||||
|
||||
changes: # if there are any unexpected changes in coverage
|
||||
default:
|
||||
enabled: no # must be yes|true to enable this status
|
||||
if_no_uploads: success
|
||||
if_not_found: success
|
||||
if_ci_failed: success
|
||||
|
||||
# No commends because we're not yet running the full test suite on PRs
|
||||
comment: off
|
34
.coveragerc
Normal file
34
.coveragerc
Normal file
|
@ -0,0 +1,34 @@
|
|||
[run]
|
||||
branch = True
|
||||
cover_pylib = False
|
||||
source =
|
||||
salt
|
||||
parallel = True
|
||||
concurrency = multiprocessing
|
||||
omit =
|
||||
tests/*.py
|
||||
setup.py
|
||||
|
||||
[report]
|
||||
# Regexes for lines to exclude from consideration
|
||||
exclude_lines =
|
||||
# Have to re-enable the standard pragma
|
||||
pragma: no cover
|
||||
|
||||
# Don't complain about missing debug-only code:
|
||||
def __repr__
|
||||
|
||||
# Don't complain if tests don't hit defensive assertion code:
|
||||
raise AssertionError
|
||||
raise NotImplementedError
|
||||
|
||||
# Don't complain if non-runnable code isn't run:
|
||||
if 0:
|
||||
if __name__ == .__main__.:
|
||||
|
||||
|
||||
ignore_errors = True
|
||||
|
||||
[paths]
|
||||
source =
|
||||
salt
|
7
Gemfile
7
Gemfile
|
@ -2,9 +2,8 @@
|
|||
|
||||
source 'https://rubygems.org'
|
||||
|
||||
# Point this back at the test-kitchen package after 1.23.3 is relased
|
||||
gem 'test-kitchen', :git => 'https://github.com/dwoz/test-kitchen.git', :branch => 'winrm_opts'
|
||||
gem 'kitchen-salt', '~>0.2'
|
||||
gem 'test-kitchen', '~>1.23.3'
|
||||
gem 'kitchen-salt', '~>0.4.1'
|
||||
gem 'kitchen-sync'
|
||||
gem 'git'
|
||||
|
||||
|
@ -14,7 +13,7 @@ end
|
|||
|
||||
group :windows do
|
||||
gem 'winrm', '~>2.0'
|
||||
gem 'winrm-fs', '~>1.3.1'
|
||||
gem 'winrm-fs', '~>1.3.1'
|
||||
end
|
||||
|
||||
group :ec2 do
|
||||
|
|
11
Pipfile
11
Pipfile
|
@ -20,17 +20,18 @@ boto = ">=2.32.1"
|
|||
boto3 = ">=1.2.1"
|
||||
moto = ">=0.3.6"
|
||||
SaltPyLint = ">=v2017.3.6"
|
||||
pytest = ">=3.5.0"
|
||||
pytest = ">=4.0.1"
|
||||
pytest-cov = "*"
|
||||
pytest-salt = "==2018.12.8"
|
||||
pytest-timeout = ">=1.3.3"
|
||||
pytest-tempdir = ">=2018.8.11"
|
||||
pytest-helpers-namespace = ">=2017.11.11"
|
||||
|
||||
[packages.futures]
|
||||
# Required by Tornado to handle threads stuff.
|
||||
version = ">=2.0"
|
||||
markers = "python_version < '3.0'"
|
||||
|
||||
[dev-packages.pytest-salt]
|
||||
git = "git://github.com/saltstack/pytest-salt.git"
|
||||
ref = "master"
|
||||
|
||||
[dev-packages.httpretty]
|
||||
# httpretty Needs to be here for now even though it's a dependency of boto.
|
||||
# A pip install on a fresh system will decide to target httpretty 0.8.10 to
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
What is SaltStack?
|
||||
==================
|
||||
|
||||
SaltStack makes software for complex systems management at scale.
|
||||
SaltStack makes software for complex systems management at scale.
|
||||
SaltStack is the company that created and maintains the Salt Open
|
||||
project and develops and sells SaltStack Enterprise software, services
|
||||
and support. Easy enough to get running in minutes, scalable enough to
|
||||
|
|
13
doc/_themes/saltstack2/layout.html
vendored
13
doc/_themes/saltstack2/layout.html
vendored
|
@ -71,6 +71,14 @@
|
|||
{%- endmacro %}
|
||||
<html>
|
||||
<head>
|
||||
<!-- Google Tag Manager -->
|
||||
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
||||
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
||||
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
||||
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
||||
})(window,document,'script','dataLayer','GTM-MCK7VL3');</script>
|
||||
<!-- End Google Tag Manager -->
|
||||
|
||||
<meta charset="{{ encoding }}">
|
||||
{{ metatags }}
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
|
@ -120,6 +128,11 @@
|
|||
</head>
|
||||
|
||||
<body class="index">
|
||||
<!-- Google Tag Manager (noscript) -->
|
||||
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-MCK7VL3"
|
||||
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
|
||||
<!-- End Google Tag Manager (noscript) -->
|
||||
|
||||
<!--[if lt IE 8]>
|
||||
<p>You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser.</a></p>
|
||||
<![endif]-->
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-API" "1" "Sep 21, 2018" "2018.3.3" "Salt"
|
||||
.TH "SALT-API" "1" "Sep 21, 2018" "2018.3.4" "Salt"
|
||||
.SH NAME
|
||||
salt-api \- salt-api Command
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-CALL" "1" "Sep 21, 2018" "2018.3.3" "Salt"
|
||||
.TH "SALT-CALL" "1" "Sep 21, 2018" "2018.3.4" "Salt"
|
||||
.SH NAME
|
||||
salt-call \- salt-call Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-CLOUD" "1" "Sep 21, 2018" "2018.3.3" "Salt"
|
||||
.TH "SALT-CLOUD" "1" "Sep 21, 2018" "2018.3.4" "Salt"
|
||||
.SH NAME
|
||||
salt-cloud \- Salt Cloud Command
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-CP" "1" "Sep 21, 2018" "2018.3.3" "Salt"
|
||||
.TH "SALT-CP" "1" "Sep 21, 2018" "2018.3.4" "Salt"
|
||||
.SH NAME
|
||||
salt-cp \- salt-cp Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-KEY" "1" "Sep 21, 2018" "2018.3.3" "Salt"
|
||||
.TH "SALT-KEY" "1" "Sep 21, 2018" "2018.3.4" "Salt"
|
||||
.SH NAME
|
||||
salt-key \- salt-key Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-MASTER" "1" "Sep 21, 2018" "2018.3.3" "Salt"
|
||||
.TH "SALT-MASTER" "1" "Sep 21, 2018" "2018.3.4" "Salt"
|
||||
.SH NAME
|
||||
salt-master \- salt-master Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-MINION" "1" "Sep 21, 2018" "2018.3.3" "Salt"
|
||||
.TH "SALT-MINION" "1" "Sep 21, 2018" "2018.3.4" "Salt"
|
||||
.SH NAME
|
||||
salt-minion \- salt-minion Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-PROXY" "1" "Sep 21, 2018" "2018.3.3" "Salt"
|
||||
.TH "SALT-PROXY" "1" "Sep 21, 2018" "2018.3.4" "Salt"
|
||||
.SH NAME
|
||||
salt-proxy \- salt-proxy Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-RUN" "1" "Sep 21, 2018" "2018.3.3" "Salt"
|
||||
.TH "SALT-RUN" "1" "Sep 21, 2018" "2018.3.4" "Salt"
|
||||
.SH NAME
|
||||
salt-run \- salt-run Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-SSH" "1" "Sep 21, 2018" "2018.3.3" "Salt"
|
||||
.TH "SALT-SSH" "1" "Sep 21, 2018" "2018.3.4" "Salt"
|
||||
.SH NAME
|
||||
salt-ssh \- salt-ssh Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-SYNDIC" "1" "Sep 21, 2018" "2018.3.3" "Salt"
|
||||
.TH "SALT-SYNDIC" "1" "Sep 21, 2018" "2018.3.4" "Salt"
|
||||
.SH NAME
|
||||
salt-syndic \- salt-syndic Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-UNITY" "1" "Sep 21, 2018" "2018.3.3" "Salt"
|
||||
.TH "SALT-UNITY" "1" "Sep 21, 2018" "2018.3.4" "Salt"
|
||||
.SH NAME
|
||||
salt-unity \- salt-unity Command
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT" "1" "Sep 21, 2018" "2018.3.3" "Salt"
|
||||
.TH "SALT" "1" "Sep 21, 2018" "2018.3.4" "Salt"
|
||||
.SH NAME
|
||||
salt \- salt
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT" "7" "Sep 21, 2018" "2018.3.3" "Salt"
|
||||
.TH "SALT" "7" "Sep 21, 2018" "2018.3.4" "Salt"
|
||||
.SH NAME
|
||||
salt \- Salt Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SPM" "1" "Sep 21, 2018" "2018.3.3" "Salt"
|
||||
.TH "SPM" "1" "Sep 21, 2018" "2018.3.4" "Salt"
|
||||
.SH NAME
|
||||
spm \- Salt Package Manager Command
|
||||
.
|
||||
|
|
|
@ -2599,6 +2599,8 @@ can have multiple root directories. The subdirectories in the multiple file
|
|||
roots cannot match, otherwise the downloaded files will not be able to be
|
||||
reliably ensured. A base environment is required to house the top file.
|
||||
|
||||
As of 2018.3.5 and 2019.2.1, it is possible to have `__env__` as a catch-all environment.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
@ -2612,6 +2614,8 @@ Example:
|
|||
prod:
|
||||
- /srv/salt/prod/services
|
||||
- /srv/salt/prod/states
|
||||
__env__:
|
||||
- /srv/salt/default
|
||||
|
||||
.. note::
|
||||
For masterless Salt, this parameter must be specified in the minion config
|
||||
|
|
|
@ -803,6 +803,23 @@ A value of 10 minutes is a reasonable default.
|
|||
|
||||
grains_refresh_every: 0
|
||||
|
||||
.. conf_minion:: metadata_server_grains
|
||||
|
||||
``metadata_server_grains``
|
||||
--------------------------
|
||||
|
||||
.. versionadded:: 2017.7.0
|
||||
|
||||
Default: ``False``
|
||||
|
||||
Set this option to enable gathering of cloud metadata from
|
||||
``http://169.254.169.254/latest`` for use in grains (see :py:mod:`here
|
||||
<salt.grains.metadata>` for more information).
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
metadata_server_grains: True
|
||||
|
||||
.. conf_minion:: fibre_channel_grains
|
||||
|
||||
``fibre_channel_grains``
|
||||
|
|
|
@ -532,7 +532,7 @@ services. For more information on service certificates, see the following link:
|
|||
|
||||
* `Manage Certificates`__
|
||||
|
||||
.. __: https://msdn.microsoft.com/en-us/library/azure/gg981929.aspx
|
||||
.. __: https://docs.microsoft.com/en-us/azure/cloud-services/cloud-services-certs-create
|
||||
|
||||
The following functions are available.
|
||||
|
||||
|
|
|
@ -235,3 +235,17 @@ Defined in: State
|
|||
__sdb__
|
||||
-------
|
||||
Defined in: SDB
|
||||
|
||||
|
||||
Additional Globals
|
||||
==================
|
||||
|
||||
Defined for: Runners, Execution Modules, Wheels
|
||||
|
||||
* ``__jid__``: The job ID
|
||||
* ``__user__``: The user
|
||||
* ``__tag__``: The jid tag
|
||||
* ``__jid_event__``: A :py:class:`salt.utils.event.NamespacedEvent`.
|
||||
|
||||
:py:class:`NamespacedEvent <salt.utils.event.NamespacedEvent>` defines a single
|
||||
method :py:meth:`fire_event <salt.utils.event.NamespacedEvent.fire_event>`, that takes data and tag. The :ref:`Runner docs <runners>` has examples.
|
||||
|
|
|
@ -130,7 +130,7 @@ Cloud ``salt.cloud.clouds`` (:ref:`index <all-salt.clouds>`) ``
|
|||
Engine ``salt.engines`` (:ref:`index <engines>`) ``engines`` ``engines_dirs``
|
||||
Execution ``salt.modules`` (:ref:`index <all-salt.modules>`) ``modules`` ``module_dirs``
|
||||
Executor ``salt.executors`` (:ref:`index <all-salt.executors>`) ``executors`` [#no-fs]_ ``executor_dirs``
|
||||
File Server ``salt.fileserver`` (:ref:`index <file-server>`) ``fileserver`` [#no-fs]_ ``fileserver_dirs``
|
||||
File Server ``salt.fileserver`` (:ref:`index <file-server>`) ``fileserver`` ``fileserver_dirs``
|
||||
Grain ``salt.grains`` (:ref:`index <all-salt.grains>`) ``grains`` ``grains_dirs``
|
||||
Log Handler ``salt.log.handlers`` (:ref:`index <external-logging-handlers>`) ``log_handlers`` ``log_handlers_dirs``
|
||||
Net API ``salt.netapi`` (:ref:`index <all-netapi-modules>`) ``netapi`` [#no-fs]_ ``netapi_dirs``
|
||||
|
@ -143,13 +143,13 @@ Returner ``salt.returners`` (:ref:`index <all-salt.returners>`) ``
|
|||
Roster ``salt.roster`` (:ref:`index <all-salt.roster>`) ``roster`` ``roster_dirs``
|
||||
Runner ``salt.runners`` (:ref:`index <all-salt.runners>`) ``runners`` ``runner_dirs``
|
||||
SDB ``salt.sdb`` (:ref:`index <all-salt.sdb>`) ``sdb`` ``sdb_dirs``
|
||||
Search ``salt.search`` ``search`` [#no-fs]_ ``search_dirs``
|
||||
Serializer ``salt.serializers`` (:ref:`index <all-salt.serializers>`) ``serializers`` [#no-fs]_ ``serializers_dirs``
|
||||
SPM pkgdb ``salt.spm.pkgdb`` ``pkgdb`` [#no-fs]_ ``pkgdb_dirs``
|
||||
SPM pkgfiles ``salt.spm.pkgfiles`` ``pkgfiles`` [#no-fs]_ ``pkgfiles_dirs``
|
||||
SSH Wrapper ``salt.client.ssh.wrapper`` ``wrapper`` [#no-fs]_ ``wrapper_dirs``
|
||||
State ``salt.states`` (:ref:`index <all-salt.states>`) ``states`` ``states_dirs``
|
||||
Thorium ``salt.thorium`` (:ref:`index <all-salt.thorium>`) ``thorium`` [#no-fs]_ ``thorium_dirs``
|
||||
Thorium ``salt.thorium`` (:ref:`index <all-salt.thorium>`) ``thorium`` ``thorium_dirs``
|
||||
Tokens ``salt.tokens`` ``tokens`` ``tokens_dirs``
|
||||
Top ``salt.tops`` (:ref:`index <all-salt.tops>`) ``tops`` ``top_dirs``
|
||||
Util ``salt.utils`` ``utils`` ``utils_dirs``
|
||||
Wheel ``salt.wheels`` (:ref:`index <all-salt.wheel>`) ``wheel`` ``wheel_dirs``
|
||||
|
@ -223,6 +223,12 @@ object.
|
|||
Executor
|
||||
--------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:glob:
|
||||
|
||||
/ref/executors/index
|
||||
|
||||
Executors control how execution modules get called. The default is to just call
|
||||
them, but this can be customized.
|
||||
|
||||
|
@ -322,11 +328,6 @@ SDB
|
|||
SDB is a way to store data that's not associated with a minion. See
|
||||
:ref:`Storing Data in Other Databases <sdb>`.
|
||||
|
||||
Search
|
||||
------
|
||||
|
||||
A system for indexing the file server and pillars. Removed in 2018.3.
|
||||
|
||||
Serializer
|
||||
----------
|
||||
|
||||
|
@ -375,6 +376,16 @@ Thorium
|
|||
|
||||
Modules for use in the :ref:`Thorium <thorium-reactor>` event reactor.
|
||||
|
||||
Tokens
|
||||
------
|
||||
|
||||
Token stores for :ref:`External Authentication <acl-eauth>`. See the
|
||||
:py:mod:`salt.tokens` docstring for details.
|
||||
|
||||
.. note:
|
||||
The runner to load tokens modules is
|
||||
:py:func:`saltutil.sync_eauth_tokens <salt.runners.saltutil.sync_eauth_tokens>`.
|
||||
|
||||
Tops
|
||||
----
|
||||
|
||||
|
|
|
@ -163,10 +163,10 @@ A few examples of salt states from the community:
|
|||
* https://github.com/bclermont/states
|
||||
* https://github.com/pcrews/salt-data
|
||||
|
||||
Follow on ohloh
|
||||
===============
|
||||
Follow on Open Hub
|
||||
==================
|
||||
|
||||
https://www.ohloh.net/p/salt
|
||||
https://www.openhub.net/p/salt
|
||||
|
||||
Other community links
|
||||
=====================
|
||||
|
@ -178,6 +178,7 @@ Other community links
|
|||
- `Facebook <https://www.facebook.com/SaltStack>`_
|
||||
- `Twitter <https://twitter.com/SaltStackInc>`_
|
||||
- `Wikipedia page <http://en.wikipedia.org/wiki/Salt_(software)>`_
|
||||
- `Stack Overflow <https://stackoverflow.com/questions/tagged/salt-stack>`_
|
||||
|
||||
Hack the Source
|
||||
===============
|
||||
|
|
|
@ -87,6 +87,13 @@ the context into the included file is required:
|
|||
.. code-block:: jinja
|
||||
|
||||
{% from 'lib.sls' import test with context %}
|
||||
|
||||
Includes must use full paths, like so:
|
||||
|
||||
.. code-block:: jinja
|
||||
:caption: spam/eggs.jinja
|
||||
|
||||
{% include 'spam/foobar.jinja' %}
|
||||
|
||||
Including Context During Include/Import
|
||||
---------------------------------------
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -531,7 +531,13 @@ Global Remotes
|
|||
|
||||
The ``all_saltenvs`` per-remote configuration parameter overrides the logic
|
||||
Salt uses to map branches/tags to fileserver environments (i.e. saltenvs). This
|
||||
allows a single branch/tag to appear in *all* saltenvs.
|
||||
allows a single branch/tag to appear in *all* GitFS saltenvs.
|
||||
|
||||
.. note::
|
||||
``all_saltenvs`` only works *within* GitFS. That is, files in a branch
|
||||
configured using ``all_saltenvs`` will *not* show up in a fileserver
|
||||
environment defined via some other fileserver backend (e.g.
|
||||
:conf_master:`file_roots`).
|
||||
|
||||
This is very useful in particular when working with :ref:`salt formulas
|
||||
<conventions-formula>`. Prior to the addition of this feature, it was necessary
|
||||
|
@ -728,6 +734,19 @@ Then the ``roots`` backend (the default backend of files in ``/srv/salt``) will
|
|||
be searched first for the requested file; then, if it is not found on the
|
||||
master, each configured git remote will be searched.
|
||||
|
||||
.. note::
|
||||
|
||||
This can be used together with `file_roots` accepting `__env__` as a catch-all
|
||||
environment, since 2018.3.5 and 2019.2.1:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
file_roots:
|
||||
base:
|
||||
- /srv/salt
|
||||
__env__:
|
||||
- /srv/salt
|
||||
|
||||
Branches, Environments, and Top Files
|
||||
=====================================
|
||||
|
||||
|
|
|
@ -177,7 +177,7 @@ $MAKE install
|
|||
############################################################################
|
||||
echo -n -e "\033]0;Build_Env: libsodium: download\007"
|
||||
|
||||
PKGURL="https://download.libsodium.org/libsodium/releases/libsodium-1.0.15.tar.gz"
|
||||
PKGURL="https://download.libsodium.org/libsodium/releases/old/libsodium-1.0.15.tar.gz"
|
||||
PKGDIR="libsodium-1.0.15"
|
||||
|
||||
download $PKGURL
|
||||
|
|
|
@ -158,13 +158,20 @@ echo -n -e "\033]0;Build_Pkg: Add Version to .xml\007"
|
|||
if [ "$PYVER" == "2" ]; then
|
||||
TITLE="Salt $VERSION"
|
||||
DESC="Salt $VERSION with Python 2"
|
||||
SEDSTR="s/@PY2@/_py2/g"
|
||||
else
|
||||
TITLE="Salt $VERSION (Python 3)"
|
||||
DESC="Salt $VERSION with Python 3"
|
||||
SEDSTR="s/@PY2@//g"
|
||||
fi
|
||||
|
||||
cd $PKGRESOURCES
|
||||
cp distribution.xml.dist distribution.xml
|
||||
|
||||
# Select the appropriate welcome text
|
||||
# This is only necessary until Sodium, then this can be removed
|
||||
sed -E -i '' "$SEDSTR" distribution.xml
|
||||
|
||||
SEDSTR="s/@TITLE@/$TITLE/g"
|
||||
sed -E -i '' "$SEDSTR" distribution.xml
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
mime-type="image/png"
|
||||
scaling="proportional" />
|
||||
<!-- Define documents displayed at various steps -->
|
||||
<welcome file="welcome.rtf"
|
||||
<welcome file="welcome@PY2@.rtf"
|
||||
mime-type="text/rtf" />
|
||||
<license file="license.rtf"
|
||||
mime-type="text/rtf" />
|
||||
|
|
32
pkg/osx/pkg-resources/welcome_py2.rtf
Normal file
32
pkg/osx/pkg-resources/welcome_py2.rtf
Normal file
|
@ -0,0 +1,32 @@
|
|||
{\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340
|
||||
{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\froman\fcharset0 Times-Roman;\f2\fnil\fcharset0 PTMono-Regular;
|
||||
}
|
||||
{\colortbl;\red255\green255\blue255;\red0\green0\blue233;}
|
||||
\vieww28300\viewh14680\viewkind0
|
||||
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
|
||||
|
||||
\f0\fs24 \cf0 WARNING: Python 2 Support will be discontinued in Sodium. Salt will only ship Python 3 installers starting with the Sodium release.\
|
||||
\
|
||||
\pard\pardeftab720\sl280\sa240\partightenfactor0
|
||||
{\field{\*\fldinst{HYPERLINK "http://saltstack.com/"}}{\fldrslt
|
||||
\f1 \cf2 \expnd0\expndtw0\kerning0
|
||||
\ul \ulc2 SaltStack}}
|
||||
\f1 \expnd0\expndtw0\kerning0
|
||||
is extremely fast and scalable systems and configuration management software for predictive orchestration, cloud and data center automation, server provisioning, application deployment and more. \
|
||||
Documentation for Salt is available at {\field{\*\fldinst{HYPERLINK "http://docs.saltstack.com/"}}{\fldrslt \cf2 \ul \ulc2 http://docs.saltstack.com}} \
|
||||
This package will install Salt on your Mac. Salt installs into
|
||||
\f2\fs22 /opt/salt
|
||||
\f1\fs24 .\
|
||||
Sample configuration files (
|
||||
\f2\fs22 master.dist
|
||||
\f1\fs24 and
|
||||
\f2\fs22 minion.dist
|
||||
\f1\fs24 ) will be installed to
|
||||
\f2\fs22 /etc/salt
|
||||
\f1\fs24 . Create copies of them without the '
|
||||
\f2\fs22 .dist
|
||||
\f1\fs24 ' in the filename and edit as you see fit.\
|
||||
This Salt package uses a custom-built Python. To install additional Python modules for Salt, use the associated 'pip' binary. For example, if you need LDAP support in Salt you will need the 'python-ldap' module. Install it with
|
||||
\f2\fs22 /opt/salt/bin/pip install python-ldap
|
||||
\f1\fs24 \
|
||||
Note that some Python modules need a compiler available. Installing Apple's Xcode Command Line Tools should provide the necessary utilities. Alternatively, {\field{\*\fldinst{HYPERLINK "http://macports.org/"}}{\fldrslt \cf2 \ul \ulc2 MacPorts}}, {\field{\*\fldinst{HYPERLINK "http://finkproject.org/"}}{\fldrslt \cf2 \ul \ulc2 Fink}}, or {\field{\*\fldinst{HYPERLINK "http://brew.sh/"}}{\fldrslt \cf2 \ul \ulc2 Homebrew}} may provide what you need.}
|
|
@ -22,22 +22,10 @@
|
|||
|
||||
# Load parameters
|
||||
param(
|
||||
[switch]$Silent
|
||||
[switch]$Silent,
|
||||
[switch]$NoPipDependencies
|
||||
)
|
||||
|
||||
Write-Output "================================================================="
|
||||
Write-Output ""
|
||||
Write-Output " Development Environment Installation"
|
||||
Write-Output ""
|
||||
Write-Output " - Installs All Salt Dependencies"
|
||||
Write-Output " - Detects 32/64 bit Architectures"
|
||||
Write-Output ""
|
||||
Write-Output " To run silently add -Silent"
|
||||
Write-Output " eg: dev_env.ps1 -Silent"
|
||||
Write-Output ""
|
||||
Write-Output "================================================================="
|
||||
Write-Output ""
|
||||
|
||||
#==============================================================================
|
||||
# Get the Directory of actual script
|
||||
#==============================================================================
|
||||
|
@ -49,6 +37,22 @@ $script_path = $script_path.DirectoryName
|
|||
#==============================================================================
|
||||
$script_name = $MyInvocation.MyCommand.Name
|
||||
|
||||
Write-Output "================================================================="
|
||||
Write-Output ""
|
||||
Write-Output " Development Environment Installation"
|
||||
Write-Output ""
|
||||
Write-Output " - Installs All Salt Dependencies"
|
||||
Write-Output " - Detects 32/64 bit Architectures"
|
||||
Write-Output ""
|
||||
Write-Output " To run silently add -Silent"
|
||||
Write-Output " eg: ${script_name} -Silent"
|
||||
Write-Output ""
|
||||
Write-Output " To run skip installing pip dependencies add -NoPipDependencies"
|
||||
Write-Output " eg: ${script_name} -NoPipDependencies"
|
||||
Write-Output ""
|
||||
Write-Output "================================================================="
|
||||
Write-Output ""
|
||||
|
||||
#==============================================================================
|
||||
# Import Modules
|
||||
#==============================================================================
|
||||
|
@ -211,25 +215,46 @@ if ( ! [bool]$Env:SALT_PIP_LOCAL_CACHE) {
|
|||
}
|
||||
|
||||
#==============================================================================
|
||||
# Install pypi resources using pip
|
||||
# Install windows specific pypi resources using pip
|
||||
# caching depends on environment variable SALT_REQ_LOCAL_CACHE
|
||||
#==============================================================================
|
||||
Write-Output " ----------------------------------------------------------------"
|
||||
Write-Output " - $script_name :: Installing pypi resources using pip . . ."
|
||||
Write-Output " - $script_name :: Installing windows specific pypi resources using pip . . ."
|
||||
Write-Output " ----------------------------------------------------------------"
|
||||
if ( ! [bool]$Env:SALT_REQ_LOCAL_CACHE) {
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip --disable-pip-version-check --no-cache-dir install -r $($script_path)\req.txt" "pip install"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip --disable-pip-version-check --no-cache-dir install -r $($script_path)\req_win.txt" "pip install"
|
||||
} else {
|
||||
if ( (Get-ChildItem $Env:SALT_REQ_LOCAL_CACHE | Measure-Object).Count -eq 0 ) {
|
||||
# folder empty
|
||||
Write-Output " pip download from req.txt into empty local cache SALT_REQ $Env:SALT_REQ_LOCAL_CACHE"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip --disable-pip-version-check download --dest $Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req.txt" "pip download"
|
||||
Write-Output " pip download from req_win.txt into empty local cache SALT_REQ $Env:SALT_REQ_LOCAL_CACHE"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip --disable-pip-version-check download --dest $Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req_win.txt" "pip download"
|
||||
}
|
||||
Write-Output " reading from local pip cache $Env:SALT_REQ_LOCAL_CACHE"
|
||||
Write-Output " If a (new) resource is missing, please delete all files in this cache, go online and repeat"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip --disable-pip-version-check install --no-index --find-links=$Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req.txt" "pip install"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip --disable-pip-version-check install --no-index --find-links=$Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req_win.txt" "pip install"
|
||||
}
|
||||
|
||||
#==============================================================================
|
||||
# Install pypi resources using pip
|
||||
# caching depends on environment variable SALT_REQ_LOCAL_CACHE
|
||||
#==============================================================================
|
||||
If ($NoPipDependencies -eq $false) {
|
||||
Write-Output " ----------------------------------------------------------------"
|
||||
Write-Output " - $script_name :: Installing pypi resources using pip . . ."
|
||||
Write-Output " ----------------------------------------------------------------"
|
||||
if ( ! [bool]$Env:SALT_REQ_LOCAL_CACHE) {
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip --disable-pip-version-check --no-cache-dir install -r $($script_path)\req.txt" "pip install"
|
||||
} else {
|
||||
if ( (Get-ChildItem $Env:SALT_REQ_LOCAL_CACHE | Measure-Object).Count -eq 0 ) {
|
||||
# folder empty
|
||||
Write-Output " pip download from req.txt into empty local cache SALT_REQ $Env:SALT_REQ_LOCAL_CACHE"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip --disable-pip-version-check download --dest $Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req.txt" "pip download"
|
||||
}
|
||||
Write-Output " reading from local pip cache $Env:SALT_REQ_LOCAL_CACHE"
|
||||
Write-Output " If a (new) resource is missing, please delete all files in this cache, go online and repeat"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip --disable-pip-version-check install --no-index --find-links=$Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req.txt" "pip install"
|
||||
}
|
||||
}
|
||||
#==============================================================================
|
||||
# Cleaning Up PyWin32
|
||||
#==============================================================================
|
||||
|
|
|
@ -22,22 +22,10 @@
|
|||
|
||||
# Load parameters
|
||||
param(
|
||||
[switch]$Silent
|
||||
[switch]$Silent,
|
||||
[switch]$NoPipDependencies
|
||||
)
|
||||
|
||||
Write-Output "================================================================="
|
||||
Write-Output ""
|
||||
Write-Output " Development Environment Installation"
|
||||
Write-Output ""
|
||||
Write-Output " - Installs All Salt Dependencies"
|
||||
Write-Output " - Detects 32/64 bit Architectures"
|
||||
Write-Output ""
|
||||
Write-Output " To run silently add -Silent"
|
||||
Write-Output " eg: dev_env.ps1 -Silent"
|
||||
Write-Output ""
|
||||
Write-Output "================================================================="
|
||||
Write-Output ""
|
||||
|
||||
#==============================================================================
|
||||
# Get the Directory of actual script
|
||||
#==============================================================================
|
||||
|
@ -49,6 +37,22 @@ $script_path = $script_path.DirectoryName
|
|||
#==============================================================================
|
||||
$script_name = $MyInvocation.MyCommand.Name
|
||||
|
||||
Write-Output "================================================================="
|
||||
Write-Output ""
|
||||
Write-Output " Development Environment Installation"
|
||||
Write-Output ""
|
||||
Write-Output " - Installs All Salt Dependencies"
|
||||
Write-Output " - Detects 32/64 bit Architectures"
|
||||
Write-Output ""
|
||||
Write-Output " To run silently add -Silent"
|
||||
Write-Output " eg: ${script_name} -Silent"
|
||||
Write-Output ""
|
||||
Write-Output " To run skip installing pip dependencies add -NoPipDependencies"
|
||||
Write-Output " eg: ${script_name} -NoPipDependencies"
|
||||
Write-Output ""
|
||||
Write-Output "================================================================="
|
||||
Write-Output ""
|
||||
|
||||
#==============================================================================
|
||||
# Import Modules
|
||||
#==============================================================================
|
||||
|
@ -211,23 +215,45 @@ if ( ! [bool]$Env:SALT_PIP_LOCAL_CACHE) {
|
|||
}
|
||||
|
||||
#==============================================================================
|
||||
# Install pypi resources using pip
|
||||
# Install windows specific pypi resources using pip
|
||||
# caching depends on environment variable SALT_REQ_LOCAL_CACHE
|
||||
#==============================================================================
|
||||
Write-Output " ----------------------------------------------------------------"
|
||||
Write-Output " - $script_name :: Installing pypi resources using pip . . ."
|
||||
Write-Output " - $script_name :: Installing windows specific pypi resources using pip . . ."
|
||||
Write-Output " ----------------------------------------------------------------"
|
||||
if ( ! [bool]$Env:SALT_REQ_LOCAL_CACHE) {
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip --disable-pip-version-check --no-cache-dir install -r $($script_path)\req.txt" "pip install"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip --disable-pip-version-check --no-cache-dir install -r $($script_path)\req_win.txt" "pip install"
|
||||
} else {
|
||||
if ( (Get-ChildItem $Env:SALT_REQ_LOCAL_CACHE | Measure-Object).Count -eq 0 ) {
|
||||
# folder empty
|
||||
Write-Output " pip download from req.txt into empty local cache SALT_REQ $Env:SALT_REQ_LOCAL_CACHE"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip --disable-pip-version-check download --dest $Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req.txt" "pip download"
|
||||
Write-Output " pip download from req_win.txt into empty local cache SALT_REQ $Env:SALT_REQ_LOCAL_CACHE"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip --disable-pip-version-check download --dest $Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req_win.txt" "pip download"
|
||||
}
|
||||
Write-Output " reading from local pip cache $Env:SALT_REQ_LOCAL_CACHE"
|
||||
Write-Output " If a (new) resource is missing, please delete all files in this cache, go online and repeat"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip --disable-pip-version-check install --no-index --find-links=$Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req.txt" "pip install"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip --disable-pip-version-check install --no-index --find-links=$Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req_win.txt" "pip install"
|
||||
}
|
||||
|
||||
#==============================================================================
|
||||
# Install pypi resources using pip
|
||||
# caching depends on environment variable SALT_REQ_LOCAL_CACHE
|
||||
#==============================================================================
|
||||
If ($NoPipDependencies -eq $false) {
|
||||
Write-Output " ----------------------------------------------------------------"
|
||||
Write-Output " - $script_name :: Installing pypi resources using pip . . ."
|
||||
Write-Output " ----------------------------------------------------------------"
|
||||
if ( ! [bool]$Env:SALT_REQ_LOCAL_CACHE) {
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip --disable-pip-version-check --no-cache-dir install -r $($script_path)\req.txt" "pip install"
|
||||
} else {
|
||||
if ( (Get-ChildItem $Env:SALT_REQ_LOCAL_CACHE | Measure-Object).Count -eq 0 ) {
|
||||
# folder empty
|
||||
Write-Output " pip download from req.txt into empty local cache SALT_REQ $Env:SALT_REQ_LOCAL_CACHE"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip --disable-pip-version-check download --dest $Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req.txt" "pip download"
|
||||
}
|
||||
Write-Output " reading from local pip cache $Env:SALT_REQ_LOCAL_CACHE"
|
||||
Write-Output " If a (new) resource is missing, please delete all files in this cache, go online and repeat"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip --disable-pip-version-check install --no-index --find-links=$Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req.txt" "pip install"
|
||||
}
|
||||
}
|
||||
|
||||
#==============================================================================
|
||||
|
@ -262,11 +288,13 @@ Remove-Item "$($ini['Settings']['Scripts3Dir'])\pywin32_*" -Force -Recurse
|
|||
#==============================================================================
|
||||
# Fix PyCrypto
|
||||
#==============================================================================
|
||||
Write-Output " ----------------------------------------------------------------"
|
||||
Write-Output " - $script_name :: Fixing PyCrypto . . ."
|
||||
Write-Output " ----------------------------------------------------------------"
|
||||
$nt_file = "$($ini['Settings']['Python3Dir'])\Lib\site-packages\Crypto\Random\OSRNG\nt.py"
|
||||
(Get-Content $nt_file) | Foreach-Object {$_ -replace '^import winrandom$', 'from Crypto.Random.OSRNG import winrandom'} | Set-Content $nt_file
|
||||
If ($NoPipDependencies -eq $false) {
|
||||
Write-Output " ----------------------------------------------------------------"
|
||||
Write-Output " - $script_name :: Fixing PyCrypto . . ."
|
||||
Write-Output " ----------------------------------------------------------------"
|
||||
$nt_file = "$($ini['Settings']['Python3Dir'])\Lib\site-packages\Crypto\Random\OSRNG\nt.py"
|
||||
(Get-Content $nt_file) | Foreach-Object {$_ -replace '^import winrandom$', 'from Crypto.Random.OSRNG import winrandom'} | Set-Content $nt_file
|
||||
}
|
||||
|
||||
#==============================================================================
|
||||
# Copy DLLs to Python Directory
|
||||
|
|
|
@ -70,6 +70,22 @@ ${StrStrAdv}
|
|||
!define MUI_ICON "salt.ico"
|
||||
!define MUI_UNICON "salt.ico"
|
||||
!define MUI_WELCOMEFINISHPAGE_BITMAP "panel.bmp"
|
||||
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "panel.bmp"
|
||||
|
||||
# This entire if block can be removed for the Sodium release... including the !define MUI_WELCOMEPAGE_TEXT
|
||||
# NSIS will just use the default like it does for Python 3, which should be the same test
|
||||
!if "${PYTHON_VERSION}" == "2"
|
||||
!define MUI_WELCOMEPAGE_TEXT "\
|
||||
WARNING: Python 2 Support will be discontinued in Sodium. Salt will only ship Python 3 \
|
||||
installers starting with the Sodium release.$\r$\n\
|
||||
$\r$\n\
|
||||
Setup will guide you through the installation of ${PRODUCT_NAME} ${PRODUCT_VERSION}.$\r$\n\
|
||||
$\r$\n\
|
||||
It is recommended that you close all other applications before starting Setup. This will make it possible to \
|
||||
update relevant system files without having to reboot your computer.$\r$\n\
|
||||
$\r$\n\
|
||||
Click Next to continue."
|
||||
!endif
|
||||
|
||||
# Welcome page
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
-r req_win.txt
|
||||
backports-abc==0.5
|
||||
backports.ssl-match-hostname==3.5.0.1
|
||||
certifi
|
||||
|
@ -28,7 +29,6 @@ pyOpenSSL==17.5.0
|
|||
python-dateutil==2.6.1
|
||||
python-gnupg==0.4.1
|
||||
pythonnet==2.3.0
|
||||
pywin32==223
|
||||
PyYAML==3.12
|
||||
pyzmq==16.0.3
|
||||
requests==2.21.0
|
||||
|
@ -37,4 +37,3 @@ smmap==0.9.0
|
|||
timelib==0.2.4
|
||||
tornado==4.5.1
|
||||
wheel==0.30.0a0
|
||||
WMI==1.4.9
|
||||
|
|
2
pkg/windows/req_win.txt
Normal file
2
pkg/windows/req_win.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
pywin32==223
|
||||
WMI==1.4.9
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
mock>=2.0.0
|
||||
SaltPyLint>=v2017.3.6
|
||||
pytest>=3.5.0
|
||||
git+https://github.com/saltstack/pytest-salt.git@master#egg=pytest-salt
|
||||
testinfra>=1.7.0,!=1.17.0
|
||||
|
||||
# httpretty Needs to be here for now even though it's a dependency of boto.
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
pytest>=3.5.0
|
||||
pytest-helpers-namespace
|
||||
pytest-tempdir
|
||||
# PyTest
|
||||
pytest >= 4.0.1
|
||||
pytest-cov
|
||||
pytest-salt == 2018.12.8
|
||||
pytest-timeout >= 1.3.3
|
||||
pytest-tempdir >= 2018.8.11
|
||||
pytest-helpers-namespace >= 2017.11.11
|
||||
pytest-salt-runtests-bridge >= 2019.1.30
|
||||
|
|
|
@ -23,13 +23,11 @@ pyvmomi
|
|||
setproctitle
|
||||
cherrypy>=3.2.2,<18.0.0; python_version < '3.5' and sys.platform != 'win32' and sys.platform != 'darwin'
|
||||
cherrypy>=3.2.2; python_version >= '3.5' and sys.platform != 'win32' and sys.platform != 'darwin'
|
||||
ldap; sys.platform != 'win32' and sys.platform != 'darwin'
|
||||
pyinotify; sys.platform != 'win32' and sys.platform != 'darwin'
|
||||
PyMySQL; sys.platform != 'win32' and sys.platform != 'darwin'
|
||||
jsonschema
|
||||
strict_rfc3339
|
||||
rfc3987
|
||||
jinja2
|
||||
pyOpenSSL
|
||||
ioflo
|
||||
dnspython
|
||||
|
|
|
@ -52,8 +52,8 @@ def beacon(config):
|
|||
beacons:
|
||||
service:
|
||||
- services:
|
||||
salt-master:
|
||||
mysql:
|
||||
salt-master: {}
|
||||
mysql: {}
|
||||
|
||||
The config above sets up beacons to check for
|
||||
the salt-master and mysql services.
|
||||
|
|
|
@ -329,7 +329,7 @@ class SyncClientMixin(object):
|
|||
print_func=print_func
|
||||
)
|
||||
|
||||
# TODO: document these, and test that they exist
|
||||
# TODO: test that they exist
|
||||
# TODO: Other things to inject??
|
||||
func_globals = {'__jid__': jid,
|
||||
'__user__': data['user'],
|
||||
|
|
|
@ -1344,6 +1344,24 @@ class Cloud(object):
|
|||
output['ret'] = action_out
|
||||
return output
|
||||
|
||||
@staticmethod
|
||||
def vm_config(name, main, provider, profile, overrides):
|
||||
'''
|
||||
Create vm config.
|
||||
|
||||
:param str name: The name of the vm
|
||||
:param dict main: The main cloud config
|
||||
:param dict provider: The provider config
|
||||
:param dict profile: The profile config
|
||||
:param dict overrides: The vm's config overrides
|
||||
'''
|
||||
vm = main.copy()
|
||||
vm = salt.utils.dictupdate.update(vm, provider)
|
||||
vm = salt.utils.dictupdate.update(vm, profile)
|
||||
vm.update(overrides)
|
||||
vm['name'] = name
|
||||
return vm
|
||||
|
||||
def extras(self, extra_):
|
||||
'''
|
||||
Extra actions
|
||||
|
@ -1430,12 +1448,13 @@ class Cloud(object):
|
|||
ret[name] = {'Error': msg}
|
||||
continue
|
||||
|
||||
vm_ = main_cloud_config.copy()
|
||||
vm_.update(provider_details)
|
||||
vm_.update(profile_details)
|
||||
vm_.update(vm_overrides)
|
||||
|
||||
vm_['name'] = name
|
||||
vm_ = self.vm_config(
|
||||
name,
|
||||
main_cloud_config,
|
||||
provider_details,
|
||||
profile_details,
|
||||
vm_overrides,
|
||||
)
|
||||
if self.opts['parallel']:
|
||||
process = multiprocessing.Process(
|
||||
target=self.create,
|
||||
|
|
|
@ -1938,15 +1938,10 @@ PROVIDER_CONFIG_DEFAULTS = {
|
|||
# <---- Salt Cloud Configuration Defaults ------------------------------------
|
||||
|
||||
|
||||
def _validate_file_roots(file_roots):
|
||||
def _normalize_roots(file_roots):
|
||||
'''
|
||||
If the file_roots option has a key that is None then we will error out,
|
||||
just replace it with an empty list
|
||||
Normalize file or pillar roots.
|
||||
'''
|
||||
if not isinstance(file_roots, dict):
|
||||
log.warning('The file_roots parameter is not properly formatted,'
|
||||
' using defaults')
|
||||
return {'base': _expand_glob_path([salt.syspaths.BASE_FILE_ROOTS_DIR])}
|
||||
for saltenv, dirs in six.iteritems(file_roots):
|
||||
normalized_saltenv = six.text_type(saltenv)
|
||||
if normalized_saltenv != saltenv:
|
||||
|
@ -1958,6 +1953,30 @@ def _validate_file_roots(file_roots):
|
|||
return file_roots
|
||||
|
||||
|
||||
def _validate_pillar_roots(pillar_roots):
|
||||
'''
|
||||
If the pillar_roots option has a key that is None then we will error out,
|
||||
just replace it with an empty list
|
||||
'''
|
||||
if not isinstance(pillar_roots, dict):
|
||||
log.warning('The pillar_roots parameter is not properly formatted,'
|
||||
' using defaults')
|
||||
return {'base': _expand_glob_path([salt.syspaths.BASE_PILLAR_ROOTS_DIR])}
|
||||
return _normalize_roots(pillar_roots)
|
||||
|
||||
|
||||
def _validate_file_roots(file_roots):
|
||||
'''
|
||||
If the file_roots option has a key that is None then we will error out,
|
||||
just replace it with an empty list
|
||||
'''
|
||||
if not isinstance(file_roots, dict):
|
||||
log.warning('The file_roots parameter is not properly formatted,'
|
||||
' using defaults')
|
||||
return {'base': _expand_glob_path([salt.syspaths.BASE_FILE_ROOTS_DIR])}
|
||||
return _normalize_roots(file_roots)
|
||||
|
||||
|
||||
def _expand_glob_path(file_roots):
|
||||
'''
|
||||
Applies shell globbing to a set of directories and returns
|
||||
|
@ -3767,7 +3786,7 @@ def apply_minion_config(overrides=None,
|
|||
# nothing else!
|
||||
opts['open_mode'] = opts['open_mode'] is True
|
||||
opts['file_roots'] = _validate_file_roots(opts['file_roots'])
|
||||
opts['pillar_roots'] = _validate_file_roots(opts['pillar_roots'])
|
||||
opts['pillar_roots'] = _validate_pillar_roots(opts['pillar_roots'])
|
||||
# Make sure ext_mods gets set if it is an untrue value
|
||||
# (here to catch older bad configs)
|
||||
opts['extension_modules'] = (
|
||||
|
|
|
@ -51,7 +51,11 @@ def find_file(path, saltenv='base', **kwargs):
|
|||
if os.path.isabs(path):
|
||||
return fnd
|
||||
if saltenv not in __opts__['file_roots']:
|
||||
return fnd
|
||||
if '__env__' in __opts__['file_roots']:
|
||||
log.debug("salt environment '%s' maps to __env__ file_roots directory", saltenv)
|
||||
saltenv = '__env__'
|
||||
else:
|
||||
return fnd
|
||||
|
||||
def _add_file_stat(fnd):
|
||||
'''
|
||||
|
@ -220,6 +224,9 @@ def file_hash(load, fnd):
|
|||
if 'path' not in load or 'saltenv' not in load:
|
||||
return ''
|
||||
path = fnd['path']
|
||||
saltenv = load['saltenv']
|
||||
if saltenv not in __opts__['file_roots'] and '__env__' in __opts__['file_roots']:
|
||||
saltenv = '__env__'
|
||||
ret = {}
|
||||
|
||||
# if the file doesn't exist, we can't get a hash
|
||||
|
@ -234,7 +241,7 @@ def file_hash(load, fnd):
|
|||
cache_path = os.path.join(__opts__['cachedir'],
|
||||
'roots',
|
||||
'hash',
|
||||
load['saltenv'],
|
||||
saltenv,
|
||||
'{0}.hash.{1}'.format(fnd['rel'],
|
||||
__opts__['hash_type']))
|
||||
# if we have a cache, serve that if the mtime hasn't changed
|
||||
|
@ -293,8 +300,13 @@ def _file_lists(load, form):
|
|||
# "env" is not supported; Use "saltenv".
|
||||
load.pop('env')
|
||||
|
||||
if load['saltenv'] not in __opts__['file_roots']:
|
||||
return []
|
||||
saltenv = load['saltenv']
|
||||
if saltenv not in __opts__['file_roots']:
|
||||
if '__env__' in __opts__['file_roots']:
|
||||
log.debug("salt environment '%s' maps to __env__ file_roots directory", saltenv)
|
||||
saltenv = '__env__'
|
||||
else:
|
||||
return []
|
||||
|
||||
list_cachedir = os.path.join(__opts__['cachedir'], 'file_lists', 'roots')
|
||||
if not os.path.isdir(list_cachedir):
|
||||
|
@ -303,8 +315,8 @@ def _file_lists(load, form):
|
|||
except os.error:
|
||||
log.critical('Unable to make cachedir %s', list_cachedir)
|
||||
return []
|
||||
list_cache = os.path.join(list_cachedir, '{0}.p'.format(load['saltenv']))
|
||||
w_lock = os.path.join(list_cachedir, '.{0}.w'.format(load['saltenv']))
|
||||
list_cache = os.path.join(list_cachedir, '{0}.p'.format(salt.utils.files.safe_filename_leaf(saltenv)))
|
||||
w_lock = os.path.join(list_cachedir, '.{0}.w'.format(salt.utils.files.safe_filename_leaf(saltenv)))
|
||||
cache_match, refresh_cache, save_cache = \
|
||||
salt.fileserver.check_file_list_cache(
|
||||
__opts__, form, list_cache, w_lock
|
||||
|
@ -390,7 +402,7 @@ def _file_lists(load, form):
|
|||
# (i.e. the "path" variable)
|
||||
ret['links'][rel_path] = link_dest
|
||||
|
||||
for path in __opts__['file_roots'][load['saltenv']]:
|
||||
for path in __opts__['file_roots'][saltenv]:
|
||||
for root, dirs, files in salt.utils.path.os_walk(
|
||||
path,
|
||||
followlinks=__opts__['fileserver_followsymlinks']):
|
||||
|
@ -445,7 +457,7 @@ def symlink_list(load):
|
|||
load.pop('env')
|
||||
|
||||
ret = {}
|
||||
if load['saltenv'] not in __opts__['file_roots']:
|
||||
if load['saltenv'] not in __opts__['file_roots'] and '__env__' not in __opts__['file_roots']:
|
||||
return ret
|
||||
|
||||
if 'prefix' in load:
|
||||
|
|
|
@ -22,6 +22,7 @@ import locale
|
|||
import uuid
|
||||
from errno import EACCES, EPERM
|
||||
import datetime
|
||||
import warnings
|
||||
|
||||
__proxyenabled__ = ['*']
|
||||
__FQDN__ = None
|
||||
|
@ -34,7 +35,12 @@ _supported_dists += ('arch', 'mageia', 'meego', 'vmware', 'bluewhite64',
|
|||
|
||||
# linux_distribution deprecated in py3.7
|
||||
try:
|
||||
from platform import linux_distribution
|
||||
from platform import linux_distribution as _deprecated_linux_distribution
|
||||
|
||||
def linux_distribution(**kwargs):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
return _deprecated_linux_distribution(**kwargs)
|
||||
except ImportError:
|
||||
from distro import linux_distribution
|
||||
|
||||
|
@ -1389,7 +1395,9 @@ _OS_FAMILY_MAP = {
|
|||
'KDE neon': 'Debian',
|
||||
'Void': 'Void',
|
||||
'IDMS': 'Debian',
|
||||
'AIX': 'AIX'
|
||||
'Funtoo': 'Gentoo',
|
||||
'AIX': 'AIX',
|
||||
'TurnKey': 'Debian',
|
||||
}
|
||||
|
||||
# Matches any possible format:
|
||||
|
|
|
@ -1582,7 +1582,7 @@ def _split_repo_str(repo):
|
|||
Return APT source entry as a tuple.
|
||||
'''
|
||||
split = sourceslist.SourceEntry(repo)
|
||||
return split.type, split.uri, split.dist, split.comps
|
||||
return split.type, split.architectures, split.uri, split.dist, split.comps
|
||||
|
||||
|
||||
def _consolidate_repo_sources(sources):
|
||||
|
@ -1771,7 +1771,7 @@ def get_repo(repo, **kwargs):
|
|||
|
||||
if repos:
|
||||
try:
|
||||
repo_type, repo_uri, repo_dist, repo_comps = _split_repo_str(repo)
|
||||
repo_type, repo_architectures, repo_uri, repo_dist, repo_comps = _split_repo_str(repo)
|
||||
if ppa_auth:
|
||||
uri_match = re.search('(http[s]?://)(.+)', repo_uri)
|
||||
if uri_match:
|
||||
|
@ -1844,7 +1844,11 @@ def del_repo(repo, **kwargs):
|
|||
if repos:
|
||||
deleted_from = dict()
|
||||
try:
|
||||
repo_type, repo_uri, repo_dist, repo_comps = _split_repo_str(repo)
|
||||
repo_type, \
|
||||
repo_architectures, \
|
||||
repo_uri, \
|
||||
repo_dist, \
|
||||
repo_comps = _split_repo_str(repo)
|
||||
except SyntaxError:
|
||||
raise SaltInvocationError(
|
||||
'Error: repo \'{0}\' not a well formatted definition'
|
||||
|
@ -1852,8 +1856,10 @@ def del_repo(repo, **kwargs):
|
|||
)
|
||||
|
||||
for source in repos:
|
||||
if (source.type == repo_type and source.uri == repo_uri and
|
||||
source.dist == repo_dist):
|
||||
if (source.type == repo_type
|
||||
and source.architectures == repo_architectures
|
||||
and source.uri == repo_uri
|
||||
and source.dist == repo_dist):
|
||||
|
||||
s_comps = set(source.comps)
|
||||
r_comps = set(repo_comps)
|
||||
|
@ -2319,7 +2325,11 @@ def mod_repo(repo, saltenv='base', **kwargs):
|
|||
repos = [s for s in sources if not s.invalid]
|
||||
mod_source = None
|
||||
try:
|
||||
repo_type, repo_uri, repo_dist, repo_comps = _split_repo_str(repo)
|
||||
repo_type, \
|
||||
repo_architectures, \
|
||||
repo_uri, \
|
||||
repo_dist, \
|
||||
repo_comps = _split_repo_str(repo)
|
||||
except SyntaxError:
|
||||
raise SyntaxError(
|
||||
'Error: repo \'{0}\' not a well formatted definition'.format(repo)
|
||||
|
@ -2387,6 +2397,8 @@ def mod_repo(repo, saltenv='base', **kwargs):
|
|||
|
||||
if 'architectures' in kwargs:
|
||||
kwargs['architectures'] = kwargs['architectures'].split(',')
|
||||
else:
|
||||
kwargs['architectures'] = repo_architectures
|
||||
|
||||
if 'disabled' in kwargs:
|
||||
kwargs['disabled'] = salt.utils.data.is_true(kwargs['disabled'])
|
||||
|
@ -2408,6 +2420,8 @@ def mod_repo(repo, saltenv='base', **kwargs):
|
|||
mod_source = source
|
||||
if not source.comps:
|
||||
mod_source = source
|
||||
if kwargs['architectures'] != source.architectures:
|
||||
mod_source = source
|
||||
if mod_source:
|
||||
break
|
||||
|
||||
|
|
|
@ -388,6 +388,9 @@ def _get_snapshot_version_metadata(artifactory_url, repository, group_id, artifa
|
|||
extension = snapshot_version.find('extension').text
|
||||
value = snapshot_version.find('value').text
|
||||
extension_version_dict[extension] = value
|
||||
if snapshot_version.find('classifier') is not None:
|
||||
classifier = snapshot_version.find('classifier').text
|
||||
extension_version_dict[classifier] = value
|
||||
|
||||
return {
|
||||
'snapshot_versions': extension_version_dict
|
||||
|
|
|
@ -19,8 +19,7 @@ The firewall configuration is generated by Capirca_.
|
|||
|
||||
.. _Capirca: https://github.com/google/capirca
|
||||
|
||||
Capirca is not yet available on PyPI threrefore it has to be installed
|
||||
directly form Git: ``pip install -e git+git@github.com:google/capirca.git#egg=aclgen``.
|
||||
To install Capirca, execute: ``pip install capirca``.
|
||||
'''
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
|
@ -34,7 +33,10 @@ log = logging.getLogger(__file__)
|
|||
# Import third party libs
|
||||
from salt.ext import six
|
||||
try:
|
||||
import aclgen
|
||||
import capirca
|
||||
import capirca.aclgen
|
||||
import capirca.lib.policy
|
||||
import capirca.lib.aclgenerator
|
||||
HAS_CAPIRCA = True
|
||||
except ImportError:
|
||||
HAS_CAPIRCA = False
|
||||
|
@ -69,10 +71,12 @@ def __virtual__():
|
|||
# module globals
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# define the default values for all possible term fields
|
||||
# we could also extract them from the `policy` module, inspecting the `Policy`
|
||||
# class, but that might be overkill & it would make the code less obvious.
|
||||
# we can revisit this later if necessary.
|
||||
|
||||
_TERM_FIELDS = {
|
||||
'action': [],
|
||||
'address': [],
|
||||
|
@ -161,7 +165,19 @@ _SERVICES = {}
|
|||
|
||||
|
||||
if HAS_CAPIRCA:
|
||||
class _Policy(aclgen.policy.Policy):
|
||||
_TempTerm = capirca.lib.policy.Term
|
||||
|
||||
def _add_object(self, obj):
|
||||
return
|
||||
|
||||
setattr(_TempTerm, 'AddObject', _add_object)
|
||||
dumy_term = _TempTerm(None)
|
||||
for item in dir(dumy_term):
|
||||
if hasattr(item, '__func__') or item.startswith('_') or item != item.lower():
|
||||
continue
|
||||
_TERM_FIELDS[item] = getattr(dumy_term, item)
|
||||
|
||||
class _Policy(capirca.lib.policy.Policy):
|
||||
'''
|
||||
Extending the Capirca Policy class to allow inserting custom filters.
|
||||
'''
|
||||
|
@ -169,7 +185,7 @@ if HAS_CAPIRCA:
|
|||
self.filters = []
|
||||
self.filename = ''
|
||||
|
||||
class _Term(aclgen.policy.Term):
|
||||
class _Term(capirca.lib.policy.Term):
|
||||
'''
|
||||
Extending the Capirca Term class to allow setting field valued on the fly.
|
||||
'''
|
||||
|
@ -186,10 +202,10 @@ def _import_platform_generator(platform):
|
|||
for a class inheriting the `ACLGenerator` class.
|
||||
'''
|
||||
log.debug('Using platform: {plat}'.format(plat=platform))
|
||||
for mod_name, mod_obj in inspect.getmembers(aclgen):
|
||||
for mod_name, mod_obj in inspect.getmembers(capirca.aclgen):
|
||||
if mod_name == platform and inspect.ismodule(mod_obj):
|
||||
for plat_obj_name, plat_obj in inspect.getmembers(mod_obj): # pylint: disable=unused-variable
|
||||
if inspect.isclass(plat_obj) and issubclass(plat_obj, aclgen.aclgenerator.ACLGenerator):
|
||||
if inspect.isclass(plat_obj) and issubclass(plat_obj, capirca.lib.aclgenerator.ACLGenerator):
|
||||
log.debug('Identified Capirca class {cls} for {plat}'.format(
|
||||
cls=plat_obj,
|
||||
plat=platform))
|
||||
|
@ -366,7 +382,11 @@ def _clean_term_opts(term_opts):
|
|||
# IP-type fields need to be transformed
|
||||
ip_values = []
|
||||
for addr in value:
|
||||
ip_values.append(aclgen.policy.nacaddr.IP(addr))
|
||||
if six.PY2:
|
||||
addr = six.text_type(addr)
|
||||
# Adding this, as ipaddress would complain about valid
|
||||
# addresses not being valid. #pythonIsFun
|
||||
ip_values.append(capirca.lib.policy.nacaddr.IP(addr))
|
||||
value = ip_values[:]
|
||||
clean_opts[field] = value
|
||||
return clean_opts
|
||||
|
@ -427,7 +447,7 @@ def _merge_list_of_dict(first, second, prepend=True):
|
|||
if first and not second:
|
||||
return first
|
||||
# Determine overlaps
|
||||
# So we don't change the position of the existing terms/filters
|
||||
# So we dont change the position of the existing terms/filters
|
||||
overlaps = []
|
||||
merged = []
|
||||
appended = []
|
||||
|
@ -514,7 +534,7 @@ def _get_policy_object(platform,
|
|||
continue # go to the next filter
|
||||
filter_name = filter_.keys()[0]
|
||||
filter_config = filter_.values()[0]
|
||||
header = aclgen.policy.Header() # same header everywhere
|
||||
header = capirca.lib.policy.Header() # same header everywhere
|
||||
target_opts = [
|
||||
platform,
|
||||
filter_name
|
||||
|
@ -524,7 +544,7 @@ def _get_policy_object(platform,
|
|||
filter_options = _make_it_list({}, filter_name, filter_options)
|
||||
# make sure the filter options are sent as list
|
||||
target_opts.extend(filter_options)
|
||||
target = aclgen.policy.Target(target_opts)
|
||||
target = capirca.lib.policy.Target(target_opts)
|
||||
header.AddObject(target)
|
||||
filter_terms = []
|
||||
for term_ in filter_config.get('terms', []):
|
||||
|
|
|
@ -280,7 +280,7 @@ def _run(cmd,
|
|||
'''
|
||||
if 'pillar' in kwargs and not pillar_override:
|
||||
pillar_override = kwargs['pillar']
|
||||
if _is_valid_shell(shell) is False:
|
||||
if output_loglevel != 'quiet' and _is_valid_shell(shell) is False:
|
||||
log.warning(
|
||||
'Attempt to run a shell command with what may be an invalid shell! '
|
||||
'Check to ensure that the shell <%s> is valid for this user.',
|
||||
|
|
|
@ -22,6 +22,7 @@ import re
|
|||
|
||||
# Import salt libs
|
||||
import salt.utils.args
|
||||
import salt.utils.compat
|
||||
import salt.utils.data
|
||||
import salt.utils.functools
|
||||
import salt.utils.path
|
||||
|
@ -31,9 +32,6 @@ import salt.utils.versions
|
|||
from salt.exceptions import CommandExecutionError, MinionError
|
||||
from salt.ext import six
|
||||
|
||||
# Workaround for 'reload' builtin of py2.7
|
||||
if six.PY3:
|
||||
from importlib import reload # pylint: disable=no-name-in-module
|
||||
|
||||
# Import third party libs
|
||||
HAS_PORTAGE = False
|
||||
|
@ -69,13 +67,13 @@ def __virtual__():
|
|||
|
||||
def _vartree():
|
||||
import portage # pylint: disable=3rd-party-module-not-gated
|
||||
portage = reload(portage)
|
||||
portage = salt.utils.compat.reload(portage)
|
||||
return portage.db[portage.root]['vartree']
|
||||
|
||||
|
||||
def _porttree():
|
||||
import portage # pylint: disable=3rd-party-module-not-gated
|
||||
portage = reload(portage)
|
||||
portage = salt.utils.compat.reload(portage)
|
||||
return portage.db[portage.root]['porttree']
|
||||
|
||||
|
||||
|
|
|
@ -91,8 +91,12 @@ def install(gems, # pylint: disable=C0103
|
|||
Doesn't play nice with multiple gems at once
|
||||
:param rdoc: boolean : False
|
||||
Generate RDoc documentation for the gem(s).
|
||||
For rubygems > 3 this is interpreted as the --no-document arg and the
|
||||
ri option will then be ignored
|
||||
:param ri: boolean : False
|
||||
Generate RI documentation for the gem(s).
|
||||
For rubygems > 3 this is interpreted as the --no-document arg and the
|
||||
rdoc option will then be ignored
|
||||
:param pre_releases: boolean : False
|
||||
Include pre-releases in the available versions
|
||||
:param proxy: string : None
|
||||
|
@ -119,12 +123,18 @@ def install(gems, # pylint: disable=C0103
|
|||
options = []
|
||||
if version:
|
||||
options.extend(['--version', version])
|
||||
if not rdoc:
|
||||
options.append('--no-rdoc')
|
||||
if not ri:
|
||||
options.append('--no-ri')
|
||||
if pre_releases:
|
||||
options.append('--pre')
|
||||
if _has_rubygems_3(ruby=ruby, runas=runas, gem_bin=gem_bin):
|
||||
if not rdoc or not ri:
|
||||
options.append('--no-document')
|
||||
if pre_releases:
|
||||
options.append('--prerelease')
|
||||
else:
|
||||
if not rdoc:
|
||||
options.append('--no-rdoc')
|
||||
if not ri:
|
||||
options.append('--no-ri')
|
||||
if pre_releases:
|
||||
options.append('--pre')
|
||||
if proxy:
|
||||
options.extend(['-p', proxy])
|
||||
if source:
|
||||
|
@ -224,6 +234,45 @@ def update_system(version='', ruby=None, runas=None, gem_bin=None):
|
|||
runas=runas)
|
||||
|
||||
|
||||
def version(ruby=None, runas=None, gem_bin=None):
|
||||
'''
|
||||
Print out the version of gem
|
||||
|
||||
:param gem_bin: string : None
|
||||
Full path to ``gem`` binary to use.
|
||||
:param ruby: string : None
|
||||
If RVM or rbenv are installed, the ruby version and gemset to use.
|
||||
Ignored if ``gem_bin`` is specified.
|
||||
:param runas: string : None
|
||||
The user to run gem as.
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' gem.version
|
||||
'''
|
||||
cmd = ['--version']
|
||||
stdout = _gem(cmd,
|
||||
ruby,
|
||||
gem_bin=gem_bin,
|
||||
runas=runas)
|
||||
ret = {}
|
||||
for line in salt.utils.itertools.split(stdout, '\n'):
|
||||
match = re.match(r'[.0-9]+', line)
|
||||
if match:
|
||||
ret = line
|
||||
break
|
||||
return ret
|
||||
|
||||
|
||||
def _has_rubygems_3(ruby=None, runas=None, gem_bin=None):
|
||||
match = re.match(r'^3\..*', version(ruby=ruby, runas=runas, gem_bin=gem_bin))
|
||||
if match:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def list_(prefix='', ruby=None, runas=None, gem_bin=None):
|
||||
'''
|
||||
List locally installed gems.
|
||||
|
|
|
@ -979,7 +979,7 @@ def clone(cwd,
|
|||
information on securing the keypair from the remote side in the
|
||||
``authorized_keys`` file.
|
||||
|
||||
.. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE%20FORMAT
|
||||
.. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE_FORMAT
|
||||
|
||||
.. versionchanged:: 2015.8.7
|
||||
|
||||
|
@ -2035,7 +2035,7 @@ def fetch(cwd,
|
|||
information on securing the keypair from the remote side in the
|
||||
``authorized_keys`` file.
|
||||
|
||||
.. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE%20FORMAT
|
||||
.. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE_FORMAT
|
||||
|
||||
.. versionchanged:: 2015.8.7
|
||||
|
||||
|
@ -2847,7 +2847,7 @@ def ls_remote(cwd=None,
|
|||
information on securing the keypair from the remote side in the
|
||||
``authorized_keys`` file.
|
||||
|
||||
.. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE%20FORMAT
|
||||
.. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE_FORMAT
|
||||
|
||||
.. versionchanged:: 2015.8.7
|
||||
|
||||
|
@ -2940,6 +2940,7 @@ def merge(cwd,
|
|||
git_opts='',
|
||||
user=None,
|
||||
password=None,
|
||||
identity=None,
|
||||
ignore_retcode=False,
|
||||
output_encoding=None,
|
||||
**kwargs):
|
||||
|
@ -2983,6 +2984,22 @@ def merge(cwd,
|
|||
|
||||
.. versionadded:: 2016.3.4
|
||||
|
||||
identity
|
||||
Path to a private key to use for ssh URLs. Salt will not attempt to use
|
||||
passphrase-protected keys unless invoked from the minion using
|
||||
``salt-call``, to prevent blocking waiting for user input. Key can also
|
||||
be specified as a SaltStack file server URL, eg.
|
||||
``salt://location/identity_file``.
|
||||
|
||||
.. note::
|
||||
For greater security with passphraseless private keys, see the
|
||||
`sshd(8)`_ manpage for information on securing the keypair from the
|
||||
remote side in the ``authorized_keys`` file.
|
||||
|
||||
.. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE_FORMAT
|
||||
|
||||
.. versionadded:: 2018.3.5,2019.2.1,Neon
|
||||
|
||||
ignore_retcode : False
|
||||
If ``True``, do not log an error to the minion log if the git command
|
||||
returns a nonzero exit status.
|
||||
|
@ -3024,10 +3041,12 @@ def merge(cwd,
|
|||
command.extend(_format_opts(opts))
|
||||
if rev:
|
||||
command.append(rev)
|
||||
|
||||
return _git_run(command,
|
||||
cwd=cwd,
|
||||
user=user,
|
||||
password=password,
|
||||
identity=identity,
|
||||
ignore_retcode=ignore_retcode,
|
||||
output_encoding=output_encoding)['stdout']
|
||||
|
||||
|
@ -3382,7 +3401,7 @@ def pull(cwd,
|
|||
information on securing the keypair from the remote side in the
|
||||
``authorized_keys`` file.
|
||||
|
||||
.. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE%20FORMAT
|
||||
.. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE_FORMAT
|
||||
|
||||
.. versionchanged:: 2015.8.7
|
||||
|
||||
|
@ -3508,7 +3527,7 @@ def push(cwd,
|
|||
information on securing the keypair from the remote side in the
|
||||
``authorized_keys`` file.
|
||||
|
||||
.. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE%20FORMAT
|
||||
.. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE_FORMAT
|
||||
|
||||
.. versionchanged:: 2015.8.7
|
||||
|
||||
|
@ -3792,7 +3811,7 @@ def remote_refs(url,
|
|||
information on securing the keypair from the remote side in the
|
||||
``authorized_keys`` file.
|
||||
|
||||
.. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE%20FORMAT
|
||||
.. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE_FORMAT
|
||||
|
||||
.. versionchanged:: 2015.8.7
|
||||
|
||||
|
@ -4101,6 +4120,7 @@ def reset(cwd,
|
|||
git_opts='',
|
||||
user=None,
|
||||
password=None,
|
||||
identity=None,
|
||||
ignore_retcode=False,
|
||||
output_encoding=None):
|
||||
'''
|
||||
|
@ -4137,6 +4157,22 @@ def reset(cwd,
|
|||
|
||||
.. versionadded:: 2016.3.4
|
||||
|
||||
identity
|
||||
Path to a private key to use for ssh URLs. Salt will not attempt to use
|
||||
passphrase-protected keys unless invoked from the minion using
|
||||
``salt-call``, to prevent blocking waiting for user input. Key can also
|
||||
be specified as a SaltStack file server URL, eg.
|
||||
``salt://location/identity_file``.
|
||||
|
||||
.. note::
|
||||
For greater security with passphraseless private keys, see the
|
||||
`sshd(8)`_ manpage for information on securing the keypair from the
|
||||
remote side in the ``authorized_keys`` file.
|
||||
|
||||
.. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE_FORMAT
|
||||
|
||||
.. versionadded:: 2018.3.5,2019.2.1,Neon
|
||||
|
||||
ignore_retcode : False
|
||||
If ``True``, do not log an error to the minion log if the git command
|
||||
returns a nonzero exit status.
|
||||
|
@ -4174,6 +4210,7 @@ def reset(cwd,
|
|||
cwd=cwd,
|
||||
user=user,
|
||||
password=password,
|
||||
identity=identity,
|
||||
ignore_retcode=ignore_retcode,
|
||||
output_encoding=output_encoding)['stdout']
|
||||
|
||||
|
@ -4662,7 +4699,7 @@ def submodule(cwd,
|
|||
information on securing the keypair from the remote side in the
|
||||
``authorized_keys`` file.
|
||||
|
||||
.. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE%20FORMAT
|
||||
.. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE_FORMAT
|
||||
|
||||
.. versionchanged:: 2015.8.7
|
||||
|
||||
|
|
|
@ -226,6 +226,7 @@ def _resolve_user_group_names(opts):
|
|||
if _info and _param in _info:
|
||||
_id = _info[_param]
|
||||
opts[ind] = _param + '=' + six.text_type(_id)
|
||||
opts[ind] = opts[ind].replace('\\040', '\\ ')
|
||||
return opts
|
||||
|
||||
|
||||
|
@ -727,7 +728,7 @@ def set_fstab(
|
|||
'name': name,
|
||||
'device': device.replace('\\ ', '\\040'),
|
||||
'fstype': fstype,
|
||||
'opts': opts,
|
||||
'opts': opts.replace('\\ ', '\\040'),
|
||||
'dump': dump,
|
||||
'pass_num': pass_num,
|
||||
}
|
||||
|
|
|
@ -1266,6 +1266,7 @@ def user_exists(user,
|
|||
'''
|
||||
run_verify = False
|
||||
server_version = version(**connection_args)
|
||||
compare_version = '10.2.0' if 'MariaDB' in server_version else '8.0.11'
|
||||
dbc = _connect(**connection_args)
|
||||
# Did we fail to connect with the user we are checking
|
||||
# Its password might have previously change with the same command/state
|
||||
|
@ -1297,7 +1298,7 @@ def user_exists(user,
|
|||
else:
|
||||
qry += ' AND ' + password_column + ' = \'\''
|
||||
elif password:
|
||||
if salt.utils.versions.version_cmp(server_version, '8.0.11') >= 0:
|
||||
if salt.utils.versions.version_cmp(server_version, compare_version) >= 0:
|
||||
run_verify = True
|
||||
else:
|
||||
_password = password
|
||||
|
@ -1404,6 +1405,7 @@ def user_create(user,
|
|||
salt '*' mysql.user_create 'username' 'hostname' allow_passwordless=True
|
||||
'''
|
||||
server_version = version(**connection_args)
|
||||
compare_version = '10.2.0' if 'MariaDB' in server_version else '8.0.11'
|
||||
if user_exists(user, host, **connection_args):
|
||||
log.info('User \'%s\'@\'%s\' already exists', user, host)
|
||||
return False
|
||||
|
@ -1424,7 +1426,7 @@ def user_create(user,
|
|||
qry += ' IDENTIFIED BY %(password)s'
|
||||
args['password'] = six.text_type(password)
|
||||
elif password_hash is not None:
|
||||
if salt.utils.versions.version_cmp(server_version, '8.0.11') >= 0:
|
||||
if salt.utils.versions.version_cmp(server_version, compare_version) >= 0:
|
||||
qry += ' IDENTIFIED BY %(password)s'
|
||||
else:
|
||||
qry += ' IDENTIFIED BY PASSWORD %(password)s'
|
||||
|
@ -1508,9 +1510,10 @@ def user_chpass(user,
|
|||
salt '*' mysql.user_chpass frank localhost allow_passwordless=True
|
||||
'''
|
||||
server_version = version(**connection_args)
|
||||
compare_version = '10.2.0' if 'MariaDB' in server_version else '8.0.11'
|
||||
args = {}
|
||||
if password is not None:
|
||||
if salt.utils.versions.version_cmp(server_version, '8.0.11') >= 0:
|
||||
if salt.utils.versions.version_cmp(server_version, compare_version) >= 0:
|
||||
password_sql = '%(password)s'
|
||||
else:
|
||||
password_sql = 'PASSWORD(%(password)s)'
|
||||
|
@ -1533,28 +1536,23 @@ def user_chpass(user,
|
|||
password_column = __password_column(**connection_args)
|
||||
|
||||
cur = dbc.cursor()
|
||||
if salt.utils.versions.version_cmp(server_version, '8.0.11') >= 0:
|
||||
qry = ("ALTER USER '" + user + "'@'" + host + "'"
|
||||
" IDENTIFIED BY '" + password + "';")
|
||||
args = {}
|
||||
args['user'] = user
|
||||
args['host'] = host
|
||||
if salt.utils.versions.version_cmp(server_version, compare_version) >= 0:
|
||||
qry = "ALTER USER %(user)s@%(host)s IDENTIFIED BY %(password)s;"
|
||||
else:
|
||||
qry = ('UPDATE mysql.user SET ' + password_column + '='
|
||||
+ password_sql +
|
||||
qry = ('UPDATE mysql.user SET ' + password_column + '=' + password_sql +
|
||||
' WHERE User=%(user)s AND Host = %(host)s;')
|
||||
args['user'] = user
|
||||
args['host'] = host
|
||||
if salt.utils.data.is_true(allow_passwordless) and \
|
||||
salt.utils.data.is_true(unix_socket):
|
||||
if host == 'localhost':
|
||||
if salt.utils.versions.version_cmp(server_version, '8.0.11') >= 0:
|
||||
qry = ("ALTER USER '" + user + "'@'" + host + "'"
|
||||
" IDENTIFIED BY '" + password + "';")
|
||||
args = {}
|
||||
args['unix_socket'] = 'auth_socket'
|
||||
if salt.utils.versions.version_cmp(server_version, compare_version) >= 0:
|
||||
qry = "ALTER USER %(user)s@%(host)s IDENTIFIED WITH %(unix_socket)s AS %(user)s;"
|
||||
else:
|
||||
qry = ('UPDATE mysql.user SET ' + password_column + '='
|
||||
+ password_sql + ', plugin=%(unix_socket)s' +
|
||||
' WHERE User=%(user)s AND Host = %(host)s;')
|
||||
args['unix_socket'] = 'unix_socket'
|
||||
else:
|
||||
log.error('Auth via unix_socket can be set only for host=localhost')
|
||||
try:
|
||||
|
@ -1565,7 +1563,7 @@ def user_chpass(user,
|
|||
log.error(err)
|
||||
return False
|
||||
|
||||
if salt.utils.versions.version_cmp(server_version, '8.0.11') >= 0:
|
||||
if salt.utils.versions.version_cmp(server_version, compare_version) >= 0:
|
||||
_execute(cur, 'FLUSH PRIVILEGES;')
|
||||
log.info(
|
||||
'Password for user \'%s\'@\'%s\' has been %s',
|
||||
|
@ -1869,7 +1867,8 @@ def grant_exists(grant,
|
|||
|
||||
server_version = version(**connection_args)
|
||||
if 'ALL' in grant:
|
||||
if salt.utils.versions.version_cmp(server_version, '8.0') >= 0:
|
||||
if salt.utils.versions.version_cmp(server_version, '8.0') >= 0 and \
|
||||
'MariaDB' not in server_version:
|
||||
grant = ','.join([i for i in __all_privileges__])
|
||||
else:
|
||||
grant = 'ALL PRIVILEGES'
|
||||
|
|
|
@ -19,6 +19,8 @@ The firewall configuration is generated by Capirca_.
|
|||
|
||||
.. _Capirca: https://github.com/google/capirca
|
||||
|
||||
To install Capirca, execute: ``pip install capirca``.
|
||||
|
||||
To be able to load configuration on network devices,
|
||||
it requires NAPALM_ library to be installed: ``pip install napalm``.
|
||||
Please check Installation_ for complete details.
|
||||
|
@ -34,7 +36,10 @@ log = logging.getLogger(__file__)
|
|||
# Import third party libs
|
||||
try:
|
||||
# pylint: disable=W0611
|
||||
import aclgen
|
||||
import capirca
|
||||
import capirca.aclgen
|
||||
import capirca.lib.policy
|
||||
import capirca.lib.aclgenerator
|
||||
HAS_CAPIRCA = True
|
||||
# pylint: enable=W0611
|
||||
except ImportError:
|
||||
|
|
|
@ -1620,7 +1620,7 @@ def set_authentication_profile(profile=None, deploy=False):
|
|||
'''
|
||||
|
||||
if not profile:
|
||||
CommandExecutionError("Profile name option must not be none.")
|
||||
raise CommandExecutionError("Profile name option must not be none.")
|
||||
|
||||
ret = {}
|
||||
|
||||
|
@ -1657,7 +1657,7 @@ def set_hostname(hostname=None, deploy=False):
|
|||
'''
|
||||
|
||||
if not hostname:
|
||||
CommandExecutionError("Hostname option must not be none.")
|
||||
raise CommandExecutionError("Hostname option must not be none.")
|
||||
|
||||
ret = {}
|
||||
|
||||
|
@ -1697,7 +1697,7 @@ def set_management_icmp(enabled=True, deploy=False):
|
|||
elif enabled is False:
|
||||
value = "yes"
|
||||
else:
|
||||
CommandExecutionError("Invalid option provided for service enabled option.")
|
||||
raise CommandExecutionError("Invalid option provided for service enabled option.")
|
||||
|
||||
ret = {}
|
||||
|
||||
|
@ -1737,7 +1737,7 @@ def set_management_http(enabled=True, deploy=False):
|
|||
elif enabled is False:
|
||||
value = "yes"
|
||||
else:
|
||||
CommandExecutionError("Invalid option provided for service enabled option.")
|
||||
raise CommandExecutionError("Invalid option provided for service enabled option.")
|
||||
|
||||
ret = {}
|
||||
|
||||
|
@ -1777,7 +1777,7 @@ def set_management_https(enabled=True, deploy=False):
|
|||
elif enabled is False:
|
||||
value = "yes"
|
||||
else:
|
||||
CommandExecutionError("Invalid option provided for service enabled option.")
|
||||
raise CommandExecutionError("Invalid option provided for service enabled option.")
|
||||
|
||||
ret = {}
|
||||
|
||||
|
@ -1817,7 +1817,7 @@ def set_management_ocsp(enabled=True, deploy=False):
|
|||
elif enabled is False:
|
||||
value = "yes"
|
||||
else:
|
||||
CommandExecutionError("Invalid option provided for service enabled option.")
|
||||
raise CommandExecutionError("Invalid option provided for service enabled option.")
|
||||
|
||||
ret = {}
|
||||
|
||||
|
@ -1857,7 +1857,7 @@ def set_management_snmp(enabled=True, deploy=False):
|
|||
elif enabled is False:
|
||||
value = "yes"
|
||||
else:
|
||||
CommandExecutionError("Invalid option provided for service enabled option.")
|
||||
raise CommandExecutionError("Invalid option provided for service enabled option.")
|
||||
|
||||
ret = {}
|
||||
|
||||
|
@ -1897,7 +1897,7 @@ def set_management_ssh(enabled=True, deploy=False):
|
|||
elif enabled is False:
|
||||
value = "yes"
|
||||
else:
|
||||
CommandExecutionError("Invalid option provided for service enabled option.")
|
||||
raise CommandExecutionError("Invalid option provided for service enabled option.")
|
||||
|
||||
ret = {}
|
||||
|
||||
|
@ -1937,7 +1937,7 @@ def set_management_telnet(enabled=True, deploy=False):
|
|||
elif enabled is False:
|
||||
value = "yes"
|
||||
else:
|
||||
CommandExecutionError("Invalid option provided for service enabled option.")
|
||||
raise CommandExecutionError("Invalid option provided for service enabled option.")
|
||||
|
||||
ret = {}
|
||||
|
||||
|
@ -2130,7 +2130,7 @@ def set_permitted_ip(address=None, deploy=False):
|
|||
'''
|
||||
|
||||
if not address:
|
||||
CommandExecutionError("Address option must not be empty.")
|
||||
raise CommandExecutionError("Address option must not be empty.")
|
||||
|
||||
ret = {}
|
||||
|
||||
|
@ -2166,7 +2166,7 @@ def set_timezone(tz=None, deploy=False):
|
|||
'''
|
||||
|
||||
if not tz:
|
||||
CommandExecutionError("Timezone name option must not be none.")
|
||||
raise CommandExecutionError("Timezone name option must not be none.")
|
||||
|
||||
ret = {}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ import collections
|
|||
# Import third party libs
|
||||
import copy
|
||||
import os
|
||||
import copy
|
||||
import logging
|
||||
from salt.ext import six
|
||||
|
||||
|
@ -157,7 +156,7 @@ def get(key,
|
|||
'skipped.', default, ret, type(ret).__name__
|
||||
)
|
||||
elif isinstance(default, list):
|
||||
ret = salt.utils.data.traverse_dict_and_list(
|
||||
ret = salt.utils.data.traverse_dict_and_list( # pylint: disable=redefined-variable-type
|
||||
pillar_dict,
|
||||
key,
|
||||
[],
|
||||
|
@ -345,7 +344,7 @@ def ls(*args):
|
|||
salt '*' pillar.ls
|
||||
'''
|
||||
|
||||
return list(items(*args).keys())
|
||||
return list(items(*args))
|
||||
|
||||
|
||||
def item(*args, **kwargs):
|
||||
|
@ -544,7 +543,7 @@ def keys(key, delimiter=DEFAULT_TARGET_DELIM):
|
|||
if not isinstance(ret, dict):
|
||||
raise ValueError("Pillar value in key {0} is not a dict".format(key))
|
||||
|
||||
return ret.keys()
|
||||
return list(ret)
|
||||
|
||||
|
||||
def file_exists(path, saltenv=None):
|
||||
|
|
|
@ -10,6 +10,7 @@ import os
|
|||
import shutil
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils.compat
|
||||
import salt.utils.data
|
||||
import salt.utils.files
|
||||
import salt.utils.path
|
||||
|
@ -57,7 +58,7 @@ def _get_portage():
|
|||
portage module must be reloaded or it can't catch the changes
|
||||
in portage.* which had been added after when the module was loaded
|
||||
'''
|
||||
return reload(portage)
|
||||
return salt.utils.compat.reload(portage)
|
||||
|
||||
|
||||
def _porttree():
|
||||
|
|
|
@ -46,6 +46,7 @@ import salt.utils.data
|
|||
import salt.utils.functools
|
||||
import salt.utils.path
|
||||
import salt.utils.pkg
|
||||
from salt.ext.six import string_types
|
||||
from salt.exceptions import CommandExecutionError
|
||||
|
||||
# Define the module's virtual name
|
||||
|
@ -474,12 +475,16 @@ def install(name=None, refresh=False, pkgs=None, version=None, test=False, **kwa
|
|||
|
||||
pkg2inst = ''
|
||||
if pkgs: # multiple packages specified
|
||||
pkg2inst = []
|
||||
for pkg in pkgs:
|
||||
if list(pkg.items())[0][1]: # version specified
|
||||
pkg2inst += '{0}@{1} '.format(list(pkg.items())[0][0],
|
||||
list(pkg.items())[0][1])
|
||||
if getattr(pkg, 'items', False):
|
||||
if list(pkg.items())[0][1]: # version specified
|
||||
pkg2inst.append('{0}@{1}'.format(list(pkg.items())[0][0],
|
||||
list(pkg.items())[0][1]))
|
||||
else:
|
||||
pkg2inst.append(list(pkg.items())[0][0])
|
||||
else:
|
||||
pkg2inst += '{0} '.format(list(pkg.items())[0][0])
|
||||
pkg2inst.append("{0}".format(pkg))
|
||||
log.debug('Installing these packages instead of %s: %s',
|
||||
name, pkg2inst)
|
||||
|
||||
|
@ -499,7 +504,10 @@ def install(name=None, refresh=False, pkgs=None, version=None, test=False, **kwa
|
|||
|
||||
# Install or upgrade the package
|
||||
# If package is already installed
|
||||
cmd.append(pkg2inst)
|
||||
if isinstance(pkg2inst, string_types):
|
||||
cmd.append(pkg2inst)
|
||||
elif isinstance(pkg2inst, list):
|
||||
cmd = cmd + pkg2inst
|
||||
|
||||
out = __salt__['cmd.run_all'](cmd, output_loglevel='trace')
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ import re
|
|||
import subprocess
|
||||
|
||||
# Import salt libs
|
||||
from salt.ext import six
|
||||
import salt.utils.decorators.path
|
||||
import salt.utils.data
|
||||
import salt.utils.files
|
||||
|
@ -44,9 +43,8 @@ if six.PY3:
|
|||
|
||||
|
||||
def __virtual__():
|
||||
# TODO: This could work on windows with some love
|
||||
if salt.utils.platform.is_windows():
|
||||
return (False, 'The module cannot be loaded on windows.')
|
||||
if not salt.utils.path.which('ssh'):
|
||||
return False, 'The module requires the ssh binary.'
|
||||
return True
|
||||
|
||||
|
||||
|
@ -753,9 +751,10 @@ def set_auth_key(
|
|||
if not os.path.isdir(os.path.dirname(fconfig)):
|
||||
dpath = os.path.dirname(fconfig)
|
||||
os.makedirs(dpath)
|
||||
if os.geteuid() == 0:
|
||||
os.chown(dpath, uinfo['uid'], uinfo['gid'])
|
||||
os.chmod(dpath, 448)
|
||||
if not salt.utils.platform.is_windows():
|
||||
if os.geteuid() == 0:
|
||||
os.chown(dpath, uinfo['uid'], uinfo['gid'])
|
||||
os.chmod(dpath, 448)
|
||||
# If SELINUX is available run a restorecon on the file
|
||||
rcon = salt.utils.path.which('restorecon')
|
||||
if rcon:
|
||||
|
@ -784,9 +783,10 @@ def set_auth_key(
|
|||
raise CommandExecutionError(msg.format(exc))
|
||||
|
||||
if new_file:
|
||||
if os.geteuid() == 0:
|
||||
os.chown(fconfig, uinfo['uid'], uinfo['gid'])
|
||||
os.chmod(fconfig, 384)
|
||||
if not salt.utils.platform.is_windows():
|
||||
if os.geteuid() == 0:
|
||||
os.chown(fconfig, uinfo['uid'], uinfo['gid'])
|
||||
os.chmod(fconfig, 384)
|
||||
# If SELINUX is available run a restorecon on the file
|
||||
rcon = salt.utils.path.which('restorecon')
|
||||
if rcon:
|
||||
|
@ -1104,10 +1104,11 @@ def rm_known_host(user=None, hostname=None, config=None, port=None):
|
|||
ssh_hostname = _hostname_and_port_to_ssh_hostname(hostname, port)
|
||||
cmd = ['ssh-keygen', '-R', ssh_hostname, '-f', full]
|
||||
cmd_result = __salt__['cmd.run'](cmd, python_shell=False)
|
||||
# ssh-keygen creates a new file, thus a chown is required.
|
||||
if os.geteuid() == 0 and user:
|
||||
uinfo = __salt__['user.info'](user)
|
||||
os.chown(full, uinfo['uid'], uinfo['gid'])
|
||||
if not salt.utils.platform.is_windows():
|
||||
# ssh-keygen creates a new file, thus a chown is required.
|
||||
if os.geteuid() == 0 and user:
|
||||
uinfo = __salt__['user.info'](user)
|
||||
os.chown(full, uinfo['uid'], uinfo['gid'])
|
||||
return {'status': 'removed', 'comment': cmd_result}
|
||||
|
||||
|
||||
|
@ -1317,12 +1318,13 @@ def set_known_host(user=None,
|
|||
"Couldn't append to known hosts file: '{0}'".format(exception)
|
||||
)
|
||||
|
||||
if os.geteuid() == 0 and user:
|
||||
os.chown(full, uinfo['uid'], uinfo['gid'])
|
||||
if origmode:
|
||||
os.chmod(full, origmode)
|
||||
else:
|
||||
os.chmod(full, 0o600)
|
||||
if not salt.utils.platform.is_windows():
|
||||
if os.geteuid() == 0 and user:
|
||||
os.chown(full, uinfo['uid'], uinfo['gid'])
|
||||
if origmode:
|
||||
os.chmod(full, origmode)
|
||||
else:
|
||||
os.chmod(full, 0o600)
|
||||
|
||||
if key and hash_known_hosts:
|
||||
cmd_result = __salt__['ssh.hash_known_hosts'](user=user, config=full)
|
||||
|
@ -1446,10 +1448,11 @@ def hash_known_hosts(user=None, config=None):
|
|||
cmd = ['ssh-keygen', '-H', '-f', full]
|
||||
cmd_result = __salt__['cmd.run'](cmd, python_shell=False)
|
||||
os.chmod(full, origmode)
|
||||
# ssh-keygen creates a new file, thus a chown is required.
|
||||
if os.geteuid() == 0 and user:
|
||||
uinfo = __salt__['user.info'](user)
|
||||
os.chown(full, uinfo['uid'], uinfo['gid'])
|
||||
if not salt.utils.platform.is_windows():
|
||||
# ssh-keygen creates a new file, thus a chown is required.
|
||||
if os.geteuid() == 0 and user:
|
||||
uinfo = __salt__['user.info'](user)
|
||||
os.chown(full, uinfo['uid'], uinfo['gid'])
|
||||
return {'status': 'updated', 'comment': cmd_result}
|
||||
|
||||
|
||||
|
|
|
@ -739,7 +739,7 @@ def set_lcm_config(config_mode=None,
|
|||
cmd += ' RefreshFrequencyMins = {0};'.format(refresh_freq)
|
||||
if reboot_if_needed is not None:
|
||||
if not isinstance(reboot_if_needed, bool):
|
||||
SaltInvocationError('reboot_if_needed must be a boolean value')
|
||||
raise SaltInvocationError('reboot_if_needed must be a boolean value')
|
||||
if reboot_if_needed:
|
||||
reboot_if_needed = '$true'
|
||||
else:
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -205,17 +205,22 @@ def get_zone():
|
|||
Returns:
|
||||
str: Timezone in unix format
|
||||
|
||||
Raises:
|
||||
CommandExecutionError: If timezone could not be gathered
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' timezone.get_zone
|
||||
'''
|
||||
win_zone = __utils__['reg.read_value'](
|
||||
hive='HKLM',
|
||||
key='SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation',
|
||||
vname='TimeZoneKeyName')['vdata']
|
||||
return mapper.get_unix(win_zone.lower(), 'Unknown')
|
||||
cmd = ['tzutil', '/g']
|
||||
res = __salt__['cmd.run_all'](cmd, python_shell=False)
|
||||
if res['retcode'] or not res['stdout']:
|
||||
raise CommandExecutionError('tzutil encountered an error getting '
|
||||
'timezone',
|
||||
info=res)
|
||||
return mapper.get_unix(res['stdout'].lower(), 'Unknown')
|
||||
|
||||
|
||||
def get_offset():
|
||||
|
|
|
@ -390,7 +390,7 @@ def _passphrase_callback(passphrase):
|
|||
Returns a callback function used to supply a passphrase for private keys
|
||||
'''
|
||||
def f(*args):
|
||||
return salt.utils.stringutils.to_str(passphrase)
|
||||
return salt.utils.stringutils.to_bytes(passphrase)
|
||||
return f
|
||||
|
||||
|
||||
|
@ -961,7 +961,7 @@ def create_crl( # pylint: disable=too-many-arguments,too-many-locals
|
|||
|
||||
serial_number = rev_item['serial_number'].replace(':', '')
|
||||
# OpenSSL bindings requires this to be a non-unicode string
|
||||
serial_number = salt.utils.stringutils.to_str(serial_number)
|
||||
serial_number = salt.utils.stringutils.to_bytes(serial_number)
|
||||
|
||||
if 'not_after' in rev_item and not include_expired:
|
||||
not_after = datetime.datetime.strptime(
|
||||
|
@ -976,6 +976,7 @@ def create_crl( # pylint: disable=too-many-arguments,too-many-locals
|
|||
rev_date = datetime.datetime.strptime(
|
||||
rev_item['revocation_date'], '%Y-%m-%d %H:%M:%S')
|
||||
rev_date = rev_date.strftime('%Y%m%d%H%M%SZ')
|
||||
rev_date = salt.utils.stringutils.to_bytes(rev_date)
|
||||
|
||||
rev = OpenSSL.crypto.Revoked()
|
||||
rev.set_serial(serial_number)
|
||||
|
@ -1005,7 +1006,7 @@ def create_crl( # pylint: disable=too-many-arguments,too-many-locals
|
|||
'days': days_valid
|
||||
}
|
||||
if digest:
|
||||
export_kwargs['digest'] = bytes(digest)
|
||||
export_kwargs['digest'] = salt.utils.stringutils.to_bytes(digest)
|
||||
else:
|
||||
log.warning('No digest specified. The default md5 digest will be used.')
|
||||
|
||||
|
@ -1573,7 +1574,7 @@ def create_certificate(
|
|||
pem_type='CERTIFICATE'
|
||||
)
|
||||
else:
|
||||
return cert.as_pem()
|
||||
return salt.utils.stringutils.to_str(cert.as_pem())
|
||||
# pylint: enable=too-many-locals
|
||||
|
||||
|
||||
|
|
|
@ -34,6 +34,11 @@ import salt.utils.odict
|
|||
import salt.utils.stringutils
|
||||
from salt.ext import six
|
||||
|
||||
try:
|
||||
from collections.abc import Mapping
|
||||
except ImportError:
|
||||
from collections import Mapping
|
||||
|
||||
|
||||
class NestDisplay(object):
|
||||
'''
|
||||
|
@ -142,7 +147,7 @@ class NestDisplay(object):
|
|||
if self.retcode != 0:
|
||||
color = self.RED
|
||||
for ind in ret:
|
||||
if isinstance(ind, (list, tuple, dict)):
|
||||
if isinstance(ind, (list, tuple, Mapping)):
|
||||
out.append(
|
||||
self.ustring(
|
||||
indent,
|
||||
|
@ -150,11 +155,11 @@ class NestDisplay(object):
|
|||
'|_'
|
||||
)
|
||||
)
|
||||
prefix = '' if isinstance(ind, dict) else '- '
|
||||
prefix = '' if isinstance(ind, Mapping) else '- '
|
||||
self.display(ind, indent + 2, prefix, out)
|
||||
else:
|
||||
self.display(ind, indent, '- ', out)
|
||||
elif isinstance(ret, dict):
|
||||
elif isinstance(ret, Mapping):
|
||||
if indent:
|
||||
color = self.CYAN
|
||||
if self.retcode != 0:
|
||||
|
|
|
@ -19,6 +19,7 @@ import salt.transport.frame
|
|||
import salt.utils.immutabletypes as immutabletypes
|
||||
import salt.utils.stringutils
|
||||
from salt.exceptions import SaltReqTimeoutError
|
||||
from salt.utils.data import CaseInsensitiveDict
|
||||
|
||||
# Import third party libs
|
||||
from salt.ext import six
|
||||
|
@ -205,6 +206,8 @@ class Serial(object):
|
|||
elif isinstance(obj, (set, immutabletypes.ImmutableSet)):
|
||||
# msgpack can't handle set so translate it to tuple
|
||||
return tuple(obj)
|
||||
elif isinstance(obj, CaseInsensitiveDict):
|
||||
return dict(obj)
|
||||
# Nothing known exceptions found. Let msgpack raise it's own.
|
||||
return obj
|
||||
|
||||
|
|
|
@ -2,26 +2,36 @@
|
|||
'''
|
||||
Retrieve EC2 instance data for minions for ec2_tags and ec2_tags_list
|
||||
|
||||
The minion id must be the AWS instance-id or value in 'tag_match_key'.
|
||||
For example set 'tag_match_key' to 'Name', to have the minion-id matched against the
|
||||
tag 'Name'. The tag contents must be unique. The value of tag_match_value can
|
||||
be 'uqdn' or 'asis'. if 'uqdn' strips any domain before comparison.
|
||||
The minion id must be the AWS instance-id or value in ``tag_match_key``. For
|
||||
example set ``tag_match_key`` to ``Name`` to have the minion-id matched against
|
||||
the tag 'Name'. The tag contents must be unique. The value of
|
||||
``tag_match_value`` can be 'uqdn' or 'asis'. if 'uqdn', then the domain will be
|
||||
stripped before comparison.
|
||||
|
||||
The option use_grain can be set to True. This allows the use of an
|
||||
instance-id grain instead of the minion-id. Since this is a potential
|
||||
security risk, the configuration can be further expanded to include
|
||||
a list of minions that are trusted to only allow the alternate id
|
||||
of the instances to specific hosts. There is no glob matching at
|
||||
this time.
|
||||
Additionally, the ``use_grain`` option can be set to ``True``. This allows the
|
||||
use of an instance-id grain instead of the minion-id. Since this is a potential
|
||||
security risk, the configuration can be further expanded to include a list of
|
||||
minions that are trusted to only allow the alternate id of the instances to
|
||||
specific hosts. There is no glob matching at this time.
|
||||
|
||||
The optional 'tag_list_key' indicates which keys should be added to
|
||||
'ec2_tags_list' and be split by tag_list_sep (default `;`). If a tag key is
|
||||
included in 'tag_list_key' it is removed from ec2_tags. If a tag does not
|
||||
exist it is still included as an empty list.
|
||||
.. note::
|
||||
If you are using ``use_grain: True`` in the configuration for this external
|
||||
pillar module, the minion must have :conf_minion:`metadata_server_grains`
|
||||
enabled in the minion config file (see also :py:mod:`here
|
||||
<salt.grains.metadata>`).
|
||||
|
||||
It is important to also note that enabling the ``use_grain`` option allows
|
||||
the minion to manipulate the pillar data returned, as described above.
|
||||
|
||||
The optional ``tag_list_key`` indicates which keys should be added to
|
||||
``ec2_tags_list`` and be split by ``tag_list_sep`` (by default ``;``). If a tag
|
||||
key is included in ``tag_list_key`` it is removed from ec2_tags. If a tag does
|
||||
not exist it is still included as an empty list.
|
||||
|
||||
|
||||
Note: restart the salt-master for changes to take effect.
|
||||
|
||||
..note::
|
||||
As with any master configuration change, restart the salt-master daemon for
|
||||
changes to take effect.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
|
@ -38,11 +48,10 @@ exist it is still included as an empty list.
|
|||
- trusted-minion-2
|
||||
- trusted-minion-3
|
||||
|
||||
This is a very simple pillar that simply retrieves the instance data
|
||||
from AWS. Currently the only portion implemented are EC2 tags, which
|
||||
returns a list of key/value pairs for all of the EC2 tags assigned to
|
||||
the instance.
|
||||
|
||||
This is a very simple pillar configuration that simply retrieves the instance
|
||||
data from AWS. Currently the only portion implemented are EC2 tags, which
|
||||
returns a list of key/value pairs for all of the EC2 tags assigned to the
|
||||
instance.
|
||||
'''
|
||||
|
||||
# Import python libs
|
||||
|
|
|
@ -225,8 +225,7 @@ def returner(ret):
|
|||
'functions', job_id, job_fun
|
||||
)
|
||||
return
|
||||
|
||||
if ret.get('return', None) is None:
|
||||
if ret.get('data', None) is None and ret.get('return') is None:
|
||||
log.info(
|
||||
'Won\'t push new data to Elasticsearch, job with jid=%s was '
|
||||
'not successful', job_id
|
||||
|
|
|
@ -77,6 +77,9 @@ def _walk_through(job_dir):
|
|||
except Exception:
|
||||
log.exception('Failed to deserialize %s', load_path)
|
||||
continue
|
||||
if not job:
|
||||
log.error('Deserialization of job succeded but there is no data in %s', load_path)
|
||||
continue
|
||||
jid = job['jid']
|
||||
yield jid, job, t_path, final
|
||||
|
||||
|
|
|
@ -7,10 +7,8 @@ The following Type: "Zabbix trapper" with "Type of information" Text items are r
|
|||
.. code-block:: cfg
|
||||
|
||||
Key: salt.trap.info
|
||||
Key: salt.trap.average
|
||||
Key: salt.trap.warning
|
||||
Key: salt.trap.high
|
||||
Key: salt.trap.disaster
|
||||
|
||||
To use the Zabbix returner, append '--return zabbix' to the salt command. ex:
|
||||
|
||||
|
@ -21,15 +19,10 @@ To use the Zabbix returner, append '--return zabbix' to the salt command. ex:
|
|||
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
import logging
|
||||
import os
|
||||
|
||||
# Import Salt libs
|
||||
from salt.ext import six
|
||||
import salt.utils.files
|
||||
|
||||
# Get logging started
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# Define the module's virtual name
|
||||
|
@ -55,37 +48,24 @@ def zbx():
|
|||
return False
|
||||
|
||||
|
||||
def zabbix_send(key, host, output):
|
||||
with salt.utils.files.fopen(zbx()['zabbix_config'], 'r') as file_handle:
|
||||
for line in file_handle:
|
||||
if "ServerActive" in line:
|
||||
flag = "true"
|
||||
server = line.rsplit('=')
|
||||
server = server[1].rsplit(',')
|
||||
for s in server:
|
||||
cmd = zbx()['sender'] + " -z " + s.replace('\n', '') + " -s " + host + " -k " + key + " -o \"" + output +"\""
|
||||
__salt__['cmd.shell'](cmd)
|
||||
break
|
||||
else:
|
||||
flag = "false"
|
||||
if flag == 'false':
|
||||
cmd = zbx()['sender'] + " -c " + zbx()['config'] + " -s " + host + " -k " + key + " -o \"" + output +"\""
|
||||
def zabbix_send(key, output):
|
||||
cmd = zbx()['sender'] + " -c " + zbx()['config'] + " -k " + key + " -o \"" + output +"\""
|
||||
__salt__['cmd.shell'](cmd)
|
||||
|
||||
|
||||
def returner(ret):
|
||||
changes = False
|
||||
errors = False
|
||||
job_minion_id = ret['id']
|
||||
host = job_minion_id
|
||||
|
||||
if type(ret['return']) is dict:
|
||||
for state, item in six.iteritems(ret['return']):
|
||||
if 'comment' in item and 'name' in item and not item['result']:
|
||||
if 'comment' in item and 'name' in item and item['result'] is False:
|
||||
errors = True
|
||||
zabbix_send("salt.trap.high", host, 'SALT:\nname: {0}\ncomment: {1}'.format(item['name'], item['comment']))
|
||||
if 'comment' in item and 'name' in item and item['changes']:
|
||||
zabbix_send("salt.trap.high", 'SALT:\nname: {0}\ncomment: {1}'.format(item['name'], item['comment']))
|
||||
elif 'comment' in item and 'name' in item and item['changes']:
|
||||
changes = True
|
||||
zabbix_send("salt.trap.warning", host, 'SALT:\nname: {0}\ncomment: {1}'.format(item['name'], item['comment']))
|
||||
zabbix_send("salt.trap.warning", 'SALT:\nname: {0}\ncomment: {1}'.format(item['name'], item['comment']))
|
||||
|
||||
if not changes and not errors:
|
||||
zabbix_send("salt.trap.info", host, 'SALT {0} OK'.format(job_minion_id))
|
||||
zabbix_send("salt.trap.info", 'SALT {0} OK'.format(job_minion_id))
|
||||
|
|
|
@ -209,7 +209,7 @@ def orchestrate_high(data, test=None, queue=False, pillar=None, **kwargs):
|
|||
def orchestrate_show_sls(mods,
|
||||
saltenv='base',
|
||||
test=None,
|
||||
exclude=None,
|
||||
queue=False,
|
||||
pillar=None,
|
||||
pillarenv=None,
|
||||
pillar_enc=None):
|
||||
|
@ -234,12 +234,12 @@ def orchestrate_show_sls(mods,
|
|||
minion = salt.minion.MasterMinion(__opts__)
|
||||
running = minion.functions['state.show_sls'](
|
||||
mods,
|
||||
saltenv,
|
||||
test,
|
||||
exclude,
|
||||
queue,
|
||||
pillar=pillar,
|
||||
pillarenv=pillarenv,
|
||||
pillar_enc=pillar_enc)
|
||||
pillar_enc=pillar_enc,
|
||||
saltenv=saltenv)
|
||||
|
||||
ret = {minion.opts['id']: running}
|
||||
return ret
|
||||
|
|
|
@ -3767,12 +3767,14 @@ class BaseHighState(object):
|
|||
statefiles = []
|
||||
for saltenv, states in six.iteritems(matches):
|
||||
for sls_match in states:
|
||||
try:
|
||||
if saltenv in self.avail:
|
||||
statefiles = fnmatch.filter(self.avail[saltenv], sls_match)
|
||||
except KeyError:
|
||||
all_errors.extend(
|
||||
['No matching salt environment for environment '
|
||||
'\'{0}\' found'.format(saltenv)]
|
||||
elif '__env__' in self.avail:
|
||||
statefiles = fnmatch.filter(self.avail['__env__'], sls_match)
|
||||
else:
|
||||
all_errors.append(
|
||||
'No matching salt environment for environment '
|
||||
'\'{0}\' found'.format(saltenv)
|
||||
)
|
||||
# if we did not found any sls in the fileserver listing, this
|
||||
# may be because the sls was generated or added later, we can
|
||||
|
|
|
@ -2421,7 +2421,6 @@ def managed(name,
|
|||
'to True to allow the managed file to be empty.'
|
||||
.format(contents_id)
|
||||
)
|
||||
|
||||
if isinstance(use_contents, six.binary_type) and b'\0' in use_contents:
|
||||
contents = use_contents
|
||||
elif isinstance(use_contents, six.text_type) and str('\0') in use_contents:
|
||||
|
@ -2435,9 +2434,10 @@ def managed(name,
|
|||
'contents_grains is not a string or list of strings, and '
|
||||
'is not binary data. SLS is likely malformed.'
|
||||
)
|
||||
contents = os.linesep.join(
|
||||
[line.rstrip('\n').rstrip('\r') for line in validated_contents]
|
||||
)
|
||||
contents = ''
|
||||
for part in validated_contents:
|
||||
for line in part.splitlines():
|
||||
contents += line.rstrip('\n').rstrip('\r') + os.linesep
|
||||
if contents_newline and not contents.endswith(os.linesep):
|
||||
contents += os.linesep
|
||||
if template:
|
||||
|
@ -2503,6 +2503,7 @@ def managed(name,
|
|||
ret, 'Defaults must be formed as a dict')
|
||||
|
||||
if not replace and os.path.exists(name):
|
||||
ret_perms = {}
|
||||
# Check and set the permissions if necessary
|
||||
if salt.utils.platform.is_windows():
|
||||
ret = __salt__['file.check_perms'](
|
||||
|
@ -2514,10 +2515,19 @@ def managed(name,
|
|||
inheritance=win_inheritance,
|
||||
reset=win_perms_reset)
|
||||
else:
|
||||
ret, _ = __salt__['file.check_perms'](
|
||||
ret, ret_perms = __salt__['file.check_perms'](
|
||||
name, ret, user, group, mode, attrs, follow_symlinks)
|
||||
if __opts__['test']:
|
||||
ret['comment'] = 'File {0} not updated'.format(name)
|
||||
if isinstance(ret_perms, dict) and \
|
||||
'lmode' in ret_perms and \
|
||||
mode != ret_perms['lmode']:
|
||||
ret['comment'] = ('File {0} will be updated with permissions '
|
||||
'{1} from its current '
|
||||
'state of {2}'.format(name,
|
||||
mode,
|
||||
ret_perms['lmode']))
|
||||
else:
|
||||
ret['comment'] = 'File {0} not updated'.format(name)
|
||||
elif not ret['changes'] and ret['result']:
|
||||
ret['comment'] = ('File {0} exists with proper permissions. '
|
||||
'No changes made.'.format(name))
|
||||
|
@ -3266,7 +3276,7 @@ def directory(name,
|
|||
ret, _ = __salt__['file.check_perms'](
|
||||
full, ret, user, group, file_mode, None, follow_symlinks)
|
||||
except CommandExecutionError as exc:
|
||||
if not exc.strerror.endswith('does not exist'):
|
||||
if not exc.strerror.startswith('Path not found'):
|
||||
errors.append(exc.strerror)
|
||||
|
||||
if check_dirs:
|
||||
|
|
|
@ -685,6 +685,15 @@ def latest(name,
|
|||
if https_pass is not None and not isinstance(https_pass, six.string_types):
|
||||
https_pass = six.text_type(https_pass)
|
||||
|
||||
# Check for lfs filter settings, and setup lfs_opts accordingly. These opts
|
||||
# will be passed where appropriate to ensure that these commands are
|
||||
# authenticated and that the git LFS plugin can download files.
|
||||
use_lfs = bool(
|
||||
__salt__['git.config_get_regexp'](
|
||||
r'filter\.lfs\.',
|
||||
**{'global': True}))
|
||||
lfs_opts = {'identity': identity} if use_lfs else {}
|
||||
|
||||
if os.path.isfile(target):
|
||||
return _fail(
|
||||
ret,
|
||||
|
@ -1560,7 +1569,8 @@ def latest(name,
|
|||
opts=['--hard', remote_rev],
|
||||
user=user,
|
||||
password=password,
|
||||
output_encoding=output_encoding)
|
||||
output_encoding=output_encoding,
|
||||
**lfs_opts)
|
||||
ret['changes']['forced update'] = True
|
||||
comments.append(
|
||||
'Repository was hard-reset to {0}'.format(remote_loc)
|
||||
|
@ -1613,7 +1623,8 @@ def latest(name,
|
|||
opts=merge_opts,
|
||||
user=user,
|
||||
password=password,
|
||||
output_encoding=output_encoding)
|
||||
output_encoding=output_encoding,
|
||||
**lfs_opts)
|
||||
comments.append(
|
||||
'Repository was fast-forwarded to {0}'
|
||||
.format(remote_loc)
|
||||
|
@ -1633,7 +1644,8 @@ def latest(name,
|
|||
remote_rev if rev == 'HEAD' else rev],
|
||||
user=user,
|
||||
password=password,
|
||||
output_encoding=output_encoding)
|
||||
output_encoding=output_encoding,
|
||||
**lfs_opts)
|
||||
comments.append(
|
||||
'Repository was reset to {0} (fast-forward)'
|
||||
.format(rev)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
Network ACL
|
||||
===========
|
||||
|
||||
Manage the firewall configuration on the network device namaged through NAPALM.
|
||||
Manage the firewall configuration on the network device managed through NAPALM.
|
||||
The firewall configuration is generated by Capirca_.
|
||||
|
||||
.. _Capirca: https://github.com/google/capirca
|
||||
|
@ -18,7 +18,13 @@ The firewall configuration is generated by Capirca_.
|
|||
Dependencies
|
||||
------------
|
||||
|
||||
Capirca: ``pip install -e git+git@github.com:google/capirca.git#egg=aclgen``
|
||||
Capirca
|
||||
~~~~~~~
|
||||
|
||||
To install Capirca, execute: ``pip install capirca``.
|
||||
|
||||
NAPALM
|
||||
~~~~~~
|
||||
|
||||
To be able to load configuration on network devices,
|
||||
it requires NAPALM_ library to be installed: ``pip install napalm``.
|
||||
|
@ -35,7 +41,10 @@ log = logging.getLogger(__file__)
|
|||
# Import third party libs
|
||||
try:
|
||||
# pylint: disable=W0611
|
||||
import aclgen
|
||||
import capirca
|
||||
import capirca.aclgen
|
||||
import capirca.lib.policy
|
||||
import capirca.lib.aclgenerator
|
||||
HAS_CAPIRCA = True
|
||||
# pylint: enable=W0611
|
||||
except ImportError:
|
||||
|
|
|
@ -30,6 +30,7 @@ except ImportError:
|
|||
HAS_PKG_RESOURCES = False
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils.data
|
||||
import salt.utils.versions
|
||||
from salt.version import SaltStackVersion as _SaltStackVersion
|
||||
from salt.exceptions import CommandExecutionError, CommandNotFoundError
|
||||
|
@ -87,20 +88,6 @@ def __virtual__():
|
|||
return False
|
||||
|
||||
|
||||
def _find_key(prefix, pip_list):
|
||||
'''
|
||||
Does a case-insensitive match in the pip_list for the desired package.
|
||||
'''
|
||||
try:
|
||||
match = next(
|
||||
iter(x for x in pip_list if x.lower() == prefix.lower())
|
||||
)
|
||||
except StopIteration:
|
||||
return None
|
||||
else:
|
||||
return match
|
||||
|
||||
|
||||
def _fulfills_version_spec(version, version_spec):
|
||||
'''
|
||||
Check version number against version specification info and return a
|
||||
|
@ -214,23 +201,20 @@ def _check_if_installed(prefix, state_pkg_name, version_spec, ignore_installed,
|
|||
ret = {'result': False, 'comment': None}
|
||||
|
||||
# If we are not passed a pip list, get one:
|
||||
if not pip_list:
|
||||
pip_list = __salt__['pip.list'](prefix, bin_env=bin_env,
|
||||
user=user, cwd=cwd,
|
||||
env_vars=env_vars, **kwargs)
|
||||
|
||||
# Check if the requested package is already installed.
|
||||
prefix_realname = _find_key(prefix, pip_list)
|
||||
pip_list = salt.utils.data.CaseInsensitiveDict(
|
||||
pip_list or __salt__['pip.list'](prefix, bin_env=bin_env,
|
||||
user=user, cwd=cwd,
|
||||
env_vars=env_vars, **kwargs)
|
||||
)
|
||||
|
||||
# If the package was already installed, check
|
||||
# the ignore_installed and force_reinstall flags
|
||||
if ignore_installed is False and prefix_realname is not None:
|
||||
if ignore_installed is False and prefix in pip_list:
|
||||
if force_reinstall is False and not upgrade:
|
||||
# Check desired version (if any) against currently-installed
|
||||
if (
|
||||
any(version_spec) and
|
||||
_fulfills_version_spec(pip_list[prefix_realname],
|
||||
version_spec)
|
||||
_fulfills_version_spec(pip_list[prefix], version_spec)
|
||||
) or (not any(version_spec)):
|
||||
ret['result'] = True
|
||||
ret['comment'] = ('Python package {0} was already '
|
||||
|
@ -250,7 +234,7 @@ def _check_if_installed(prefix, state_pkg_name, version_spec, ignore_installed,
|
|||
if 'rc' in spec[1]:
|
||||
include_rc = True
|
||||
available_versions = __salt__['pip.list_all_versions'](
|
||||
prefix_realname, bin_env=bin_env, include_alpha=include_alpha,
|
||||
prefix, bin_env=bin_env, include_alpha=include_alpha,
|
||||
include_beta=include_beta, include_rc=include_rc, user=user,
|
||||
cwd=cwd)
|
||||
desired_version = ''
|
||||
|
@ -266,9 +250,9 @@ def _check_if_installed(prefix, state_pkg_name, version_spec, ignore_installed,
|
|||
ret['comment'] = ('Python package {0} was already '
|
||||
'installed and\nthe available upgrade '
|
||||
'doesn\'t fulfills the version '
|
||||
'requirements'.format(prefix_realname))
|
||||
'requirements'.format(prefix))
|
||||
return ret
|
||||
if _pep440_version_cmp(pip_list[prefix_realname], desired_version) == 0:
|
||||
if _pep440_version_cmp(pip_list[prefix], desired_version) == 0:
|
||||
ret['result'] = True
|
||||
ret['comment'] = ('Python package {0} was already '
|
||||
'installed'.format(state_pkg_name))
|
||||
|
@ -903,10 +887,12 @@ def installed(name,
|
|||
|
||||
# Case for packages that are not an URL
|
||||
if prefix:
|
||||
pipsearch = __salt__['pip.list'](prefix, bin_env,
|
||||
user=user, cwd=cwd,
|
||||
env_vars=env_vars,
|
||||
**kwargs)
|
||||
pipsearch = salt.utils.data.CaseInsensitiveDict(
|
||||
__salt__['pip.list'](prefix, bin_env,
|
||||
user=user, cwd=cwd,
|
||||
env_vars=env_vars,
|
||||
**kwargs)
|
||||
)
|
||||
|
||||
# If we didn't find the package in the system after
|
||||
# installing it report it
|
||||
|
@ -917,12 +903,10 @@ def installed(name,
|
|||
'\'pip.freeze\'.'.format(pkg)
|
||||
)
|
||||
else:
|
||||
pkg_name = _find_key(prefix, pipsearch)
|
||||
if pkg_name.lower() in already_installed_packages:
|
||||
continue
|
||||
ver = pipsearch[pkg_name]
|
||||
ret['changes']['{0}=={1}'.format(pkg_name,
|
||||
ver)] = 'Installed'
|
||||
if prefix in pipsearch \
|
||||
and prefix.lower() not in already_installed_packages:
|
||||
ver = pipsearch[prefix]
|
||||
ret['changes']['{0}=={1}'.format(prefix, ver)] = 'Installed'
|
||||
# Case for packages that are an URL
|
||||
else:
|
||||
ret['changes']['{0}==???'.format(state_name)] = 'Installed'
|
||||
|
|
|
@ -457,6 +457,9 @@ def managed(name, ppa=None, **kwargs):
|
|||
sanitizedkwargs[kwarg])
|
||||
if precomments != kwargcomments:
|
||||
break
|
||||
elif kwarg == 'architectures' and sanitizedkwargs[kwarg]:
|
||||
if set(sanitizedkwargs[kwarg]) != set(pre[kwarg]):
|
||||
break
|
||||
else:
|
||||
if __grains__['os_family'] in ('RedHat', 'Suse') \
|
||||
and any(isinstance(x, bool) for x in
|
||||
|
@ -476,11 +479,18 @@ def managed(name, ppa=None, **kwargs):
|
|||
|
||||
if __opts__['test']:
|
||||
ret['comment'] = (
|
||||
'Package repo \'{0}\' will be configured. This may cause pkg '
|
||||
'Package repo \'{0}\' would be configured. This may cause pkg '
|
||||
'states to behave differently than stated if this action is '
|
||||
'repeated without test=True, due to the differences in the '
|
||||
'configured repositories.'.format(name)
|
||||
)
|
||||
if pre:
|
||||
for kwarg in sanitizedkwargs:
|
||||
if sanitizedkwargs.get(kwarg) != pre.get(kwarg):
|
||||
ret['changes'][kwarg] = {'new': sanitizedkwargs.get(kwarg),
|
||||
'old': pre.get(kwarg)}
|
||||
else:
|
||||
ret['changes']['repo'] = name
|
||||
return ret
|
||||
|
||||
# empty file before configure
|
||||
|
@ -509,9 +519,8 @@ def managed(name, ppa=None, **kwargs):
|
|||
if pre:
|
||||
for kwarg in sanitizedkwargs:
|
||||
if post.get(kwarg) != pre.get(kwarg):
|
||||
change = {'new': post[kwarg],
|
||||
'old': pre.get(kwarg)}
|
||||
ret['changes'][kwarg] = change
|
||||
ret['changes'][kwarg] = {'new': post.get(kwarg),
|
||||
'old': pre.get(kwarg)}
|
||||
else:
|
||||
ret['changes'] = {'repo': repo}
|
||||
|
||||
|
|
|
@ -284,6 +284,8 @@ def state(name,
|
|||
|
||||
cmd_kw['tgt_type'] = tgt_type
|
||||
cmd_kw['ssh'] = ssh
|
||||
if 'roster' in kwargs:
|
||||
cmd_kw['roster'] = kwargs['roster']
|
||||
cmd_kw['expect_minions'] = expect_minions
|
||||
if highstate:
|
||||
fun = 'state.highstate'
|
||||
|
|
|
@ -261,7 +261,7 @@ def set_(name,
|
|||
for p_name in current_policy[policy_data['output_section']]:
|
||||
if policy_name.lower() == p_name.lower():
|
||||
currently_set = True
|
||||
pol_id = policy_name
|
||||
pol_id = p_name
|
||||
break
|
||||
# Check aliases
|
||||
else:
|
||||
|
|
|
@ -109,7 +109,15 @@ def creds(provider):
|
|||
__Expiration__ = data['Expiration']
|
||||
return __AccessKeyId__, __SecretAccessKey__, __Token__
|
||||
else:
|
||||
return provider['id'], provider['key'], ''
|
||||
ret_credentials = provider['id'], provider['key'], ''
|
||||
|
||||
if provider.get('role_arn') is not None:
|
||||
provider_shadow = provider.copy()
|
||||
provider_shadow.pop("role_arn", None)
|
||||
log.info("Assuming the role: %s", provider.get('role_arn'))
|
||||
ret_credentials = assumed_creds(provider_shadow, role_arn=provider.get('role_arn'), location='us-east-1')
|
||||
|
||||
return ret_credentials
|
||||
|
||||
|
||||
def sig2(method, endpoint, params, provider, aws_api_version):
|
||||
|
|
|
@ -8,6 +8,7 @@ from __future__ import absolute_import, print_function, unicode_literals
|
|||
import sys
|
||||
import copy
|
||||
import types
|
||||
import importlib
|
||||
|
||||
# Import salt libs
|
||||
import salt.loader
|
||||
|
@ -58,3 +59,13 @@ def cmp(x, y):
|
|||
Return negative if x<y, zero if x==y, positive if x>y.
|
||||
'''
|
||||
return (x > y) - (x < y)
|
||||
|
||||
|
||||
def reload(mod):
|
||||
'''
|
||||
Compatibility helper function to replace the ``reload`` builtin from Python 2.
|
||||
'''
|
||||
try:
|
||||
return importlib.reload(mod)
|
||||
except AttributeError:
|
||||
return reload(mod)
|
||||
|
|
|
@ -13,9 +13,9 @@ import logging
|
|||
import re
|
||||
|
||||
try:
|
||||
from collections.abc import Mapping
|
||||
from collections.abc import Mapping, MutableMapping, Sequence
|
||||
except ImportError:
|
||||
from collections import Mapping
|
||||
from collections import Mapping, MutableMapping, Sequence
|
||||
|
||||
# Import Salt libs
|
||||
import salt.utils.dictupdate
|
||||
|
@ -24,6 +24,7 @@ import salt.utils.yaml
|
|||
from salt.defaults import DEFAULT_TARGET_DELIM
|
||||
from salt.exceptions import SaltException
|
||||
from salt.utils.decorators.jinja import jinja_filter
|
||||
from salt.utils.odict import OrderedDict
|
||||
|
||||
# Import 3rd-party libs
|
||||
from salt.ext import six
|
||||
|
@ -32,6 +33,87 @@ from salt.ext.six.moves import range # pylint: disable=redefined-builtin
|
|||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CaseInsensitiveDict(MutableMapping):
|
||||
'''
|
||||
Inspired by requests' case-insensitive dict implementation, but works with
|
||||
non-string keys as well.
|
||||
'''
|
||||
def __init__(self, init=None, **kwargs):
|
||||
'''
|
||||
Force internal dict to be ordered to ensure a consistent iteration
|
||||
order, irrespective of case.
|
||||
'''
|
||||
self._data = OrderedDict()
|
||||
self.update(init or {}, **kwargs)
|
||||
|
||||
def __len__(self):
|
||||
return len(self._data)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
# Store the case-sensitive key so it is available for dict iteration
|
||||
self._data[to_lowercase(key)] = (key, value)
|
||||
|
||||
def __delitem__(self, key):
|
||||
del self._data[to_lowercase(key)]
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self._data[to_lowercase(key)][1]
|
||||
|
||||
def __iter__(self):
|
||||
return (item[0] for item in six.itervalues(self._data))
|
||||
|
||||
def __eq__(self, rval):
|
||||
if not isinstance(rval, Mapping):
|
||||
# Comparing to non-mapping type (e.g. int) is always False
|
||||
return False
|
||||
return dict(self.items_lower()) == dict(CaseInsensitiveDict(rval).items_lower())
|
||||
|
||||
def __repr__(self):
|
||||
return repr(dict(six.iteritems(self)))
|
||||
|
||||
def items_lower(self):
|
||||
'''
|
||||
Returns a generator iterating over keys and values, with the keys all
|
||||
being lowercase.
|
||||
'''
|
||||
return ((key, val[1]) for key, val in six.iteritems(self._data))
|
||||
|
||||
def copy(self):
|
||||
'''
|
||||
Returns a copy of the object
|
||||
'''
|
||||
return CaseInsensitiveDict(six.iteritems(self._data))
|
||||
|
||||
|
||||
def __change_case(data, attr, preserve_dict_class=False):
|
||||
try:
|
||||
return getattr(data, attr)()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
data_type = data.__class__
|
||||
|
||||
if isinstance(data, Mapping):
|
||||
return (data_type if preserve_dict_class else dict)(
|
||||
(__change_case(key, attr, preserve_dict_class),
|
||||
__change_case(val, attr, preserve_dict_class))
|
||||
for key, val in six.iteritems(data)
|
||||
)
|
||||
elif isinstance(data, Sequence):
|
||||
return data_type(
|
||||
__change_case(item, attr, preserve_dict_class) for item in data)
|
||||
else:
|
||||
return data
|
||||
|
||||
|
||||
def to_lowercase(data, preserve_dict_class=False):
|
||||
return __change_case(data, 'lower', preserve_dict_class)
|
||||
|
||||
|
||||
def to_uppercase(data, preserve_dict_class=False):
|
||||
return __change_case(data, 'upper', preserve_dict_class)
|
||||
|
||||
|
||||
@jinja_filter('compare_dicts')
|
||||
def compare_dicts(old=None, new=None):
|
||||
'''
|
||||
|
|
|
@ -23,6 +23,7 @@ import shlex
|
|||
import socket
|
||||
import ssl
|
||||
import string
|
||||
import functools
|
||||
|
||||
# Import Salt libs
|
||||
import salt.utils.files
|
||||
|
@ -45,6 +46,7 @@ try:
|
|||
except ImportError:
|
||||
HAS_DNSPYTHON = False
|
||||
HAS_DIG = salt.utils.path.which('dig') is not None
|
||||
DIG_OPTIONS = '+search +fail +noall +answer +nocl +nottl'
|
||||
HAS_DRILL = salt.utils.path.which('drill') is not None
|
||||
HAS_HOST = salt.utils.path.which('host') is not None
|
||||
HAS_NSLOOKUP = salt.utils.path.which('nslookup') is not None
|
||||
|
@ -229,7 +231,7 @@ def _lookup_dig(name, rdtype, timeout=None, servers=None, secure=None):
|
|||
:param servers: [] of servers to use
|
||||
:return: [] of records or False if error
|
||||
'''
|
||||
cmd = 'dig +search +fail +noall +answer +noclass +nottl -t {0} '.format(rdtype)
|
||||
cmd = 'dig {0} -t {1} '.format(DIG_OPTIONS, rdtype)
|
||||
if servers:
|
||||
cmd += ''.join(['@{0} '.format(srv) for srv in servers])
|
||||
if timeout is not None:
|
||||
|
@ -364,12 +366,13 @@ def _lookup_host(name, rdtype, timeout=None, server=None):
|
|||
'''
|
||||
cmd = 'host -t {0} '.format(rdtype)
|
||||
|
||||
if server is not None:
|
||||
cmd += '@{0} '.format(server)
|
||||
if timeout:
|
||||
cmd += '-W {0} '.format(int(timeout))
|
||||
cmd += name
|
||||
if server is not None:
|
||||
cmd += ' {0}'.format(server)
|
||||
|
||||
cmd = __salt__['cmd.run_all'](cmd + name, python_shell=False, output_loglevel='quiet')
|
||||
cmd = __salt__['cmd.run_all'](cmd, python_shell=False, output_loglevel='quiet')
|
||||
|
||||
if 'invalid type' in cmd['stderr']:
|
||||
raise ValueError('Invalid DNS type {}'.format(rdtype))
|
||||
|
@ -380,7 +383,8 @@ def _lookup_host(name, rdtype, timeout=None, server=None):
|
|||
return []
|
||||
|
||||
res = []
|
||||
for line in cmd['stdout'].splitlines():
|
||||
_stdout = cmd['stdout'] if server is None else cmd['stdout'].split('\n\n')[-1]
|
||||
for line in _stdout.splitlines():
|
||||
if rdtype != 'CNAME' and 'is an alias' in line:
|
||||
continue
|
||||
line = line.split(' ', 3)[-1]
|
||||
|
@ -563,12 +567,15 @@ def lookup(
|
|||
timeout /= len(servers)
|
||||
|
||||
# Inject a wrapper for multi-server behaviour
|
||||
def _multi_srvr(**res_kwargs):
|
||||
for server in servers:
|
||||
s_res = resolver(server=server, **res_kwargs)
|
||||
if s_res:
|
||||
return s_res
|
||||
resolver = _multi_srvr
|
||||
def _multi_srvr(resolv_func):
|
||||
@functools.wraps(resolv_func)
|
||||
def _wrapper(**res_kwargs):
|
||||
for server in servers:
|
||||
s_res = resolv_func(server=server, **res_kwargs)
|
||||
if s_res:
|
||||
return s_res
|
||||
return _wrapper
|
||||
resolver = _multi_srvr(resolver)
|
||||
|
||||
if not walk:
|
||||
name = [name]
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
from __future__ import absolute_import, unicode_literals, print_function
|
||||
|
||||
# Import salt libs
|
||||
from salt.ext import six
|
||||
import salt.utils.files
|
||||
import salt.utils.stringutils
|
||||
from salt.exceptions import SaltException
|
||||
|
||||
|
||||
|
@ -85,14 +85,11 @@ class BufferedReader(object):
|
|||
multiplier = 1
|
||||
self.__buffered = self.__buffered[self.__chunk_size:]
|
||||
|
||||
if six.PY3:
|
||||
# Data is a byte object in Python 3
|
||||
# Decode it in order to append to self.__buffered str later
|
||||
data = self.__file.read(self.__chunk_size * multiplier).decode(
|
||||
__salt_system_encoding__
|
||||
)
|
||||
else:
|
||||
data = self.__file.read(self.__chunk_size * multiplier)
|
||||
data = self.__file.read(self.__chunk_size * multiplier)
|
||||
# Data is a byte object in Python 3
|
||||
# Decode it in order to append to self.__buffered str later
|
||||
# Use the salt util in case it's already a string (Windows)
|
||||
data = salt.utils.stringutils.to_str(data)
|
||||
|
||||
if not data:
|
||||
self.__file.close()
|
||||
|
|
|
@ -416,11 +416,13 @@ def flopen(*args, **kwargs):
|
|||
'''
|
||||
Shortcut for fopen with lock and context manager.
|
||||
'''
|
||||
with fopen(*args, **kwargs) as f_handle:
|
||||
filename, args = args[0], args[1:]
|
||||
writing = 'wa'
|
||||
with fopen(filename, *args, **kwargs) as f_handle:
|
||||
try:
|
||||
if is_fcntl_available(check_sunos=True):
|
||||
lock_type = fcntl.LOCK_SH
|
||||
if 'w' in args[1] or 'a' in args[1]:
|
||||
if args and any([write in args[0] for write in writing]):
|
||||
lock_type = fcntl.LOCK_EX
|
||||
fcntl.flock(f_handle.fileno(), lock_type)
|
||||
yield f_handle
|
||||
|
|
|
@ -1410,6 +1410,19 @@ class Pygit2(GitProvider):
|
|||
override_params, cache_root, role
|
||||
)
|
||||
|
||||
def peel(self, obj):
|
||||
'''
|
||||
Compatibility function for pygit2.Reference objects. Older versions of
|
||||
pygit2 use .get_object() to return the object to which the reference
|
||||
points, while newer versions use .peel(). In pygit2 0.27.4,
|
||||
.get_object() was removed. This function will try .peel() first and
|
||||
fall back to .get_object().
|
||||
'''
|
||||
try:
|
||||
return obj.peel()
|
||||
except AttributeError:
|
||||
return obj.get_object()
|
||||
|
||||
def checkout(self):
|
||||
'''
|
||||
Checkout the configured branch/tag
|
||||
|
@ -1428,7 +1441,7 @@ class Pygit2(GitProvider):
|
|||
return None
|
||||
|
||||
try:
|
||||
head_sha = local_head.get_object().hex
|
||||
head_sha = self.peel(local_head).hex
|
||||
except AttributeError:
|
||||
# Shouldn't happen, but just in case a future pygit2 API change
|
||||
# breaks things, avoid a traceback and log an error.
|
||||
|
@ -1477,7 +1490,7 @@ class Pygit2(GitProvider):
|
|||
try:
|
||||
if remote_ref in refs:
|
||||
# Get commit id for the remote ref
|
||||
oid = self.repo.lookup_reference(remote_ref).get_object().id
|
||||
oid = self.peel(self.repo.lookup_reference(remote_ref)).id
|
||||
if local_ref not in refs:
|
||||
# No local branch for this remote, so create one and point
|
||||
# it at the commit id of the remote ref
|
||||
|
@ -1485,7 +1498,7 @@ class Pygit2(GitProvider):
|
|||
|
||||
try:
|
||||
target_sha = \
|
||||
self.repo.lookup_reference(remote_ref).get_object().hex
|
||||
self.peel(self.repo.lookup_reference(remote_ref)).hex
|
||||
except KeyError:
|
||||
log.error(
|
||||
'pygit2 was unable to get SHA for %s in %s remote '
|
||||
|
@ -1857,8 +1870,8 @@ class Pygit2(GitProvider):
|
|||
refs/remotes/origin/
|
||||
'''
|
||||
try:
|
||||
return self.repo.lookup_reference(
|
||||
'refs/remotes/origin/{0}'.format(ref)).get_object().tree
|
||||
return self.peel(self.repo.lookup_reference(
|
||||
'refs/remotes/origin/{0}'.format(ref))).tree
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
|
@ -1867,8 +1880,8 @@ class Pygit2(GitProvider):
|
|||
Return a pygit2.Tree object matching a tag ref fetched into refs/tags/
|
||||
'''
|
||||
try:
|
||||
return self.repo.lookup_reference(
|
||||
'refs/tags/{0}'.format(ref)).get_object().tree
|
||||
return self.peel(self.repo.lookup_reference(
|
||||
'refs/tags/{0}'.format(ref))).tree
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
|
@ -2993,7 +3006,11 @@ class GitPillar(GitBase):
|
|||
elif repo.env:
|
||||
env = repo.env
|
||||
else:
|
||||
env = 'base' if repo.branch == repo.base else repo.get_checkout_target()
|
||||
if repo.branch == repo.base:
|
||||
env = 'base'
|
||||
else:
|
||||
tgt = repo.get_checkout_target()
|
||||
env = 'base' if tgt == repo.base else tgt
|
||||
if repo._mountpoint:
|
||||
if self.link_mountpoint(repo):
|
||||
self.pillar_dirs[repo.linkdir] = env
|
||||
|
|
|
@ -149,7 +149,7 @@ def nodegroup_comp(nodegroup, nodegroups, skip=None, first_call=True):
|
|||
# No compound operators found in nodegroup definition. Check for
|
||||
# group type specifiers
|
||||
group_type_re = re.compile('^[A-Z]@')
|
||||
regex_chars = ['(', '[', '{', '\\', '?''}])']
|
||||
regex_chars = ['(', '[', '{', '\\', '?', '}', ']', ')']
|
||||
if not [x for x in ret if '*' in x or group_type_re.match(x)]:
|
||||
# No group type specifiers and no wildcards.
|
||||
# Treat this as an expression.
|
||||
|
|
|
@ -1984,7 +1984,7 @@ def parse_host_port(host_port):
|
|||
if _s_[0] == "[":
|
||||
if "]" in host_port:
|
||||
host, _s_ = _s_.lstrip("[").rsplit("]", 1)
|
||||
host = ipaddress.IPv6Address(host)
|
||||
host = ipaddress.IPv6Address(host).compressed
|
||||
if _s_[0] == ":":
|
||||
port = int(_s_.lstrip(":"))
|
||||
else:
|
||||
|
@ -2002,7 +2002,7 @@ def parse_host_port(host_port):
|
|||
host = _s_
|
||||
try:
|
||||
if not isinstance(host, ipaddress._BaseAddress):
|
||||
host_ip = ipaddress.ip_address(host)
|
||||
host_ip = ipaddress.ip_address(host).compressed
|
||||
host = host_ip
|
||||
except ValueError:
|
||||
log.debug('"%s" Not an IP address? Assuming it is a hostname.', host)
|
||||
|
|
|
@ -806,7 +806,7 @@ def default_signals(*signals):
|
|||
old_signals = {}
|
||||
for signum in signals:
|
||||
try:
|
||||
old_signals[signum] = signal.getsignal(signum)
|
||||
saved_signal = signal.getsignal(signum)
|
||||
signal.signal(signum, signal.SIG_DFL)
|
||||
except ValueError as exc:
|
||||
# This happens when a netapi module attempts to run a function
|
||||
|
@ -816,6 +816,8 @@ def default_signals(*signals):
|
|||
'Failed to register signal for signum %d: %s',
|
||||
signum, exc
|
||||
)
|
||||
else:
|
||||
old_signals[signum] = saved_signal
|
||||
|
||||
# Do whatever is needed with the reset signals
|
||||
yield
|
||||
|
|
|
@ -333,7 +333,9 @@ def build_whitespace_split_regex(text):
|
|||
lexer = shlex.shlex(text)
|
||||
lexer.whitespace_split = True
|
||||
lexer.commenters = ''
|
||||
if '\'' in text:
|
||||
if r"'\"" in text:
|
||||
lexer.quotes = ''
|
||||
elif '\'' in text:
|
||||
lexer.quotes = '"'
|
||||
elif '"' in text:
|
||||
lexer.quotes = '\''
|
||||
|
|
|
@ -14,13 +14,11 @@ import re
|
|||
import time
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils.compat
|
||||
import salt.utils.data
|
||||
from salt.utils.timeout import wait_for
|
||||
import salt.ext.six as six
|
||||
|
||||
# Workaround for 'reload' builtin of py2.7
|
||||
if six.PY3:
|
||||
from importlib import reload # pylint: disable=no-name-in-module
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -140,7 +138,7 @@ def vb_get_manager():
|
|||
'''
|
||||
global _virtualboxManager
|
||||
if _virtualboxManager is None and HAS_LIBS:
|
||||
reload(vboxapi)
|
||||
salt.utils.compat.reload(vboxapi)
|
||||
_virtualboxManager = vboxapi.VirtualBoxManager(None, None)
|
||||
|
||||
return _virtualboxManager
|
||||
|
|
|
@ -66,6 +66,7 @@ import re
|
|||
import tempfile
|
||||
|
||||
# Import Salt libs
|
||||
import salt.modules.cmdmod
|
||||
import salt.utils.files
|
||||
import salt.utils.platform
|
||||
from salt.exceptions import CommandExecutionError
|
||||
|
@ -117,8 +118,8 @@ def _auditpol_cmd(cmd):
|
|||
Raises:
|
||||
CommandExecutionError: If the command encounters an error
|
||||
'''
|
||||
ret = __salt__['cmd.run_all'](cmd='auditpol {0}'.format(cmd),
|
||||
python_shell=True)
|
||||
ret = salt.modules.cmdmod.run_all(cmd='auditpol {0}'.format(cmd),
|
||||
python_shell=True)
|
||||
if ret['retcode'] == 0:
|
||||
return ret['stdout'].splitlines()
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ r'''
|
|||
A salt util for modifying firewall settings.
|
||||
|
||||
.. versionadded:: 2018.3.4
|
||||
.. versionadded:: Fluorine
|
||||
.. versionadded:: 2019.2.0
|
||||
|
||||
This util allows you to modify firewall settings in the local group policy in
|
||||
addition to the normal firewall settings. Parameters are taken from the
|
||||
|
|
|
@ -8,10 +8,16 @@ from __future__ import absolute_import, print_function, unicode_literals
|
|||
import re
|
||||
import sys
|
||||
import platform
|
||||
import warnings
|
||||
|
||||
# linux_distribution deprecated in py3.7
|
||||
try:
|
||||
from platform import linux_distribution
|
||||
from platform import linux_distribution as _deprecated_linux_distribution
|
||||
|
||||
def linux_distribution(**kwargs):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
return _deprecated_linux_distribution(**kwargs)
|
||||
except ImportError:
|
||||
from distro import linux_distribution
|
||||
|
||||
|
|
5
setup.py
5
setup.py
|
@ -874,7 +874,10 @@ class SaltDistribution(distutils.dist.Distribution):
|
|||
self.name = 'salt-ssh' if PACKAGED_FOR_SALT_SSH else 'salt'
|
||||
self.salt_version = __version__ # pylint: disable=undefined-variable
|
||||
self.description = 'Portable, distributed, remote execution and configuration management system'
|
||||
with open(SALT_LONG_DESCRIPTION_FILE) as f:
|
||||
kwargs = {}
|
||||
if IS_PY3:
|
||||
kwargs['encoding'] = 'utf-8'
|
||||
with open(SALT_LONG_DESCRIPTION_FILE, **kwargs) as f:
|
||||
self.long_description = f.read()
|
||||
self.long_description_content_type = 'text/x-rst'
|
||||
self.author = 'Thomas S Hatch'
|
||||
|
|
|
@ -55,7 +55,7 @@ import salt.log.setup
|
|||
from salt.utils.odict import OrderedDict
|
||||
|
||||
# Define the pytest plugins we rely on
|
||||
pytest_plugins = ['tempdir', 'helpers_namespace'] # pylint: disable=invalid-name
|
||||
pytest_plugins = ['tempdir', 'helpers_namespace', 'salt-from-filenames'] # pylint: disable=invalid-name
|
||||
|
||||
# Define where not to collect tests from
|
||||
collect_ignore = ['setup.py']
|
||||
|
|
|
@ -183,7 +183,7 @@ class TestDaemon(object):
|
|||
'''
|
||||
Set up the master and minion daemons, and run related cases
|
||||
'''
|
||||
MINIONS_CONNECT_TIMEOUT = MINIONS_SYNC_TIMEOUT = 120
|
||||
MINIONS_CONNECT_TIMEOUT = MINIONS_SYNC_TIMEOUT = 300
|
||||
|
||||
def __init__(self, parser):
|
||||
self.parser = parser
|
||||
|
@ -219,6 +219,8 @@ class TestDaemon(object):
|
|||
if getattr(self.parser.options, 'ssh', False):
|
||||
self.prep_ssh()
|
||||
|
||||
self.wait_for_minions(time.time(), self.MINIONS_CONNECT_TIMEOUT)
|
||||
|
||||
if self.parser.options.sysinfo:
|
||||
try:
|
||||
print_header(
|
||||
|
@ -743,6 +745,12 @@ class TestDaemon(object):
|
|||
master_opts['root_dir'] = os.path.join(TMP, 'rootdir')
|
||||
master_opts['pki_dir'] = os.path.join(TMP, 'rootdir', 'pki', 'master')
|
||||
master_opts['syndic_master'] = 'localhost'
|
||||
file_tree = {
|
||||
'root_dir': os.path.join(FILES, 'pillar', 'base', 'file_tree'),
|
||||
'follow_dir_links': False,
|
||||
'keep_newline': True,
|
||||
}
|
||||
master_opts['ext_pillar'].append({'file_tree': file_tree})
|
||||
|
||||
# This is the syndic for master
|
||||
# Let's start with a copy of the syndic master configuration
|
||||
|
@ -1179,84 +1187,6 @@ class TestDaemon(object):
|
|||
k for (k, v) in six.iteritems(running) if v and v[0]['jid'] == jid
|
||||
]
|
||||
|
||||
def wait_for_minion_connections(self, targets, timeout):
|
||||
salt.utils.process.appendproctitle('WaitForMinionConnections')
|
||||
sys.stdout.write(
|
||||
' {LIGHT_BLUE}*{ENDC} Waiting at most {0} for minions({1}) to '
|
||||
'connect back\n'.format(
|
||||
(timeout > 60 and
|
||||
timedelta(seconds=timeout) or
|
||||
'{0} secs'.format(timeout)),
|
||||
', '.join(targets),
|
||||
**self.colors
|
||||
)
|
||||
)
|
||||
sys.stdout.flush()
|
||||
expected_connections = set(targets)
|
||||
now = datetime.now()
|
||||
expire = now + timedelta(seconds=timeout)
|
||||
while now <= expire:
|
||||
sys.stdout.write(
|
||||
'\r{0}\r'.format(
|
||||
' ' * getattr(self.parser.options, 'output_columns', PNUM)
|
||||
)
|
||||
)
|
||||
sys.stdout.write(
|
||||
' * {LIGHT_YELLOW}[Quit in {0}]{ENDC} Waiting for {1}'.format(
|
||||
'{0}'.format(expire - now).rsplit('.', 1)[0],
|
||||
', '.join(expected_connections),
|
||||
**self.colors
|
||||
)
|
||||
)
|
||||
sys.stdout.flush()
|
||||
|
||||
try:
|
||||
responses = self.client.cmd(
|
||||
list(expected_connections), 'test.ping', tgt_type='list',
|
||||
)
|
||||
# we'll get this exception if the master process hasn't finished starting yet
|
||||
except SaltClientError:
|
||||
time.sleep(0.1)
|
||||
now = datetime.now()
|
||||
continue
|
||||
for target in responses:
|
||||
if target not in expected_connections:
|
||||
# Someone(minion) else "listening"?
|
||||
continue
|
||||
expected_connections.remove(target)
|
||||
sys.stdout.write(
|
||||
'\r{0}\r'.format(
|
||||
' ' * getattr(self.parser.options, 'output_columns',
|
||||
PNUM)
|
||||
)
|
||||
)
|
||||
sys.stdout.write(
|
||||
' {LIGHT_GREEN}*{ENDC} {0} connected.\n'.format(
|
||||
target, **self.colors
|
||||
)
|
||||
)
|
||||
sys.stdout.flush()
|
||||
|
||||
if not expected_connections:
|
||||
return
|
||||
|
||||
time.sleep(1)
|
||||
now = datetime.now()
|
||||
else: # pylint: disable=W0120
|
||||
print(
|
||||
'\n {LIGHT_RED}*{ENDC} WARNING: Minions failed to connect '
|
||||
'back. Tests requiring them WILL fail'.format(**self.colors)
|
||||
)
|
||||
try:
|
||||
print_header(
|
||||
'=', sep='=', inline=True,
|
||||
width=getattr(self.parser.options, 'output_columns', PNUM)
|
||||
|
||||
)
|
||||
except TypeError:
|
||||
print_header('=', sep='=', inline=True)
|
||||
raise SystemExit()
|
||||
|
||||
def sync_minion_modules_(self, modules_kind, targets, timeout=None):
|
||||
if not timeout:
|
||||
timeout = 120
|
||||
|
@ -1333,3 +1263,20 @@ class TestDaemon(object):
|
|||
def sync_minion_grains(self, targets, timeout=None):
|
||||
salt.utils.process.appendproctitle('SyncMinionGrains')
|
||||
self.sync_minion_modules_('grains', targets, timeout=timeout)
|
||||
|
||||
def wait_for_minions(self, start, timeout, sleep=5):
|
||||
'''
|
||||
Ensure all minions and masters (including sub-masters) are connected.
|
||||
'''
|
||||
while True:
|
||||
try:
|
||||
ret = self.client.run_job('*', 'test.ping')
|
||||
except salt.exceptions.SaltClientError:
|
||||
ret = None
|
||||
if ret and 'minions' not in ret:
|
||||
continue
|
||||
if ret and sorted(ret['minions']) == ['minion', 'sub_minion']:
|
||||
break
|
||||
if time.time() - start >= timeout:
|
||||
raise RuntimeError("Ping Minions Failed")
|
||||
time.sleep(sleep)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue