Merge branch '2017.7' into 'develop'

Conflicts:
  - salt/cloud/clouds/joyent.py
  - salt/engines/slack.py
This commit is contained in:
rallytime 2017-07-26 17:51:36 -06:00
commit 1f0b90aa57
85 changed files with 1815 additions and 445 deletions

View file

@ -311,6 +311,9 @@
# public keys from the minions. Note that this is insecure.
#auto_accept: False
# The size of key that should be generated when creating new keys.
#keysize: 2048
# Time in minutes that an incoming public key with a matching name found in
# pki_dir/minion_autosign/keyid is automatically accepted. Expired autosign keys
# are removed when the master checks the minion_autosign directory.
@ -968,6 +971,21 @@
#pillar_cache_backend: disk
###### Reactor Settings #####
###########################################
# Define a salt reactor. See https://docs.saltstack.com/en/latest/topics/reactor/
#reactor: []
#Set the TTL for the cache of the reactor configuration.
#reactor_refresh_interval: 60
#Configure the number of workers for the runner/wheel in the reactor.
#reactor_worker_threads: 10
#Define the queue size for workers in the reactor.
#reactor_worker_hwm: 10000
##### Syndic settings #####
##########################################
# The Salt syndic is used to pass commands through a master from a higher

View file

@ -620,6 +620,9 @@
# you do so at your own risk!
#open_mode: False
# The size of key that should be generated when creating new keys.
#keysize: 2048
# Enable permissive access to the salt keys. This allows you to run the
# master or minion as root, but have a non-root group be given access to
# your pki_dir. To make the access explicit, root must belong to the group
@ -661,6 +664,21 @@
# ssl_version: PROTOCOL_TLSv1_2
###### Reactor Settings #####
###########################################
# Define a salt reactor. See https://docs.saltstack.com/en/latest/topics/reactor/
#reactor: []
#Set the TTL for the cache of the reactor configuration.
#reactor_refresh_interval: 60
#Configure the number of workers for the runner/wheel in the reactor.
#reactor_worker_threads: 10
#Define the queue size for workers in the reactor.
#reactor_worker_hwm: 10000
###### Thread settings #####
###########################################
# Disable multiprocessing support, by default when a minion receives a

View file

