Merge branch '2019.2' into 51879-fix-binary-pillar-return-error

This commit is contained in:
Daniel Wozniak 2019-04-11 16:33:20 -07:00 committed by GitHub
commit ead856ee93
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
108 changed files with 1474 additions and 745 deletions

View file

@ -132,6 +132,7 @@ MOCK_MODULES = [
'tornado.ioloop',
'tornado.iostream',
'tornado.netutil',
'tornado.queues',
'tornado.simple_httpclient',
'tornado.stack_context',
'tornado.web',

View file

@ -9,7 +9,7 @@ Synopsis
.. code-block:: bash
salt-unity salt '*' test.ping
salt-unity salt '*' test.version
Description
===========
@ -35,4 +35,4 @@ See also
:manpage:`salt-minion(1)`
:manpage:`salt-run(1)`
:manpage:`salt-ssh(1)`
:manpage:`salt-syndic(1)`
:manpage:`salt-syndic(1)`

View file

@ -11,9 +11,9 @@ Synopsis
salt -E '.*' [ options ] sys.doc cmd
salt -G 'os:Arch.*' [ options ] test.ping
salt -G 'os:Arch.*' [ options ] test.version
salt -C 'G@os:Arch.* and webserv* or G@kernel:FreeBSD' [ options ] test.ping
salt -C 'G@os:Arch.* and webserv* or G@kernel:FreeBSD' [ options ] test.version
Description
===========

View file

@ -199,30 +199,31 @@ Sending Commands
================
Communication between the Master and a Minion may be verified by running
the ``test.ping`` command:
the ``test.version`` command:
.. code-block:: bash
[root@master ~]# salt alpha test.ping
[root@master ~]# salt alpha test.version
alpha:
True
2018.3.4
Communication between the Master and all Minions may be tested in a
similar way:
.. code-block:: bash
[root@master ~]# salt '*' test.ping
[root@master ~]# salt '*' test.version
alpha:
True
2018.3.4
bravo:
True
2018.3.4
charlie:
True
2018.3.4
delta:
True
2018.3.4
Each of the Minions should send a ``True`` response as shown above.
Each of the Minions should send a ``2018.3.4`` response as shown above,
or any other salt version installed.
What's Next?
============

View file

@ -30,7 +30,7 @@ The same could be done by command line:
.. code-block:: bash
salt -t 40 --module-executors='[splay, direct_call]' --executor-opts='{splaytime: 30}' '*' test.ping
salt -t 40 --module-executors='[splay, direct_call]' --executor-opts='{splaytime: 30}' '*' test.version
And the same command called via netapi will look like this:
@ -43,7 +43,7 @@ And the same command called via netapi will look like this:
-d '[{
"client": "local",
"tgt": "*",
"fun": "test.ping",
"fun": "test.version",
"module_executors": ["splay", "direct_call"],
"executor_opts": {"splaytime": 10}
}]'

View file

@ -107,11 +107,11 @@ comes with a number of functions to execute peer communication in different
ways. Currently there are three functions in the publish module. These examples
will show how to test the peer system via the salt-call command.
To execute test.ping on all minions:
To execute test.version on all minions:
.. code-block:: bash
# salt-call publish.publish \* test.ping
# salt-call publish.publish \* test.version
To execute the manage.up runner:
@ -123,7 +123,7 @@ To match minions using other matchers, use ``tgt_type``:
.. code-block:: bash
# salt-call publish.publish 'webserv* and not G@os:Ubuntu' test.ping tgt_type='compound'
# salt-call publish.publish 'webserv* and not G@os:Ubuntu' test.version tgt_type='compound'
.. note::
In pre-2017.7.0 releases, use ``expr_form`` instead of ``tgt_type``.

View file

@ -31,7 +31,7 @@ Specifying what returners to use is done when the command is invoked:
.. code-block:: bash
salt '*' test.ping --return redis_return
salt '*' test.version --return redis_return
This command will ensure that the redis_return returner is used.
@ -39,10 +39,10 @@ It is also possible to specify multiple returners:
.. code-block:: bash
salt '*' test.ping --return mongo_return,redis_return,cassandra_return
salt '*' test.version --return mongo_return,redis_return,cassandra_return
In this scenario all three returners will be called and the data from the
test.ping command will be sent out to the three named returners.
test.version command will be sent out to the three named returners.
Writing a Returner
==================
@ -61,13 +61,13 @@ Other optional functions can be included to add support for
``returner``
The ``returner`` function must accept a single argument. The argument
contains return data from the called minion function. If the minion
function ``test.ping`` is called, the value of the argument will be a
function ``test.version`` is called, the value of the argument will be a
dictionary. Run the following command from a Salt master to get a sample
of the dictionary:
.. code-block:: bash
salt-call --local --metadata test.ping --out=pprint
salt-call --local --metadata test.version --out=pprint
.. code-block:: python
@ -246,12 +246,12 @@ Sample:
"master_minion": {
"fun_args": [],
"jid": "20150330121011408195",
"return": true,
"return": "2018.3.4",
"retcode": 0,
"success": true,
"cmd": "_return",
"_stamp": "2015-03-30T12:10:12.708663",
"fun": "test.ping",
"fun": "test.version",
"id": "master_minion"
}
}
@ -267,9 +267,9 @@ Sample:
{
"local": {
"minion1": "test.ping",
"minion3": "test.ping",
"minion2": "test.ping"
"minion1": "test.version",
"minion3": "test.version",
"minion2": "test.version"
}
}
@ -344,7 +344,7 @@ Testing the Returner
The ``returner``, ``prep_jid``, ``save_load``, ``get_load``, and
``event_return`` functions can be tested by configuring the
:conf_master:`master_job_cache` and `Event Returners`_ in the master config
file and submitting a job to ``test.ping`` each minion from the master.
file and submitting a job to ``test.version`` each minion from the master.
Once you have successfully exercised the Master Job Cache functions, test the
External Job Cache functions using the ``ret`` execution module.
@ -352,7 +352,7 @@ External Job Cache functions using the ``ret`` execution module.
.. code-block:: bash
salt-call ret.get_jids cassandra_cql --output=json
salt-call ret.get_fun cassandra_cql test.ping --output=json
salt-call ret.get_fun cassandra_cql test.version --output=json
salt-call ret.get_minions cassandra_cql --output=json
salt-call ret.get_jid cassandra_cql 20150330121011408195 --output=json

View file