@ -258,8 +258,8 @@ if on_saltstack:
copyright = time.strftime("%Y")
# < --- START do not merge these settings to other branches START ---> #
build_type = 'develop' # latest, previous, develop, next
release = version # version, latest_release, previous_release
build_type = 'latest' # latest, previous, develop, next
release = latest_release # version, latest_release, previous_release
# < --- END do not merge these settings to other branches END ---> #
# Set google custom search engine
@ -320,11 +320,21 @@ rst_prolog = """\
.. _`salt-packagers`: https://groups.google.com/forum/#!forum/salt-packagers
.. |windownload| raw:: html
<p>x86: <a href="https://repo.saltstack.com/windows/Salt-Minion-{release}-x86-Setup.exe"><strong>Salt-Minion-{release}-x86-Setup.exe</strong></a>
| <a href="https://repo.saltstack.com/windows/Salt-Minion-{release}-x86-Setup.exe.md5"><strong>md5</strong></a></p>
<p>Python2 x86: <a
href="https://repo.saltstack.com/windows/Salt-Minion-{release}-Py2-x86-Setup.exe"><strong>Salt-Minion-{release}-x86-Setup.exe</strong></a>
| <a href="https://repo.saltstack.com/windows/Salt-Minion-{release}-Py2-x86-Setup.exe.md5"><strong>md5</strong></a></p>
<p>Python2 AMD64: <a
href="https://repo.saltstack.com/windows/Salt-Minion-{release}-Py2-AMD64-Setup.exe"><strong>Salt-Minion-{release}-AMD64-Setup.exe</strong></a>
| <a href="https://repo.saltstack.com/windows/Salt-Minion-{release}-Py2-AMD64-Setup.exe.md5"><strong>md5</strong></a></p>
<p>Python3 x86: <a
href="https://repo.saltstack.com/windows/Salt-Minion-{release}-Py3-x86-Setup.exe"><strong>Salt-Minion-{release}-x86-Setup.exe</strong></a>
| <a href="https://repo.saltstack.com/windows/Salt-Minion-{release}-Py3-x86-Setup.exe.md5"><strong>md5</strong></a></p>
<p>Python3 AMD64: <a
href="https://repo.saltstack.com/windows/Salt-Minion-{release}-Py3-AMD64-Setup.exe"><strong>Salt-Minion-{release}-AMD64-Setup.exe</strong></a>
| <a href="https://repo.saltstack.com/windows/Salt-Minion-{release}-Py3-AMD64-Setup.exe.md5"><strong>md5</strong></a></p>
<p>AMD64: <a href="https://repo.saltstack.com/windows/Salt-Minion-{release}-AMD64-Setup.exe"><strong>Salt-Minion-{release}-AMD64-Setup.exe</strong></a>
| <a href="https://repo.saltstack.com/windows/Salt-Minion-{release}-AMD64-Setup.exe.md5"><strong>md5</strong></a></p>
.. |osxdownload| raw:: html

View file

@ -321,7 +321,27 @@ Restart using states
********************
Now we can apply the workaround to restart the Minion in reliable way.
The following example works on both UNIX-like and Windows operating systems:
The following example works on UNIX-like operating systems:
.. code-block:: jinja
{%- if grains['os'] != 'Windows' %
Restart Salt Minion:
cmd.run:
- name: 'salt-call --local service.restart salt-minion'
- bg: True
- onchanges:
- pkg: Upgrade Salt Minion
{%- endif %}
Note that restarting the ``salt-minion`` service on Windows operating systems is
not always necessary when performing an upgrade. The installer stops the
``salt-minion`` service, removes it, deletes the contents of the ``\salt\bin``
directory, installs the new code, re-creates the ``salt-minion`` service, and
starts it (by default). The restart step **would** be necessary during the
upgrade process, however, if the minion config was edited after the upgrade or
installation. If a minion restart is necessary, the state above can be edited
as follows:
.. code-block:: jinja
@ -337,8 +357,8 @@ The following example works on both UNIX-like and Windows operating systems:
- pkg: Upgrade Salt Minion
However, it requires more advanced tricks to upgrade from legacy version of
Salt (before ``2016.3.0``), where executing commands in the background is not
supported:
Salt (before ``2016.3.0``) on UNIX-like operating systems, where executing
commands in the background is not supported:
.. code-block:: jinja

View file

@ -94,64 +94,6 @@ The user to run the Salt processes
user: root
.. conf_master:: max_open_files
``max_open_files``
------------------
Default: ``100000``
Each minion connecting to the master uses AT LEAST one file descriptor, the
master subscription connection. If enough minions connect you might start
seeing on the console(and then salt-master crashes):
.. code-block:: bash
Too many open files (tcp_listener.cpp:335)
Aborted (core dumped)
.. code-block:: yaml
max_open_files: 100000
By default this value will be the one of `ulimit -Hn`, i.e., the hard limit for
max open files.
To set a different value than the default one, uncomment, and configure this
setting. Remember that this value CANNOT be higher than the hard limit. Raising
the hard limit depends on the OS and/or distribution, a good way to find the
limit is to search the internet for something like this:
.. code-block:: text
raise max open files hard limit debian
.. conf_master:: worker_threads
``worker_threads``
------------------
Default: ``5``
The number of threads to start for receiving commands and replies from minions.
If minions are stalling on replies because you have many minions, raise the
worker_threads value.
Worker threads should not be put below 3 when using the peer system, but can
drop down to 1 worker otherwise.
.. note::
When the master daemon starts, it is expected behaviour to see
multiple salt-master processes, even if 'worker_threads' is set to '1'. At
a minimum, a controlling process will start along with a Publisher, an
EventPublisher, and a number of MWorker processes will be started. The
number of MWorker processes is tuneable by the 'worker_threads'
configuration value while the others are not.
.. code-block:: yaml
worker_threads: 5
.. conf_master:: ret_port
``ret_port``
@ -946,6 +888,74 @@ to socket concurrently.
sock_pool_size: 15
.. conf_master:: ipc_mode
``ipc_mode``
------------
Default: ``ipc``
The ipc strategy. (i.e., sockets versus tcp, etc.) Windows platforms lack
POSIX IPC and must rely on TCP based inter-process communications. ``ipc_mode``
is set to ``tcp`` by default on Windows.
.. code-block:: yaml
ipc_mode: ipc
.. conf_master::
``tcp_master_pub_port``
-----------------------
Default: ``4512``
The TCP port on which events for the master should be published if ``ipc_mode`` is TCP.
.. code-block:: yaml
tcp_master_pub_port: 4512
.. conf_master:: tcp_master_pull_port
``tcp_master_pull_port``
------------------------
Default: ``4513``
The TCP port on which events for the master should be pulled if ``ipc_mode`` is TCP.
.. code-block:: yaml
tcp_master_pull_port: 4513
.. conf_master:: tcp_master_publish_pull
``tcp_master_publish_pull``
---------------------------
Default: ``4514``
The TCP port on which events for the master should be pulled fom and then republished onto
the event bus on the master.
.. code-block:: yaml
tcp_master_publish_pull: 4514
.. conf_master:: tcp_master_workers
``tcp_master_workers``
----------------------
Default: ``4515``
The TCP port for ``mworkers`` to connect to on the master.
.. code-block:: yaml
tcp_master_workers: 4515
.. _salt-ssh-configuration:
@ -1192,6 +1202,19 @@ public keys from minions.
auto_accept: False
.. conf_master:: keysize
``keysize``
-----------
Default: ``2048``
The size of key that should be generated when creating new keys.
.. code-block:: yaml
keysize: 2048
.. conf_master:: autosign_timeout
``autosign_timeout``
@ -1236,6 +1259,24 @@ minion IDs for which keys will automatically be rejected. Will override both
membership in the :conf_master:`autosign_file` and the
:conf_master:`auto_accept` setting.
.. conf_master:: permissive_pki_access
``permissive_pki_access``
-------------------------
Default: ``False``
Enable permissive access to the salt keys. This allows you to run the
master or minion as root, but have a non-root group be given access to
your pki_dir. To make the access explicit, root must belong to the group
you've given access to. This is potentially quite insecure. If an autosign_file
is specified, enabling permissive_pki_access will allow group access to that
specific file.
.. code-block:: yaml
permissive_pki_access: False
.. conf_master:: publisher_acl
``publisher_acl``
@ -1278,6 +1319,20 @@ This is completely disabled by default.
- cmd.*
- test.echo
.. conf_master:: sudo_acl
``sudo_acl``
------------
Default: ``False``
Enforce ``publisher_acl`` and ``publisher_acl_blacklist`` when users have sudo
access to the salt command.
.. code-block:: yaml
sudo_acl: False
.. conf_master:: external_auth
``external_auth``
@ -1462,6 +1517,19 @@ Do not disable this unless it is absolutely clear what this does.
rotate_aes_key: True
.. conf_master:: publish_session
``publish_session``
-------------------
Default: ``86400``
The number of seconds between AES key rotations on the master.
.. code-block:: yaml
publish_session: Default: 86400
.. conf_master:: ssl
``ssl``
@ -1492,6 +1560,24 @@ constant names without ssl module prefix: ``CERT_REQUIRED`` or ``PROTOCOL_SSLv23
``allow_minion_key_revoke``
---------------------------
Default: ``False``
By default, the master deletes its cache of minion data when the key for that
minion is removed. To preserve the cache after key deletion, set
``preserve_minion_cache`` to True.
WARNING: This may have security implications if compromised minions auth with
a previous deleted minion ID.
.. code-block:: yaml
preserve_minion_cache: False
.. conf_master:: allow_minion_key_revoke
``allow_minion_key_revoke``
---------------------------
Default: ``True``
Controls whether a minion can request its own key revocation. When True
@ -1504,6 +1590,127 @@ the master will drop the request and the minion's key will remain accepted.
rotate_aes_key: True
Master Large Scale Tuning Settings
==================================
.. conf_master:: max_open_files
``max_open_files``
------------------
Default: ``100000``
Each minion connecting to the master uses AT LEAST one file descriptor, the
master subscription connection. If enough minions connect you might start
seeing on the console(and then salt-master crashes):
.. code-block:: bash
Too many open files (tcp_listener.cpp:335)
Aborted (core dumped)
.. code-block:: yaml
max_open_files: 100000
By default this value will be the one of `ulimit -Hn`, i.e., the hard limit for
max open files.
To set a different value than the default one, uncomment, and configure this
setting. Remember that this value CANNOT be higher than the hard limit. Raising
the hard limit depends on the OS and/or distribution, a good way to find the
limit is to search the internet for something like this:
.. code-block:: text
raise max open files hard limit debian
.. conf_master:: worker_threads
``worker_threads``
------------------
Default: ``5``
The number of threads to start for receiving commands and replies from minions.
If minions are stalling on replies because you have many minions, raise the
worker_threads value.
Worker threads should not be put below 3 when using the peer system, but can
drop down to 1 worker otherwise.
.. note::
When the master daemon starts, it is expected behaviour to see
multiple salt-master processes, even if 'worker_threads' is set to '1'. At
a minimum, a controlling process will start along with a Publisher, an
EventPublisher, and a number of MWorker processes will be started. The
number of MWorker processes is tuneable by the 'worker_threads'
configuration value while the others are not.
.. code-block:: yaml
worker_threads: 5
.. conf_master:: pub_hwm
``pub_hwm``
-----------
Default: ``1000``
The zeromq high water mark on the publisher interface.
.. code-block:: yaml
pub_hwm: 1000
.. conf_master:: zmq_backlog
``zmq_backlog``
---------------
Default: ``1000``
The listen queue size of the ZeroMQ backlog.
.. code-block:: yaml
zmq_backlog: 1000
.. conf_master:: salt_event_pub_hwm
.. conf_master:: event_publisher_pub_hwm
``salt_event_pub_hwm`` and ``event_publisher_pub_hwm``
------------------------------------------------------
These two ZeroMQ High Water Mark settings, ``salt_event_pub_hwm`` and
``event_publisher_pub_hwm`` are significant for masters with thousands of
minions. When these are insufficiently high it will manifest in random
responses missing in the CLI and even missing from the job cache. Masters
that have fast CPUs and many cores with appropriate ``worker_threads``
will not need these set as high.
The ZeroMQ high-water-mark for the ``SaltEvent`` pub socket default is:
.. code-block:: yaml
salt_event_pub_hwm: 20000
The ZeroMQ high-water-mark for the ``EventPublisher`` pub socket default is:
.. code-block:: yaml
event_publisher_pub_hwm: 10000
As an example, on single master deployment with 8,000 minions, 2.4GHz CPUs,
24 cores, and 32GiB memory has these settings:
.. code-block:: yaml
salt_event_pub_hwm: 128000
event_publisher_pub_hwm: 64000
.. _master-module-management:
Master Module Management
@ -3245,6 +3452,26 @@ configuration.
pillar_opts: False
.. conf_master:: pillar_safe_render_error
``pillar_safe_render_error``
----------------------------
Default: ``True``
The pillar_safe_render_error option prevents the master from passing pillar
render errors to the minion. This is set on by default because the error could
contain templating data which would give that minion information it shouldn't
have, like a password! When set ``True`` the error message will only show:
.. code-block:: shell
Rendering SLS 'my.sls' failed. Please see master log for details.
.. code-block:: yaml
pillar_safe_render_error: True
.. _master-configuration-ext-pillar:
.. conf_master:: ext_pillar
@ -3915,6 +4142,62 @@ can be utilized:
pillar_cache_backend: disk
Master Reactor Settings
=======================
.. conf_master:: reactor
``reactor``
-----------
Default: ``[]``
Defines a salt reactor. See the :ref:`Reactor <reactor>` documentation for more
information.
.. code-block:: yaml
reactor: []
.. conf_master:: reactor_refresh_interval
``reactor_refresh_interval``
----------------------------
Default: ``60``
The TTL for the cache of the reactor configuration.
.. code-block:: yaml
reactor_refresh_interval: 60
.. conf_master:: reactor_worker_threads
``reactor_worker_threads``
--------------------------
Default: ``10``
The number of workers for the runner/wheel in the reactor.
.. code-block:: yaml
reactor_worker_threads: 10
.. conf_master:: reactor_worker_hwm
``reactor_worker_hwm``
----------------------
Default: ``10000``
The queue size for workers in the reactor.
.. code-block:: yaml
reactor_worker_hwm: 10000
.. _syndic-server-settings:
Syndic Server Settings
@ -4381,6 +4664,63 @@ option then the master will log a warning message.
- /etc/roles/webserver
Keepalive Settings
==================
.. conf_master:: tcp_keepalive
``tcp_keepalive``
-----------------
Default: ``True``
The tcp keepalive interval to set on TCP ports. This setting can be used to tune Salt
connectivity issues in messy network environments with misbehaving firewalls.
.. code-block:: yaml
tcp_keepalive: True
.. conf_master:: tcp_keepalive_cnt
``tcp_keepalive_cnt``
---------------------
Default: ``-1``
Sets the ZeroMQ TCP keepalive count. May be used to tune issues with minion disconnects.
.. code-block:: yaml
tcp_keepalive_cnt: -1
.. conf_master:: tcp_keepalive_idle
``tcp_keepalive_idle``
----------------------
Default: ``300``
Sets ZeroMQ TCP keepalive idle. May be used to tune issues with minion disconnects.
.. code-block:: yaml
tcp_keepalive_idle: 300
.. conf_master:: tcp_keepalive_intvl
``tcp_keepalive_intvl``
-----------------------
Default: ``-1``
Sets ZeroMQ TCP keepalive interval. May be used to tune issues with minion disconnects.
.. code-block:: yaml
tcp_keepalive_intvl': -1
.. _winrepo-master-config-opts:
Windows Software Repo Settings
@ -4519,7 +4859,7 @@ URL of the repository:
.. code-block:: yaml
winrepo_remotes:
winrepo_remotes_ng:
- '<commit_id> https://github.com/saltstack/salt-winrepo-ng.git'
Replace ``<commit_id>`` with the SHA1 hash of a commit ID. Specifying a commit

View file

@ -782,6 +782,20 @@ seconds each iteration.
acceptance_wait_time_max: 0
.. conf_minion:: rejected_retry
``rejected_retry``
------------------
Default: ``False``
If the master rejects the minion's public key, retry instead of exiting.
Rejected keys will be handled the same as waiting on acceptance.
.. code-block:: yaml
rejected_retry: False
.. conf_minion:: random_reauth_delay
``random_reauth_delay``
@ -1212,7 +1226,7 @@ If certain returners should be disabled, this is the place
.. conf_minion:: enable_whitelist_modules
``whitelist_modules``
----------------------------
---------------------
Default: ``[]`` (Module whitelisting is disabled. Adding anything to the config option
will cause only the listed modules to be enabled. Modules not in the list will
@ -1304,6 +1318,20 @@ A list of extra directories to search for Salt renderers
render_dirs:
- /var/lib/salt/renderers
.. conf_minion:: utils_dirs
``utils_dirs``
--------------
Default: ``[]``
A list of extra directories to search for Salt utilities
.. code-block:: yaml
utils_dirs:
- /var/lib/salt/utils
.. conf_minion:: cython_enable
``cython_enable``
@ -1352,6 +1380,20 @@ below.
providers:
service: systemd
.. conf_minion:: modules_max_memory
``modules_max_memory``
----------------------
Default: ``-1``
Specify a max size (in bytes) for modules on import. This feature is currently
only supported on *nix operating systems and requires psutil.
.. code-block:: yaml
modules_max_memory: -1
.. conf_minion:: extmod_whitelist
.. conf_minion:: extmod_blacklist
@ -1377,8 +1419,8 @@ whitelist an empty list.
modules:
- specific_module
Valid options:
- beacons
- clouds
- sdb
@ -1524,6 +1566,52 @@ environment lacks one.
default_top: dev
.. conf_minion:: startup_states
``startup_states``
------------------
Default: ``''``
States to run when the minion daemon starts. To enable, set ``startup_states`` to:
- ``highstate``: Execute state.highstate
- ``sls``: Read in the sls_list option and execute the named sls files
- ``top``: Read top_file option and execute based on that file on the Master
.. code-block:: yaml
startup_states: ''
.. conf_minion:: sls_list
``sls_list``
------------
Default: ``[]``
List of states to run when the minion starts up if ``startup_states`` is set to ``sls``.
.. code-block:: yaml
sls_list:
- edit.vim
- hyper
.. conf_minion:: top_file
``top_file``
------------
Default: ``''``
Top file to execute if ``startup_states`` is set to ``top``.
.. code-block:: yaml
top_file: ''
State Management Settings
=========================
@ -1540,7 +1628,7 @@ The default renderer used for local state executions
renderer: yaml_jinja
.. conf_master:: test
.. conf_minion:: test
``test``
--------
@ -2058,6 +2146,35 @@ before the initial key exchange. The master fingerprint can be found by running
master_finger: 'ba:30:65:2a:d6:9e:20:4f:d8:b2:f3:a7:d4:65:11:13'
.. conf_minion:: keysize
``keysize``
-----------
Default: ``2048``
The size of key that should be generated when creating new keys.
.. code-block:: yaml
keysize: 2048
.. conf_minion:: permissive_pki_access
``permissive_pki_access``
-------------------------
Default: ``False``
Enable permissive access to the salt keys. This allows you to run the
master or minion as root, but have a non-root group be given access to
your pki_dir. To make the access explicit, root must belong to the group
you've given access to. This is potentially quite insecure.
.. code-block:: yaml
permissive_pki_access: False
.. conf_minion:: verify_master_pubkey_sign
``verify_master_pubkey_sign``
@ -2165,7 +2282,7 @@ blocked. If `cmd_whitelist_glob` is NOT SET, then all shell commands are permitt
- 'cat /etc/fstab'
.. conf_master:: ssl
.. conf_minion:: ssl
``ssl``
-------
@ -2191,6 +2308,62 @@ constant names without ssl module prefix: ``CERT_REQUIRED`` or ``PROTOCOL_SSLv23
ssl_version: PROTOCOL_TLSv1_2
Reactor Settings
================
.. conf_minion:: reactor
``reactor``
-----------
Default: ``[]``
Defines a salt reactor. See the :ref:`Reactor <reactor>` documentation for more
information.
.. code-block:: yaml
reactor: []
.. conf_minion:: reactor_refresh_interval
``reactor_refresh_interval``
----------------------------
Default: ``60``
The TTL for the cache of the reactor configuration.
.. code-block:: yaml
reactor_refresh_interval: 60
.. conf_minion:: reactor_worker_threads
``reactor_worker_threads``
--------------------------
Default: ``10``
The number of workers for the runner/wheel in the reactor.
.. code-block:: yaml
reactor_worker_threads: 10
.. conf_minion:: reactor_worker_hwm
``reactor_worker_hwm``
----------------------
Default: ``10000``
The queue size for workers in the reactor.
.. code-block:: yaml
reactor_worker_hwm: 10000
Thread Settings
===============
@ -2461,6 +2634,62 @@ option then the minion will log a warning message.
- /etc/roles/webserver
Keepalive Settings
==================
.. conf_minion:: tcp_keepalive
``tcp_keepalive``
-----------------
Default: ``True``
The tcp keepalive interval to set on TCP ports. This setting can be used to tune Salt
connectivity issues in messy network environments with misbehaving firewalls.
.. code-block:: yaml
tcp_keepalive: True
.. conf_minion:: tcp_keepalive_cnt
``tcp_keepalive_cnt``
---------------------
Default: ``-1``
Sets the ZeroMQ TCP keepalive count. May be used to tune issues with minion disconnects.
.. code-block:: yaml
tcp_keepalive_cnt: -1
.. conf_minion:: tcp_keepalive_idle
``tcp_keepalive_idle``
----------------------
Default: ``300``
Sets ZeroMQ TCP keepalive idle. May be used to tune issues with minion disconnects.
.. code-block:: yaml
tcp_keepalive_idle: 300
.. conf_minion:: tcp_keepalive_intvl
``tcp_keepalive_intvl``
-----------------------
Default: ``-1``
Sets ZeroMQ TCP keepalive interval. May be used to tune issues with minion disconnects.
.. code-block:: yaml
tcp_keepalive_intvl': -1
Frozen Build Update Settings
============================
@ -2562,6 +2791,36 @@ out.
winrepo_dir: 'D:\winrepo'
.. conf_minion:: winrepo_dir_ng
``winrepo_dir_ng``
------------------
.. versionadded:: 2015.8.0
A new :ref:`ng <windows-package-manager>` repo was added.
Default: ``/srv/salt/win/repo-ng``
Location on the minion where the :conf_minion:`winrepo_remotes_ng` are checked
out for 2015.8.0 and later minions.
.. code-block:: yaml
winrepo_dir_ng: /srv/salt/win/repo-ng
.. conf_minion:: winrepo_source_dir
``winrepo_source_dir``
----------------------
Default: ``salt://win/repo-ng/``
The source location for the winrepo sls files.
.. code-block:: yaml
winrepo_source_dir: salt://win/repo-ng/
.. conf_minion:: winrepo_cachefile
.. conf_minion:: win_repo_cachefile
@ -2614,3 +2873,33 @@ URL of the repository:
Replace ``<commit_id>`` with the SHA1 hash of a commit ID. Specifying a commit
ID is useful in that it allows one to revert back to a previous version in the
event that an error is introduced in the latest revision of the repo.
.. conf_minion:: winrepo_remotes_ng
``winrepo_remotes_ng``
----------------------
.. versionadded:: 2015.8.0
A new :ref:`ng <windows-package-manager>` repo was added.
Default: ``['https://github.com/saltstack/salt-winrepo-ng.git']``
List of git repositories to checkout and include in the winrepo for
2015.8.0 and later minions.
.. code-block:: yaml
winrepo_remotes_ng:
- https://github.com/saltstack/salt-winrepo-ng.git
To specify a specific revision of the repository, prepend a commit ID to the
URL of the repository:
.. code-block:: yaml
winrepo_remotes_ng:
- '<commit_id> https://github.com/saltstack/salt-winrepo-ng.git'
Replace ``<commit_id>`` with the SHA1 hash of a commit ID. Specifying a commit
ID is useful in that it allows one to revert back to a previous version in the
event that an error is introduced in the latest revision of the repo.

View file

@ -351,7 +351,7 @@ Returns:
.. versionadded:: 2017.7.0
Wraps a text around quoutes.
This text will be wrapped in quotes.
.. jinja_ref:: regex_search
@ -766,19 +766,43 @@ Returns:
Check a whitelist and/or blacklist to see if the value matches it.
Example:
This filter can be used with either a whitelist or a blacklist individually,
or a whitelist and a blacklist can be passed simultaneously.
If whitelist is used alone, value membership is checked against the
whitelist only. If the value is found, the function returns ``True``.
Otherwise, it returns ``False``.
If blacklist is used alone, value membership is checked against the
blacklist only. If the value is found, the function returns ``False``.
Otherwise, it returns ``True``.
If both a whitelist and a blacklist are provided, value membership in the
blacklist will be examined first. If the value is not found in the blacklist,
then the whitelist is checked. If the value isn't found in the whitelist,
the function returns ``False``.
Whitelist Example:
.. code-block:: jinja
{{ 5 | check_whitelist_blacklist(whitelist=[5, 6, 7]) }}
{{ 5 | check_whitelist_blacklist(blacklist=[5, 6, 7]) }}
{{ 5 | check_whitelist_blacklist(whitelist=[5, 6, 7]) }}
Returns:
.. code-block:: python
True
True
Blacklist Example:
.. code-block:: jinja
{{ 5 | check_whitelist_blacklist(blacklist=[5, 6, 7]) }}
.. code-block:: python
False
.. jinja_ref:: date_format
@ -841,6 +865,13 @@ Example:
{{ 'wall of text' | to_bytes }}
.. note::
This option may have adverse effects when using the default renderer, ``yaml_jinja``.
This is due to the fact that YAML requires proper handling in regard to special
characters. Please see the section on :ref:`YAML ASCII support <yaml_plain_ascii>`
in the :ref:`YAML Idiosyncracies <yaml-idiosyncrasies>` documentation for more
information.
.. jinja_ref:: json_decode_list
@ -892,16 +923,22 @@ Returns:
------------
.. versionadded:: 2017.7.0
.. versionadded:: Oxygen
Renamed from ``rand_str`` to ``random_hash`` to more accurately describe
what the filter does.
Generate a random string and applies a hash. Default hashing: md5.
Generates a random number between 1 and the number passed to the filter, and
then hashes it. The default hash type is the one specified by the minion's
:conf_minion:`hash_type` config option, but an alternate hash type can be
passed to the filter as an argument.
Example:
.. code-block:: jinja
{% set passwd_length = 17 %}
{{ passwd_length | rand_str }}
{{ passwd_length | rand_str('sha512') }}
{% set num_range = 99999999 %}
{{ num_range | rand_str }}
{{ num_range | rand_str('sha512') }}
Returns:
@ -1202,7 +1239,7 @@ Example:
.. code-block:: jinja
{{ ['192.168.0.1', 'foo', 'bar', 'fe80::'] | ipv4 }}
{{ ['192.168.0.1', 'foo', 'bar', 'fe80::'] | ipv6 }}
Returns:
@ -1245,7 +1282,7 @@ Returns:
.. versionadded:: 2017.7.0
Return the size of the network.
Return the size of the network. This utility works for both IPv4 and IPv6.
Example:
@ -1305,6 +1342,13 @@ Example:
{{ '00:11:22:33:44:55' | mac_str_to_bytes }}
.. note::
This option may have adverse effects when using the default renderer, ``yaml_jinja``.
This is due to the fact that YAML requires proper handling in regard to special
characters. Please see the section on :ref:`YAML ASCII support <yaml_plain_ascii>`
in the :ref:`YAML Idiosyncracies <yaml-idiosyncrasies>` documentation for more
information.
.. jinja_ref:: dns_check

View file

@ -28,8 +28,6 @@ The following salt-cloud drivers have known issues running with Python 3. These
- Joyent
- Any driver that relies on the `apache-libcloud` library such as cloudstack, dimenstiondata, gce, nova, and openstack
- When running under Python 3, users who require Unicode support should ensure that a locale is set on their machines.
Users using the `C` locale are advised to switch to a UTF-aware locale to ensure proper functionality with Salt with Python 3.
@ -945,3 +943,13 @@ The ``glusterfs`` state had the following function removed:
The ``openvswitch_port`` state had the following change:
- The ``type`` option was removed from the ``present`` function. Please use ``tunnel_type`` instead.
Build Notes
===========
Windows Installer Packages
--------------------------
Windows Installer packages have been patched with the following PR: 42347_
.. _42347: https://github.com/saltstack/salt/pull/42347

View file

@ -0,0 +1,183 @@
============================
Salt 2017.7.1 Release Notes
============================
Version 2017.7.1 is a bugfix release for :ref:`2017.7.0 <release-2017-7-0>`.
Changes for v2017.7.0..v2017.7.1
--------------------------------
Extended changelog courtesy of Todd Stansell (https://github.com/tjstansell/salt-changelogs):
*Generated at: 2017-07-26T01:09:40Z*
Statistics:
- Total Merges: **11**
- Total Issue references: **9**
- Total PR references: **22**
Changes:
- **PR** `#42548`_: (*gtmanfred*) pass in empty kwarg for reactor
@ *2017-07-26T00:41:20Z*
- **ISSUE** `#460`_: (*whiteinge*) Add a topic and a ref for modules/states/returners/renderers/runners
| refs: `#42548`_
* 711b742c54 Merge pull request `#42548`_ from gtmanfred/2017.7.1
* 0257c1dc32 pass in empty kwarg for reactor
* b948e980d2 update chunk, not kwarg in chunk
- **PR** `#42522`_: (*gtmanfred*) pacman wildcard is only for repository installs
@ *2017-07-24T20:51:05Z*
- **ISSUE** `#42519`_: (*xuhcc*) Error when installing package from file under Arch Linux
| refs: `#42522`_
* 50c1635dcc Merge pull request `#42522`_ from gtmanfred/2017.7.1
* 7787fb9e1b pacman wildcard is only for repository installs
- **PR** `#42508`_: (*rallytime*) Back-port `#42474`_ to 2017.7.1
@ *2017-07-24T20:49:51Z*
- **PR** `#42474`_: (*whiteinge*) Cmd arg kwarg parsing test
| refs: `#42508`_
- **PR** `#39646`_: (*terminalmage*) Handle deprecation of passing string args to load_args_and_kwargs
| refs: `#42474`_
* 05c07ac049 Merge pull request `#42508`_ from rallytime/`bp-42474`_
* 76fb074433 Add a test.arg variant that cleans the pub kwargs by default
* 624f63648e Lint fixes
* d246a5fc61 Add back support for string kwargs
* 854e098aa0 Add LocalClient.cmd test for arg/kwarg parsing
- **PR** `#42472`_: (*rallytime*) Back-port `#42435`_ to 2017.7.1
@ *2017-07-24T15:11:13Z*
- **ISSUE** `#42427`_: (*grichmond-salt*) Issue Passing Variables created from load_json as Inline Pillar Between States
| refs: `#42435`_
- **PR** `#42435`_: (*terminalmage*) Modify our custom YAML loader to treat unicode literals as unicode strings
| refs: `#42472`_
* 95fe2558e4 Merge pull request `#42472`_ from rallytime/`bp-42435`_
* 5c47af5b98 Modify our custom YAML loader to treat unicode literals as unicode strings
- **PR** `#42473`_: (*rallytime*) Back-port `#42436`_ to 2017.7.1
@ *2017-07-24T15:10:29Z*
- **ISSUE** `#42374`_: (*tyhunt99*) [2017.7.0] salt-run mange.versions throws exception if minion is offline or unresponsive
| refs: `#42436`_
- **PR** `#42436`_: (*garethgreenaway*) Fixes to versions function in manage runner
| refs: `#42473`_
* 5b99d45f54 Merge pull request `#42473`_ from rallytime/`bp-42436`_
* 82ed919803 Updating the versions function inside the manage runner to account for when a minion is offline and we are unable to determine it's version.
- **PR** `#42471`_: (*rallytime*) Back-port `#42399`_ to 2017.7.1
@ *2017-07-24T15:09:50Z*
- **ISSUE** `#42381`_: (*zebooka*) Git.detached broken in 2017.7.0
| refs: `#42399`_
- **ISSUE** `#38878`_: (*tomlaredo*) [Naming consistency] git.latest "rev" option VS git.detached "ref" option
| refs: `#38898`_
- **PR** `#42399`_: (*rallytime*) Update old "ref" references to "rev" in git.detached state
| refs: `#42471`_
- **PR** `#38898`_: (*terminalmage*) git.detached: rename ref to rev for consistency
| refs: `#42399`_
* 3d1a2d3f9f Merge pull request `#42471`_ from rallytime/`bp-42399`_
* b9a4669e5a Update old "ref" references to "rev" in git.detached state
- **PR** `#42470`_: (*rallytime*) Back-port `#42031`_ to 2017.7.1
@ *2017-07-24T15:09:30Z*
- **ISSUE** `#42400`_: (*Enquier*) Conflict in execution of passing pillar data to orch/reactor event executions 2017.7.0
| refs: `#42031`_
- **PR** `#42031`_: (*skizunov*) Fix: Reactor emits critical error
| refs: `#42470`_
* 09766bccbc Merge pull request `#42470`_ from rallytime/`bp-42031`_
* 0a0c6287a4 Fix: Reactor emits critical error
- **PR** `#42469`_: (*rallytime*) Back-port `#42027`_ to 2017.7.1
@ *2017-07-21T22:41:02Z*
- **ISSUE** `#41949`_: (*jrporcaro*) Event returner doesn't work with Windows Master
| refs: `#42027`_
- **PR** `#42027`_: (*gtmanfred*) import salt.minion for EventReturn for Windows
| refs: `#42469`_
* d7b172a15b Merge pull request `#42469`_ from rallytime/`bp-42027`_
* ed612b4ee7 import salt.minion for EventReturn for Windows
- **PR** `#42466`_: (*rallytime*) Back-port `#42452`_ to 2017.7.1
@ *2017-07-21T19:41:24Z*
- **PR** `#42452`_: (*Ch3LL*) update windows urls to new py2/py3 naming scheme
| refs: `#42466`_
* 8777b1a825 Merge pull request `#42466`_ from rallytime/`bp-42452`_
* c10196f68c update windows urls to new py2/py3 naming scheme
- **PR** `#42439`_: (*rallytime*) Back-port `#42409`_ to 2017.7.1
@ *2017-07-21T17:38:10Z*
- **PR** `#42409`_: (*twangboy*) Add Scripts to build Py3 on Mac
| refs: `#42439`_
* fceaaf41d0 Merge pull request `#42439`_ from rallytime/`bp-42409`_
* 8176964b41 Remove build and dist, sign pkgs
* 2c14d92a07 Fix hard coded pip path
* 82fdd7c2e1 Add support for Py3
* 2478447246 Update Python and other reqs
- **PR** `#42441`_: (*rallytime*) Back-port `#42433`_ to 2017.7.1
@ *2017-07-21T17:37:01Z*
- **ISSUE** `#42403`_: (*astronouth7303*) [2017.7] Pillar empty when state is applied from orchestrate
| refs: `#42433`_
- **PR** `#42433`_: (*terminalmage*) Only force saltenv/pillarenv to be a string when not None
| refs: `#42441`_
* 660400560b Merge pull request `#42441`_ from rallytime/`bp-42433`_
* 17f347123a Only force saltenv/pillarenv to be a string when not None
.. _`#38878`: https://github.com/saltstack/salt/issues/38878
.. _`#38898`: https://github.com/saltstack/salt/pull/38898
.. _`#39646`: https://github.com/saltstack/salt/pull/39646
.. _`#41949`: https://github.com/saltstack/salt/issues/41949
.. _`#42027`: https://github.com/saltstack/salt/pull/42027
.. _`#42031`: https://github.com/saltstack/salt/pull/42031
.. _`#42374`: https://github.com/saltstack/salt/issues/42374
.. _`#42381`: https://github.com/saltstack/salt/issues/42381
.. _`#42399`: https://github.com/saltstack/salt/pull/42399
.. _`#42400`: https://github.com/saltstack/salt/issues/42400
.. _`#42403`: https://github.com/saltstack/salt/issues/42403
.. _`#42409`: https://github.com/saltstack/salt/pull/42409
.. _`#42427`: https://github.com/saltstack/salt/issues/42427
.. _`#42433`: https://github.com/saltstack/salt/pull/42433
.. _`#42435`: https://github.com/saltstack/salt/pull/42435
.. _`#42436`: https://github.com/saltstack/salt/pull/42436
.. _`#42439`: https://github.com/saltstack/salt/pull/42439
.. _`#42441`: https://github.com/saltstack/salt/pull/42441
.. _`#42452`: https://github.com/saltstack/salt/pull/42452
.. _`#42466`: https://github.com/saltstack/salt/pull/42466
.. _`#42469`: https://github.com/saltstack/salt/pull/42469
.. _`#42470`: https://github.com/saltstack/salt/pull/42470
.. _`#42471`: https://github.com/saltstack/salt/pull/42471
.. _`#42472`: https://github.com/saltstack/salt/pull/42472
.. _`#42473`: https://github.com/saltstack/salt/pull/42473
.. _`#42474`: https://github.com/saltstack/salt/pull/42474
.. _`#42508`: https://github.com/saltstack/salt/pull/42508
.. _`#42519`: https://github.com/saltstack/salt/issues/42519
.. _`#42522`: https://github.com/saltstack/salt/pull/42522
.. _`#42548`: https://github.com/saltstack/salt/pull/42548
.. _`#460`: https://github.com/saltstack/salt/issues/460
.. _`bp-42027`: https://github.com/saltstack/salt/pull/42027
.. _`bp-42031`: https://github.com/saltstack/salt/pull/42031
.. _`bp-42399`: https://github.com/saltstack/salt/pull/42399
.. _`bp-42409`: https://github.com/saltstack/salt/pull/42409
.. _`bp-42433`: https://github.com/saltstack/salt/pull/42433
.. _`bp-42435`: https://github.com/saltstack/salt/pull/42435
.. _`bp-42436`: https://github.com/saltstack/salt/pull/42436
.. _`bp-42452`: https://github.com/saltstack/salt/pull/42452
.. _`bp-42474`: https://github.com/saltstack/salt/pull/42474

View file

@ -32,6 +32,8 @@ Builds for a few platforms are available as part of the RC at https://repo.salts
Available builds:
- Ubuntu16
- Redhat7
- Windows
.. FreeBSD

View file

@ -64,7 +64,8 @@ Deploy ssh key for salt-ssh
===========================
By default, salt-ssh will generate key pairs for ssh, the default path will be
/etc/salt/pki/master/ssh/salt-ssh.rsa
``/etc/salt/pki/master/ssh/salt-ssh.rsa``. The key generation happens when you run
``salt-ssh`` for the first time.
You can use ssh-copy-id, (the OpenSSH key deployment tool) to deploy keys to your servers.

View file

@ -28,6 +28,7 @@ hit `Enter`. Also, you can convert tabs to 2 spaces by these commands in Vim:
Indentation
===========
The suggested syntax for YAML files is to use 2 spaces for indentation,
but YAML will follow whatever indentation system that the individual file
uses. Indentation of two spaces works very well for SLS files given the
@ -112,8 +113,24 @@ PyYAML will load these values as boolean ``True`` or ``False``. Un-capitalized
versions will also be loaded as booleans (``true``, ``false``, ``yes``, ``no``,
``on``, and ``off``). This can be especially problematic when constructing
Pillar data. Make sure that your Pillars which need to use the string versions
of these values are enclosed in quotes. Pillars will be parsed twice by salt,
so you'll need to wrap your values in multiple quotes, for example '"false"'.
of these values are enclosed in quotes. Pillars will be parsed twice by salt,
so you'll need to wrap your values in multiple quotes, including double quotation
marks (``" "``) and single quotation marks (``' '``). Note that spaces are included
in the quotation type examples for clarity.
Multiple quoting examples looks like this:
.. code-block:: yaml
- '"false"'
- "'True'"
- "'YES'"
- '"No"'
.. note::
When using multiple quotes in this manner, they must be different. Using ``"" ""``
or ``'' ''`` won't work in this case (spaces are included in examples for clarity).
The '%' Sign
============
@ -248,8 +265,10 @@ Alternatively, they can be defined the "old way", or with multiple
- require:
- user: fred
YAML support only plain ASCII
=============================
.. _yaml_plain_ascii:
YAML supports only plain ASCII
==============================
According to YAML specification, only ASCII characters can be used.

View file

@ -54,7 +54,7 @@ types like so:
salt '*' mymodule.observe_the_awesomeness
'''
print __utils__['foo.bar']()
return __utils__['foo.bar']()
Utility modules, like any other kind of Salt extension, support using a
:ref:`__virtual__ function <modules-virtual-name>` to conditionally load them,
@ -81,11 +81,56 @@ the ``foo`` utility module with a ``__virtual__`` function.
def bar():
return 'baz'
Also you could even write your utility modules in object oriented fashion:
.. code-block:: python
# -*- coding: utf-8 -*-
'''
My utils module
---------------
This module contains common functions for use in my other custom types.
'''
class Foo(object):
def __init__(self):
pass
def bar(self):
return 'baz'
And import them into other custom modules:
.. code-block:: python
# -*- coding: utf-8 -*-
'''
My awesome execution module
---------------------------
'''
import mymodule
def observe_the_awesomeness():
'''
Prints information from my utility module
CLI Example:
.. code-block:: bash
salt '*' mymodule.observe_the_awesomeness
'''
foo = mymodule.Foo()
return foo.bar()
These are, of course, contrived examples, but they should serve to show some of
the possibilities opened up by writing utility modules. Keep in mind though
that States still have access to all of the execution modules, so it is not
that states still have access to all of the execution modules, so it is not
necessary to write a utility module to make a function available to both a
state and an execution module. One good use case for utililty modules is one
state and an execution module. One good use case for utility modules is one
where it is necessary to invoke the same function from a custom :ref:`outputter
<all-salt.output>`/returner, as well as an execution module.

View file

@ -19,14 +19,16 @@
# $1 : <version> : the version of salt to build
# (a git tag, not a branch)
# (defaults to git-repo state)
# $2 : <package dir> : the staging area for the package
# $2 : <pythin ver> : The version of Python to use in the
# build. Default is 2
# $3 : <package dir> : the staging area for the package
# defaults to /tmp/salt_pkg
#
# Example:
# The following will build Salt v2015.8.3 and stage all files
# in /tmp/custom_pkg:
# The following will build Salt v2015.8.3 with Python 2 and
# stage all files in /tmp/custom_pkg:
#
# ./build.sh v2015.8.3 /tmp/custom_pkg
# ./build.sh v2015.8.3 2 /tmp/custom_pkg
#
############################################################################
echo -n -e "\033]0;Build: Variables\007"
@ -41,9 +43,15 @@ else
fi
if [ "$2" == "" ]; then
PYVER=2
else
PYVER=$2
fi
if [ "$3" == "" ]; then
PKGDIR=/tmp/salt_pkg
else
PKGDIR=$2
PKGDIR=$3
fi
############################################################################
@ -51,6 +59,12 @@ fi
############################################################################
SRCDIR=`git rev-parse --show-toplevel`
PKGRESOURCES=$SRCDIR/pkg/osx
if [ "$PYVER" == "2" ]; then
PYTHON=/opt/salt/bin/python
else
PYTHON=/opt/salt/bin/python3
fi
CPUARCH=`uname -m`
############################################################################
# Make sure this is the Salt Repository
@ -66,16 +80,23 @@ fi
# Create the Build Environment
############################################################################
echo -n -e "\033]0;Build: Build Environment\007"
sudo $PKGRESOURCES/build_env.sh
sudo $PKGRESOURCES/build_env.sh $PYVER
############################################################################
# Install Salt
############################################################################
echo -n -e "\033]0;Build: Install Salt\007"
sudo /opt/salt/bin/python $SRCDIR/setup.py install
sudo rm -rm $SRCDIR/build
sudo rm -rm $SRCDIR/dist
sudo $PYTHON $SRCDIR/setup.py install
############################################################################
# Build Package
############################################################################
echo -n -e "\033]0;Build: Package Salt\007"
sudo $PKGRESOURCES/build_pkg.sh $VERSION $PKGDIR
sudo $PKGRESOURCES/build_pkg.sh $VERSION $PYVER $PKGDIR
############################################################################
# Sign Package
############################################################################
sudo $PKGRESOURCES/build_sig.sh salt-$VERSION-py$PYVER-$CPUARCH.pkg salt-$VERSION-py$PYVER-$CPUARCH-signed.pkg

View file

@ -6,18 +6,21 @@
# Authors: CR Oldham, Shane Lee
# Date: December 2015
#
# Description: This script sets up a build environment for salt on macOS.
# Description: This script sets up a build environment for Salt on macOS.
#
# Requirements:
# - XCode Command Line Tools (xcode-select --install)
#
# Usage:
# This script is not passed any parameters
# This script can be passed 1 parameter
# $1 : <python version> : the version of Python to use for the
# build environment. Default is 2
#
# Example:
# The following will set up a build environment for salt on macOS
# The following will set up a Python 3 build environment for Salt
# on macOS
#
# ./dev_env.sh
# ./dev_env.sh 3
#
############################################################################
@ -31,6 +34,15 @@ quit_on_error() {
exit -1
}
############################################################################
# Check passed parameters, set defaults
############################################################################
if [ "$1" == "" ]; then
PYVER=2
else
PYVER=$1
fi
############################################################################
# Parameters Required for the script to function properly
############################################################################
@ -45,6 +57,15 @@ SHADIR=$SCRIPTDIR/shasums
PKG_CONFIG_PATH=/opt/salt/lib/pkgconfig
CFLAGS="-I/opt/salt/include"
LDFLAGS="-L/opt/salt/lib"
if [ "$PYVER" == "2" ]; then
PYDIR=/opt/salt/lib/python2.7
PYTHON=/opt/salt/bin/python
PIP=/opt/salt/bin/pip
else
PYDIR=/opt/salt/lib/python3.5
PYTHON=/opt/salt/bin/python3
PIP=/opt/salt/bin/pip3
fi
############################################################################
# Determine Which XCode is being used (XCode or XCode Command Line Tools)
@ -121,8 +142,8 @@ BUILDDIR=$SCRIPTDIR/build
############################################################################
echo -n -e "\033]0;Build_Env: pkg-config\007"
PKGURL="http://pkgconfig.freedesktop.org/releases/pkg-config-0.29.tar.gz"
PKGDIR="pkg-config-0.29"
PKGURL="http://pkgconfig.freedesktop.org/releases/pkg-config-0.29.2.tar.gz"
PKGDIR="pkg-config-0.29.2"
download $PKGURL
@ -140,8 +161,8 @@ sudo -H $MAKE install
############################################################################
echo -n -e "\033]0;Build_Env: libsodium\007"
PKGURL="https://download.libsodium.org/libsodium/releases/libsodium-1.0.12.tar.gz"
PKGDIR="libsodium-1.0.12"
PKGURL="https://download.libsodium.org/libsodium/releases/libsodium-1.0.13.tar.gz"
PKGDIR="libsodium-1.0.13"
download $PKGURL
@ -159,8 +180,8 @@ sudo -H $MAKE install
############################################################################
echo -n -e "\033]0;Build_Env: zeromq\007"
PKGURL="http://download.zeromq.org/zeromq-4.1.3.tar.gz"
PKGDIR="zeromq-4.1.3"
PKGURL="http://download.zeromq.org/zeromq-4.1.4.tar.gz"
PKGDIR="zeromq-4.1.4"
download $PKGURL
@ -178,13 +199,13 @@ sudo -H $MAKE install
############################################################################
echo -n -e "\033]0;Build_Env: OpenSSL\007"
PKGURL="http://openssl.org/source/openssl-1.0.2f.tar.gz"
PKGDIR="openssl-1.0.2f"
PKGURL="http://openssl.org/source/openssl-1.0.2l.tar.gz"
PKGDIR="openssl-1.0.2l"
download $PKGURL
echo "################################################################################"
echo "Building OpenSSL 1.0.2f"
echo "Building OpenSSL"
echo "################################################################################"
cd $PKGDIR
./Configure darwin64-x86_64-cc --prefix=/opt/salt --openssldir=/opt/salt/openssl
@ -197,13 +218,18 @@ sudo -H $MAKE install
############################################################################
echo -n -e "\033]0;Build_Env: Python\007"
PKGURL="https://www.python.org/ftp/python/2.7.12/Python-2.7.12.tar.xz"
PKGDIR="Python-2.7.12"
if [ "$PYVER" == "2" ]; then
PKGURL="https://www.python.org/ftp/python/2.7.13/Python-2.7.13.tar.xz"
PKGDIR="Python-2.7.13"
else
PKGURL="https://www.python.org/ftp/python/3.5.3/Python-3.5.3.tar.xz"
PKGDIR="Python-3.5.3"
fi
download $PKGURL
echo "################################################################################"
echo "Building Python 2.7.12"
echo "Building Python"
echo "################################################################################"
echo "Note there are some test failures"
cd $PKGDIR
@ -215,7 +241,7 @@ sudo -H $MAKE install
############################################################################
# upgrade pip
############################################################################
sudo -H /opt/salt/bin/pip install --upgrade pip
sudo -H $PIP install --upgrade pip
############################################################################
# Download and install salt python dependencies
@ -227,23 +253,23 @@ cd $BUILDDIR
echo "################################################################################"
echo "Installing Salt Dependencies with pip (normal)"
echo "################################################################################"
sudo -H /opt/salt/bin/pip install \
-r $SRCDIR/pkg/osx/req.txt \
--no-cache-dir
sudo -H $PIP install \
-r $SRCDIR/pkg/osx/req.txt \
--no-cache-dir
echo "################################################################################"
echo "Installing Salt Dependencies with pip (build_ext)"
echo "################################################################################"
sudo -H /opt/salt/bin/pip install \
-r $SRCDIR/pkg/osx/req_ext.txt \
--global-option=build_ext \
--global-option="-I/opt/salt/include" \
--no-cache-dir
sudo -H $PIP install \
-r $SRCDIR/pkg/osx/req_ext.txt \
--global-option=build_ext \
--global-option="-I/opt/salt/include" \
--no-cache-dir
echo "--------------------------------------------------------------------------------"
echo "Create Symlink to certifi for openssl"
echo "--------------------------------------------------------------------------------"
sudo ln -s /opt/salt/lib/python2.7/site-packages/certifi/cacert.pem /opt/salt/openssl/cert.pem
sudo ln -s $PYDIR/site-packages/certifi/cacert.pem /opt/salt/openssl/cert.pem
echo -n -e "\033]0;Build_Env: Finished\007"

View file

@ -15,13 +15,16 @@
# This script can be passed 2 parameters
# $1 : <version> : the version name to give the package (overrides
# version of the git repo) (Defaults to the git repo version)
# $2 : <package dir> : the staging area for the package defaults to
# $2 : <python ver> : the version of python that was built (defaults
# to 2)
# $3 : <package dir> : the staging area for the package defaults to
# /tmp/salt_pkg
#
# Example:
# The following will build Salt and stage all files in /tmp/salt_pkg:
# The following will build Salt version 2017.7.0 with Python 3 and
# stage all files in /tmp/salt_pkg:
#
# ./build.sh
# ./build.sh 2017.7.0 3
#
############################################################################
@ -45,11 +48,18 @@ else
VERSION=$1
fi
# Get/Set temp directory
# Get/Set Python Version
if [ "$2" == "" ]; then
PYVER=2
else
PYVER=$2
fi
# Get/Set temp directory
if [ "$3" == "" ]; then
PKGDIR=/tmp/salt_pkg
else
PKGDIR=$2
PKGDIR=$3
fi
CPUARCH=`uname -m`
@ -114,7 +124,11 @@ sudo rm -rdf $PKGDIR/opt/salt/lib/engines
sudo rm -rdf $PKGDIR/opt/salt/share/aclocal
sudo rm -rdf $PKGDIR/opt/salt/share/doc
sudo rm -rdf $PKGDIR/opt/salt/share/man/man1/pkg-config.1
sudo rm -rdf $PKGDIR/opt/salt/lib/python2.7/test
if [ "$PYVER" == "2" ]; then
sudo rm -rdf $PKGDIR/opt/salt/lib/python2.7/test
else
sudo rm -rdf $PKGDIR/opt/salt/lib/python3.5/test
fi
echo -n -e "\033]0;Build_Pkg: Remove compiled python files\007"
sudo find $PKGDIR/opt/salt -name '*.pyc' -type f -delete
@ -133,15 +147,30 @@ cp $SRCDIR/conf/master $PKGDIR/etc/salt/master.dist
############################################################################
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"
else
TITLE="Salt $VERSION (Python 3)"
DESC="Salt $VERSION with Python 3"
fi
cd $PKGRESOURCES
cp distribution.xml.dist distribution.xml
SEDSTR="s/@VERSION@/$VERSION/"
echo $SEDSTR
sed -i '' $SEDSTR distribution.xml
SEDSTR="s/@TITLE@/$TITLE/g"
sed -E -i '' "$SEDSTR" distribution.xml
SEDSTR="s/@CPUARCH@/$CPUARCH/"
echo $SEDSTR
sed -i '' $SEDSTR distribution.xml
SEDSTR="s/@DESC@/$DESC/g"
sed -E -i '' "$SEDSTR" distribution.xml
SEDSTR="s/@VERSION@/$VERSION/g"
sed -E -i '' "$SEDSTR" distribution.xml
SEDSTR="s/@PYVER@/$PYVER/g"
sed -E -i '' "$SEDSTR" distribution.xml
SEDSTR="s/@CPUARCH@/$CPUARCH/g"
sed -i '' "$SEDSTR" distribution.xml
############################################################################
# Build the Package
@ -152,10 +181,10 @@ pkgbuild --root=$PKGDIR \
--scripts=pkg-scripts \
--identifier=com.saltstack.salt \
--version=$VERSION \
--ownership=recommended salt-src-$VERSION-$CPUARCH.pkg
--ownership=recommended salt-src-$VERSION-py$PYVER-$CPUARCH.pkg
productbuild --resources=pkg-resources \
--distribution=distribution.xml \
--package-path=salt-src-$VERSION-$CPUARCH.pkg \
--version=$VERSION salt-$VERSION-$CPUARCH.pkg
--package-path=salt-src-$VERSION-py$PYVER-$CPUARCH.pkg \
--version=$VERSION salt-$VERSION-py$PYVER-$CPUARCH.pkg

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<installer-gui-script minSpecVersion="2">
<title>Salt @VERSION@</title>
<title>@TITLE@</title>
<organization>com.saltstack.salt</organization>
<!-- Define minimum system requirements -->
<volume-check>
@ -25,7 +25,7 @@
<!-- List all component packages -->
<pkg-ref id="com.saltstack.salt"
version="@VERSION@"
auth="root">salt-src-@VERSION@-@CPUARCH@.pkg</pkg-ref>
auth="root">salt-src-@VERSION@-py@PYVER@-@CPUARCH@.pkg</pkg-ref>
<!-- List them again here. They can now be organized
as a hierarchy if you want. -->
<choices-outline>
@ -34,8 +34,8 @@
<!-- Define each choice above -->
<choice id="com.saltstack.salt"
visible="false"
title="Salt @VERSION@"
description="Salt @VERSION@"
title="@TITLE@"
description="@DESC@"
start_selected="true">
<pkg-ref id="com.saltstack.salt" />
</choice>

View file

@ -1,34 +1,31 @@
apache-libcloud==0.20.1
apache-libcloud==2.1.0
backports.ssl_match_hostname==3.5.0.1
backports_abc==0.4
backports_abc==0.5
certifi
cffi==1.5.0
CherryPy==4.0.0
click==6.2
enum34==1.1.2
cffi==1.10.0
CherryPy==11.0.0
click==6.7
enum34==1.1.6
gitdb==0.6.4
GitPython==1.0.1
idna==2.0
ioflo==1.5.0
ipaddress==1.0.16
Jinja2==2.9.4
libnacl==1.4.4
GitPython==2.1.5
idna==2.5
ipaddress==1.0.18
Jinja2==2.9.6
linode-python==1.1.1
Mako==1.0.3
MarkupSafe==0.23
msgpack-python==0.4.7
pyasn1==0.1.9
pycparser==2.14
Mako==1.0.7
MarkupSafe==1.0
msgpack-python==0.4.8
pyasn1==0.2.3
pycparser==2.18
pycrypto==2.6.1
python-dateutil==2.4.2
python-gnupg==0.3.8
PyYAML==3.11
pyzmq==15.2.0
raet==0.6.5
requests==2.9.1
python-dateutil==2.6.1
python-gnupg==0.4.1
PyYAML==3.12
pyzmq==16.0.2
requests==2.18.1
singledispatch==3.4.0.3
six==1.10.0
smmap==0.9.0
timelib==0.2.4
tornado==4.3
vultr==0.1.2
tornado==4.5.1
vultr==1.0rc1

View file

@ -1,2 +1,2 @@
cryptography==1.2.2
pyOpenSSL==0.15.1
cryptography==2.0
pyOpenSSL==17.1.0

View file

@ -1 +0,0 @@
6ddbbce47cc49597433d98ca05c2f62f07ed1070807b645602a8e9e9b996adc6fa66fa20a33cd7d23d4e7e925e25071d7301d288149fbe4e8c5f06d5438dda1f ./Python-2.7.12.tar.xz

View file

@ -0,0 +1 @@
f37c9a28ce129d01e63c84d7db627a06402854578f62d17927334ea21ede318e04bbf66e890e3f47c85333e6b19f6e5581fb3f3e27efd24be27017d1b6529c4b ./Python-2.7.13.tar.xz

View file

@ -0,0 +1 @@
bbcc20e315c63dbc8901d7e7bfa29d4dbdad9335720757d8d679730319fd1d9fcfdb55cf62d620c9b052134170f162c28d653a8af60923185b8932524d827864 ./Python-3.5.3.tar.xz

View file

@ -1 +0,0 @@
1e63960da42bcc90945463ae1f5b1355849881dce5bba6d293391f8d6f0932063a5bfd433a071cb184af90ebeab469acc34710587116922144d61f3d7661901b ./libsodium-1.0.12.tar.gz

View file

@ -0,0 +1 @@
c619b12fdf0b2e59174b6e383a62d5499ebcd720fdbb2c1a41a98a46c285df075202423454b294fefee185432441e943805397d7656f7cd7837de425da623929 ./libsodium-1.0.13.tar.gz

View file

@ -1 +0,0 @@
50abf6dc94cafd06e7fd20770808bdc675c88daa369e4f752bd584ab17f72a57357c1ca1eca3c83e6745b5a3c9c73c99dce70adaa904d73f6df4c75bc7138351 ./openssl-1.0.2f.tar.gz

View file

@ -0,0 +1 @@
047d964508ad6025c79caabd8965efd2416dc026a56183d0ef4de7a0a6769ce8e0b4608a3f8393d326f6d03b26a2b067e6e0c750f35b20be190e595e8290c0e3 ./openssl-1.0.2l.tar.gz

View file

@ -0,0 +1 @@
4861ec6428fead416f5cbbbb0bbad10b9152967e481d4b0ff2eb396a9f297f552984c9bb72f6864a37dcd8fca1d9ccceda3ef18d8f121938dbe4fdf2b870fe75 ./pkg-config-0.29.2.tar.gz

View file

@ -1 +0,0 @@
c2857cd67801c0db5d204912453ff6bdc7da3ea61f8b1c6b38983d48dffb958725e7723f909abbc057c7b34a85c27290eec6943808312a75909306076064aa63 ./pkg-config-0.29.tar.gz

View file

@ -1 +0,0 @@
2c993d18ea44e1cba890e024176af65b85b842ca4f8a22d319be4ace8388ab8828dd706b065f02754025bf271b1d7aa878c3f6655878248f7826452cb2a6134c ./zeromq-4.1.3.tar.gz

View file

@ -0,0 +1 @@
8a8cf4f52ad78dddfff104bfba0f80bbc12566920906a0fafb9fc340aa92f5577c2923cb2e5346c69835cd2ea1609647a8893c2883cd22c1f0340a720511460c ./zeromq-4.1.4.tar.gz

View file

@ -110,6 +110,13 @@ if not %errorLevel%==0 (
)
@echo.
:: Remove build and dist directories
@echo %0 :: Remove build and dist directories...
@echo ---------------------------------------------------------------------
rd /s /q "%SrcDir%\build"
rd /s /q "%SrcDir%\dist"
@echo.
:: Install Current Version of salt
@echo %0 :: Install Current Version of salt...
@echo ---------------------------------------------------------------------

View file

@ -424,13 +424,14 @@ def list_nodes_full(conn=None, call=None): # pylint: disable=unused-argument
for group in list_resource_groups():
nodes = compconn.virtual_machines.list(group)
for node in nodes:
private_ips, public_ips = __get_ips_from_node(group, node)
ret[node.name] = object_to_dict(node)
ret[node.name]['id'] = node.id
ret[node.name]['name'] = node.name
ret[node.name]['size'] = node.hardware_profile.vm_size
ret[node.name]['state'] = node.provisioning_state
ret[node.name]['private_ips'] = node.network_profile.network_interfaces
ret[node.name]['public_ips'] = node.network_profile.network_interfaces
ret[node.name]['private_ips'] = private_ips
ret[node.name]['public_ips'] = public_ips
ret[node.name]['storage_profile']['data_disks'] = []
ret[node.name]['resource_group'] = group
for disk in node.storage_profile.data_disks:
@ -450,6 +451,30 @@ def list_nodes_full(conn=None, call=None): # pylint: disable=unused-argument
return ret
def __get_ips_from_node(resource_group, node):
'''
List private and public IPs from a VM interface
'''
global netconn # pylint: disable=global-statement,invalid-name
if not netconn:
netconn = get_conn(NetworkManagementClient)
private_ips = []
public_ips = []
for node_iface in node.network_profile.network_interfaces:
node_iface_name = node_iface.id.split('/')[-1]
network_interface = netconn.network_interfaces.get(resource_group, node_iface_name)
for ip_configuration in network_interface.ip_configurations:
if ip_configuration.private_ip_address:
private_ips.append(ip_configuration.private_ip_address)
if ip_configuration.public_ip_address and ip_configuration.public_ip_address.id:
public_iface_name = ip_configuration.public_ip_address.id.split('/')[-1]
public_iface = netconn.public_ip_addresses.get(resource_group, public_iface_name)
public_ips.append(public_iface.ip_address)
return private_ips, public_ips
def list_resource_groups(conn=None, call=None): # pylint: disable=unused-argument
'''
List resource groups associated with the account

View file

@ -1071,10 +1071,10 @@ def query(action=None,
timenow = datetime.datetime.utcnow()
timestamp = timenow.strftime('%a, %d %b %Y %H:%M:%S %Z').strip()
with salt.utils.files.fopen(ssh_keyfile, 'r') as kh_:
rsa_key = RSA.importKey(kh_)
rsa_key = RSA.importKey(kh_.read())
rsa_ = PKCS1_v1_5.new(rsa_key)
hash_ = SHA256.new()
hash_.update(timestamp)
hash_.update(timestamp.encode(__salt_system_encoding__))
signed = base64.b64encode(rsa_.sign(hash_))
keyid = '/{0}/keys/{1}'.format(user.split('/')[0], ssh_keyname)
@ -1085,7 +1085,7 @@ def query(action=None,
'Date': timestamp,
'Authorization': 'Signature keyId="{0}",algorithm="rsa-sha256" {1}'.format(
keyid,
signed
signed.decode(__salt_system_encoding__)
),
}

View file

@ -135,6 +135,14 @@ Alternatively, one could use the private IP to connect by specifying:
ssh_interface: private_ips
.. note::
When using floating ips from networks, if the OpenStack driver is unable to
allocate a new ip address for the server, it will check that for
unassociated ip addresses in the floating ip pool. If SaltCloud is running
in parallel mode, it is possible that more than one server will attempt to
use the same ip address.
'''
# Import python libs
@ -854,40 +862,43 @@ def _assign_floating_ips(vm_, conn, kwargs):
pool = OpenStack_1_1_FloatingIpPool(
net['floating'], conn.connection
)
for idx in pool.list_floating_ips():
if idx.node_id is None:
floating.append(idx)
try:
floating.append(pool.create_floating_ip())
except Exception as e:
log.debug('Cannot allocate IP from floating pool \'%s\'. Checking for unassociated ips.',
net['floating'])
for idx in pool.list_floating_ips():
if idx.node_id is None:
floating.append(idx)
break
if not floating:
try:
floating.append(pool.create_floating_ip())
except Exception as e:
raise SaltCloudSystemExit(
'Floating pool \'{0}\' does not have any more '
'please create some more or use a different '
'pool.'.format(net['floating'])
)
raise SaltCloudSystemExit(
'There are no more floating IP addresses '
'available, please create some more'
)
# otherwise, attempt to obtain list without specifying pool
# this is the same as 'nova floating-ip-list'
elif ssh_interface(vm_) != 'private_ips':
try:
# This try/except is here because it appears some
# *cough* Rackspace *cough*
# OpenStack providers return a 404 Not Found for the
# floating ip pool URL if there are no pools setup
pool = OpenStack_1_1_FloatingIpPool(
'', conn.connection
)
for idx in pool.list_floating_ips():
if idx.node_id is None:
floating.append(idx)
try:
floating.append(pool.create_floating_ip())
except Exception as e:
log.debug('Cannot allocate IP from the default floating pool. Checking for unassociated ips.')
for idx in pool.list_floating_ips():
if idx.node_id is None:
floating.append(idx)
break
if not floating:
try:
floating.append(pool.create_floating_ip())
except Exception as e:
raise SaltCloudSystemExit(
'There are no more floating IP addresses '
'available, please create some more'
)
log.warning(
'There are no more floating IP addresses '
'available, please create some more if necessary'
)
except Exception as e:
if str(e).startswith('404'):
pass

View file

@ -151,7 +151,7 @@ def avail_locations(conn=None, call=None):
ret[img_name] = {}
for attr in dir(img):
if attr.startswith('_'):
if attr.startswith('_') or attr == 'driver':
continue
attr_value = getattr(img, attr)
@ -188,7 +188,7 @@ def avail_images(conn=None, call=None):
ret[img_name] = {}
for attr in dir(img):
if attr.startswith('_'):
if attr.startswith('_') or attr in ('driver', 'get_uuid'):
continue
attr_value = getattr(img, attr)
if isinstance(attr_value, string_types) and not six.PY3:
@ -223,7 +223,7 @@ def avail_sizes(conn=None, call=None):
ret[size_name] = {}
for attr in dir(size):
if attr.startswith('_'):
if attr.startswith('_') or attr in ('driver', 'get_uuid'):
continue
try:

View file

@ -353,7 +353,7 @@ VALID_OPTS = {
# The TCP port on which minion events should be pulled if ipc_mode is TCP
'tcp_pull_port': int,
# The TCP port on which events for the master should be pulled if ipc_mode is TCP
# The TCP port on which events for the master should be published if ipc_mode is TCP
'tcp_master_pub_port': int,
# The TCP port on which events for the master should be pulled if ipc_mode is TCP

View file

@ -50,8 +50,8 @@ def start(docker_url='unix://var/run/docker.sock',
.. code-block:: yaml
engines:
docker_events:
docker_url: unix://var/run/docker.sock
- docker_events:
docker_url: unix://var/run/docker.sock
The config above sets up engines to listen
for events from the Docker daemon and publish

View file

@ -14,25 +14,25 @@ keys make the engine interactive.
.. code-block:: yaml
engines:
- hipchat:
api_url: http://api.hipchat.myteam.com
token: 'XXXXXX'
room: 'salt'
control: True
valid_users:
- SomeUser
valid_commands:
- test.ping
- cmd.run
- list_jobs
- list_commands
aliases:
list_jobs:
cmd: jobs.list_jobs
list_commands:
cmd: pillar.get salt:engines:hipchat:valid_commands target=saltmaster tgt_type=list
max_rooms: 0
wait_time: 1
- hipchat:
api_url: http://api.hipchat.myteam.com
token: 'XXXXXX'
room: 'salt'
control: True
valid_users:
- SomeUser
valid_commands:
- test.ping
- cmd.run
- list_jobs
- list_commands
aliases:
list_jobs:
cmd: jobs.list_jobs
list_commands:
cmd: pillar.get salt:engines:hipchat:valid_commands target=saltmaster
max_rooms: 0
wait_time: 1
'''
from __future__ import absolute_import

View file

@ -12,13 +12,13 @@ them onto a logstash endpoint via HTTP requests.
engines:
- http_logstash:
url: http://blabla.com/salt-stuff
tags:
- salt/job/*/new
- salt/job/*/ret/*
funs:
- probes.results
- bgp.config
url: http://blabla.com/salt-stuff
tags:
- salt/job/*/new
- salt/job/*/ret/*
funs:
- probes.results
- bgp.config
'''
from __future__ import absolute_import

View file

@ -24,6 +24,9 @@ master config.
:configuration:
Example configuration
.. code-block:: yaml
engines:
- logentries:
endpoint: data.logentries.com

View file

@ -8,6 +8,9 @@ them onto a logstash endpoint.
:configuration:
Example configuration
.. code-block:: yaml
engines:
- logstash:
host: log.my_network.com

View file

@ -7,10 +7,10 @@ Example Config in Master or Minion config
.. code-block:: yaml
engines:
reactor:
refresh_interval: 60
worker_threads: 10
worker_hwm: 10000
- reactor:
refresh_interval: 60
worker_threads: 10
worker_hwm: 10000
reactor:
- 'salt/cloud/*/destroyed':

View file

@ -8,6 +8,9 @@ events based on the channels they are subscribed to.
:configuration:
Example configuration
.. code-block:: yaml
engines:
- redis_sentinel:
hosts:

View file

@ -18,70 +18,73 @@ the saltmaster's minion pillar.
.. versionadded: 2016.3.0
:configuration: Example configuration using only a "default" group. The default group is not special. In addition, other groups are being loaded from pillars
:configuration: Example configuration using only a "default" group. The default group is not special.
In addition, other groups are being loaded from pillars.
.. code-block:: yaml
.. code-block:: yaml
engines:
slack:
token: 'xoxb-xxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx'
control: True
fire_all: False
groups_pillar_name: "slack_engine:groups_pillar"
groups:
default:
users:
- *
commands:
- test.ping
- cmd.run
- list_jobs
- list_commands
aliases:
list_jobs:
cmd: jobs.list_jobs
list_commands:
cmd: pillar.get salt:engines:slack:valid_commands target=saltmaster tgt_type=list
default_target:
target: saltmaster
tgt_type: glob
targets:
test.ping:
target: '*'
tgt_type: glob
cmd.run:
target: saltmaster
tgt_type: list
engines:
- slack:
token: 'xoxb-xxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx'
control: True
fire_all: False
groups_pillar_name: "slack_engine:groups_pillar"
groups:
default:
users:
- *
commands:
- test.ping
- cmd.run
- list_jobs
- list_commands
aliases:
list_jobs:
cmd: jobs.list_jobs
list_commands:
cmd: pillar.get salt:engines:slack:valid_commands target=saltmaster tgt_type=list
default_target:
target: saltmaster
tgt_type: glob
targets:
test.ping:
target: '*'
tgt_type: glob
cmd.run:
target: saltmaster
tgt_type: list
:configuration: Example configuration using the "default" group and a non-default group and a pillar that will be merged in
If the user is '*' (without the quotes) then the group's users or commands will match all users as appropriate
:configuration: Example configuration using the "default" group and a non-default group and a pillar that will be merged in
If the user is '*' (without the quotes) then the group's users or commands will match all users as appropriate
.. versionadded: 2017.7.0
.. versionadded: 2017.7.0
engines:
slack:
groups_pillar: slack_engine_pillar
token: 'xoxb-xxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx'
control: True
fire_all: True
tag: salt/engines/slack
groups_pillar_name: "slack_engine:groups_pillar"
groups:
default:
valid_users:
- *
valid_commands:
- test.ping
aliases:
list_jobs:
cmd: jobs.list_jobs
list_commands:
cmd: pillar.get salt:engines:slack:valid_commands target=saltmaster tgt_type=list
gods:
users:
- garethgreenaway
commands:
- *
.. code-block:: yaml
engines:
- slack:
groups_pillar: slack_engine_pillar
token: 'xoxb-xxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx'
control: True
fire_all: True
tag: salt/engines/slack
groups_pillar_name: "slack_engine:groups_pillar"
groups:
default:
valid_users:
- *
valid_commands:
- test.ping
aliases:
list_jobs:
cmd: jobs.list_jobs
list_commands:
cmd: pillar.get salt:engines:slack:valid_commands target=saltmaster tgt_type=list
gods:
users:
- garethgreenaway
commands:
- *
:depends: slackclient
@ -707,7 +710,7 @@ def run_command_async(msg):
log.debug("Command {} will run via runner_functions".format(cmd))
# pylint is tripping
# pylint: disable=missing-whitespace-after-comma
job_id_dict = runner.async(cmd, {"args":args, "kwargs":kwargs})
job_id_dict = runner.async(cmd, {"args": args, "kwargs": kwargs})
job_id = job_id_dict['jid']
# Default to trying to run as a client module.
@ -716,7 +719,7 @@ def run_command_async(msg):
log.debug("Command {} will run via local.cmd_async, targeting {}".format(cmd, target))
log.debug("Running {}, {}, {}, {}, {}".format(str(target), cmd, args, kwargs, str(tgt_type)))
# according to https://github.com/saltstack/salt-api/issues/164, tgt_type has changed to expr_form
job_id = local.cmd_async(str(target), cmd, arg=args, kwargs=kwargs, expr_form=str(tgt_type))
job_id = local.cmd_async(str(target), cmd, arg=args, kwargs=kwargs, tgt_type=str(tgt_type))
log.info("ret from local.cmd_async is {}".format(job_id))
return job_id

View file

@ -2,7 +2,7 @@
'''
Subversion Fileserver Backend
After enabling this backend, branches, and tags in a remote subversion
After enabling this backend, branches and tags in a remote subversion
repository are exposed to salt as different environments. To enable this
backend, add ``svn`` to the :conf_master:`fileserver_backend` option in the
Master config file.
@ -719,7 +719,7 @@ def file_hash(load, fnd):
def _file_lists(load, form):
'''
Return a dict containing the file lists for files, dirs, emtydirs and symlinks
Return a dict containing the file lists for files, dirs, emptydirs and symlinks
'''
if 'env' in load:
salt.utils.warn_until(

View file

@ -1010,28 +1010,20 @@ def _windows_platform_data():
os_release = platform.release()
kernel_version = platform.version()
info = salt.utils.win_osinfo.get_os_version_info()
server = {'Vista': '2008Server',
'7': '2008ServerR2',
'8': '2012Server',
'8.1': '2012ServerR2',
'10': '2016Server'}
# Starting with Python 2.7.12 and 3.5.2 the `platform.uname()` function
# started reporting the Desktop version instead of the Server version on
# Server versions of Windows, so we need to look those up
# Check for Python >=2.7.12 or >=3.5.2
ver = pythonversion()['pythonversion']
if ((six.PY2 and
salt.utils.compare_versions(ver, '>=', [2, 7, 12, 'final', 0]))
or
(six.PY3 and
salt.utils.compare_versions(ver, '>=', [3, 5, 2, 'final', 0]))):
# (Product Type 1 is Desktop, Everything else is Server)
if info['ProductType'] > 1:
server = {'Vista': '2008Server',
'7': '2008ServerR2',
'8': '2012Server',
'8.1': '2012ServerR2',
'10': '2016Server'}
os_release = server.get(os_release,
'Grain not found. Update lookup table '
'in the `_windows_platform_data` '
'function in `grains\\core.py`')
# So, if you find a Server Platform that's a key in the server
# dictionary, then lookup the actual Server Release.
# (Product Type 1 is Desktop, Everything else is Server)
if info['ProductType'] > 1 and os_release in server:
os_release = server[os_release]
service_pack = None
if info['ServicePackMajor'] > 0:

View file

@ -195,7 +195,7 @@ def minion_mods(
generated modules in __context__
:param dict utils: Utility functions which should be made available to
Salt modules in __utils__. See `utils_dir` in
Salt modules in __utils__. See `utils_dirs` in
salt.config for additional information about
configuration.

View file

@ -306,14 +306,16 @@ def load_args_and_kwargs(func, args, data=None, ignore_invalid=False):
else:
string_kwarg = salt.utils.args.parse_input([arg], condition=False)[1] # pylint: disable=W0632
if string_kwarg:
log.critical(
'String kwarg(s) %s passed to '
'salt.minion.load_args_and_kwargs(). This is no longer '
'supported, so the kwarg(s) will be ignored. Arguments '
'passed to salt.minion.load_args_and_kwargs() should be '
'passed to salt.utils.args.parse_input() first to load '
'and condition them properly.', string_kwarg
)
if argspec.keywords or next(six.iterkeys(string_kwarg)) in argspec.args:
# Function supports **kwargs or is a positional argument to
# the function.
_kwargs.update(string_kwarg)
else:
# **kwargs not in argspec and parsed argument name not in
# list of positional arguments. This keyword argument is
# invalid.
for key, val in six.iteritems(string_kwarg):
invalid_kwargs.append('{0}={1}'.format(key, val))
else:
_args.append(arg)

View file

@ -1,6 +1,10 @@
# -*- coding: utf-8 -*-
'''
Compendium of generic DNS utilities
Compendium of generic DNS utilities.
.. note::
Some functions in the ``dnsutil`` execution module depend on ``dig``.
'''
# Import python libs
from __future__ import absolute_import
@ -232,7 +236,7 @@ def check_ip(ip_addr):
.. code-block:: bash
salt ns1 dig.check_ip 127.0.0.1
salt ns1 dnsutil.check_ip 127.0.0.1
'''
if _has_dig():
return __salt__['dig.check_ip'](ip_addr)
@ -242,7 +246,7 @@ def check_ip(ip_addr):
def A(host, nameserver=None):
'''
Return the A record(s) for `host`.
Return the A record(s) for ``host``.
Always returns a list.
@ -267,7 +271,7 @@ def A(host, nameserver=None):
def AAAA(host, nameserver=None):
'''
Return the AAAA record(s) for `host`.
Return the AAAA record(s) for ``host``.
Always returns a list.
@ -302,7 +306,7 @@ def NS(domain, resolve=True, nameserver=None):
.. code-block:: bash
salt ns1 dig.NS google.com
salt ns1 dnsutil.NS google.com
'''
if _has_dig():
@ -323,7 +327,7 @@ def SPF(domain, record='SPF', nameserver=None):
.. code-block:: bash
salt ns1 dig.SPF google.com
salt ns1 dnsutil.SPF google.com
'''
if _has_dig():
return __salt__['dig.SPF'](domain, record, nameserver)
@ -346,7 +350,7 @@ def MX(domain, resolve=False, nameserver=None):
.. code-block:: bash
salt ns1 dig.MX google.com
salt ns1 dnsutil.MX google.com
'''
if _has_dig():
return __salt__['dig.MX'](domain, resolve, nameserver)

View file

@ -978,6 +978,10 @@ def login(*registries):
cmd = ['docker', 'login', '-u', username, '-p', password]
if registry.lower() != 'hub':
cmd.append(registry)
log.debug(
'Attempting to login to docker registry \'%s\' as user \'%s\'',
registry, username
)
login_cmd = __salt__['cmd.run_all'](
cmd,
python_shell=False,

View file

@ -185,15 +185,24 @@ def _git_run(command, cwd=None, user=None, password=None, identity=None,
identity = [identity]
# try each of the identities, independently
tmp_identity_file = None
for id_file in identity:
if 'salt://' in id_file:
_id_file = id_file
id_file = __salt__['cp.cache_file'](id_file, saltenv)
with salt.utils.files.set_umask(0o077):
tmp_identity_file = salt.utils.mkstemp()
_id_file = id_file
id_file = __salt__['cp.get_file'](id_file,
tmp_identity_file,
saltenv)
if not id_file:
log.error('identity {0} does not exist.'.format(_id_file))
__salt__['file.remove'](tmp_identity_file)
continue
else:
__salt__['file.set_mode'](id_file, '0600')
if user:
os.chown(id_file,
__salt__['file.user_to_uid'](user),
-1)
else:
if not __salt__['file.file_exists'](id_file):
missing_keys.append(id_file)
@ -264,6 +273,11 @@ def _git_run(command, cwd=None, user=None, password=None, identity=None,
if not salt.utils.is_windows() and 'GIT_SSH' in env:
os.remove(env['GIT_SSH'])
# Cleanup the temporary identity file
if tmp_identity_file and os.path.exists(tmp_identity_file):
log.debug('Removing identity file {0}'.format(tmp_identity_file))
__salt__['file.remove'](tmp_identity_file)
# If the command was successful, no need to try additional IDs
if result['retcode'] == 0:
return result

View file

@ -262,7 +262,7 @@ def create_keytab(name, keytab, enctypes=None):
.. code-block:: bash
salt 'kdc.example.com' host/host1.example.com host1.example.com.keytab
salt 'kdc.example.com' kerberos.create_keytab host/host1.example.com host1.example.com.keytab
'''
ret = {}

View file

@ -569,33 +569,33 @@ def install(name=None,
continue
targets.append('{0}{1}{2}'.format(param, prefix, verstr))
if wildcards:
# Resolve wildcard matches
_available = list_repo_pkgs(*[x[0] for x in wildcards], refresh=refresh)
for pkgname, verstr in wildcards:
candidates = _available.get(pkgname, [])
match = salt.utils.fnmatch_multiple(candidates, verstr)
if match is not None:
targets.append('='.join((pkgname, match)))
else:
errors.append(
'No version matching \'{0}\' found for package \'{1}\' '
'(available: {2})'.format(
verstr,
pkgname,
', '.join(candidates) if candidates else 'none'
if wildcards:
# Resolve wildcard matches
_available = list_repo_pkgs(*[x[0] for x in wildcards], refresh=refresh)
for pkgname, verstr in wildcards:
candidates = _available.get(pkgname, [])
match = salt.utils.fnmatch_multiple(candidates, verstr)
if match is not None:
targets.append('='.join((pkgname, match)))
else:
errors.append(
'No version matching \'{0}\' found for package \'{1}\' '
'(available: {2})'.format(
verstr,
pkgname,
', '.join(candidates) if candidates else 'none'
)
)
)
if refresh:
try:
# Prevent a second refresh when we run the install command
cmd.remove('-y')
except ValueError:
# Shouldn't happen since we only add -y when refresh is True,
# but just in case that code above is inadvertently changed,
# don't let this result in a traceback.
pass
if refresh:
try:
# Prevent a second refresh when we run the install command
cmd.remove('-y')
except ValueError:
# Shouldn't happen since we only add -y when refresh is True,
# but just in case that code above is inadvertently changed,
# don't let this result in a traceback.
pass
if not errors:
cmd.extend(targets)

View file

@ -346,9 +346,10 @@ def summary():
def plugin_sync():
'''
Runs a plugin synch between the puppet master and agent
Runs a plugin sync between the puppet master and agent
CLI Example:
.. code-block:: bash
salt '*' puppet.plugin_sync

View file

@ -150,7 +150,9 @@ class Registry(object): # pylint: disable=R0903
_winreg.REG_DWORD: 'REG_DWORD',
_winreg.REG_EXPAND_SZ: 'REG_EXPAND_SZ',
_winreg.REG_MULTI_SZ: 'REG_MULTI_SZ',
_winreg.REG_SZ: 'REG_SZ'
_winreg.REG_SZ: 'REG_SZ',
# REG_QWORD isn't in the winreg library
11: 'REG_QWORD'
}
self.opttype_reverse = {
_winreg.REG_OPTION_NON_VOLATILE: 'REG_OPTION_NON_VOLATILE',

View file

@ -265,14 +265,14 @@ def _get_opts(**kwargs):
if 'saltenv' in kwargs:
saltenv = kwargs['saltenv']
if not isinstance(saltenv, six.string_types):
if saltenv is not None and not isinstance(saltenv, six.string_types):
opts['environment'] = str(kwargs['saltenv'])
else:
opts['environment'] = kwargs['saltenv']
if 'pillarenv' in kwargs:
pillarenv = kwargs['pillarenv']
if not isinstance(pillarenv, six.string_types):
if pillarenv is not None and not isinstance(pillarenv, six.string_types):
opts['pillarenv'] = str(kwargs['pillarenv'])
else:
opts['pillarenv'] = kwargs['pillarenv']

View file

@ -312,6 +312,18 @@ def arg_repr(*args, **kwargs):
return {"args": repr(args), "kwargs": repr(kwargs)}
def arg_clean(*args, **kwargs):
'''
Like test.arg but cleans kwargs of the __pub* items
CLI Example:
.. code-block:: bash
salt '*' test.arg_clean 1 "two" 3.1 txt="hello" wow='{a: 1, b: "hello"}'
'''
return dict(args=args, kwargs=salt.utils.clean_kwargs(**kwargs))
def fib(num):
'''
Return the num-th Fibonacci number, and the time it took to compute in

View file

@ -1687,9 +1687,6 @@ def check_perms(path,
perms = changes[user]['perms']
try:
log.debug('*' * 68)
log.debug(perms)
log.debug('*' * 68)
salt.utils.win_dacl.set_permissions(
path, user, perms, 'deny', applies_to)
ret['changes']['deny_perms'][user] = changes[user]

View file

@ -1374,10 +1374,19 @@ def create_certificate(
['listen_in', 'preqrequired', '__prerequired__']:
kwargs.pop(ignore, None)
cert_txt = __salt__['publish.publish'](
certs = __salt__['publish.publish'](
tgt=ca_server,
fun='x509.sign_remote_certificate',
arg=str(kwargs))[ca_server]
arg=str(kwargs))
if not any(certs):
raise salt.exceptions.SaltInvocationError(
'ca_server did not respond'
' salt master must permit peers to'
' call the sign_remote_certificate function.')
cert_txt = certs[ca_server]
if path:
return write_pem(
text=cert_txt,

View file

@ -129,7 +129,7 @@ def targets(tgt, tgt_type='glob', **kwargs): # pylint: disable=W0613
'host': ('ipv6-private', 'ipv6-global', 'ipv4-private', 'ipv4-public')
})
if isinstance(roster_order, (tuple, list)):
salt.utils.warn_until('Oxygen',
salt.utils.warn_until('Fluorine',
'Using legacy syntax for roster_order')
roster_order = {
'host': roster_order
@ -137,7 +137,7 @@ def targets(tgt, tgt_type='glob', **kwargs): # pylint: disable=W0613
for config_key, order in roster_order.items():
for idx, key in enumerate(order):
if key in ('public', 'private', 'local'):
salt.utils.warn_until('Oxygen',
salt.utils.warn_until('Fluorine',
'roster_order {0} will include IPv6 soon. '
'Set order to ipv4-{0} if needed.'.format(key))
order[idx] = 'ipv4-' + key

View file

@ -86,7 +86,8 @@ def update(branch=None, repo=None):
else:
pillar = salt.utils.gitfs.GitPillar(__opts__)
pillar.init_remotes(pillar_conf,
salt.pillar.git_pillar.PER_REMOTE_OVERRIDES)
salt.pillar.git_pillar.PER_REMOTE_OVERRIDES,
salt.pillar.git_pillar.PER_REMOTE_ONLY)
for remote in pillar.remotes:
# Skip this remote if it doesn't match the search criteria
if branch is not None:

View file

@ -653,6 +653,7 @@ def versions():
return ret
labels = {
-2: 'Minion offline',
-1: 'Minion requires update',
0: 'Up to date',
1: 'Minion newer than master',
@ -664,12 +665,19 @@ def versions():
master_version = salt.version.__saltstack_version__
for minion in minions:
minion_version = salt.version.SaltStackVersion.parse(minions[minion])
ver_diff = cmp(minion_version, master_version)
if not minions[minion]:
minion_version = False
ver_diff = -2
else:
minion_version = salt.version.SaltStackVersion.parse(minions[minion])
ver_diff = cmp(minion_version, master_version)
if ver_diff not in version_status:
version_status[ver_diff] = {}
version_status[ver_diff][minion] = minion_version.string
if minion_version:
version_status[ver_diff][minion] = minion_version.string
else:
version_status[ver_diff][minion] = minion_version
# Add version of Master to output
version_status[2] = master_version.string

View file

@ -1436,7 +1436,10 @@ def absent(name):
ret['comment'] = 'File {0} is set for removal'.format(name)
return ret
try:
__salt__['file.remove'](name)
if salt.utils.is_windows():
__salt__['file.remove'](name, force=True)
else:
__salt__['file.remove'](name)
ret['comment'] = 'Removed file {0}'.format(name)
ret['changes']['removed'] = name
return ret
@ -2452,12 +2455,16 @@ def managed(name,
if sfn and os.path.isfile(sfn):
os.remove(sfn)
return ret
if sfn and os.path.isfile(sfn):
os.remove(sfn)
# Since we generated a new tempfile and we are not returning here
# lets change the original sfn to the new tempfile or else we will
# get file not found
if sfn and os.path.isfile(sfn):
os.remove(sfn)
sfn = tmp_filename
sfn = tmp_filename
else:
ret = {'changes': {},
'comment': '',
@ -3818,12 +3825,13 @@ def replace(name,
A regular expression, to be matched using Python's
:py:func:`~re.search`.
..note::
.. note::
If you need to match a literal string that contains regex special
characters, you may want to use salt's custom Jinja filter,
``escape_regex``.
..code-block:: jinja
.. code-block:: jinja
{{ 'http://example.com?foo=bar%20baz' | escape_regex }}

View file

@ -2214,7 +2214,7 @@ def detached(name,
# Determine if supplied ref is a hash
remote_rev_type = 'ref'
if len(ref) <= 40 \
if len(rev) <= 40 \
and all(x in string.hexdigits for x in rev):
rev = rev.lower()
remote_rev_type = 'hash'
@ -2420,7 +2420,7 @@ def detached(name,
https_pass=https_pass,
ignore_retcode=False)
if 'refs/remotes/'+remote+'/'+ref in all_remote_refs:
if 'refs/remotes/'+remote+'/'+rev in all_remote_refs:
checkout_commit_id = all_remote_refs['refs/remotes/' + remote + '/' + rev]
elif 'refs/tags/' + rev in all_remote_refs:
checkout_commit_id = all_remote_refs['refs/tags/' + rev]

View file

@ -109,7 +109,7 @@ def managed(name,
template_mode='755',
saltenv=None,
template_engine='jinja',
skip_verify=True,
skip_verify=False,
defaults=None,
test=False,
commit=True,
@ -194,10 +194,12 @@ def managed(name,
- :mod:`py<salt.renderers.py>`
- :mod:`wempy<salt.renderers.wempy>`
skip_verify: True
skip_verify: False
If ``True``, hash verification of remote file sources (``http://``, ``https://``, ``ftp://``) will be skipped,
and the ``source_hash`` argument will be ignored.
.. versionchanged:: 2017.7.1
test: False
Dry run? If set to ``True``, will apply the config, discard and return the changes. Default: ``False``
(will commit the changes on the device).

View file

@ -1434,6 +1434,15 @@ def installed(
'result': True,
'comment': 'No packages to install provided'}
# If just a name (and optionally a version) is passed, just pack them into
# the pkgs argument.
if name and not any((pkgs, sources)):
if version:
pkgs = [{name: version}]
version = None
else:
pkgs = [name]
kwargs['saltenv'] = __env__
refresh = salt.utils.pkg.check_refresh(__opts__, refresh)
if not isinstance(pkg_verify, list):
@ -1600,7 +1609,7 @@ def installed(
if salt.utils.is_freebsd():
force = True # Downgrades need to be forced.
try:
pkg_ret = __salt__['pkg.install'](name,
pkg_ret = __salt__['pkg.install'](name=None,
refresh=refresh,
version=version,
force=force,

View file

@ -160,9 +160,13 @@ def row_absent(name, db, table, where_sql, where_args=None):
changes['changes']['old'] = rows[0]
else:
cursor = conn.execute("DELETE FROM `" +
table + "` WHERE " + where_sql,
where_args)
if where_args is None:
cursor = conn.execute("DELETE FROM `" +
table + "` WHERE " + where_sql)
else:
cursor = conn.execute("DELETE FROM `" +
table + "` WHERE " + where_sql,
where_args)
conn.commit()
if cursor.rowcount == 1:
changes['result'] = True

View file

@ -495,6 +495,7 @@ def container_setting(name, container, settings=None):
processModel.maxProcesses: 1
processModel.userName: TestUser
processModel.password: TestPassword
processModel.identityType: SpecificUser
Example of usage for the ``Sites`` container:

View file

@ -1451,6 +1451,24 @@ def expr_match(line, expr):
def check_whitelist_blacklist(value, whitelist=None, blacklist=None):
'''
Check a whitelist and/or blacklist to see if the value matches it.
value
The item to check the whitelist and/or blacklist against.
whitelist
The list of items that are white-listed. If ``value`` is found
in the whitelist, then the function returns ``True``. Otherwise,
it returns ``False``.
blacklist
The list of items that are black-listed. If ``value`` is found
in the blacklist, then the function returns ``False``. Otherwise,
it returns ``True``.
If both a whitelist and a blacklist are provided, value membership
in the blacklist will be examined first. If the value is not found
in the blacklist, then the whitelist is checked. If the value isn't
found in the whitelist, the function returns ``False``.
'''
if blacklist is not None:
if not hasattr(blacklist, '__iter__'):

View file

@ -59,6 +59,7 @@ import fnmatch
import hashlib
import logging
import datetime
import sys
from collections import MutableMapping
from multiprocessing.util import Finalize
from salt.ext.six.moves import range
@ -1159,6 +1160,16 @@ class EventReturn(salt.utils.process.SignalHandlingMultiprocessingProcess):
A dedicated process which listens to the master event bus and queues
and forwards events to the specified returner.
'''
def __new__(cls, *args, **kwargs):
if sys.platform.startswith('win'):
# This is required for Windows. On Linux, when a process is
# forked, the module namespace is copied and the current process
# gets all of sys.modules from where the fork happens. This is not
# the case for Windows.
import salt.minion
instance = super(EventReturn, cls).__new__(cls, *args, **kwargs)
return instance
def __init__(self, opts, log_queue=None):
'''
Initialize the EventReturn system

View file

@ -462,8 +462,8 @@ def query(url,
# We want to use curl_http if we have a proxy defined
if proxy_host and proxy_port:
if HAS_CURL_HTTPCLIENT is False:
ret['error'] = ('proxy_host and proxy_port has been set. This requires pycurl, but the '
'pycurl library does not seem to be installed')
ret['error'] = ('proxy_host and proxy_port has been set. This requires pycurl and tornado, '
'but the libraries does not seem to be installed')
log.error(ret['error'])
return ret

View file

@ -274,6 +274,8 @@ class ReactWrap(object):
try:
f_call = salt.utils.format_call(l_fun, low)
kwargs = f_call.get('kwargs', {})
if 'kwarg' not in kwargs:
kwargs['kwarg'] = {}
# TODO: Setting the user doesn't seem to work for actual remote publishes
if low['state'] in ('runner', 'wheel'):

View file

@ -333,6 +333,7 @@ import logging
import errno
import random
import yaml
import copy
# Import Salt libs
import salt.config
@ -844,7 +845,7 @@ class Schedule(object):
if argspec.keywords:
# this function accepts **kwargs, pack in the publish data
for key, val in six.iteritems(ret):
kwargs['__pub_{0}'.format(key)] = val
kwargs['__pub_{0}'.format(key)] = copy.deepcopy(val)
ret['return'] = self.functions[func](*args, **kwargs)
@ -1132,21 +1133,28 @@ class Schedule(object):
log.error('Invalid date string {0}. '
'Ignoring job {1}.'.format(i, job))
continue
when = int(time.mktime(when__.timetuple()))
if when >= now:
_when.append(when)
_when.append(int(time.mktime(when__.timetuple())))
if data['_splay']:
_when.append(data['_splay'])
# Sort the list of "whens" from earlier to later schedules
_when.sort()
for i in _when:
if i < now and len(_when) > 1:
# Remove all missed schedules except the latest one.
# We need it to detect if it was triggered previously.
_when.remove(i)
if _when:
# Grab the first element
# which is the next run time
# Grab the first element, which is the next run time or
# last scheduled time in the past.
when = _when[0]
if '_run' not in data:
data['_run'] = True
# Prevent run of jobs from the past
data['_run'] = bool(when >= now)
if not data['_next_fire_time']:
data['_next_fire_time'] = when

View file

@ -73,6 +73,9 @@ class AliasedLoader(object):
def __getattr__(self, name):
return getattr(self.wrapped, name)
def __contains__(self, name):
return name in self.wrapped
class AliasedModule(object):
'''

View file

@ -4,6 +4,7 @@ from __future__ import absolute_import
import warnings
# Import third party libs
import re
import yaml
from yaml.nodes import MappingNode, SequenceNode
from yaml.constructor import ConstructorError
@ -101,6 +102,11 @@ class SaltYamlSafeLoader(yaml.SafeLoader, object):
# an empty string. Change it to '0'.
if node.value == '':
node.value = '0'
elif node.tag == 'tag:yaml.org,2002:str':
# If any string comes in as a quoted unicode literal, eval it into
# the proper unicode string type.
if re.match(r'^u([\'"]).+\1$', node.value, flags=re.IGNORECASE):
node.value = eval(node.value, {}, {}) # pylint: disable=W0123
return super(SaltYamlSafeLoader, self).construct_scalar(node)
def flatten_mapping(self, node):

View file

@ -645,18 +645,22 @@ def system_information():
release = platform.release()
if platform.win32_ver()[0]:
import win32api # pylint: disable=3rd-party-module-not-gated
if ((sys.version_info.major == 2 and sys.version_info >= (2, 7, 12)) or
(sys.version_info.major == 3 and sys.version_info >= (3, 5, 2))):
if win32api.GetVersionEx(1)[8] > 1:
server = {'Vista': '2008Server',
'7': '2008ServerR2',
'8': '2012Server',
'8.1': '2012ServerR2',
'10': '2016Server'}
release = server.get(platform.release(),
'UNKServer')
_, ver, sp, extra = platform.win32_ver()
version = ' '.join([release, ver, sp, extra])
server = {'Vista': '2008Server',
'7': '2008ServerR2',
'8': '2012Server',
'8.1': '2012ServerR2',
'10': '2016Server'}
# Starting with Python 2.7.12 and 3.5.2 the `platform.uname()` function
# started reporting the Desktop version instead of the Server version on
# Server versions of Windows, so we need to look those up
# So, if you find a Server Platform that's a key in the server
# dictionary, then lookup the actual Server Release.
# If this is a Server Platform then `GetVersionEx` will return a number
# greater than 1.
if win32api.GetVersionEx(1)[8] > 1 and release in server:
release = server[release]
_, ver, sp, extra = platform.win32_ver()
version = ' '.join([release, ver, sp, extra])
system = [
('system', platform.system()),

View file

@ -94,3 +94,25 @@ class StdTest(ModuleCase):
ret = self.client.cmd('minion', 'test.ping', full_return=True)
for mid, data in ret.items():
self.assertIn('retcode', data)
def test_cmd_arg_kwarg_parsing(self):
ret = self.client.cmd('minion', 'test.arg_clean',
arg=[
'foo',
'bar=off',
'baz={qux: 123}'
],
kwarg={
'quux': 'Quux',
})
self.assertEqual(ret['minion'], {
'args': ['foo'],
'kwargs': {
'bar': False,
'baz': {
'qux': 123,
},
'quux': 'Quux',
},
})

View file

@ -0,0 +1,10 @@
{% set salt_foo_bar_exist = 'foo.bar' in salt %}
{% set salt_test_ping_exist = 'test.ping' in salt %}
test-ping-exist:
test.succeed_without_changes:
- name: salt_test_ping_exist_{{ salt_test_ping_exist }}
foo-bar-not-exist:
test.succeed_without_changes:
- name: salt_foo_bar_exist_{{ salt_foo_bar_exist }}

View file

@ -41,7 +41,7 @@ def _git_version():
git_version = subprocess.Popen(
['git', '--version'],
shell=False,
close_fds=False if salt.utils.is_windows else True,
close_fds=False if salt.utils.is_windows() else True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE).communicate()[0]
except OSError:

View file

@ -21,3 +21,12 @@ class TestJinjaRenderer(ModuleCase):
ret = self.run_function('state.sls', ['jinja_dot_notation'])
for state_ret in ret.values():
self.assertTrue(state_ret['result'])
def test_salt_contains_function(self):
'''
Test if we are able to check if a function exists inside the "salt"
wrapper (AliasLoader) which is available on Jinja templates.
'''
ret = self.run_function('state.sls', ['jinja_salt_contains_function'])
for state_ret in ret.values():
self.assertTrue(state_ret['result'])

View file

@ -10,6 +10,7 @@ from tests.support.unit import skipIf, TestCase
from tests.support.mock import NO_MOCK, NO_MOCK_REASON, MagicMock, patch
# Import salt libs
import salt.utils
import salt.modules.pip as pip
from salt.exceptions import CommandExecutionError
@ -289,17 +290,23 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
mock_path.isdir.return_value = True
pkg = 'mock'
venv_path = '/test_env'
def join(*args):
return '/'.join(args)
return os.sep.join(args)
mock_path.join = join
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
if salt.utils.is_windows():
venv_path = 'c:\\test_env'
bin_path = os.path.join(venv_path, 'Scripts', 'pip.exe').encode('string-escape')
else:
venv_path = '/test_env'
bin_path = os.path.join(venv_path, 'bin', 'pip')
pip.install(pkg, bin_env=venv_path)
mock.assert_called_once_with(
[os.path.join(venv_path, 'bin', 'pip'), 'install', pkg],
env={'VIRTUAL_ENV': '/test_env'},
[bin_path, 'install', pkg],
env={'VIRTUAL_ENV': venv_path},
saltenv='base',
runas=None,
use_vt=False,

View file

@ -27,7 +27,7 @@ except ImportError:
PY2 = sys.version_info[0] == 2
# The following used to make sure we are not
# testing already existing data
# Note strftime retunrns a str, so we need to make it unicode
# Note strftime returns a str, so we need to make it unicode
TIMEINT = int(time.time())
if PY2:

View file

@ -161,6 +161,7 @@ class TimezoneModuleTestCase(TestCase, LoaderModuleMockMixin):
with patch('salt.modules.timezone._get_zone_aix', MagicMock(return_value=self.TEST_TZ)):
assert timezone.get_zone() == self.TEST_TZ
@skipIf(salt.utils.is_windows(), 'os.symlink not available in Windows')
@patch('salt.utils.which', MagicMock(return_value=False))
@patch('os.path.exists', MagicMock(return_value=True))
@patch('os.unlink', MagicMock())
@ -175,6 +176,7 @@ class TimezoneModuleTestCase(TestCase, LoaderModuleMockMixin):
name, args, kwargs = timezone.__salt__['file.sed'].mock_calls[0]
assert args == ('/etc/sysconfig/clock', '^ZONE=.*', 'ZONE="UTC"')
@skipIf(salt.utils.is_windows(), 'os.symlink not available in Windows')
@patch('salt.utils.which', MagicMock(return_value=False))
@patch('os.path.exists', MagicMock(return_value=True))
@patch('os.unlink', MagicMock())
@ -189,6 +191,7 @@ class TimezoneModuleTestCase(TestCase, LoaderModuleMockMixin):
name, args, kwargs = timezone.__salt__['file.sed'].mock_calls[0]
assert args == ('/etc/sysconfig/clock', '^TIMEZONE=.*', 'TIMEZONE="UTC"')
@skipIf(salt.utils.is_windows(), 'os.symlink not available in Windows')
@patch('salt.utils.which', MagicMock(return_value=False))
@patch('os.path.exists', MagicMock(return_value=True))
@patch('os.unlink', MagicMock())
@ -207,6 +210,7 @@ class TimezoneModuleTestCase(TestCase, LoaderModuleMockMixin):
name, args, kwargs = _fopen.return_value.__enter__.return_value.write.mock_calls[0]
assert args == ('UTC',)
@skipIf(salt.utils.is_windows(), 'os.symlink not available in Windows')
@patch('salt.utils.which', MagicMock(return_value=False))
@patch('os.path.exists', MagicMock(return_value=True))
@patch('os.unlink', MagicMock())
@ -225,6 +229,7 @@ class TimezoneModuleTestCase(TestCase, LoaderModuleMockMixin):
name, args, kwargs = _fopen.return_value.__enter__.return_value.write.mock_calls[0]
assert args == ('UTC',)
@skipIf(salt.utils.is_windows(), 'os.symlink not available in Windows')
@patch('salt.utils.which', MagicMock(return_value=True))
@patch('os.path.exists', MagicMock(return_value=True))
@patch('os.unlink', MagicMock())
@ -239,6 +244,7 @@ class TimezoneModuleTestCase(TestCase, LoaderModuleMockMixin):
with patch('salt.modules.timezone._timedatectl', MagicMock(return_value={'stdout': 'rtc in local tz:yes'})):
assert timezone.get_hwclock() == 'localtime'
@skipIf(salt.utils.is_windows(), 'os.symlink not available in Windows')
@patch('salt.utils.which', MagicMock(return_value=False))
@patch('os.path.exists', MagicMock(return_value=True))
@patch('os.unlink', MagicMock())
@ -254,6 +260,7 @@ class TimezoneModuleTestCase(TestCase, LoaderModuleMockMixin):
assert args == (['tail', '-n', '1', '/etc/adjtime'],)
assert kwarg == {'python_shell': False}
@skipIf(salt.utils.is_windows(), 'os.symlink not available in Windows')
@patch('salt.utils.which', MagicMock(return_value=False))
@patch('os.path.exists', MagicMock(return_value=True))
@patch('os.unlink', MagicMock())
@ -284,6 +291,7 @@ class TimezoneModuleTestCase(TestCase, LoaderModuleMockMixin):
assert args == (['tail', '-n', '1', '/etc/adjtime'],)
assert kwarg == {'python_shell': False}
@skipIf(salt.utils.is_windows(), 'os.symlink not available in Windows')
@patch('salt.utils.which', MagicMock(return_value=False))
@patch('os.path.exists', MagicMock(return_value=True))
@patch('os.unlink', MagicMock())
@ -299,6 +307,7 @@ class TimezoneModuleTestCase(TestCase, LoaderModuleMockMixin):
with patch('salt.utils.files.fopen', mock_open()):
assert timezone.get_hwclock() == 'localtime'
@skipIf(salt.utils.is_windows(), 'os.symlink not available in Windows')
@patch('salt.utils.which', MagicMock(return_value=False))
@patch('os.path.exists', MagicMock(return_value=True))
@patch('os.unlink', MagicMock())
@ -315,6 +324,7 @@ class TimezoneModuleTestCase(TestCase, LoaderModuleMockMixin):
with patch.dict(timezone.__grains__, {'os_family': ['AIX']}):
assert timezone.get_hwclock() == hwclock
@skipIf(salt.utils.is_windows(), 'os.symlink not available in Windows')
@patch('salt.utils.which', MagicMock(return_value=False))
@patch('os.path.exists', MagicMock(return_value=True))
@patch('os.unlink', MagicMock())
@ -330,6 +340,7 @@ class TimezoneModuleTestCase(TestCase, LoaderModuleMockMixin):
assert timezone.set_hwclock('forty two')
assert timezone.set_hwclock('UTC')
@skipIf(salt.utils.is_windows(), 'os.symlink not available in Windows')
@patch('salt.utils.which', MagicMock(return_value=False))
@patch('os.path.exists', MagicMock(return_value=True))
@patch('os.unlink', MagicMock())
@ -349,6 +360,7 @@ class TimezoneModuleTestCase(TestCase, LoaderModuleMockMixin):
assert args == (['rtc', '-z', 'GMT'],)
assert kwargs == {'python_shell': False}
@skipIf(salt.utils.is_windows(), 'os.symlink not available in Windows')
@patch('salt.utils.which', MagicMock(return_value=False))
@patch('os.path.exists', MagicMock(return_value=True))
@patch('os.unlink', MagicMock())
@ -365,6 +377,7 @@ class TimezoneModuleTestCase(TestCase, LoaderModuleMockMixin):
assert args == (['timezonectl', 'set-local-rtc', 'false'],)
assert kwargs == {'python_shell': False}
@skipIf(salt.utils.is_windows(), 'os.symlink not available in Windows')
@patch('salt.utils.which', MagicMock(return_value=False))
@patch('os.path.exists', MagicMock(return_value=True))
@patch('os.unlink', MagicMock())
@ -380,6 +393,7 @@ class TimezoneModuleTestCase(TestCase, LoaderModuleMockMixin):
name, args, kwargs = timezone.__salt__['file.sed'].mock_calls[0]
assert args == ('/etc/sysconfig/clock', '^ZONE=.*', 'ZONE="TEST_TIMEZONE"')
@skipIf(salt.utils.is_windows(), 'os.symlink not available in Windows')
@patch('salt.utils.which', MagicMock(return_value=False))
@patch('os.path.exists', MagicMock(return_value=True))
@patch('os.unlink', MagicMock())
@ -395,6 +409,7 @@ class TimezoneModuleTestCase(TestCase, LoaderModuleMockMixin):
name, args, kwargs = timezone.__salt__['file.sed'].mock_calls[0]
assert args == ('/etc/sysconfig/clock', '^TIMEZONE=.*', 'TIMEZONE="TEST_TIMEZONE"')
@skipIf(salt.utils.is_windows(), 'os.symlink not available in Windows')
@patch('salt.utils.which', MagicMock(return_value=False))
@patch('os.path.exists', MagicMock(return_value=True))
@patch('os.unlink', MagicMock())
@ -414,6 +429,7 @@ class TimezoneModuleTestCase(TestCase, LoaderModuleMockMixin):
name, args, kwargs = timezone.__salt__['file.sed'].mock_calls[1]
assert args == ('/etc/default/rcS', '^UTC=.*', 'UTC=no')
@skipIf(salt.utils.is_windows(), 'os.symlink not available in Windows')
@patch('salt.utils.which', MagicMock(return_value=False))
@patch('os.path.exists', MagicMock(return_value=True))
@patch('os.unlink', MagicMock())

View file

@ -72,6 +72,7 @@ class UserAddTestCase(TestCase, LoaderModuleMockMixin):
# 'getent' function tests: 2
@skipIf(HAS_PWD is False, 'The pwd module is not available')
def test_getent(self):
'''
Test if user.getent already have a value
@ -359,6 +360,7 @@ class UserAddTestCase(TestCase, LoaderModuleMockMixin):
# 'list_users' function tests: 1
@skipIf(HAS_PWD is False, 'The pwd module is not available')
def test_list_users(self):
'''
Test if it returns a list of all users

View file

@ -100,7 +100,7 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
def test_contents_pillar_doesnt_add_more_newlines(self):
# make sure the newline
pillar_value = 'i am the pillar value\n'
pillar_value = 'i am the pillar value{0}'.format(os.linesep)
self.run_contents_pillar(pillar_value, expected=pillar_value)
@ -167,7 +167,9 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
'file.user_to_uid': mock_empty,
'file.group_to_gid': mock_empty}):
'file.group_to_gid': mock_empty,
'user.info': mock_empty,
'user.current': mock_user}):
comt = ('User {0} does not exist. Group {1} does not exist.'.format(user, group))
ret.update({'comment': comt, 'name': name})
self.assertDictEqual(filestate.symlink(name, target, user=user,
@ -176,7 +178,9 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
'file.user_to_uid': mock_uid,
'file.group_to_gid': mock_gid,
'file.is_link': mock_f}):
'file.is_link': mock_f,
'user.info': mock_empty,
'user.current': mock_user}):
with patch.dict(filestate.__opts__, {'test': True}):
with patch.object(os.path, 'exists', mock_f):
comt = ('Symlink {0} to {1}'
@ -191,7 +195,9 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
'file.user_to_uid': mock_uid,
'file.group_to_gid': mock_gid,
'file.is_link': mock_f}):
'file.is_link': mock_f,
'user.info': mock_empty,
'user.current': mock_user}):
with patch.dict(filestate.__opts__, {'test': False}):
with patch.object(os.path, 'isdir', mock_f):
with patch.object(os.path, 'exists', mock_f):
@ -207,7 +213,9 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
'file.user_to_uid': mock_uid,
'file.group_to_gid': mock_gid,
'file.is_link': mock_t,
'file.readlink': mock_target}):
'file.readlink': mock_target,
'user.info': mock_empty,
'user.current': mock_user}):
with patch.dict(filestate.__opts__, {'test': False}):
with patch.object(os.path, 'isdir', mock_t):
with patch.object(salt.states.file, '_check_symlink_ownership', mock_t):
@ -224,7 +232,9 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
'file.user_to_uid': mock_uid,
'file.group_to_gid': mock_gid,
'file.is_link': mock_f,
'file.readlink': mock_target}):
'file.readlink': mock_target,
'user.info': mock_empty,
'user.current': mock_user}):
with patch.dict(filestate.__opts__, {'test': False}):
with patch.object(os.path, 'isdir', mock_t):
with patch.object(os.path, 'exists', mock_f):
@ -243,7 +253,9 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
'file.user_to_uid': mock_uid,
'file.group_to_gid': mock_gid,
'file.is_link': mock_f,
'file.readlink': mock_target}):
'file.readlink': mock_target,
'user.info': mock_empty,
'user.current': mock_user}):
with patch.dict(filestate.__opts__, {'test': False}):
with patch.object(os.path, 'isdir', mock_t):
with patch.object(os.path, 'exists', mock_f):
@ -538,7 +550,10 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
'G12', 'G12', 'G12', 'G12', 'G12'])
mock_if = MagicMock(side_effect=[True, False, False, False, False,
False, False, False])
mock_ret = MagicMock(return_value=(ret, None))
if salt.utils.is_windows():
mock_ret = MagicMock(return_value=ret)
else:
mock_ret = MagicMock(return_value=(ret, None))
mock_dict = MagicMock(return_value={})
mock_cp = MagicMock(side_effect=[Exception, True])
mock_ex = MagicMock(side_effect=[Exception, {'changes': {name: name}},
@ -573,8 +588,14 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
self.assertDictEqual(filestate.managed(name, create=False),
ret)
comt = ('User salt is not available Group saltstack'
' is not available')
# Group argument is ignored on Windows systems. Group is set to
# user
if salt.utils.is_windows():
comt = ('User salt is not available Group salt'
' is not available')
else:
comt = ('User salt is not available Group saltstack'
' is not available')
ret.update({'comment': comt, 'result': False})
self.assertDictEqual(filestate.managed(name, user=user,
group=group), ret)
@ -711,17 +732,28 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
mock_t = MagicMock(return_value=True)
mock_f = MagicMock(return_value=False)
mock_perms = MagicMock(return_value=(ret, ''))
if salt.utils.is_windows():
mock_perms = MagicMock(return_value=ret)
else:
mock_perms = MagicMock(return_value=(ret, ''))
mock_uid = MagicMock(side_effect=['', 'U12', 'U12', 'U12', 'U12', 'U12',
'U12', 'U12', 'U12', 'U12', 'U12'])
mock_gid = MagicMock(side_effect=['', 'G12', 'G12', 'G12', 'G12', 'G12',
'G12', 'G12', 'G12', 'G12', 'G12'])
mock_check = MagicMock(return_value=(
None,
'The directory "{0}" will be changed'.format(name),
{'directory': 'new'}))
mock_error = CommandExecutionError
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
'file.user_to_uid': mock_uid,
'file.group_to_gid': mock_gid,
'file.stats': mock_f,
'file.check_perms': mock_perms,
'file.mkdir': mock_t}):
'file.mkdir': mock_t}), \
patch('salt.utils.win_dacl.get_sid', mock_error), \
patch('os.path.isdir', mock_t), \
patch('salt.states.file._check_directory_win', mock_check):
if salt.utils.is_windows():
comt = ('User salt is not available Group salt'
' is not available')
@ -729,8 +761,8 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
comt = ('User salt is not available Group saltstack'
' is not available')
ret.update({'comment': comt, 'name': name})
self.assertDictEqual(filestate.directory(name, user=user,
group=group), ret)
self.assertDictEqual(
filestate.directory(name, user=user, group=group), ret)
with patch.object(os.path, 'isabs', mock_f):
comt = ('Specified file {0} is not an absolute path'
@ -771,9 +803,19 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
with patch.object(os.path, 'isfile', mock_f):
with patch.dict(filestate.__opts__, {'test': True}):
comt = ('The following files will be changed:\n{0}:'
' directory - new\n'.format(name))
ret.update({'comment': comt, 'result': None, 'pchanges': {'/etc/grub.conf': {'directory': 'new'}}})
if salt.utils.is_windows():
comt = 'The directory "{0}" will be changed' \
''.format(name)
p_chg = {'directory': 'new'}
else:
comt = ('The following files will be changed:\n{0}:'
' directory - new\n'.format(name))
p_chg = {'/etc/grub.conf': {'directory': 'new'}}
ret.update({
'comment': comt,
'result': None,
'pchanges': p_chg
})
self.assertDictEqual(filestate.directory(name,
user=user,
group=group),
@ -845,8 +887,14 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
'file.source_list': mock_lst,
'cp.list_master_dirs': mock_emt,
'cp.list_master': mock_l}):
comt = ('User salt is not available Group saltstack'
' is not available')
# Group argument is ignored on Windows systems. Group is set to user
if salt.utils.is_windows():
comt = ('User salt is not available Group salt'
' is not available')
else:
comt = ('User salt is not available Group saltstack'
' is not available')
ret.update({'comment': comt})
self.assertDictEqual(filestate.recurse(name, source, user=user,
group=group), ret)
@ -954,7 +1002,8 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
ret.update({'comment': comt, 'name': name})
self.assertDictEqual(filestate.blockreplace(name), ret)
with patch.object(os.path, 'isabs', mock_t):
with patch.object(os.path, 'isabs', mock_t), \
patch.object(os.path, 'exists', mock_t):
with patch.dict(filestate.__salt__, {'file.blockreplace': mock_t}):
with patch.dict(filestate.__opts__, {'test': True}):
comt = ('Changes would be made')
@ -1312,8 +1361,15 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
'file.get_group': mock_grp,
'file.get_mode': mock_grp,
'file.check_perms': mock_t}):
comt = ('User salt is not available Group '
'saltstack is not available')
# Group argument is ignored on Windows systems. Group is set
# to user
if salt.utils.is_windows():
comt = ('User salt is not available Group salt'
' is not available')
else:
comt = ('User salt is not available Group saltstack'
' is not available')
ret.update({'comment': comt, 'result': False})
self.assertDictEqual(filestate.copy(name, source, user=user,
group=group), ret)