@ -122,6 +122,6 @@ responding to Salt calls could look like this:
Print a list of all of the minions that are up
'''
client = salt.client.LocalClient(__opts__['conf_file'])
minions = client.cmd('*', 'test.ping', timeout=1)
minions = client.cmd('*', 'test.version', timeout=1)
for minion in sorted(minions):
print minion

View file

@ -22,5 +22,5 @@ allowed during blackout. This is configured with the special pillar key
.. code-block:: yaml
minion_blackout_whitelist:
- test.ping
- pillar.get
- test.version
- pillar.get

View file

@ -328,7 +328,7 @@ it can be verified with Salt:
.. code-block:: bash
# salt 'ami.example.com' test.ping
# salt 'ami.example.com' test.version
Required Settings

View file

@ -108,7 +108,7 @@ it can be verified with Salt:
.. code-block:: bash
salt newinstance test.ping
salt newinstance test.version
Profile Options

View file

@ -138,7 +138,7 @@ it can be verified with Salt:
.. code-block:: bash
salt newinstance test.ping
salt newinstance test.version
Profile Options

View file

@ -28,9 +28,9 @@ Minion Configuration
====================
The default minion configuration is set up in this file. Minions created by
salt-cloud derive their configuration from this file. Almost all parameters
found in :ref:`Configuring the Salt Minion <configuration-salt-minion>` can
be used here.
salt-cloud derive their configuration from this file. Almost all parameters
found in :ref:`Configuring the Salt Minion <configuration-salt-minion>` can be
used here.
.. code-block:: yaml
@ -44,7 +44,7 @@ and its listening port, if the port is not set to the default.
Similar to most other settings, Minion configuration settings are inherited
across configuration files. For example, the master setting might be contained
in the main ``cloud`` configuration file as demonstrated above, but additional
settings can be placed in the provider or profile:
settings can be placed in the provider, profile or map configuration files:
.. code-block:: yaml

View file

@ -123,7 +123,7 @@ Post-Deploy Commands
Once a minion has been deployed, it has the option to run a salt command.
Normally, this would be the :py:func:`state.apply <salt.modules.state.apply_>`,
which would finish provisioning the VM. Another common option (for testing) is
to use :py:func:`test.ping <salt.modules.test.ping>`. This is configured in the
to use :py:func:`test.version <salt.modules.test.version>`. This is configured in the
main cloud config file:
.. code-block:: yaml

View file

@ -170,7 +170,7 @@ it can be verified with Salt:
.. code-block:: bash
salt gce-instance test.ping
salt gce-instance test.version
GCE Specific Settings

View file

@ -84,7 +84,7 @@ it can be verified with Salt:
.. code-block:: bash
# salt my-centos7-clone test.ping
# salt my-centos7-clone test.version
Required Settings

View file

@ -62,7 +62,7 @@ it can be verified with Salt:
.. code-block:: bash
salt linode-instance test.ping
salt linode-instance test.version
Listing Sizes

View file

@ -96,7 +96,7 @@ Once the instance has been created with salt-minion installed, connectivity to i
.. code-block:: bash
salt my-new-vm test.ping
salt my-new-vm test.version
OpenNebula uses an image --> template --> virtual machine paradigm where the template draws on the image, or disk,
and virtual machines are created from templates. Because of this, there is no need to define a ``size`` in the cloud

View file

@ -91,7 +91,7 @@ it can be verified with Salt:
.. code-block:: bash
# salt myubuntu test.ping
# salt myubuntu test.version
Required Settings

View file

@ -91,7 +91,7 @@ it can be verified with Salt:
.. code-block:: bash
# salt myubuntu test.ping
# salt myubuntu test.version
Required Settings

View file

@ -195,7 +195,7 @@ Connectivity to the new "Salted" instances can now be verified with Salt:
.. code-block:: bash
salt 'my-instance-*' test.ping
salt 'my-instance-*' test.version
Credential Verification
=======================
@ -203,7 +203,7 @@ Credential Verification
Because the Saltify driver does not actually create VM's, unlike other
salt-cloud drivers, it has special behaviour when the ``deploy`` option is set
to ``False``. When the cloud configuration specifies ``deploy: False``, the
Saltify driver will attept to authenticate to the target node(s) and return
Saltify driver will attempt to authenticate to the target node(s) and return
``True`` for each one that succeeds. This can be useful to verify ports,
protocols, services and credentials are correctly configured before a live
deployment.

View file

@ -221,9 +221,9 @@ with its short hostname, ``my-vm``):
Rejected Keys:
#
#
# salt my-vm.example.com test.ping
# salt my-vm.example.com test.version
my-vm.example.com:
True
2018.3.4
#
#
# salt-cloud -d my-vm.example.com
@ -334,7 +334,7 @@ it can be verified with Salt:
.. code-block:: bash
# salt 'myserver.example.com' test.ping
# salt 'myserver.example.com' test.version
Dedicated Host
~~~~~~~~~~~~~~

View file

@ -119,7 +119,7 @@ to it can be verified with Salt:
.. code-block:: bash
salt my-id test.ping
salt my-id test.version
.. _host provisioning example:

View file

@ -111,7 +111,7 @@ the following command:
.. code-block:: bash
# salt vh_instance1 test.ping
# salt vh_instance1 test.version
You can now continue to provision new instances and they will all automatically
be set up as minions of the master you've defined in the configuration file.

View file

@ -160,7 +160,7 @@ it can be verified with Salt:
.. code-block:: bash
salt xenvm02 test.ping
salt xenvm02 test.version
Listing Sizes

View file

@ -109,7 +109,7 @@ against the command target.
The typical lifecycle of a salt job from the perspective of the master
might be as follows:
1) A command is issued on the CLI. For example, 'salt my_minion test.ping'.
1) A command is issued on the CLI. For example, 'salt my_minion test.version'.
2) The 'salt' command uses LocalClient to generate a request to the salt master
by connecting to the ReqServer on TCP:4506 and issuing the job.

View file

@ -160,7 +160,7 @@ installation is working:
salt-minion -c ./etc/salt -d
salt-key -c ./etc/salt -L
salt-key -c ./etc/salt -A
salt -c ./etc/salt '*' test.ping
salt -c ./etc/salt '*' test.version
Running the master and minion in debug mode can be helpful when developing. To
do this, add ``-l debug`` to the calls to ``salt-master`` and ``salt-minion``.

View file

@ -67,7 +67,7 @@ other minions based on standard targets (all matchers are supported except the c
external_auth:
pam:
dave:
- test.ping
- test.version
- mongo\*:
- network.*
- log\*:
@ -78,7 +78,7 @@ other minions based on standard targets (all matchers are supported except the c
steve:
- .*
The above allows for all minions to be hit by test.ping by dave, and adds a
The above allows for all minions to be hit by test.version by dave, and adds a
few functions that dave can execute on other minions. It also allows steve
unrestricted access to salt commands.

View file

@ -180,7 +180,7 @@ any user on the same system as the master with the ``-a`` option:
.. code-block:: bash
$ salt -a pam web\* test.ping
$ salt -a pam web\* test.version
The system will ask the user for the credentials required by the
authentication system and then publish the command.
@ -198,7 +198,7 @@ adding a ``-T`` option when authenticating:
.. code-block:: bash
$ salt -T -a pam web\* test.ping
$ salt -T -a pam web\* test.version
Now a token will be created that has an expiration of 12 hours (by default).
This token is stored in a file named ``salt_token`` in the active user's home

View file

@ -69,7 +69,7 @@ Job events
``G@os_family:RedHat``, etc.
:var tgt_type: The type of targeting used: ``glob``, ``grain``,
``compound``, etc.
:var fun: The function to run on minions: ``test.ping``,
:var fun: The function to run on minions: ``test.version``,
``network.interfaces``, etc.
:var arg: A list of arguments to pass to the function that will be
called.
@ -85,7 +85,7 @@ Job events
:var id: The minion ID.
:var jid: The job ID.
:var retcode: The return code for the job.
:var fun: The function the minion ran. E.g., ``test.ping``.
:var fun: The function the minion ran. E.g., ``test.version``.
:var return: The data returned from the execution module.
.. salt:event:: salt/job/<JID>/prog/<MID>/<RUN NUM>

View file

@ -25,12 +25,12 @@ The general installation process is as follows:
4. Accept the Salt :ref:`minion keys <using-salt-key>` after the Salt minion
connects.
After this, you should be able to run a simple command and receive returns from
After this, you should be able to run a simple command and receive salt version returns from
all connected Salt minions.
.. code-block:: bash
salt '*' test.ping
salt '*' test.version
Quick Install
-------------

View file

@ -516,7 +516,7 @@ Testing the Salt minion
.. code-block:: bash
sudo salt '*' test.ping
sudo salt '*' test.version
You should get the following response: ``{'your minion hostname': True}``

View file

@ -405,6 +405,29 @@ Returns:
None
.. jinja_ref:: regex_replace
``regex_replace``
-----------------
.. versionadded:: 2017.7.0
Searches for a pattern and replaces with a sequence of characters.
Example:
.. code-block:: jinja
{% set my_text = 'yes, this is a TEST' %}
{{ my_text | regex_replace(' ([a-z])', '__\\1', ignorecase=True) }}
Returns:
.. code-block:: text
yes,__this__is__a__TEST
.. jinja_ref:: uuid
``uuid``

View file

@ -98,7 +98,7 @@ the 'url' key above should say ``url: http://127.0.0.1:8000``
.. code-block:: bash
salt p8000 test.ping
salt p8000 test.version
8. The REST service implements a degenerately simple pkg and service provider as
well as a small set of grains. To "install" a package, use a standard

View file

@ -289,7 +289,7 @@ a BGP policy referenced in many places, you can do so by running:
.. code-block:: bash
salt '*' net.replae_pattern OLD-POLICY-CONFIG new-policy-config
salt '*' net.replace_pattern OLD-POLICY-CONFIG new-policy-config
Similarly, you can also replace entire configuration blocks using the
:mod:`net.blockreplace <salt.modules.napalm_network.blockreplace>` function.

View file

@ -127,7 +127,7 @@ command:
.. code-block:: bash
salt-ssh '*' test.ping
salt-ssh '*' test.version
Commands with ``salt-ssh`` follow the same syntax as the ``salt`` command.
@ -218,8 +218,8 @@ YAML contents:
ssh_wipe: True
Instead of having to call
``salt-ssh --config-dir=path/to/config/dir --max-procs=30 --wipe \* test.ping`` you
can call ``salt-ssh \* test.ping``.
``salt-ssh --config-dir=path/to/config/dir --max-procs=30 --wipe \* test.version`` you
can call ``salt-ssh \* test.version``.
Boolean-style options should be specified in their YAML representation.

View file

@ -9,11 +9,11 @@ supported.
.. code-block:: bash
salt '*' -b 10 test.ping
salt '*' -b 10 test.version
salt -G 'os:RedHat' --batch-size 25% apache.signal restart
This will only run test.ping on 10 of the targeted minions at a time and then
This will only run test.version on 10 of the targeted minions at a time and then
restart apache on 25% of the minions matching ``os:RedHat`` at a time and work
through them all until the task is complete. This makes jobs like rolling web
server restarts behind a load balancer or doing maintenance on BSD firewalls

View file

@ -32,7 +32,7 @@ matches the :mod:`regular expression <python2:re>` ``web-dc1-srv.*``:
.. code-block:: bash
salt -C 'webserv* and G@os:Debian or E@web-dc1-srv.*' test.ping
salt -C 'webserv* and G@os:Debian or E@web-dc1-srv.*' test.version
That same example expressed in a :term:`top file` looks like the following:
@ -49,20 +49,20 @@ Excluding a minion based on its ID is also possible:
.. code-block:: bash
salt -C 'not web-dc1-srv' test.ping
salt -C 'not web-dc1-srv' test.version
Versions prior to 2015.8.0 a leading ``not`` was not supported in compound
matches. Instead, something like the following was required:
.. code-block:: bash
salt -C '* and not G@kernel:Darwin' test.ping
salt -C '* and not G@kernel:Darwin' test.version
Excluding a minion based on its ID was also possible:
.. code-block:: bash
salt -C '* and not web-dc1-srv' test.ping
salt -C '* and not web-dc1-srv' test.version
Precedence Matching
-------------------
@ -71,7 +71,7 @@ Matchers can be grouped together with parentheses to explicitly declare preceden
.. code-block:: bash
salt -C '( ms-1 or G@id:ms-3 ) and G@id:ms-3' test.ping
salt -C '( ms-1 or G@id:ms-3 ) and G@id:ms-3' test.version
.. note::

View file

@ -31,39 +31,39 @@ Match all minions:
.. code-block:: bash
salt '*' test.ping
salt '*' test.version
Match all minions in the example.net domain or any of the example domains:
.. code-block:: bash
salt '*.example.net' test.ping
salt '*.example.*' test.ping
salt '*.example.net' test.version
salt '*.example.*' test.version
Match all the ``webN`` minions in the example.net domain (``web1.example.net``,
``web2.example.net````webN.example.net``):
.. code-block:: bash
salt 'web?.example.net' test.ping
salt 'web?.example.net' test.version
Match the ``web1`` through ``web5`` minions:
.. code-block:: bash
salt 'web[1-5]' test.ping
salt 'web[1-5]' test.version
Match the ``web1`` and ``web3`` minions:
.. code-block:: bash
salt 'web[1,3]' test.ping
salt 'web[1,3]' test.version
Match the ``web-x``, ``web-y``, and ``web-z`` minions:
.. code-block:: bash
salt 'web-[x-z]' test.ping
salt 'web-[x-z]' test.version
.. note::
@ -81,7 +81,7 @@ Match both ``web1-prod`` and ``web1-devel`` minions:
.. code-block:: bash
salt -E 'web1-(prod|devel)' test.ping
salt -E 'web1-(prod|devel)' test.version
When using regular expressions in a State's :term:`top file`, you must specify
the matcher as the first option. The following example executes the contents of
@ -102,4 +102,4 @@ At the most basic level, you can specify a flat list of minion IDs:
.. code-block:: bash
salt -L 'web1,web2,web3' test.ping
salt -L 'web1,web2,web3' test.version

View file

@ -10,7 +10,7 @@ For example, the following matches all CentOS minions:
.. code-block:: bash
salt -G 'os:CentOS' test.ping
salt -G 'os:CentOS' test.version
Match all minions with 64-bit CPUs, and return number of CPU cores for each
matching minion:

View file

@ -37,7 +37,7 @@ the target is the grain key followed by a glob expression: "os:Arch*".
.. code-block:: bash
salt -G 'os:Fedora' test.ping
salt -G 'os:Fedora' test.version
Will return True from all of the minions running Fedora.
@ -62,7 +62,7 @@ This is well defined with an example:
.. code-block:: bash
salt -C 'G@os:Debian and webser* or E@db.*' test.ping
salt -C 'G@os:Debian and webser* or E@db.*' test.version
In this example any minion who's id starts with ``webser`` and is running
Debian, or any minion who's id starts with db will be matched.

View file

@ -9,14 +9,14 @@ notation).
.. code-block:: bash
salt -S 192.168.40.20 test.ping
salt -S 2001:db8::/64 test.ping
salt -S 192.168.40.20 test.version
salt -S 2001:db8::/64 test.version
Ipcidr matching can also be used in compound matches
.. code-block:: bash
salt -C 'S@10.0.0.0/24 and G@os:Debian' test.ping
salt -C 'S@10.0.0.0/24 and G@os:Debian' test.version
It is also possible to use in both pillar and state-matching

View file

@ -57,7 +57,7 @@ To match a nodegroup on the CLI, use the ``-N`` command-line option:
.. code-block:: bash
salt -N group1 test.ping
salt -N group1 test.version
.. versionadded:: 2019.2.0
.. note::

View file

@ -21,7 +21,7 @@ Example:
.. code-block:: bash
salt -I 'somekey:specialvalue' test.ping
salt -I 'somekey:specialvalue' test.version
Like with :ref:`Grains <targeting-grains>`, it is possible to use globbing
as well as match nested values in Pillar, by adding colons for each level that
@ -31,4 +31,4 @@ is being traversed. The below example would match minions with a pillar named
.. code-block:: bash
salt -I 'foo:bar:baz*' test.ping
salt -I 'foo:bar:baz*' test.version

View file

@ -72,11 +72,11 @@ One might target host1 through host100 in the test.com domain with Salt as follo
.. code-block:: bash
salt --range %test:CLUSTER test.ping
salt --range %test:CLUSTER test.version
The following salt command would target three hosts: ``frontend``, ``backend``, and ``mysql``:
.. code-block:: bash
salt --range %test:APPS test.ping
salt --range %test:APPS test.version

View file

@ -346,12 +346,12 @@ event bus, and returns ``True`` if that event's tag matches. For example:
run_remote_ex:
local.cmd:
- tgt: '*'
- func: test.ping
- func: test.version
- require:
- check: salt/foo/*/bar
This formula will look for an event whose tag is ``salt/foo/<anything>/bar`` and
if it comes in, issue a ``test.ping`` to all minions.
if it comes in, issue a ``test.version`` to all minions.
Register Persistence

View file

@ -131,15 +131,15 @@ On the Master node:
Unaccepted Keys:
Rejected Keys:
# salt '*' test.ping
# salt '*' test.version
minion_1:
True
2018.3.4
minion_2:
True
2018.3.4
minion_4:
True
2018.3.4
minion_3:
True
2018.3.4
Topology
========

View file

@ -277,7 +277,7 @@ This command will return data about all of the hypervisors and respective
virtual machines.
Now that the new VM is booted it should have contacted the Salt Master, a
``test.ping`` will reveal if the new VM is running.
``test.version`` will reveal if the new VM is running.
QEMU copy on write support

View file

@ -81,7 +81,7 @@ simple `salt-call` command:
.. code-block:: bash
salt-call --local dockerng.call test test.ping
salt-call --local dockerng.call test test.version
salt-call --local dockerng.call test network.interfaces
salt-call --local dockerng.call test disk.usage
salt-call --local dockerng.call test pkg.list_pkgs

View file

@ -227,9 +227,10 @@ This allows you to use any number of potential fallback passwords.
This scenario is especially true, and even slower, when the proxy
minion first starts. If the correct password is not the first password
on the list, it may take up to a minute for ``test.ping`` to respond
with a ``True`` result. Once the initial authorization is complete, the
responses for commands will be a little faster.
on the list, it may take up to a minute for ``test.version`` to respond
with salt's version installed (Example: ``2018.3.4``. Once the initial
authorization is complete, the responses for commands will be a little
faster.
To avoid these longer waiting periods, SaltStack recommends moving the
correct password to the top of the list and restarting the proxy minion
@ -366,7 +367,7 @@ proxy processes!
.. code-block:: bash
# salt 'esxi-*' test.ping
# salt 'esxi-*' test.version
esxi-1:
True
esxi-3:
@ -377,7 +378,7 @@ Executing Commands
==================
Now that you've configured your Proxy Minions and have them responding successfully
to a ``test.ping``, we can start executing commands against the ESXi hosts via Salt.
to a ``test.version``, we can start executing commands against the ESXi hosts via Salt.
It's important to understand how this particular proxy works, and there are a couple
of important pieces to be aware of in order to start running remote execution and

View file

@ -28,8 +28,11 @@ FirewallD use the command line client ``firewall-cmd``.
firewall-cmd --permanent --zone=<zone> --add-port=4505-4506/tcp
Please choose the desired zone according to your setup. Don't forget to reload
after you made your changes.
A network zone defines the security level of trust for the the network.
The user should choose an appropriate zone value for their setup.
Possible values include: drop, block, public, external, dmz, work, home, internal, trusted.
Don't forget to reload after you made your changes.
.. code-block:: bash
@ -229,5 +232,5 @@ be set on the Master:
needs to communicate with the listening network socket of
``salt-master`` on the *loopback* interface. Without this you will
see no outgoing Salt traffic from the master, even for a simple
``salt '*' test.ping``, because the ``salt`` client never reached
``salt '*' test.version``, because the ``salt`` client never reached
the ``salt-master`` to tell it to carry out the execution.

View file

@ -27,14 +27,14 @@ following function. The default filter is a glob on the minion id. For example:
.. code-block:: bash
salt '*' test.ping
salt '*.example.org' test.ping
salt '*' test.version
salt '*.example.org' test.version
Targets can be based on minion system information using the Grains system:
.. code-block:: bash
salt -G 'os:Ubuntu' test.ping
salt -G 'os:Ubuntu' test.version
.. seealso:: :ref:`Grains system <targeting-grains>`
@ -42,19 +42,19 @@ Targets can be filtered by regular expression:
.. code-block:: bash
salt -E 'virtmach[0-9]' test.ping
salt -E 'virtmach[0-9]' test.version
Targets can be explicitly specified in a list:
.. code-block:: bash
salt -L 'foo,bar,baz,quo' test.ping
salt -L 'foo,bar,baz,quo' test.version
Or Multiple target types can be combined in one command:
.. code-block:: bash
salt -C 'G@os:Ubuntu and webser* or E@database.*' test.ping
salt -C 'G@os:Ubuntu and webser* or E@database.*' test.version
function
@ -74,7 +74,7 @@ Show all currently available minions:
.. code-block:: bash
salt '*' test.ping
salt '*' test.version
Run an arbitrary shell command:
@ -99,4 +99,4 @@ Optional, keyword arguments are also supported:
salt '*' pip.install salt timeout=5 upgrade=True
They are always in the form of ``kwarg=argument``.
They are always in the form of ``kwarg=argument``.

View file

@ -238,7 +238,7 @@ The minion will connect to the first master from its master list
[DEBUG ] Decrypting the current master AES key
A test.ping on the master the minion is currently connected to should be run to
A test.version on the master the minion is currently connected to should be run to
test connectivity.
If successful, that master should be turned off. A firewall-rule denying the

View file

@ -238,16 +238,16 @@ start with looks like this:
.. code-block:: bash
salt '*' test.ping
salt '*' test.version
The ``*`` is the target, which specifies all minions.
``test.ping`` tells the minion to run the :py:func:`test.ping
<salt.modules.test.ping>` function.
``test.version`` tells the minion to run the :py:func:`test.version
<salt.modules.test.version>` function.
In the case of ``test.ping``, ``test`` refers to a :ref:`execution module
<writing-execution-modules>`. ``ping`` refers to the :py:func:`ping
<salt.modules.test.ping>` function contained in the aforementioned ``test``
In the case of ``test.version``, ``test`` refers to a :ref:`execution module
<writing-execution-modules>`. ``version`` refers to the :py:func:`version
<salt.modules.test.version>` function contained in the aforementioned ``test``
module.
.. note::
@ -257,12 +257,10 @@ module.
services.
The result of running this command will be the master instructing all of the
minions to execute :py:func:`test.ping <salt.modules.test.ping>` in parallel
and return the result.
This is not an actual ICMP ping, but rather a simple function which returns ``True``.
Using :py:func:`test.ping <salt.modules.test.ping>` is a good way of confirming that a minion is
connected.
minions to execute :py:func:`test.version <salt.modules.test.version>` in parallel
and return the result. Using :py:func:`test.version <salt.modules.test.version>`
is a good way of confirming that a minion is connected, and reaffirm to the user
the salt version(s) they have installed on the minions.
.. note::
@ -271,7 +269,7 @@ connected.
well by using the :conf_minion:`id` parameter.
Of course, there are hundreds of other modules that can be called just as
``test.ping`` can. For example, the following would return disk usage on all
``test.version`` can. For example, the following would return disk usage on all
targeted minions:
.. code-block:: bash
@ -591,7 +589,7 @@ This formula can be referenced via the following command:
.. note::
:py:func:`state.apply <salt.modules.state.apply_>` is just another remote
execution function, just like :py:func:`test.ping <salt.modules.test.ping>`
execution function, just like :py:func:`test.version <salt.modules.test.version>`
or :py:func:`disk.usage <salt.modules.disk.usage>`. It simply takes the
name of an SLS file as an argument.

View file

@ -412,9 +412,9 @@ following:
.. code-block:: bash
sudo salt '*' test.ping
sudo salt '*' test.version
You should see your minion answering the ping. It's now time to do some
You should see your minion answering with its salt version. It's now time to do some
configuration.

View file

@ -56,13 +56,24 @@ def _install_requirements(session, *extra_requirements):
# Install requirements
distro_requirements = None
if not IS_WINDOWS:
if IS_WINDOWS:
_distro_requirements = os.path.join(REPO_ROOT, 'requirements', 'static', 'windows.txt')
if os.path.exists(_distro_requirements):
with open(_distro_requirements) as rfh:
if 'ioflo' in rfh.read():
# Because we still install ioflo, which requires setuptools-git, which fails with a
# weird SSL certificate issue(weird because the requirements file requirements install
# fine), let's previously have setuptools-git installed
session.install('setuptools-git')
distro_requirements = _distro_requirements
else:
# The distro package doesn't output anything for Windows
session.install('distro')
output = session.run('distro', '-j', silent=True)
distro = json.loads(output.strip())
session.log('Distro information:\n%s', pprint.pformat(distro))
distro_keys = [
'{id}'.format(**distro),
'{id}-{version}'.format(**distro),
'{id}-{version_parts[major]}'.format(**distro)
]
@ -120,11 +131,6 @@ def _install_requirements(session, *extra_requirements):
if extra_requirements:
session.install(*extra_requirements)
if IS_WINDOWS:
# Windows hacks :/
nox_windows_setup = os.path.join(REPO_ROOT, 'tests', 'support', 'nox-windows-setup.py')
session.run('python', nox_windows_setup)
def _run_with_coverage(session, *test_cmd):
session.install('coverage==4.5.3')
@ -149,7 +155,7 @@ def _run_with_coverage(session, *test_cmd):
@nox.parametrize('coverage', [False, True])
def runtests(session, coverage):
# Install requirements
_install_requirements(session, 'unittest-xml-reporting<2.4.0')
_install_requirements(session, 'unittest-xml-reporting==2.2.1')
# Create required artifacts directories
_create_ci_directories()

View file

@ -0,0 +1,34 @@
# This is a compilation of requirements installed on salt-jenkins git.salt state run
apache-libcloud==1.0.0
boto3
boto>=2.46.0
cffi
cherrypy==17.3.0
dnspython
docker
futures>=2.0; python_version < '3.0'
GitPython
ioflo
jsonschema<=2.6.0
keyring==5.7.1
kubernetes<4.0
mock<1.1.0
more-itertools==5.0.0
moto
msgpack-python >= 0.4.2, != 0.5.5
psutil
pycrypto>=2.6.1
pyinotify
pyopenssl
python-etcd==0.4.2
python-gnupg
pyvmomi
pyzmq
requests
rfc3987
salttesting==2017.6.1
setproctitle
strict_rfc3339
timelib
tornado<5.0
virtualenv

View file

@ -0,0 +1,109 @@
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile -o requirements/static/arch.txt requirements/zeromq.txt requirements/pytest.txt requirements/static/arch.in
#
apache-libcloud==1.0.0
asn1crypto==0.24.0 # via cryptography
atomicwrites==1.3.0 # via pytest
attrs==19.1.0 # via pytest
aws-xray-sdk==0.95 # via moto
backports-abc==0.5 # via tornado
backports.functools-lru-cache==1.5 # via cheroot, jaraco.functools
backports.ssl-match-hostname==3.7.0.1 # via docker, websocket-client
backports.tempfile==1.0 # via moto
backports.weakref==1.0.post1 # via backports.tempfile
boto3==1.9.118
boto==2.49.0
botocore==1.12.118 # via boto3, moto, s3transfer
cachetools==3.1.0 # via google-auth
certifi==2019.3.9 # via kubernetes, requests, tornado
cffi==1.12.2
chardet==3.0.4 # via requests
cheroot==6.5.4 # via cherrypy
cherrypy==17.3.0
contextlib2==0.5.5 # via cherrypy
cookies==2.2.1 # via responses
coverage==4.5.3 # via pytest-cov
cryptography==2.6.1 # via moto, pyopenssl
dnspython==1.16.0
docker-pycreds==0.4.0 # via docker
docker==3.7.1
docutils==0.14 # via botocore
ecdsa==0.13 # via python-jose
enum34==1.1.6 # via cryptography
funcsigs==1.0.2 # via pytest
functools32==3.2.3.post2 # via jsonschema
future==0.17.1 # via python-jose
futures==3.2.0 ; python_version < "3.0"
gitdb2==2.0.5 # via gitpython
gitpython==2.1.11
google-auth==1.6.3 # via kubernetes
idna==2.8 # via requests
ioflo==1.7.5
ipaddress==1.0.22 # via cryptography, docker, kubernetes
jaraco.functools==2.0 # via tempora
jinja2==2.10
jmespath==0.9.4 # via boto3, botocore
jsondiff==1.1.1 # via moto
jsonpickle==1.1 # via aws-xray-sdk
jsonschema==2.6.0
keyring==5.7.1
kubernetes==3.0.0
markupsafe==1.1.1
mock==1.0.1
more-itertools==5.0.0
moto==1.3.7
msgpack-python==0.5.6
msgpack==0.6.1
pathlib2==2.3.3 # via pytest
pluggy==0.9.0 # via pytest
portend==2.3 # via cherrypy
psutil==5.6.1
py==1.8.0 # via pytest
pyaml==18.11.0 # via moto
pyasn1-modules==0.2.4 # via google-auth
pyasn1==0.4.5 # via pyasn1-modules, rsa
pycparser==2.19 # via cffi
pycrypto==2.6.1
pycryptodome==3.7.3 # via python-jose
pyinotify==0.9.6
pyopenssl==19.0.0
pytest-cov==2.6.1
pytest-helpers-namespace==2019.1.8
pytest-salt-runtests-bridge==2019.1.30
pytest-salt==2018.12.8
pytest-tempdir==2018.8.11
pytest-timeout==1.3.3
pytest==4.3.1
python-dateutil==2.8.0 # via botocore, kubernetes, moto
python-etcd==0.4.2
python-gnupg==0.4.4
python-jose==2.0.2 # via moto
pytz==2018.9 # via moto, tempora
pyvmomi==6.7.1.2018.12
pyyaml==3.13
pyzmq==18.0.1 ; python_version != "3.4"
requests==2.21.0
responses==0.10.6 # via moto
rfc3987==1.3.8
rsa==4.0 # via google-auth
s3transfer==0.2.0 # via boto3
salttesting==2017.6.1
scandir==1.10.0 # via pathlib2
setproctitle==1.1.10
singledispatch==3.4.0.3 # via tornado
six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, kubernetes, more-itertools, moto, pathlib2, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, singledispatch, tempora, websocket-client
smmap2==2.0.5 # via gitdb2
strict-rfc3339==0.7
tempora==1.14 # via portend
timelib==0.2.4
tornado==4.5.3 ; python_version < "3"
urllib3==1.24.1 # via botocore, kubernetes, python-etcd, requests
virtualenv==16.4.3
websocket-client==0.40.0 # via docker, kubernetes
werkzeug==0.15.0 # via moto
wrapt==1.11.1 # via aws-xray-sdk
xmltodict==0.12.0 # via moto
zc.lockfile==1.4 # via cherrypy

View file

@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile -o requirements/static/centos-6.txt requirements/zeromq.txt requirements/raet.txt requirements/pytest.txt requirements/static/centos-6.in
# pip-compile -o requirements/static/centos-6.txt requirements/zeromq.txt requirements/pytest.txt requirements/static/centos-6.in
#
apache-libcloud==1.0.0
asn1crypto==0.24.0 # via cryptography
@ -33,7 +33,7 @@ docker-pycreds==0.4.0 # via docker
docker==3.7.0
docutils==0.14 # via botocore
ecdsa==0.13 # via python-jose
enum34==1.1.6 # via cryptography, raet
enum34==1.1.6 # via cryptography
funcsigs==1.0.2 # via pytest
functools32==3.2.3.post2 # via jsonschema
future==0.17.1 # via python-jose
@ -54,7 +54,6 @@ junos-eznc==2.2.0
jxmlease==1.0.1
keyring==5.7.1
kubernetes==3.0.0
libnacl==1.6.1
lxml==4.3.2 # via junos-eznc, ncclient
markupsafe==1.1.1
meld3==1.0.2 # via supervisor
@ -96,7 +95,6 @@ pytz==2018.9 # via moto, tempora
pyvmomi==6.7.1.2018.12
pyyaml==3.13
pyzmq==18.0.1 ; python_version != "3.4"
raet==0.6.8
requests==2.21.0
responses==0.10.5 # via moto
rfc3987==1.3.8
@ -108,7 +106,7 @@ scp==0.13.1 # via junos-eznc
selectors2==2.0.1 # via ncclient
setproctitle==1.1.10
singledispatch==3.4.0.3 # via tornado
six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, more-itertools, moto, ncclient, pathlib2, pynacl, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, raet, responses, salttesting, singledispatch, tempora, websocket-client
six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, more-itertools, moto, ncclient, pathlib2, pynacl, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, singledispatch, tempora, websocket-client
smmap==0.9.0 # via gitdb
strict-rfc3339==0.7
supervisor==3.3.5 ; python_version < "3"

View file

@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile -o requirements/static/centos-7.txt requirements/zeromq.txt requirements/raet.txt requirements/pytest.txt requirements/static/centos-7.in
# pip-compile -o requirements/static/centos-7.txt requirements/zeromq.txt requirements/pytest.txt requirements/static/centos-7.in
#
apache-libcloud==1.0.0
asn1crypto==0.24.0 # via cryptography
@ -33,7 +33,7 @@ docker-pycreds==0.4.0 # via docker
docker==3.7.0
docutils==0.14 # via botocore
ecdsa==0.13 # via python-jose
enum34==1.1.6 # via cryptography, raet
enum34==1.1.6 # via cryptography
funcsigs==1.0.2 # via pytest
functools32==3.2.3.post2 # via jsonschema
future==0.17.1 # via python-jose
@ -54,7 +54,6 @@ junos-eznc==2.2.0
jxmlease==1.0.1
keyring==5.7.1
kubernetes==3.0.0
libnacl==1.6.1
lxml==4.3.2 # via junos-eznc, ncclient
markupsafe==1.1.1
meld3==1.0.2 # via supervisor
@ -96,7 +95,6 @@ pytz==2018.9 # via moto, tempora
pyvmomi==6.7.1.2018.12
pyyaml==3.13
pyzmq==18.0.1 ; python_version != "3.4"
raet==0.6.8
requests==2.21.0
responses==0.10.5 # via moto
rfc3987==1.3.8
@ -108,7 +106,7 @@ scp==0.13.1 # via junos-eznc
selectors2==2.0.1 # via ncclient
setproctitle==1.1.10
singledispatch==3.4.0.3 # via tornado
six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, more-itertools, moto, ncclient, pathlib2, pynacl, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, raet, responses, salttesting, singledispatch, tempora, websocket-client
six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, more-itertools, moto, ncclient, pathlib2, pynacl, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, singledispatch, tempora, websocket-client
smmap2==2.0.5 # via gitdb2
strict-rfc3339==0.7
supervisor==3.3.5 ; python_version < "3"

View file

@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile -o requirements/static/debian-8.txt requirements/zeromq.txt requirements/raet.txt requirements/pytest.txt requirements/static/debian-8.in
# pip-compile -o requirements/static/debian-8.txt requirements/zeromq.txt requirements/pytest.txt requirements/static/debian-8.in
#
apache-libcloud==1.0.0
asn1crypto==0.24.0 # via cryptography
@ -32,7 +32,7 @@ docker-pycreds==0.4.0 # via docker
docker==3.7.0
docutils==0.14 # via botocore
ecdsa==0.13 # via python-jose
enum34==1.1.6 # via cryptography, raet
enum34==1.1.6 # via cryptography
funcsigs==1.0.2 # via pytest
functools32==3.2.3.post2 # via jsonschema
future==0.17.1 # via python-jose
@ -53,7 +53,6 @@ junos-eznc==2.2.0
jxmlease==1.0.1
keyring==5.7.1
kubernetes==3.0.0
libnacl==1.6.1
lxml==4.3.2 # via junos-eznc, ncclient
markupsafe==1.1.1
mock==1.0.1
@ -93,7 +92,6 @@ pytz==2018.9 # via moto, tempora
pyvmomi==6.7.1.2018.12
pyyaml==3.13
pyzmq==18.0.1 ; python_version != "3.4"
raet==0.6.8
requests==2.21.0
responses==0.10.5 # via moto
rfc3987==1.3.8
@ -105,7 +103,7 @@ scp==0.13.1 # via junos-eznc
selectors2==2.0.1 # via ncclient
setproctitle==1.1.10
singledispatch==3.4.0.3 # via tornado
six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, more-itertools, moto, ncclient, pathlib2, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, raet, responses, salttesting, singledispatch, tempora, websocket-client
six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, more-itertools, moto, ncclient, pathlib2, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, singledispatch, tempora, websocket-client
smmap2==2.0.5 # via gitdb2
strict-rfc3339==0.7
tempora==1.14 # via portend

View file

@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile -o requirements/static/debian-9.txt requirements/zeromq.txt requirements/raet.txt requirements/pytest.txt requirements/static/debian-9.in
# pip-compile -o requirements/static/debian-9.txt requirements/zeromq.txt requirements/pytest.txt requirements/static/debian-9.in
#
apache-libcloud==1.0.0
asn1crypto==0.24.0 # via cryptography
@ -32,7 +32,7 @@ docker-pycreds==0.4.0 # via docker
docker==3.7.0
docutils==0.14 # via botocore
ecdsa==0.13 # via python-jose
enum34==1.1.6 # via cryptography, raet
enum34==1.1.6 # via cryptography
funcsigs==1.0.2 # via pytest
functools32==3.2.3.post2 # via jsonschema
future==0.17.1 # via python-jose
@ -53,7 +53,6 @@ junos-eznc==2.2.0
jxmlease==1.0.1
keyring==5.7.1
kubernetes==3.0.0
libnacl==1.6.1
lxml==4.3.2 # via junos-eznc, ncclient
markupsafe==1.1.1
mock==1.0.1
@ -93,7 +92,6 @@ pytz==2018.9 # via moto, tempora
pyvmomi==6.7.1.2018.12
pyyaml==3.13
pyzmq==18.0.1 ; python_version != "3.4"
raet==0.6.8
requests==2.21.0
responses==0.10.5 # via moto
rfc3987==1.3.8
@ -105,7 +103,7 @@ scp==0.13.1 # via junos-eznc
selectors2==2.0.1 # via ncclient
setproctitle==1.1.10
singledispatch==3.4.0.3 # via tornado
six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, more-itertools, moto, ncclient, pathlib2, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, raet, responses, salttesting, singledispatch, tempora, websocket-client
six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, more-itertools, moto, ncclient, pathlib2, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, singledispatch, tempora, websocket-client
smmap2==2.0.5 # via gitdb2
strict-rfc3339==0.7
tempora==1.14 # via portend

View file

@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile -o requirements/static/fedora-28.txt requirements/zeromq.txt requirements/raet.txt requirements/pytest.txt requirements/static/fedora-28.in
# pip-compile -o requirements/static/fedora-28.txt requirements/zeromq.txt requirements/pytest.txt requirements/static/fedora-28.in
#
apache-libcloud==1.0.0
asn1crypto==0.24.0 # via cryptography
@ -33,7 +33,7 @@ docker-pycreds==0.4.0 # via docker
docker==3.7.0
docutils==0.14 # via botocore
ecdsa==0.13 # via python-jose
enum34==1.1.6 # via cryptography, raet
enum34==1.1.6 # via cryptography
funcsigs==1.0.2 # via pytest
functools32==3.2.3.post2 # via jsonschema
future==0.17.1 # via python-jose
@ -54,7 +54,6 @@ junos-eznc==2.2.0
jxmlease==1.0.1
keyring==5.7.1
kubernetes==3.0.0
libnacl==1.6.1
lxml==4.3.2 # via junos-eznc, ncclient
markupsafe==1.1.1
mock==1.0.1
@ -95,7 +94,6 @@ pytz==2018.9 # via moto, tempora
pyvmomi==6.7.1.2018.12
pyyaml==3.13
pyzmq==18.0.1 ; python_version != "3.4"
raet==0.6.8
requests==2.21.0
responses==0.10.5 # via moto
rfc3987==1.3.8
@ -107,7 +105,7 @@ scp==0.13.1 # via junos-eznc
selectors2==2.0.1 # via ncclient
setproctitle==1.1.10
singledispatch==3.4.0.3 # via tornado
six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, more-itertools, moto, ncclient, pathlib2, pynacl, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, raet, responses, salttesting, singledispatch, tempora, websocket-client
six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, more-itertools, moto, ncclient, pathlib2, pynacl, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, singledispatch, tempora, websocket-client
smmap2==2.0.5 # via gitdb2
strict-rfc3339==0.7
tempora==1.14 # via portend

View file

@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile -o requirements/static/fedora-29.txt requirements/zeromq.txt requirements/raet.txt requirements/pytest.txt requirements/static/fedora-29.in
# pip-compile -o requirements/static/fedora-29.txt requirements/zeromq.txt requirements/pytest.txt requirements/static/fedora-29.in
#
apache-libcloud==1.0.0
asn1crypto==0.24.0 # via cryptography
@ -33,7 +33,7 @@ docker-pycreds==0.4.0 # via docker
docker==3.7.0
docutils==0.14 # via botocore
ecdsa==0.13 # via python-jose
enum34==1.1.6 # via cryptography, raet
enum34==1.1.6 # via cryptography
funcsigs==1.0.2 # via pytest
functools32==3.2.3.post2 # via jsonschema
future==0.17.1 # via python-jose
@ -54,7 +54,6 @@ junos-eznc==2.2.0
jxmlease==1.0.1
keyring==5.7.1
kubernetes==3.0.0
libnacl==1.6.1
lxml==4.3.2 # via junos-eznc, ncclient
markupsafe==1.1.1
mock==1.0.1
@ -95,7 +94,6 @@ pytz==2018.9 # via moto, tempora
pyvmomi==6.7.1.2018.12
pyyaml==3.13
pyzmq==18.0.1 ; python_version != "3.4"
raet==0.6.8
requests==2.21.0
responses==0.10.5 # via moto
rfc3987==1.3.8
@ -107,7 +105,7 @@ scp==0.13.1 # via junos-eznc
selectors2==2.0.1 # via ncclient
setproctitle==1.1.10
singledispatch==3.4.0.3 # via tornado
six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, more-itertools, moto, ncclient, pathlib2, pynacl, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, raet, responses, salttesting, singledispatch, tempora, websocket-client
six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, more-itertools, moto, ncclient, pathlib2, pynacl, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, singledispatch, tempora, websocket-client
smmap2==2.0.5 # via gitdb2
strict-rfc3339==0.7
tempora==1.14 # via portend

View file

@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile -o requirements/static/opensuse-42.txt requirements/zeromq.txt requirements/raet.txt requirements/pytest.txt requirements/static/opensuse-42.in
# pip-compile -o requirements/static/opensuse-42.txt requirements/zeromq.txt requirements/pytest.txt requirements/static/opensuse-42.in
#
apache-libcloud==1.0.0
asn1crypto==0.24.0 # via cryptography
@ -32,7 +32,7 @@ docker-pycreds==0.4.0 # via docker
docker==3.7.0
docutils==0.14 # via botocore
ecdsa==0.13 # via python-jose
enum34==1.1.6 # via cryptography, raet
enum34==1.1.6 # via cryptography
funcsigs==1.0.2 # via pytest
functools32==3.2.3.post2 # via jsonschema
future==0.17.1 # via python-jose
@ -52,7 +52,6 @@ jsonpickle==1.1 # via aws-xray-sdk
jsonschema==2.6.0
keyring==5.7.1
kubernetes==3.0.0
libnacl==1.6.1
markupsafe==1.1.1
meld3==1.0.2 # via supervisor
mock==1.0.1
@ -88,7 +87,6 @@ pytz==2018.9 # via moto, tempora
pyvmomi==6.7.1.2018.12
pyyaml==3.13
pyzmq==18.0.1 ; python_version != "3.4"
raet==0.6.8
requests==2.21.0
responses==0.10.5 # via moto
rfc3987==1.3.8
@ -99,7 +97,7 @@ scandir==1.10.0 # via pathlib2
setproctitle==1.1.10
setuptools-scm==3.2.0
singledispatch==3.4.0.3 # via tornado
six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, kubernetes, more-itertools, moto, pathlib2, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, raet, responses, salttesting, singledispatch, tempora, websocket-client
six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, kubernetes, more-itertools, moto, pathlib2, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, singledispatch, tempora, websocket-client
smmap2==2.0.5 # via gitdb2
strict-rfc3339==0.7
supervisor==3.3.5 ; python_version < "3"

View file

@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile -o requirements/static/opensuse-leap-15.txt requirements/zeromq.txt requirements/raet.txt requirements/pytest.txt requirements/static/opensuse-leap-15.in
# pip-compile -o requirements/static/opensuse-leap-15.txt requirements/zeromq.txt requirements/pytest.txt requirements/static/opensuse-leap-15.in
#
apache-libcloud==1.0.0
asn1crypto==0.24.0 # via cryptography
@ -32,7 +32,7 @@ docker-pycreds==0.4.0 # via docker
docker==3.7.0
docutils==0.14 # via botocore
ecdsa==0.13 # via python-jose
enum34==1.1.6 # via cryptography, raet
enum34==1.1.6 # via cryptography
funcsigs==1.0.2 # via pytest
functools32==3.2.3.post2 # via jsonschema
future==0.17.1 # via python-jose
@ -52,7 +52,6 @@ jsonpickle==1.1 # via aws-xray-sdk
jsonschema==2.6.0
keyring==5.7.1
kubernetes==3.0.0
libnacl==1.6.1
markupsafe==1.1.1
mock==1.0.1
more-itertools==5.0.0
@ -87,7 +86,6 @@ pytz==2018.9 # via moto, tempora
pyvmomi==6.7.1.2018.12
pyyaml==3.13
pyzmq==18.0.1 ; python_version != "3.4"
raet==0.6.8
requests==2.21.0
responses==0.10.5 # via moto
rfc3987==1.3.8
@ -98,7 +96,7 @@ scandir==1.10.0 # via pathlib2
setproctitle==1.1.10
setuptools-scm==3.2.0
singledispatch==3.4.0.3 # via tornado
six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, kubernetes, more-itertools, moto, pathlib2, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, raet, responses, salttesting, singledispatch, tempora, websocket-client
six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, kubernetes, more-itertools, moto, pathlib2, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, singledispatch, tempora, websocket-client
smmap2==2.0.5 # via gitdb2
strict-rfc3339==0.7
tempora==1.14 # via portend

View file

@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile -o requirements/static/ubuntu-14.04.txt requirements/zeromq.txt requirements/raet.txt requirements/pytest.txt requirements/static/ubuntu-14.04.in
# pip-compile -o requirements/static/ubuntu-14.04.txt requirements/zeromq.txt requirements/pytest.txt requirements/static/ubuntu-14.04.in
#
apache-libcloud==1.0.0
asn1crypto==0.24.0 # via cryptography
@ -32,7 +32,7 @@ docker-pycreds==0.4.0 # via docker
docker==3.7.0
docutils==0.14 # via botocore
ecdsa==0.13 # via python-jose
enum34==1.1.6 # via cryptography, raet
enum34==1.1.6 # via cryptography
funcsigs==1.0.2 # via pytest
functools32==3.2.3.post2 # via jsonschema
future==0.17.1 # via python-jose
@ -53,7 +53,6 @@ junos-eznc==2.2.0
jxmlease==1.0.1
keyring==5.7.1
kubernetes==3.0.0
libnacl==1.6.1
lxml==4.3.2 # via junos-eznc, ncclient
markupsafe==1.1.1
mock==1.0.1
@ -93,7 +92,6 @@ pytz==2018.9 # via moto, tempora
pyvmomi==6.7.1.2018.12
pyyaml==3.13
pyzmq==18.0.1 ; python_version != "3.4"
raet==0.6.8
requests==2.21.0
responses==0.10.5 # via moto
rfc3987==1.3.8
@ -105,7 +103,7 @@ scp==0.13.1 # via junos-eznc
selectors2==2.0.1 # via ncclient
setproctitle==1.1.10
singledispatch==3.4.0.3 # via tornado
six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, more-itertools, moto, ncclient, pathlib2, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, raet, responses, salttesting, singledispatch, tempora, websocket-client
six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, more-itertools, moto, ncclient, pathlib2, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, singledispatch, tempora, websocket-client
smmap2==2.0.5 # via gitdb2
strict-rfc3339==0.7
tempora==1.14 # via portend

View file

@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile -o requirements/static/ubuntu-16.04.txt requirements/zeromq.txt requirements/raet.txt requirements/pytest.txt requirements/static/ubuntu-16.04.in
# pip-compile -o requirements/static/ubuntu-16.04.txt requirements/zeromq.txt requirements/pytest.txt requirements/static/ubuntu-16.04.in
#
apache-libcloud==1.0.0
asn1crypto==0.24.0 # via cryptography
@ -32,7 +32,7 @@ docker-pycreds==0.4.0 # via docker
docker==3.7.0
docutils==0.14 # via botocore
ecdsa==0.13 # via python-jose
enum34==1.1.6 # via cryptography, raet
enum34==1.1.6 # via cryptography
funcsigs==1.0.2 # via pytest
functools32==3.2.3.post2 # via jsonschema
future==0.17.1 # via python-jose
@ -53,7 +53,6 @@ junos-eznc==2.2.0
jxmlease==1.0.1
keyring==5.7.1
kubernetes==3.0.0
libnacl==1.6.1
lxml==4.3.2 # via junos-eznc, ncclient
markupsafe==1.1.1
mock==1.0.1
@ -93,7 +92,6 @@ pytz==2018.9 # via moto, tempora
pyvmomi==6.7.1.2018.12
pyyaml==3.13
pyzmq==18.0.1 ; python_version != "3.4"
raet==0.6.8
requests==2.21.0
responses==0.10.5 # via moto
rfc3987==1.3.8
@ -105,7 +103,7 @@ scp==0.13.1 # via junos-eznc
selectors2==2.0.1 # via ncclient
setproctitle==1.1.10
singledispatch==3.4.0.3 # via tornado
six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, more-itertools, moto, ncclient, pathlib2, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, raet, responses, salttesting, singledispatch, tempora, websocket-client
six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, more-itertools, moto, ncclient, pathlib2, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, singledispatch, tempora, websocket-client
smmap2==2.0.5 # via gitdb2
strict-rfc3339==0.7
tempora==1.14 # via portend

View file

@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile -o requirements/static/ubuntu-18.04.txt requirements/zeromq.txt requirements/raet.txt requirements/pytest.txt requirements/static/ubuntu-18.04.in
# pip-compile -o requirements/static/ubuntu-18.04.txt requirements/zeromq.txt requirements/pytest.txt requirements/static/ubuntu-18.04.in
#
apache-libcloud==1.0.0
asn1crypto==0.24.0 # via cryptography
@ -32,7 +32,7 @@ docker-pycreds==0.4.0 # via docker
docker==3.7.0
docutils==0.14 # via botocore
ecdsa==0.13 # via python-jose
enum34==1.1.6 # via cryptography, raet
enum34==1.1.6 # via cryptography
funcsigs==1.0.2 # via pytest
functools32==3.2.3.post2 # via jsonschema
future==0.17.1 # via python-jose
@ -53,7 +53,6 @@ junos-eznc==2.2.0
jxmlease==1.0.1
keyring==5.7.1
kubernetes==3.0.0
libnacl==1.6.1
lxml==4.3.2 # via junos-eznc, ncclient
markupsafe==1.1.1
mock==1.0.1
@ -93,7 +92,6 @@ pytz==2018.9 # via moto, tempora
pyvmomi==6.7.1.2018.12
pyyaml==3.13
pyzmq==18.0.1 ; python_version != "3.4"
raet==0.6.8
requests==2.21.0
responses==0.10.5 # via moto
rfc3987==1.3.8
@ -105,7 +103,7 @@ scp==0.13.1 # via junos-eznc
selectors2==2.0.1 # via ncclient
setproctitle==1.1.10
singledispatch==3.4.0.3 # via tornado
six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, more-itertools, moto, ncclient, pathlib2, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, raet, responses, salttesting, singledispatch, tempora, websocket-client
six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, more-itertools, moto, ncclient, pathlib2, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, singledispatch, tempora, websocket-client
smmap2==2.0.5 # via gitdb2
strict-rfc3339==0.7
tempora==1.14 # via portend

View file

@ -0,0 +1,37 @@
apache-libcloud==1.0.0
boto3
boto>=2.46.0
dmidecode
dnspython
docker==2.7.0
ioflo
jsonschema<=2.6.0
keyring==5.7.1
kubernetes<4.0
mock<1.1.0
more-itertools==5.0.0
msgpack-python >= 0.4.2, != 0.5.5
patch
psutil
pycryptodomex
pyopenssl
python-etcd==0.4.2
python-gnupg
pyvmomi
rfc3987
salttesting==2017.6.1
sed
setproctitle
strict_rfc3339
supervisor; python_version < '3'
timelib
tornado<5.0
virtualenv
# If running under windows, please uncomment the following 2 requirements before running
# pip-compile -o requirements/static/windows.txt requirements/zeromq.txt requirements/raet.txt requirements/pytest.txt requirements/static/windows.in
#
# On non windows, please copy the following 2 requirements to the generated windows.txt, un-commented
#pywin32==223
#wmi==1.4.9

View file

@ -0,0 +1,88 @@
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile -o requirements/static/windows.txt requirements/zeromq.txt requirements/pytest.txt requirements/static/windows.in
#
apache-libcloud==1.0.0
asn1crypto==0.24.0 # via cryptography
atomicwrites==1.3.0 # via pytest
attrs==19.1.0 # via pytest
backports-abc==0.5 # via tornado
backports.ssl-match-hostname==3.7.0.1 # via docker, websocket-client
boto3==1.9.117
boto==2.49.0
botocore==1.12.117 # via boto3, s3transfer
cachetools==3.1.0 # via google-auth
certifi==2019.3.9 # via kubernetes, requests, tornado
cffi==1.12.2 # via cryptography
chardet==3.0.4 # via requests
coverage==4.5.3 # via pytest-cov
cryptography==2.6.1 # via pyopenssl
dmidecode==0.9.0
dnspython==1.16.0
docker-pycreds==0.4.0 # via docker
docker==2.7.0
docutils==0.14 # via botocore
enum34==1.1.6 # via cryptography
funcsigs==1.0.2 # via pytest
functools32==3.2.3.post2 # via jsonschema
futures==3.2.0 ; python_version < "3.0"
google-auth==1.6.3 # via kubernetes
idna==2.8 # via requests
ioflo==1.7.5
ipaddress==1.0.22 # via cryptography, docker, kubernetes
jinja2==2.10
jmespath==0.9.4 # via boto3, botocore
jsonschema==2.6.0
keyring==5.7.1
kubernetes==3.0.0
markupsafe==1.1.1
meld3==1.0.2 # via supervisor
mock==1.0.1
more-itertools==5.0.0
msgpack-python==0.5.6
msgpack==0.6.1
patch==1.16
pathlib2==2.3.3 # via pytest
pluggy==0.9.0 # via pytest
psutil==5.6.1
py==1.8.0 # via pytest
pyasn1-modules==0.2.4 # via google-auth
pyasn1==0.4.5 # via pyasn1-modules, rsa
pycparser==2.19 # via cffi
pycrypto==2.6.1
pycryptodomex==3.7.3
pyopenssl==19.0.0
pytest-cov==2.6.1
pytest-helpers-namespace==2019.1.8
pytest-salt-runtests-bridge==2019.1.30
pytest-salt==2018.12.8
pytest-tempdir==2018.8.11
pytest-timeout==1.3.3
pytest==4.3.1
python-dateutil==2.8.0 # via botocore, kubernetes
python-etcd==0.4.2
python-gnupg==0.4.4
pyvmomi==6.7.1.2018.12
pyyaml==3.13
pyzmq==18.0.1 ; python_version != "3.4"
requests==2.21.0
rfc3987==1.3.8
rsa==4.0 # via google-auth
s3transfer==0.2.0 # via boto3
salttesting==2017.6.1
scandir==1.10.0 # via pathlib2
sed==0.3.1
setproctitle==1.1.10
singledispatch==3.4.0.3 # via tornado
six==1.12.0 # via cryptography, docker, docker-pycreds, google-auth, kubernetes, more-itertools, pathlib2, pyopenssl, pytest, python-dateutil, pyvmomi, salttesting, singledispatch, websocket-client
strict-rfc3339==0.7
supervisor==3.3.5 ; python_version < "3"
timelib==0.2.4
tornado==4.5.3 ; python_version < "3"
urllib3==1.24.1 # via botocore, kubernetes, python-etcd, requests
virtualenv==16.4.3
websocket-client==0.40.0 # via docker, kubernetes
pywin32==223
wmi==1.4.9

View file

@ -20,7 +20,6 @@ from salt.exceptions import (
CommandExecutionError, MinionError
)
import salt.client
import salt.crypt
import salt.loader
import salt.payload
import salt.transport.client

View file

@ -1193,6 +1193,57 @@ def _clean_value(key, val):
return val
def _windows_os_release_grain(caption, product_type):
'''
helper function for getting the osrelease grain
:return:
'''
# This creates the osrelease grain based on the Windows Operating
# System Product Name. As long as Microsoft maintains a similar format
# this should be future proof
version = 'Unknown'
release = ''
if 'Server' in caption:
for item in caption.split(' '):
# If it's all digits, then it's version
if re.match(r'\d+', item):
version = item
# If it starts with R and then numbers, it's the release
# ie: R2
if re.match(r'^R\d+$', item):
release = item
os_release = '{0}Server{1}'.format(version, release)
else:
for item in caption.split(' '):
# If it's a number, decimal number, Thin or Vista, then it's the
# version
if re.match(r'^(\d+(\.\d+)?)|Thin|Vista|XP$', item):
version = item
os_release = version
# If the version is still Unknown, revert back to the old way of getting
# the os_release
# https://github.com/saltstack/salt/issues/52339
if os_release in ['Unknown']:
os_release = platform.release()
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.
# (Product Type 1 is Desktop, Everything else is Server)
if product_type > 1 and os_release in server:
os_release = server[os_release]
return os_release
def _windows_platform_data():
'''
Use the platform module for as much as we can.
@ -1240,7 +1291,6 @@ def _windows_platform_data():
except IndexError:
log.debug('Motherboard info not available on this system')
os_release = platform.release()
kernel_version = platform.version()
info = salt.utils.win_osinfo.get_os_version_info()
net_info = salt.utils.win_osinfo.get_join_info()
@ -1249,28 +1299,8 @@ def _windows_platform_data():
if info['ServicePackMajor'] > 0:
service_pack = ''.join(['SP', six.text_type(info['ServicePackMajor'])])
# This creates the osrelease grain based on the Windows Operating
# System Product Name. As long as Microsoft maintains a similar format
# this should be future proof
version = 'Unknown'
release = ''
if 'Server' in osinfo.Caption:
for item in osinfo.Caption.split(' '):
# If it's all digits, then it's version
if re.match(r'\d+', item):
version = item
# If it starts with R and then numbers, it's the release
# ie: R2
if re.match(r'^R\d+$', item):
release = item
os_release = '{0}Server{1}'.format(version, release)
else:
for item in osinfo.Caption.split(' '):
# If it's a number, decimal number, Thin or Vista, then it's the
# version
if re.match(r'^(\d+(\.\d+)?)|Thin|Vista$', item):
version = item
os_release = version
os_release = _windows_os_release_grain(caption=osinfo.Caption,
product_type=osinfo.ProductType)
grains = {
'kernelrelease': _clean_value('kernelrelease', osinfo.Version),
@ -1558,6 +1588,10 @@ def _parse_cpe_name(cpe):
Info: https://csrc.nist.gov/projects/security-content-automation-protocol/scap-specifications/cpe
Note: cpe:2.3:part:vendor:product:version:update:edition:lang:sw_edition:target_sw:target_hw:other
however some OS's do not have the full 13 elements, for example:
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
:param cpe:
:return:
'''
@ -1573,7 +1607,11 @@ def _parse_cpe_name(cpe):
ret['vendor'], ret['product'], ret['version'] = cpe[2:5]
ret['phase'] = cpe[5] if len(cpe) > 5 else None
ret['part'] = part.get(cpe[1][1:])
elif len(cpe) == 13 and cpe[1] == '2.3': # WFN to a string
elif len(cpe) == 6 and cpe[1] == '2.3': # WFN to a string
ret['vendor'], ret['product'], ret['version'] = [x if x != '*' else None for x in cpe[3:6]]
ret['phase'] = None
ret['part'] = part.get(cpe[2])
elif len(cpe) > 7 and len(cpe) <= 13 and cpe[1] == '2.3': # WFN to a string
ret['vendor'], ret['product'], ret['version'], ret['phase'] = [x if x != '*' else None for x in cpe[3:7]]
ret['part'] = part.get(cpe[2])
@ -2103,6 +2141,12 @@ def locale_info():
def hostname():
'''
Return fqdn, hostname, domainname
.. note::
On Windows the ``domain`` grain may refer to the dns entry for the host
instead of the Windows domain to which the host is joined. It may also
be empty if not a part of any domain. Refer to the ``windowsdomain``
grain instead
'''
# This is going to need some work
# Provides:

View file

@ -30,18 +30,19 @@ __func_alias__ = {
def list_(return_yaml=True,
include_pillar=True,
include_opts=True):
include_opts=True,
**kwargs):
'''
List the beacons currently configured on the minion
:param return_yaml: Whether to return YAML formatted output,
default True
default ``True``
:param include_pillar: Whether to include beacons that are
configured in pillar, default is True.
configured in pillar, default is ``True``.
:param include_opts: Whether to include beacons that are
configured in opts, default is True.
configured in opts, default is ``True``.
:return: List of currently configured Beacons.
@ -61,7 +62,9 @@ def list_(return_yaml=True,
'include_opts': include_opts},
'manage_beacons')
if res:
event_ret = eventer.get_event(tag='/salt/minion/minion_beacons_list_complete', wait=30)
event_ret = eventer.get_event(
tag='/salt/minion/minion_beacons_list_complete',
wait=kwargs.get('timeout', 30))
log.debug('event_ret %s', event_ret)
if event_ret and event_ret['complete']:
beacons = event_ret['beacons']
@ -82,11 +85,12 @@ def list_(return_yaml=True,
return {'beacons': {}}
def list_available(return_yaml=True):
def list_available(return_yaml=True, **kwargs):
'''
List the beacons currently available on the minion
:param return_yaml: Whether to return YAML formatted output, default True
:param return_yaml: Whether to return YAML formatted output, default
``True``
:return: List of currently configured Beacons.
CLI Example:
@ -102,7 +106,9 @@ def list_available(return_yaml=True):
eventer = salt.utils.event.get_event('minion', opts=__opts__)
res = __salt__['event.fire']({'func': 'list_available'}, 'manage_beacons')
if res:
event_ret = eventer.get_event(tag='/salt/minion/minion_beacons_list_available_complete', wait=30)
event_ret = eventer.get_event(
tag='/salt/minion/minion_beacons_list_available_complete',
wait=kwargs.get('timeout', 30))
if event_ret and event_ret['complete']:
beacons = event_ret['beacons']
except KeyError:
@ -134,17 +140,17 @@ def add(name, beacon_data, **kwargs):
.. code-block:: bash
salt '*' beacons.add ps "[{'salt-master': 'stopped'}, {'apache2': 'stopped'}]"
salt '*' beacons.add ps "[{'processes': {'salt-master': 'stopped', 'apache2': 'stopped'}}]"
'''
ret = {'comment': 'Failed to add beacon {0}.'.format(name),
'result': False}
if name in list_(return_yaml=False):
if name in list_(return_yaml=False, **kwargs):
ret['comment'] = 'Beacon {0} is already configured.'.format(name)
return ret
if name not in list_available(return_yaml=False):
if name not in list_available(return_yaml=False, **kwargs):
ret['comment'] = 'Beacon "{0}" is not available.'.format(name)
return ret
@ -160,7 +166,9 @@ def add(name, beacon_data, **kwargs):
'func': 'validate_beacon'},
'manage_beacons')
if res:
event_ret = eventer.get_event(tag='/salt/minion/minion_beacon_validation_complete', wait=30)
event_ret = eventer.get_event(
tag='/salt/minion/minion_beacon_validation_complete',
wait=kwargs.get('timeout', 30))
valid = event_ret['valid']
vcomment = event_ret['vcomment']
@ -179,7 +187,9 @@ def add(name, beacon_data, **kwargs):
'beacon_data': beacon_data,
'func': 'add'}, 'manage_beacons')
if res:
event_ret = eventer.get_event(tag='/salt/minion/minion_beacon_add_complete', wait=30)
event_ret = eventer.get_event(
tag='/salt/minion/minion_beacon_add_complete',
wait=kwargs.get('timeout', 30))
if event_ret and event_ret['complete']:
beacons = event_ret['beacons']
if name in beacons and beacons[name] == beacon_data:
@ -213,7 +223,7 @@ def modify(name, beacon_data, **kwargs):
ret = {'comment': '',
'result': True}
current_beacons = list_(return_yaml=False)
current_beacons = list_(return_yaml=False, **kwargs)
if name not in current_beacons:
ret['comment'] = 'Beacon {0} is not configured.'.format(name)
return ret
@ -230,7 +240,9 @@ def modify(name, beacon_data, **kwargs):
'func': 'validate_beacon'},
'manage_beacons')
if res:
event_ret = eventer.get_event(tag='/salt/minion/minion_beacon_validation_complete', wait=30)
event_ret = eventer.get_event(
tag='/salt/minion/minion_beacon_validation_complete',
wait=kwargs.get('timeout', 30))
valid = event_ret['valid']
vcomment = event_ret['vcomment']
@ -274,7 +286,9 @@ def modify(name, beacon_data, **kwargs):
eventer = salt.utils.event.get_event('minion', opts=__opts__)
res = __salt__['event.fire']({'name': name, 'beacon_data': beacon_data, 'func': 'modify'}, 'manage_beacons')
if res:
event_ret = eventer.get_event(tag='/salt/minion/minion_beacon_modify_complete', wait=30)
event_ret = eventer.get_event(
tag='/salt/minion/minion_beacon_modify_complete',
wait=kwargs.get('timeout', 30))
if event_ret and event_ret['complete']:
beacons = event_ret['beacons']
if name in beacons and beacons[name] == beacon_data:
@ -318,7 +332,9 @@ def delete(name, **kwargs):
eventer = salt.utils.event.get_event('minion', opts=__opts__)
res = __salt__['event.fire']({'name': name, 'func': 'delete'}, 'manage_beacons')
if res:
event_ret = eventer.get_event(tag='/salt/minion/minion_beacon_delete_complete', wait=30)
event_ret = eventer.get_event(
tag='/salt/minion/minion_beacon_delete_complete',
wait=kwargs.get('timeout', 30))
if event_ret and event_ret['complete']:
beacons = event_ret['beacons']
if name not in beacons:
@ -334,7 +350,7 @@ def delete(name, **kwargs):
return ret
def save():
def save(**kwargs):
'''
Save all beacons on the minion
@ -350,7 +366,7 @@ def save():
ret = {'comment': [],
'result': True}
beacons = list_(return_yaml=False, include_pillar=False)
beacons = list_(return_yaml=False, include_pillar=False, **kwargs)
# move this file into an configurable opt
sfn = os.path.join(__opts__['config_dir'],
@ -367,7 +383,8 @@ def save():
fp_.write(yaml_out)
ret['comment'] = 'Beacons saved to {0}.'.format(sfn)
except (IOError, OSError):
ret['comment'] = 'Unable to write to beacons file at {0}. Check permissions.'.format(sfn)
ret['comment'] = 'Unable to write to beacons file at {0}. Check ' \
'permissions.'.format(sfn)
ret['result'] = False
return ret
@ -376,7 +393,8 @@ def enable(**kwargs):
'''
Enable all beacons on the minion
:return: Boolean and status message on success or failure of enable.
Returns:
bool: Boolean and status message on success or failure of enable.
CLI Example:
@ -395,7 +413,9 @@ def enable(**kwargs):
eventer = salt.utils.event.get_event('minion', opts=__opts__)
res = __salt__['event.fire']({'func': 'enable'}, 'manage_beacons')
if res:
event_ret = eventer.get_event(tag='/salt/minion/minion_beacons_enabled_complete', wait=30)
event_ret = eventer.get_event(
tag='/salt/minion/minion_beacons_enabled_complete',
wait=kwargs.get('timeout', 30))
if event_ret and event_ret['complete']:
beacons = event_ret['beacons']
if 'enabled' in beacons and beacons['enabled']:
@ -413,7 +433,7 @@ def enable(**kwargs):
def disable(**kwargs):
'''
Disable all beaconsd jobs on the minion
Disable all beacons jobs on the minion
:return: Boolean and status message on success or failure of disable.
@ -434,7 +454,9 @@ def disable(**kwargs):
eventer = salt.utils.event.get_event('minion', opts=__opts__)
res = __salt__['event.fire']({'func': 'disable'}, 'manage_beacons')
if res:
event_ret = eventer.get_event(tag='/salt/minion/minion_beacons_disabled_complete', wait=30)
event_ret = eventer.get_event(
tag='/salt/minion/minion_beacons_disabled_complete',
wait=kwargs.get('timeout', 30))
log.debug('event_ret %s', event_ret)
if event_ret and event_ret['complete']:
beacons = event_ret['beacons']
@ -486,7 +508,7 @@ def enable_beacon(name, **kwargs):
if 'test' in kwargs and kwargs['test']:
ret['comment'] = 'Beacon {0} would be enabled.'.format(name)
else:
_beacons = list_(return_yaml=False)
_beacons = list_(return_yaml=False, **kwargs)
if name not in _beacons:
ret['comment'] = 'Beacon {0} is not currently configured.'.format(name)
ret['result'] = False
@ -496,7 +518,9 @@ def enable_beacon(name, **kwargs):
eventer = salt.utils.event.get_event('minion', opts=__opts__)
res = __salt__['event.fire']({'func': 'enable_beacon', 'name': name}, 'manage_beacons')
if res:
event_ret = eventer.get_event(tag='/salt/minion/minion_beacon_enabled_complete', wait=30)
event_ret = eventer.get_event(
tag='/salt/minion/minion_beacon_enabled_complete',
wait=kwargs.get('timeout', 30))
if event_ret and event_ret['complete']:
beacons = event_ret['beacons']
beacon_config_dict = _get_beacon_config_dict(beacons[name])
@ -542,7 +566,7 @@ def disable_beacon(name, **kwargs):
if 'test' in kwargs and kwargs['test']:
ret['comment'] = 'Beacons would be enabled.'
else:
_beacons = list_(return_yaml=False)
_beacons = list_(return_yaml=False, **kwargs)
if name not in _beacons:
ret['comment'] = 'Beacon {0} is not currently configured.'.format(name)
ret['result'] = False
@ -552,7 +576,9 @@ def disable_beacon(name, **kwargs):
eventer = salt.utils.event.get_event('minion', opts=__opts__)
res = __salt__['event.fire']({'func': 'disable_beacon', 'name': name}, 'manage_beacons')
if res:
event_ret = eventer.get_event(tag='/salt/minion/minion_beacon_disabled_complete', wait=30)
event_ret = eventer.get_event(
tag='/salt/minion/minion_beacon_disabled_complete',
wait=kwargs.get('timeout', 30))
if event_ret and event_ret['complete']:
beacons = event_ret['beacons']
beacon_config_dict = _get_beacon_config_dict(beacons[name])
@ -594,7 +620,9 @@ def reset(**kwargs):
eventer = salt.utils.event.get_event('minion', opts=__opts__)
res = __salt__['event.fire']({'func': 'reset'}, 'manage_beacons')
if res:
event_ret = eventer.get_event(tag='/salt/minion/minion_beacon_reset_complete', wait=30)
event_ret = eventer.get_event(
tag='/salt/minion/minion_beacon_reset_complete',
wait=kwargs.get('timeout', 30))
if event_ret and event_ret['complete']:
ret['result'] = True
ret['comment'] = 'Beacon configuration reset.'

View file

@ -570,7 +570,11 @@ def _run(cmd,
run_env = env
else:
run_env = os.environ.copy()
if salt.utils.platform.is_windows():
import nt
run_env = nt.environ.copy()
else:
run_env = os.environ.copy()
run_env.update(env)
if prepend_path:
@ -3284,7 +3288,12 @@ def shell_info(shell, list_modules=False):
# salt-call will general have home set, the salt-minion service may not
# We need to assume ports of unix shells to windows will look after
# themselves in setting HOME as they do it in many different ways
newenv = os.environ
if salt.utils.platform.is_windows():
import nt
newenv = nt.environ
else:
newenv = os.environ
if ('HOME' not in newenv) and (not salt.utils.platform.is_windows()):
newenv['HOME'] = os.path.expanduser('~')
log.debug('HOME environment set to %s', newenv['HOME'])

View file

@ -53,11 +53,10 @@ def _render_tab(lst):
for pre in lst['pre']:
ret.append('{0}\n'.format(pre))
for cron in lst['crons']:
ret.append('{0} {1} {2} {3}\n'.format(cron['path'],
cron['mask'],
cron['cmd'],
TAG
)
ret.append('{0} {1} {2}\n'.format(cron['path'],
cron['mask'],
cron['cmd'],
)
)
return ret
@ -191,23 +190,18 @@ def list_tab(user):
'pre': []
}
flag = False
comment = None
tag = '# Line managed by Salt, do not edit'
for line in data.splitlines():
if line.endswith(tag):
if len(line.split()) > 3:
# Appears to be a standard incron line
comps = line.split()
path = comps[0]
mask = comps[1]
(cmd, comment) = ' '.join(comps[2:]).split(' # ')
if len(line.split()) > 3:
# Appears to be a standard incron line
comps = line.split()
path = comps[0]
mask = comps[1]
cmd = ' '.join(comps[2:])
dat = {'path': path,
'mask': mask,
'cmd': cmd,
'comment': comment}
ret['crons'].append(dat)
comment = None
dat = {'path': path,
'mask': mask,
'cmd': cmd}
ret['crons'].append(dat)
else:
ret['pre'].append(line)
return ret

View file

@ -823,6 +823,7 @@ def active_tcp():
return {}
@salt.utils.decorators.path.which('traceroute')
def traceroute(host):
'''
Performs a traceroute to a 3rd party host
@ -840,29 +841,23 @@ def traceroute(host):
salt '*' network.traceroute archlinux.org
'''
ret = []
if not salt.utils.path.which('traceroute'):
log.info('This minion does not have traceroute installed')
return ret
cmd = 'traceroute {0}'.format(salt.utils.network.sanitize_host(host))
out = __salt__['cmd.run'](cmd)
# Parse version of traceroute
if salt.utils.platform.is_sunos() or salt.utils.platform.is_aix():
traceroute_version = [0, 0, 0]
else:
cmd2 = 'traceroute --version'
out2 = __salt__['cmd.run'](cmd2)
version_out = __salt__['cmd.run']('traceroute --version')
try:
# Linux traceroute version looks like:
# Modern traceroute for Linux, version 2.0.19, Dec 10 2012
# Darwin and FreeBSD traceroute version looks like: Version 1.4a12+[FreeBSD|Darwin]
traceroute_version_raw = re.findall(r'.*[Vv]ersion (\d+)\.([\w\+]+)\.*(\w*)', out2)[0]
log.debug('traceroute_version_raw: %s', traceroute_version_raw)
version_raw = re.findall(r'.*[Vv]ersion (\d+)\.([\w\+]+)\.*(\w*)', version_out)[0]
log.debug('traceroute_version_raw: %s', version_raw)
traceroute_version = []
for t in traceroute_version_raw:
for t in version_raw:
try:
traceroute_version.append(int(t))
except ValueError:
@ -877,26 +872,28 @@ def traceroute(host):
traceroute_version = [0, 0, 0]
for line in out.splitlines():
# Pre requirements for line parsing
skip_line = False
if ' ' not in line:
continue
skip_line = True
if line.startswith('traceroute'):
continue
skip_line = True
if salt.utils.platform.is_aix():
if line.startswith('trying to get source for'):
continue
skip_line = True
if line.startswith('source should be'):
continue
skip_line = True
if line.startswith('outgoing MTU'):
continue
skip_line = True
if line.startswith('fragmentation required'):
continue
skip_line = True
if skip_line:
log.debug('Skipping traceroute output line: %s', line)
continue
# Parse output from unix variants
if 'Darwin' in six.text_type(traceroute_version[1]) or \
'FreeBSD' in six.text_type(traceroute_version[1]) or \
'FreeBSD' in six.text_type(traceroute_version[1]) or \
__grains__['kernel'] in ('SunOS', 'AIX'):
try:
traceline = re.findall(r'\s*(\d*)\s+(.*)\s+\((.*)\)\s+(.*)$', line)[0]
@ -923,14 +920,15 @@ def traceroute(host):
except IndexError:
result = {}
# Parse output from specific version ranges
elif (traceroute_version[0] >= 2 and traceroute_version[2] >= 14
or traceroute_version[0] >= 2 and traceroute_version[1] > 0):
comps = line.split(' ')
if comps[1] == '* * *':
if len(comps) >= 2 and comps[1] == '* * *':
result = {
'count': int(comps[0]),
'hostname': '*'}
else:
elif len(comps) >= 5:
result = {
'count': int(comps[0]),
'hostname': comps[1].split()[0],
@ -938,21 +936,29 @@ def traceroute(host):
'ms1': float(comps[2].split()[0]),
'ms2': float(comps[3].split()[0]),
'ms3': float(comps[4].split()[0])}
else:
result = {}
# Parse anything else
else:
comps = line.split()
result = {
'count': comps[0],
'hostname': comps[1],
'ip': comps[2],
'ms1': comps[4],
'ms2': comps[6],
'ms3': comps[8],
'ping1': comps[3],
'ping2': comps[5],
'ping3': comps[7]}
if len(comps) >= 8:
result = {
'count': comps[0],
'hostname': comps[1],
'ip': comps[2],
'ms1': comps[4],
'ms2': comps[6],
'ms3': comps[8],
'ping1': comps[3],
'ping2': comps[5],
'ping3': comps[7]}
else:
result = {}
ret.append(result)
if not result:
log.warn('Cannot parse traceroute output line: %s', line)
return ret

View file

@ -63,10 +63,12 @@ def _ctl_cmd(cmd, name, conf_file, bin_env):
def _get_return(ret):
if ret['retcode'] == 0:
return ret['stdout']
else:
return ''
retmsg = ret['stdout']
if ret['retcode'] != 0:
# This is a non 0 exit code
if 'ERROR' not in retmsg:
retmsg = 'ERROR: {}'.format(retmsg)
return retmsg
def start(name='all', user=None, conf_file=None, bin_env=None):

View file

@ -133,7 +133,7 @@ try:
# Default to `en-US` (1033)
windll = ctypes.windll.kernel32
INSTALL_LANGUAGE = locale.windows_locale.get(
windll.GetSystemDefaultUILanguage(), 1033).replace('_', '-')
windll.GetSystemDefaultUILanguage(), 'en_US').replace('_', '-')
except ImportError:
HAS_WINDOWS_MODULES = False

View file

@ -26,6 +26,7 @@ import sys
import salt.utils.files
import salt.utils.path
import salt.utils.stringutils
import salt.utils.data
import salt.utils.platform
import salt.exceptions
from salt.ext import six
@ -366,7 +367,6 @@ def _get_certificate_obj(cert):
'''
if isinstance(cert, M2Crypto.X509.X509):
return cert
text = _text_or_file(cert)
text = get_pem_entry(text, pem_type='CERTIFICATE')
return M2Crypto.X509.load_cert_string(text)
@ -1391,11 +1391,10 @@ def create_certificate(
for ignore in list(_STATE_INTERNAL_KEYWORDS) + \
['listen_in', 'preqrequired', '__prerequired__']:
kwargs.pop(ignore, None)
certs = __salt__['publish.publish'](
tgt=ca_server,
fun='x509.sign_remote_certificate',
arg=six.text_type(kwargs))
arg=salt.utils.data.decode_dict(kwargs, to_str=True))
if not any(certs):
raise salt.exceptions.SaltInvocationError(

View file

@ -19,7 +19,6 @@ import inspect
import salt.loader
import salt.fileclient
import salt.minion
import salt.crypt
import salt.transport.client
import salt.utils.args
import salt.utils.cache

View file

@ -59,7 +59,7 @@ def present(name,
'changes': {},
'comment': []}
current_beacons = __salt__['beacons.list'](return_yaml=False)
current_beacons = __salt__['beacons.list'](return_yaml=False, **kwargs)
beacon_data = [{k: v} for k, v in six.iteritems(kwargs)]
if name in current_beacons:
@ -67,13 +67,13 @@ def present(name,
if beacon_data == current_beacons[name]:
ret['comment'].append('Job {0} in correct state'.format(name))
else:
if 'test' in __opts__ and __opts__['test']:
if __opts__.get('test'):
kwargs['test'] = True
result = __salt__['beacons.modify'](name, beacon_data)
result = __salt__['beacons.modify'](name, beacon_data, **kwargs)
ret['comment'].append(result['comment'])
ret['changes'] = result['changes']
else:
result = __salt__['beacons.modify'](name, beacon_data)
result = __salt__['beacons.modify'](name, beacon_data, **kwargs)
if not result['result']:
ret['result'] = result['result']
ret['comment'] = result['comment']
@ -86,12 +86,12 @@ def present(name,
ret['comment'].append(result['comment'])
else:
if 'test' in __opts__ and __opts__['test']:
if __opts__.get('test'):
kwargs['test'] = True
result = __salt__['beacons.add'](name, beacon_data, **kwargs)
ret['comment'].append(result['comment'])
else:
result = __salt__['beacons.add'](name, beacon_data)
result = __salt__['beacons.add'](name, beacon_data, **kwargs)
if not result['result']:
ret['result'] = result['result']
ret['comment'] = result['comment']
@ -100,8 +100,11 @@ def present(name,
ret['comment'].append('Adding {0} to beacons'.format(name))
if save:
result = __salt__['beacons.save']()
ret['comment'].append('Beacon {0} saved'.format(name))
if __opts__.get('test'):
ret['comment'].append('Beacon {0} would be saved'.format(name))
else:
result = __salt__['beacons.save']()
ret['comment'].append('Beacon {0} saved'.format(name))
ret['comment'] = '\n'.join(ret['comment'])
return ret
@ -128,9 +131,9 @@ def absent(name,
'changes': {},
'comment': []}
current_beacons = __salt__['beacons.list'](return_yaml=False)
current_beacons = __salt__['beacons.list'](return_yaml=False, **kwargs)
if name in current_beacons:
if 'test' in __opts__ and __opts__['test']:
if __opts__.get('test'):
kwargs['test'] = True
result = __salt__['beacons.delete'](name, **kwargs)
ret['comment'].append(result['comment'])
@ -146,8 +149,11 @@ def absent(name,
ret['comment'].append('{0} not configured in beacons'.format(name))
if save:
result = __salt__['beacons.save']()
ret['comment'].append('Beacon {0} saved'.format(name))
if __opts__.get('test'):
ret['comment'].append('Beacon {0} would be saved'.format(name))
else:
result = __salt__['beacons.save']()
ret['comment'].append('Beacon {0} saved'.format(name))
ret['comment'] = '\n'.join(ret['comment'])
return ret
@ -170,9 +176,9 @@ def enabled(name, **kwargs):
'changes': {},
'comment': []}
current_beacons = __salt__['beacons.list'](return_yaml=False)
current_beacons = __salt__['beacons.list'](return_yaml=False, **kwargs)
if name in current_beacons:
if 'test' in __opts__ and __opts__['test']:
if __opts__.get('test'):
kwargs['test'] = True
result = __salt__['beacons.enable_beacon'](name, **kwargs)
ret['comment'].append(result['comment'])
@ -208,9 +214,9 @@ def disabled(name, **kwargs):
'changes': {},
'comment': []}
current_beacons = __salt__['beacons.list'](return_yaml=False)
current_beacons = __salt__['beacons.list'](return_yaml=False, **kwargs)
if name in current_beacons:
if 'test' in __opts__ and __opts__['test']:
if __opts__.get('test'):
kwargs['test'] = True
result = __salt__['beacons.disable_beacon'](name, **kwargs)
ret['comment'].append(result['comment'])

View file

@ -2744,7 +2744,7 @@ def managed(name,
try:
if __opts__['test']:
if 'file.check_managed_changes' in __salt__:
ret['pchanges'] = __salt__['file.check_managed_changes'](
ret['changes'] = __salt__['file.check_managed_changes'](
name,
source,
source_hash,
@ -2775,15 +2775,17 @@ def managed(name,
reset=win_perms_reset)
except CommandExecutionError as exc:
if exc.strerror.startswith('Path not found'):
ret['pchanges'] = '{0} will be created'.format(name)
ret['changes'] = {name: 'will be created'}
if isinstance(ret['pchanges'], tuple):
ret['result'], ret['comment'] = ret['pchanges']
elif ret['pchanges']:
if isinstance(ret['changes'], tuple):
ret['result'], ret['comment'] = ret['changes']
elif ret['changes']:
ret['result'] = None
ret['comment'] = 'The file {0} is set to be changed'.format(name)
if 'diff' in ret['pchanges'] and not show_changes:
ret['pchanges']['diff'] = '<show_changes=False>'
ret['comment'] += ('\nNote: No changes made, actual changes may\n'
'be different due to other states.')
if 'diff' in ret['changes'] and not show_changes:
ret['changes']['diff'] = '<show_changes=False>'
else:
ret['result'] = True
ret['comment'] = 'The file {0} is in the correct state'.format(name)

View file

@ -86,7 +86,7 @@ def present(name, ip, clean=False): # pylint: disable=C0103
'''
ret = {'name': name,
'changes': {},
'result': None if __opts__['test'] else True,
'result': True,
'comment': ''}
if not isinstance(ip, list):
@ -135,6 +135,7 @@ def present(name, ip, clean=False): # pylint: disable=C0103
for addr, name in to_add:
if __opts__['test']:
ret['result'] = None
comments.append(
'Host {0} ({1}) would be added'.format(name, addr)
)
@ -149,6 +150,7 @@ def present(name, ip, clean=False): # pylint: disable=C0103
for addr, name in to_remove:
if __opts__['test']:
ret['result'] = None
comments.append(
'Host {0} ({1}) would be removed'.format(name, addr)
)

View file

@ -44,6 +44,9 @@ then a new cron job will be added to the user's crontab.
# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals
import logging
log = logging.getLogger(__name__)
def _check_cron(user,
path,
@ -56,6 +59,8 @@ def _check_cron(user,
arg_mask.sort()
lst = __salt__['incron.list_tab'](user)
if cmd.endswith('\n'):
cmd = cmd[:-1]
for cron in lst['crons']:
if path == cron['path'] and cron['cmd'] == cmd:
cron_mask = cron['mask'].split(',')

View file

@ -55,6 +55,7 @@ Ensure a Linux ACL list does not exist
# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals
import logging
import os
# Import salt libs
@ -62,8 +63,6 @@ from salt.ext import six
from salt.exceptions import CommandExecutionError
import salt.utils.path
import logging
log = logging.getLogger(__name__)
__virtualname__ = 'acl'
@ -108,6 +107,7 @@ def present(name, acl_type, acl_name='', perms='', recurse=False, force=False):
'comment': ''}
_octal = {'r': 4, 'w': 2, 'x': 1, '-': 0}
_octal_lookup = {0: '-', 1: 'r', 2: 'w', 4: 'x'}
if not os.path.exists(name):
ret['comment'] = '{0} does not exist'.format(name)
@ -159,20 +159,24 @@ def present(name, acl_type, acl_name='', perms='', recurse=False, force=False):
if not need_refresh:
ret['comment'] = 'Permissions are in the desired state'
else:
_num = user[_search_name]['octal']
new_perms = '{}{}{}'.format(_octal_lookup[_num & 1],
_octal_lookup[_num & 2],
_octal_lookup[_num & 4])
changes = {'new': {'acl_name': acl_name,
'acl_type': acl_type,
'perms': perms},
'old': {'acl_name': acl_name,
'acl_type': acl_type,
'perms': six.text_type(user[_search_name]['octal'])}}
'perms': new_perms}}
if __opts__['test']:
ret.update({'comment': 'Updated permissions will be applied for '
'{0}: {1} -> {2}'.format(
acl_name,
six.text_type(user[_search_name]['octal']),
perms),
'result': None, 'pchanges': changes})
'{0}: {1} -> {2}'.format(
acl_name,
new_perms,
perms),
'result': None, 'pchanges': changes})
return ret
try:
if force:

View file

@ -10,7 +10,7 @@ import logging
import socket
import weakref
import time
import threading
import sys
# Import 3rd-party libs
import msgpack
@ -20,7 +20,8 @@ import tornado
import tornado.gen
import tornado.netutil
import tornado.concurrent
from tornado.locks import Semaphore
import tornado.queues
from tornado.locks import Lock
from tornado.ioloop import IOLoop, TimeoutError as TornadoTimeoutError
from tornado.iostream import IOStream
# Import Salt libs
@ -84,6 +85,11 @@ class FutureWithTimeout(tornado.concurrent.Future):
self.set_exception(exc)
class IPCExceptionProxy(object):
def __init__(self, orig_info):
self.orig_info = orig_info
class IPCServer(object):
'''
A Tornado IPC server very similar to Tornado's TCPServer class
@ -243,36 +249,7 @@ class IPCClient(object):
case it is used as the port for a tcp
localhost connection.
'''
# Create singleton map between two sockets
instance_map = weakref.WeakKeyDictionary()
def __new__(cls, socket_path, io_loop=None):
io_loop = io_loop or tornado.ioloop.IOLoop.current()
if io_loop not in IPCClient.instance_map:
IPCClient.instance_map[io_loop] = weakref.WeakValueDictionary()
loop_instance_map = IPCClient.instance_map[io_loop]
# FIXME
key = six.text_type(socket_path)
client = loop_instance_map.get(key)
if client is None:
log.debug('Initializing new IPCClient for path: %s', key)
client = object.__new__(cls)
# FIXME
client.__singleton_init__(io_loop=io_loop, socket_path=socket_path)
client._instance_key = key
loop_instance_map[key] = client
client._refcount = 1
client._refcount_lock = threading.RLock()
else:
log.debug('Re-using IPCClient for %s', key)
with client._refcount_lock:
client._refcount += 1
return client
def __singleton_init__(self, socket_path, io_loop=None):
def __init__(self, socket_path, io_loop=None):
'''
Create a new IPC client
@ -291,10 +268,6 @@ class IPCClient(object):
encoding = 'utf-8'
self.unpacker = msgpack.Unpacker(encoding=encoding)
def __init__(self, socket_path, io_loop=None):
# Handled by singleton __new__
pass
def connected(self):
return self.stream is not None and not self.stream.closed()
@ -366,16 +339,11 @@ class IPCClient(object):
def __del__(self):
try:
with self._refcount_lock:
# Make sure we actually close no matter if something
# went wrong with our ref counting
self._refcount = 1
try:
self.close()
except socket.error as exc:
if exc.errno != errno.EBADF:
# If its not a bad file descriptor error, raise
raise
self.close()
except socket.error as exc:
if exc.errno != errno.EBADF:
# If its not a bad file descriptor error, raise
raise
except TypeError:
# This is raised when Python's GC has collected objects which
# would be needed when calling self.close()
@ -390,16 +358,6 @@ class IPCClient(object):
if self._closing:
return
if self._refcount > 1:
# Decrease refcount
with self._refcount_lock:
self._refcount -= 1
log.debug(
'This is not the last %s instance. Not closing yet.',
self.__class__.__name__
)
return
self._closing = True
log.debug('Closing %s instance', self.__class__.__name__)
@ -407,17 +365,6 @@ class IPCClient(object):
if self.stream is not None and not self.stream.closed():
self.stream.close()
# Remove the entry from the instance map so
# that a closed entry may not be reused.
# This forces this operation even if the reference
# count of the entry has not yet gone to zero.
if self.io_loop in self.__class__.instance_map:
loop_instance_map = self.__class__.instance_map[self.io_loop]
if self._instance_key in loop_instance_map:
del loop_instance_map[self._instance_key]
if not loop_instance_map:
del self.__class__.instance_map[self.io_loop]
class IPCMessageClient(IPCClient):
'''
@ -628,11 +575,121 @@ class IPCMessagePublisher(object):
pass
class IPCMessageSubscriber(IPCClient):
class IPCMessageSubscriberService(IPCClient):
'''
IPC message subscriber service that is a standalone singleton class starting once for a number
of IPCMessageSubscriber instances feeding all of them with data. It closes automatically when
there are no more subscribers.
To use this refer to IPCMessageSubscriber documentation.
'''
def __init__(self, socket_path, io_loop=None):
super(IPCMessageSubscriberService, self).__init__(
socket_path, io_loop=io_loop)
self.saved_data = []
self._read_in_progress = Lock()
self.handlers = weakref.WeakSet()
self.read_stream_future = None
def _subscribe(self, handler):
self.handlers.add(handler)
def unsubscribe(self, handler):
self.handlers.discard(handler)
def _has_subscribers(self):
return bool(self.handlers)
def _feed_subscribers(self, data):
for subscriber in self.handlers:
subscriber._feed(data)
@tornado.gen.coroutine
def _read(self, timeout, callback=None):
try:
yield self._read_in_progress.acquire(timeout=0)
except tornado.gen.TimeoutError:
raise tornado.gen.Return(None)
log.debug('IPC Subscriber Service is starting reading')
# If timeout is not specified we need to set some here to make the service able to check
# is there any handler waiting for data.
if timeout is None:
timeout = 5
self.read_stream_future = None
while self._has_subscribers():
if self.read_stream_future is None:
self.read_stream_future = self.stream.read_bytes(4096, partial=True)
try:
wire_bytes = yield FutureWithTimeout(self.io_loop,
self.read_stream_future,
timeout)
self.read_stream_future = None
self.unpacker.feed(wire_bytes)
msgs = [msg['body'] for msg in self.unpacker]
self._feed_subscribers(msgs)
except TornadoTimeoutError:
# Continue checking are there alive waiting handlers
# Keep 'read_stream_future' alive to wait it more in the next loop
continue
except tornado.iostream.StreamClosedError as exc:
log.trace('Subscriber disconnected from IPC %s', self.socket_path)
self._feed_subscribers([None])
break
except Exception as exc:
log.error('Exception occurred in Subscriber while handling stream: %s', exc)
exc = IPCExceptionProxy(sys.exc_info())
self._feed_subscribers([exc])
break
log.debug('IPC Subscriber Service is stopping due to a lack of subscribers')
self._read_in_progress.release()
raise tornado.gen.Return(None)
@tornado.gen.coroutine
def read(self, handler, timeout=None):
'''
Asynchronously read messages and invoke a callback when they are ready.
:param callback: A callback with the received data
'''
self._subscribe(handler)
while not self.connected():
try:
yield self.connect(timeout=5)
except tornado.iostream.StreamClosedError:
log.trace('Subscriber closed stream on IPC %s before connect', self.socket_path)
yield tornado.gen.sleep(1)
except Exception as exc:
log.error('Exception occurred while Subscriber connecting: %s', exc)
yield tornado.gen.sleep(1)
yield self._read(timeout)
def close(self):
'''
Routines to handle any cleanup before the instance shuts down.
Sockets and filehandles should be closed explicitly, to prevent
leaks.
'''
super(IPCMessageSubscriberService, self).close()
if self.read_stream_future is not None and self.read_stream_future.done():
exc = self.read_stream_future.exception()
if exc and not isinstance(exc, tornado.iostream.StreamClosedError):
log.error("Read future returned exception %r", exc)
def __del__(self):
if IPCMessageSubscriberService in globals():
self.close()
class IPCMessageSubscriber(object):
'''
Salt IPC message subscriber
Create an IPC client to receive messages from IPC publisher
Create or reuse an IPC client to receive messages from IPC publisher
An example of a very simple IPCMessageSubscriber connecting to an IPCMessagePublisher.
This example assumes an already running IPCMessagePublisher.
@ -661,144 +718,61 @@ class IPCMessageSubscriber(IPCClient):
# Wait for some data
package = ipc_subscriber.read_sync()
'''
def __singleton_init__(self, socket_path, io_loop=None):
super(IPCMessageSubscriber, self).__singleton_init__(
socket_path, io_loop=io_loop)
self._read_sync_future = None
self._read_stream_future = None
self._sync_ioloop_running = False
self.saved_data = []
self._sync_read_in_progress = Semaphore()
def __init__(self, socket_path, io_loop=None):
self.service = IPCMessageSubscriberService(socket_path, io_loop)
self.queue = tornado.queues.Queue()
def connected(self):
return self.service.connected()
def connect(self, callback=None, timeout=None):
return self.service.connect(callback=callback, timeout=timeout)
@tornado.gen.coroutine
def _read_sync(self, timeout):
yield self._sync_read_in_progress.acquire()
exc_to_raise = None
ret = None
try:
while True:
if self._read_stream_future is None:
self._read_stream_future = self.stream.read_bytes(4096, partial=True)
if timeout is None:
wire_bytes = yield self._read_stream_future
else:
future_with_timeout = FutureWithTimeout(
self.io_loop, self._read_stream_future, timeout)
wire_bytes = yield future_with_timeout
self._read_stream_future = None
# Remove the timeout once we get some data or an exception
# occurs. We will assume that the rest of the data is already
# there or is coming soon if an exception doesn't occur.
timeout = None
self.unpacker.feed(wire_bytes)
first = True
for framed_msg in self.unpacker:
if first:
ret = framed_msg['body']
first = False
else:
self.saved_data.append(framed_msg['body'])
if not first:
# We read at least one piece of data
break
except TornadoTimeoutError:
# In the timeout case, just return None.
# Keep 'self._read_stream_future' alive.
ret = None
except tornado.iostream.StreamClosedError as exc:
log.trace('Subscriber disconnected from IPC %s', self.socket_path)
self._read_stream_future = None
exc_to_raise = exc
except Exception as exc:
log.error('Exception occurred in Subscriber while handling stream: %s', exc)
self._read_stream_future = None
exc_to_raise = exc
if self._sync_ioloop_running:
# Stop the IO Loop so that self.io_loop.start() will return in
# read_sync().
self.io_loop.spawn_callback(self.io_loop.stop)
if exc_to_raise is not None:
raise exc_to_raise # pylint: disable=E0702
self._sync_read_in_progress.release()
raise tornado.gen.Return(ret)
def read_sync(self, timeout=None):
'''
Read a message from an IPC socket
The socket must already be connected.
The associated IO Loop must NOT be running.
:param int timeout: Timeout when receiving message
:return: message data if successful. None if timed out. Will raise an
exception for all other error conditions.
'''
if self.saved_data:
return self.saved_data.pop(0)
self._sync_ioloop_running = True
self._read_sync_future = self._read_sync(timeout)
self.io_loop.start()
self._sync_ioloop_running = False
ret_future = self._read_sync_future
self._read_sync_future = None
return ret_future.result()
def _feed(self, msgs):
for msg in msgs:
yield self.queue.put(msg)
@tornado.gen.coroutine
def _read_async(self, callback):
while not self.stream.closed():
try:
self._read_stream_future = self.stream.read_bytes(4096, partial=True)
wire_bytes = yield self._read_stream_future
self._read_stream_future = None
self.unpacker.feed(wire_bytes)
for framed_msg in self.unpacker:
body = framed_msg['body']
self.io_loop.spawn_callback(callback, body)
except tornado.iostream.StreamClosedError:
log.trace('Subscriber disconnected from IPC %s', self.socket_path)
break
except Exception as exc:
log.error('Exception occurred while Subscriber handling stream: %s', exc)
@tornado.gen.coroutine
def read_async(self, callback):
def read_async(self, callback, timeout=None):
'''
Asynchronously read messages and invoke a callback when they are ready.
:param callback: A callback with the received data
'''
while not self.connected():
self.service.read(self)
while True:
try:
yield self.connect(timeout=5)
except tornado.iostream.StreamClosedError:
log.trace('Subscriber closed stream on IPC %s before connect', self.socket_path)
yield tornado.gen.sleep(1)
except Exception as exc:
log.error('Exception occurred while Subscriber connecting: %s', exc)
yield tornado.gen.sleep(1)
yield self._read_async(callback)
if timeout is not None:
deadline = time.time() + timeout
else:
deadline = None
data = yield self.queue.get(timeout=deadline)
except tornado.gen.TimeoutError:
raise tornado.gen.Return(None)
if data is None:
break
elif isinstance(data, IPCExceptionProxy):
six.reraise(*data.orig_info)
elif callback:
self.service.io_loop.spawn_callback(callback, data)
else:
raise tornado.gen.Return(data)
def read_sync(self, timeout=None):
'''
Read a message from an IPC socket
The associated IO Loop must NOT be running.
:param int timeout: Timeout when receiving message
:return: message data if successful. None if timed out. Will raise an
exception for all other error conditions.
'''
return self.service.io_loop.run_sync(lambda: self.read_async(None, timeout))
def close(self):
'''
Routines to handle any cleanup before the instance shuts down.
Sockets and filehandles should be closed explicitly, to prevent
leaks.
'''
if not self._closing:
IPCClient.close(self)
if self._closing:
# This will prevent this message from showing up:
# '[ERROR ] Future exception was never retrieved:
# StreamClosedError'
if self._read_sync_future is not None and self._read_sync_future.done():
self._read_sync_future.exception()
if self._read_stream_future is not None and self._read_stream_future.done():
self._read_stream_future.exception()
self.service.unsubscribe(self)
self.service.close()
def __del__(self):
self.close()

View file

@ -34,7 +34,7 @@ import salt.transport.client
import salt.transport.server
import salt.transport.mixins.auth
from salt.ext import six
from salt.exceptions import SaltReqTimeoutError
from salt.exceptions import SaltReqTimeoutError, SaltException
from salt._compat import ipaddress
from salt.utils.zeromq import zmq, ZMQDefaultLoop, install_zmq, ZMQ_VERSION_INFO, LIBZMQ_VERSION_INFO
@ -260,12 +260,18 @@ class AsyncZeroMQReqChannel(salt.transport.client.ReqChannel):
@property
def master_uri(self):
if 'master_uri' in self.opts:
return self.opts['master_uri']
# if by chance master_uri is not there..
if 'master_ip' in self.opts:
return _get_master_uri(self.opts['master_ip'],
self.opts['master_port'],
source_ip=self.opts.get('source_ip'),
source_port=self.opts.get('source_ret_port'))
return self.opts['master_uri']
# if we've reached here something is very abnormal
raise SaltException('ReqChannel: missing master_uri/master_ip in self.opts')
def _package_load(self, load):
return {

View file

@ -0,0 +1,3 @@
peer:
.*:
- x509.sign_remote_certificate

View file

@ -0,0 +1,65 @@
{% set tmp_dir = pillar['tmp_dir'] %}
{{ tmp_dir }}/pki:
file.directory
{{ tmp_dir }}/pki/issued_certs:
file.directory
{{ tmp_dir }}/pki/ca.key:
x509.private_key_managed:
- bits: 4096
- require:
- file: {{ tmp_dir }}/pki
{{ tmp_dir }}/pki/ca.crt:
x509.certificate_managed:
- signing_private_key: {{ tmp_dir }}/pki/ca.key
- CN: ca.example.com
- C: US
- ST: Utah
- L: Salt Lake City
- basicConstraints: "critical CA:true"
- keyUsage: "critical cRLSign, keyCertSign"
- subjectKeyIdentifier: hash
- authorityKeyIdentifier: keyid,issuer:always
- days_valid: 3650
- days_remaining: 0
- backup: True
- managed_private_key:
name: {{ tmp_dir }}/pki/ca.key
bits: 4096
backup: True
- require:
- file: {{ tmp_dir }}/pki
- {{ tmp_dir }}/pki/ca.key
mine.send:
module.run:
- func: x509.get_pem_entries
- kwargs:
glob_path: {{ tmp_dir }}/pki/ca.crt
- onchanges:
- x509: {{ tmp_dir }}/pki/ca.crt
{{ tmp_dir }}/pki/test.key:
x509.private_key_managed:
- bits: 4096
- backup: True
test_crt:
x509.certificate_managed:
- name: {{ tmp_dir }}/pki/test.crt
- ca_server: minion
- signing_policy: ca_policy
- public_key: {{ tmp_dir }}/pki/test.key
- CN: minion
- days_remaining: 30
- backup: True
- managed_private_key:
name: {{ tmp_dir }}/pki/test.key
bits: 4096
backup: True
- require:
- {{ tmp_dir }}/pki/ca.crt
- {{ tmp_dir }}/pki/test.key

View file

@ -32,25 +32,29 @@ class BeaconsAddDeleteTest(ModuleCase):
os.unlink(self.beacons_config_file_path)
# Reset beacons
self.run_function('beacons.reset')
self.run_function('beacons.reset', f_timeout=300)
def test_add_and_delete(self):
'''
Test adding and deleting a beacon
'''
_add = self.run_function('beacons.add', ['ps', [{'processes': {'apache2': 'stopped'}}]])
_add = self.run_function(
'beacons.add',
['ps', [{'processes': {'apache2': 'stopped'}}]],
f_timeout=300
)
self.assertTrue(_add['result'])
# save added beacon
_save = self.run_function('beacons.save')
_save = self.run_function('beacons.save', f_timeout=300)
self.assertTrue(_save['result'])
# delete the beacon
_delete = self.run_function('beacons.delete', ['ps'])
_delete = self.run_function('beacons.delete', ['ps'], f_timeout=300)
self.assertTrue(_delete['result'])
# save the results
self.run_function('beacons.save')
self.run_function('beacons.save', f_timeout=300)
class BeaconsTest(ModuleCase):
@ -74,40 +78,48 @@ class BeaconsTest(ModuleCase):
self.__class__.beacons_config_file_path = os.path.join(self.minion_conf_d_dir, 'beacons.conf')
try:
# Add beacon to disable
self.run_function('beacons.add', ['ps', [{'processes': {'apache2': 'stopped'}}]])
self.run_function('beacons.save')
self.run_function('beacons.add',
['ps', [{'processes': {'apache2': 'stopped'}}]],
f_timeout=300)
self.run_function('beacons.save', f_timeout=300)
except CommandExecutionError:
self.skipTest('Unable to add beacon')
def tearDown(self):
# delete added beacon
self.run_function('beacons.delete', ['ps'])
self.run_function('beacons.save')
self.run_function('beacons.delete', ['ps'], f_timeout=300)
self.run_function('beacons.save', f_timeout=300)
# Reset beacons
self.run_function('beacons.reset')
self.run_function('beacons.reset', f_timeout=300)
def test_disable(self):
'''
Test disabling beacons
'''
# assert beacon exists
_list = self.run_function('beacons.list', return_yaml=False)
_list = self.run_function('beacons.list',
return_yaml=False,
f_timeout=300)
self.assertIn('ps', _list)
ret = self.run_function('beacons.disable')
ret = self.run_function('beacons.disable', f_timeout=300)
self.assertTrue(ret['result'])
# assert beacons are disabled
_list = self.run_function('beacons.list', return_yaml=False)
_list = self.run_function('beacons.list',
return_yaml=False,
f_timeout=300)
self.assertFalse(_list['enabled'])
# disable added beacon
ret = self.run_function('beacons.disable_beacon', ['ps'])
ret = self.run_function('beacons.disable_beacon', ['ps'], f_timeout=300)
self.assertTrue(ret['result'])
# assert beacon ps is disabled
_list = self.run_function('beacons.list', return_yaml=False)
_list = self.run_function('beacons.list',
return_yaml=False,
f_timeout=300)
for bdict in _list['ps']:
if 'enabled' in bdict:
self.assertFalse(bdict['enabled'])
@ -118,36 +130,45 @@ class BeaconsTest(ModuleCase):
Test enabling beacons
'''
# assert beacon exists
_list = self.run_function('beacons.list', return_yaml=False)
_list = self.run_function('beacons.list',
return_yaml=False,
f_timeout=300)
self.assertIn('ps', _list)
# enable beacons on minion
ret = self.run_function('beacons.enable')
ret = self.run_function('beacons.enable', f_timeout=300)
self.assertTrue(ret['result'])
# assert beacons are enabled
_list = self.run_function('beacons.list', return_yaml=False)
_list = self.run_function('beacons.list',
return_yaml=False,
f_timeout=300)
self.assertTrue(_list['enabled'])
@skipIf(True, 'Skip until https://github.com/saltstack/salt/issues/31516 problems are resolved.')
@skipIf(True, 'Skip until https://github.com/saltstack/salt/issues/31516 '
'problems are resolved.')
def test_enabled_beacons(self):
'''
Test enabled specific beacon
'''
# enable added beacon
ret = self.run_function('beacons.enable_beacon', ['ps'])
ret = self.run_function('beacons.enable_beacon', ['ps'], f_timeout=300)
self.assertTrue(ret['result'])
# assert beacon ps is enabled
_list = self.run_function('beacons.list', return_yaml=False)
_list = self.run_function('beacons.list',
return_yaml=False,
f_timeout=300)
self.assertTrue(_list['ps']['enabled'])
def test_list(self):
'''
Test lising the beacons
Test listing the beacons
'''
# list beacons
ret = self.run_function('beacons.list', return_yaml=False)
ret = self.run_function('beacons.list',
return_yaml=False,
f_timeout=300)
if 'enabled' in ret:
self.assertEqual(ret, {'ps': [{'processes': {'apache2': 'stopped'}}], 'enabled': True})
else:

View file

@ -403,3 +403,12 @@ class CMDModuleTest(ModuleCase):
self.assertIn('administrator', cmd)
else:
self.assertEqual('root', cmd)
@skipIf(not salt.utils.platform.is_windows(), 'minion is not windows')
def test_windows_env_handling(self):
'''
Ensure that nt.environ is used properly with cmd.run*
'''
out = self.run_function('cmd.run', ['set'], env={"abc": "123", "ABC": "456"}).splitlines()
self.assertIn('abc=123', out)
self.assertIn('ABC=456', out)

View file

@ -228,7 +228,7 @@ class ShadowModuleTest(ModuleCase):
def restore_shadow_file(contents):
# restore shadow file
with salt.utils.fopen('/etc/shadow', 'w') as wfh:
with salt.utils.files.fopen('/etc/shadow', 'w') as wfh:
wfh.write(contents)
with salt.utils.files.fopen('/etc/shadow', 'r') as rfh:

View file

@ -23,21 +23,24 @@ class BeaconStateTestCase(ModuleCase, SaltReturnAssertsMixin):
def setUp(self):
'''
'''
self.run_function('beacons.reset')
self.run_function('beacons.reset', f_timeout=300)
def tearDown(self):
self.run_function('beacons.reset')
self.run_function('beacons.reset', f_timeout=300)
def test_present_absent(self):
kwargs = {'/': '38%', 'interval': 5}
ret = self.run_state(
'beacon.present',
name='diskusage',
f_timeout=300,
**kwargs
)
self.assertSaltTrueReturn(ret)
ret = self.run_function('beacons.list', return_yaml=False)
ret = self.run_function('beacons.list',
return_yaml=False,
f_timeout=300)
self.assertTrue('diskusage' in ret)
self.assertTrue({'interval': 5} in ret['diskusage'])
self.assertTrue({'/': '38%'} in ret['diskusage'])
@ -45,8 +48,11 @@ class BeaconStateTestCase(ModuleCase, SaltReturnAssertsMixin):
ret = self.run_state(
'beacon.absent',
name='diskusage',
f_timeout=300
)
self.assertSaltTrueReturn(ret)
ret = self.run_function('beacons.list', return_yaml=False)
ret = self.run_function('beacons.list',
return_yaml=False,
f_timeout=300)
self.assertEqual(ret, {'beacons': {}})

View file

@ -459,6 +459,21 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
changes = next(six.itervalues(ret))['changes']
self.assertEqual('<show_changes=False>', changes['diff'])
def test_managed_show_changes_true(self):
'''
file.managed test interface
'''
name = os.path.join(TMP, 'grail_not_scene33')
with salt.utils.files.fopen(name, 'wb') as fp_:
fp_.write(b'test_managed_show_changes_false\n')
ret = self.run_state(
'file.managed', name=name, source='salt://grail/scene33',
)
changes = next(six.itervalues(ret))['changes']
self.assertIn('diff', changes)
@skipIf(IS_WINDOWS, 'Don\'t know how to fix for Windows')
def test_managed_escaped_file_path(self):
'''

View file

@ -5,9 +5,10 @@ import logging
import salt.utils.files
from salt.ext import six
import textwrap
from tests.support.helpers import with_tempfile
from tests.support.paths import BASE_FILES
from tests.support.paths import BASE_FILES, TMP, TMP_PILLAR_TREE
from tests.support.case import ModuleCase
from tests.support.unit import skipIf
from tests.support.mixins import SaltReturnAssertsMixin
@ -31,6 +32,36 @@ class x509Test(ModuleCase, SaltReturnAssertsMixin):
with salt.utils.files.fopen(cert_path) as fp:
cls.x509_cert_text = fp.read()
def setUp(self):
with salt.utils.files.fopen(os.path.join(TMP_PILLAR_TREE, 'signing_policies.sls'), 'w') as fp:
fp.write(textwrap.dedent('''\
x509_signing_policies:
ca_policy:
- minions: '*'
- signing_private_key: {0}/pki/ca.key
- signing_cert: {0}/pki/ca.crt
- O: Test Company
- basicConstraints: "CA:false"
- keyUsage: "critical digitalSignature, keyEncipherment"
- extendedKeyUsage: "critical serverAuth, clientAuth"
- subjectKeyIdentifier: hash
- authorityKeyIdentifier: keyid
- days_valid: 730
- copypath: {0}/pki
'''.format(TMP)))
with salt.utils.files.fopen(os.path.join(TMP_PILLAR_TREE, 'top.sls'), 'w') as fp:
fp.write(textwrap.dedent('''\
base:
'*':
- signing_policies
'''))
self.run_function('saltutil.refresh_pillar')
def tearDown(self):
os.remove(os.path.join(TMP_PILLAR_TREE, 'signing_policies.sls'))
os.remove(os.path.join(TMP_PILLAR_TREE, 'top.sls'))
self.run_function('saltutil.refresh_pillar')
def run_function(self, *args, **kwargs):
ret = super(x509Test, self).run_function(*args, **kwargs)
log.debug('ret = %s', ret)
@ -61,3 +92,11 @@ class x509Test(ModuleCase, SaltReturnAssertsMixin):
assert state_result['result'] is True, state_result
assert os.path.exists(keyfile)
assert os.path.exists(crtfile)
def test_cert_signing(self):
ret = self.run_function('state.apply', ['test_cert'], pillar={'tmp_dir': TMP})
key = 'x509_|-test_crt_|-{}/pki/test.crt_|-certificate_managed'.format(TMP)
assert key in ret
assert 'changes' in ret[key]
assert 'Certificate' in ret[key]['changes']
assert 'New' in ret[key]['changes']['Certificate']

View file

@ -1,102 +0,0 @@
# -*- coding: utf-8 -*-
'''
tests.support.nox-windows-setup
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This script is meant to run under the nox virtualenv to take care of required
windows procedures
'''
# pylint: disable=resource-leakage
from __future__ import absolute_import, print_function, unicode_literals
import os
import re
import sys
import site
import shutil
try:
import site
SITE_PACKAGES = site.getsitepackages()
PYTHON_EXECUTABLE_DIRECTORY = os.path.dirname(sys.executable)
PYTHON_SCRIPTS_DIR = os.path.join(PYTHON_EXECUTABLE_DIRECTORY, 'Scripts')
except AttributeError:
# The site module does not have the getsitepackages function when running within a virtualenv
# But the site-packages directory WILL be on sys.path
SITE_PACKAGES = None
for entry in sys.path:
if 'site-packages' in entry:
SITE_PACKAGES = entry
break
# Under a virtualenv, the python "binary" is under Scripts already.
# Well, not the binary, but the Python DLLs
PYTHON_EXECUTABLE_DIRECTORY = PYTHON_SCRIPTS_DIR = os.path.dirname(sys.executable)
# Requests is a Salt dependency, it's safe to import, but...
try:
import requests
HAS_REQUESTS = True
except ImportError:
HAS_REQUESTS = False
IS_64_BITS = sys.maxsize > 2**32
SALT_REPO_URL = 'https://repo.saltstack.com/windows/dependencies/{}'.format(IS_64_BITS and 64 or 32)
DLLS = ("libeay32.dll", "ssleay32.dll", "OpenSSL_License.txt", "msvcr120.dll", "libsodium.dll")
for dll in DLLS:
outfile = os.path.join(PYTHON_EXECUTABLE_DIRECTORY, dll)
if os.path.exists(outfile):
continue
src_url = '{}/{}'.format(SALT_REPO_URL, dll)
if HAS_REQUESTS:
print('Downloading {} to {}'.format(src_url, outfile))
request = requests.get(src_url, allow_redirects=True)
with open(outfile, 'wb') as wfh:
wfh.write(request.content)
else:
print('ATTENTION: The python requests package is not installed, can\'t download {}'.format(src_url))
PYWIN32_SYSTEM32_DIR = os.path.join(SITE_PACKAGES, 'pywin32_system32')
if os.path.exists(PYWIN32_SYSTEM32_DIR):
for fname in os.listdir(PYWIN32_SYSTEM32_DIR):
if not fname.endswith('.dll'):
continue
spath = os.path.join(PYWIN32_SYSTEM32_DIR, fname)
dpath = spath.replace('pywin32_system32', 'win32')
print('Moving {} to {}'.format(spath, dpath))
shutil.move(spath, dpath)
print('Deleting {}'.format(PYWIN32_SYSTEM32_DIR))
shutil.rmtree(PYWIN32_SYSTEM32_DIR, ignore_errors=True)
if os.path.exists(PYTHON_SCRIPTS_DIR):
print('Searching for pywin32 scripts to delete')
for fname in os.listdir(PYTHON_SCRIPTS_DIR):
if not fname.startswith('pywin32_'):
continue
fpath = os.path.join(PYTHON_SCRIPTS_DIR, fname)
print('Deleting {}'.format(fpath))
os.unlink(fpath)
PYTHONWIN_DIR = os.path.join(SITE_PACKAGES, 'pythonwin')
if os.path.exists(PYTHONWIN_DIR):
print('Deleting {}'.format(PYTHONWIN_DIR))
shutil.rmtree(PYTHONWIN_DIR, ignore_errors=True)
PYCRPTO_NT_FILE = os.path.join(SITE_PACKAGES, 'Crypto', 'Random', 'OSRNG', 'nt.py')
if os.path.exists(PYCRPTO_NT_FILE):
with open(PYCRPTO_NT_FILE, 'r') as rfh:
contents = rfh.read()
new_contents = re.sub(
r'^import winrandom$',
'from Crypto.Random.OSRNG import winrandom',
contents,
count=1,
flags=re.MULTILINE
)
if contents != new_contents:
print('Patching {}'.format(PYCRPTO_NT_FILE))
with open(PYCRPTO_NT_FILE, 'w') as wfh:
wfh.write(new_contents)

View file

@ -136,6 +136,28 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
os_release = core._parse_os_release('/etc/os-release', '/usr/lib/os-release')
self.assertEqual(os_release, {})
@skipIf(not salt.utils.platform.is_windows(), 'System is not Windows')
def test__windows_platform_data(self):
grains = core._windows_platform_data()
keys = ['biosversion',
'osrelease',
'domain',
'kernelrelease',
'motherboard',
'serialnumber',
'timezone',
'manufacturer',
'kernelversion',
'osservicepack',
'virtual',
'productname',
'osfullname',
'osmanufacturer',
'osversion',
'windowsdomain']
for key in keys:
self.assertIn(key, grains)
@skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
def test_gnu_slash_linux_in_os_name(self):
'''
@ -604,6 +626,115 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
'2016Server', '2019Server']
self.assertIn(returned_grains['osrelease'], valid_releases)
def test__windows_os_release_grain(self):
versions = {
'Windows 10 Home': '10',
'Windows 10 Pro': '10',
'Windows 10 Pro for Workstations': '10',
'Windows 10 Pro Education': '10',
'Windows 10 Enterprise': '10',
'Windows 10 Enterprise LTSB': '10',
'Windows 10 Education': '10',
'Windows 10 IoT Core': '10',
'Windows 10 IoT Enterprise': '10',
'Windows 10 S': '10',
'Windows 8.1': '8.1',
'Windows 8.1 Pro': '8.1',
'Windows 8.1 Enterprise': '8.1',
'Windows 8.1 OEM': '8.1',
'Windows 8.1 with Bing': '8.1',
'Windows 8': '8',
'Windows 8 Pro': '8',
'Windows 8 Enterprise': '8',
'Windows 8 OEM': '8',
'Windows 7 Starter': '7',
'Windows 7 Home Basic': '7',
'Windows 7 Home Premium': '7',
'Windows 7 Professional': '7',
'Windows 7 Enterprise': '7',
'Windows 7 Ultimate': '7',
'Windows Thin PC': 'Thin',
'Windows Vista Starter': 'Vista',
'Windows Vista Home Basic': 'Vista',
'Windows Vista Home Premium': 'Vista',
'Windows Vista Business': 'Vista',
'Windows Vista Enterprise': 'Vista',
'Windows Vista Ultimate': 'Vista',
'Windows Server 2019 Essentials': '2019Server',
'Windows Server 2019 Standard': '2019Server',
'Windows Server 2019 Datacenter': '2019Server',
'Windows Server 2016 Essentials': '2016Server',
'Windows Server 2016 Standard': '2016Server',
'Windows Server 2016 Datacenter': '2016Server',
'Windows Server 2012 R2 Foundation': '2012ServerR2',
'Windows Server 2012 R2 Essentials': '2012ServerR2',
'Windows Server 2012 R2 Standard': '2012ServerR2',
'Windows Server 2012 R2 Datacenter': '2012ServerR2',
'Windows Server 2012 Foundation': '2012Server',
'Windows Server 2012 Essentials': '2012Server',
'Windows Server 2012 Standard': '2012Server',
'Windows Server 2012 Datacenter': '2012Server',
'Windows MultiPoint Server 2012': '2012Server',
'Windows Small Business Server 2011': '2011Server',
'Windows MultiPoint Server 2011': '2011Server',
'Windows Home Server 2011': '2011Server',
'Windows MultiPoint Server 2010': '2010Server',
'Windows Server 2008 R2 Foundation': '2008ServerR2',
'Windows Server 2008 R2 Standard': '2008ServerR2',
'Windows Server 2008 R2 Enterprise': '2008ServerR2',
'Windows Server 2008 R2 Datacenter': '2008ServerR2',
'Windows Server 2008 R2 for Itanium-based Systems': '2008ServerR2',
'Windows Web Server 2008 R2': '2008ServerR2',
'Windows Storage Server 2008 R2': '2008ServerR2',
'Windows HPC Server 2008 R2': '2008ServerR2',
'Windows Server 2008 Standard': '2008Server',
'Windows Server 2008 Enterprise': '2008Server',
'Windows Server 2008 Datacenter': '2008Server',
'Windows Server 2008 for Itanium-based Systems': '2008Server',
'Windows Server Foundation 2008': '2008Server',
'Windows Essential Business Server 2008': '2008Server',
'Windows HPC Server 2008': '2008Server',
'Windows Small Business Server 2008': '2008Server',
'Windows Storage Server 2008': '2008Server',
'Windows Web Server 2008': '2008Server'
}
for caption in versions:
version = core._windows_os_release_grain(caption, 1)
self.assertEqual(
version,
versions[caption],
'version: {0}\n'
'found: {1}\n'
'caption: {2}'.format(version, versions[caption], caption)
)
embedded_versions = {
'Windows Embedded 8.1 Industry Pro': '8.1',
'Windows Embedded 8 Industry Pro': '8',
'Windows POSReady 7': '7',
'Windows Embedded Standard 7': '7',
'Windows Embedded POSReady 2009': '2009',
'Windows Embedded Standard 2009': '2009',
'Windows XP Embedded': 'XP',
}
for caption in embedded_versions:
version = core._windows_os_release_grain(caption, 1)
self.assertEqual(
version,
embedded_versions[caption],
'{0} != {1}\n'
'version: {0}\n'
'found: {1}\n'
'caption: {2}'.format(version, embedded_versions[caption], caption)
)
# Special Cases
# Windows Embedded Standard is Windows 7
caption = 'Windows Embedded Standard'
with patch('platform.release', MagicMock(return_value='7')):
version = core._windows_os_release_grain(caption, 1)
self.assertEqual(version, '7')
@skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
def test_linux_memdata(self):
'''

View file

@ -102,7 +102,7 @@ class IncronTestCase(TestCase, LoaderModuleMockMixin):
val = {'pre': [], 'crons': [{'path': '/home/cybage',
'mask': 'IN_MODIFY',
'cmd': 'echo "SALT"', 'comment': ''}]}
'cmd': 'echo "SALT"'}]}
with patch.object(incron, 'list_tab',
MagicMock(return_value=val)):
self.assertEqual(incron.set_job('cybage', '/home/cybage',
@ -135,7 +135,7 @@ class IncronTestCase(TestCase, LoaderModuleMockMixin):
val = {'pre': [], 'crons': [{'path': '/home/cybage',
'mask': 'IN_MODIFY,IN_DELETE',
'cmd': 'echo "SALT"', 'comment': ''}]}
'cmd': 'echo "SALT"'}]}
with patch.object(incron, 'list_tab',
MagicMock(return_value=val)):
mock = MagicMock(return_value='incrontab')

View file

@ -113,14 +113,15 @@ class NetworkTestCase(TestCase, LoaderModuleMockMixin):
'''
Test for Performs a traceroute to a 3rd party host
'''
with patch.object(salt.utils.path, 'which', side_effect=[False, True]):
self.assertListEqual(network.traceroute('host'), [])
with patch('salt.utils.path.which', MagicMock(return_value='traceroute')):
with patch.dict(network.__salt__, {'cmd.run': MagicMock(return_value='')}):
self.assertListEqual(network.traceroute('gentoo.org'), [])
with patch.object(salt.utils.network, 'sanitize_host',
return_value='A'):
return_value='gentoo.org'):
with patch.dict(network.__salt__, {'cmd.run':
MagicMock(return_value="")}):
self.assertListEqual(network.traceroute('host'), [])
MagicMock(return_value='')}):
self.assertListEqual(network.traceroute('gentoo.org'), [])
def test_dig(self):
'''

Some files were not shown because too many files have changed in this diff Show more