mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge branch '2019.2' into 51879-fix-binary-pillar-return-error
This commit is contained in:
commit
ead856ee93
108 changed files with 1474 additions and 745 deletions
|
@ -132,6 +132,7 @@ MOCK_MODULES = [
|
|||
'tornado.ioloop',
|
||||
'tornado.iostream',
|
||||
'tornado.netutil',
|
||||
'tornado.queues',
|
||||
'tornado.simple_httpclient',
|
||||
'tornado.stack_context',
|
||||
'tornado.web',
|
||||
|
|
|
@ -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)`
|
||||
|
|
|
@ -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
|
||||
===========
|
||||
|
|
|
@ -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?
|
||||
============
|
||||
|
|
|
@ -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}
|
||||
}]'
|
||||
|
|
|
@ -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``.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -108,7 +108,7 @@ it can be verified with Salt:
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
salt newinstance test.ping
|
||||
salt newinstance test.version
|
||||
|
||||
|
||||
Profile Options
|
||||
|
|
|
@ -138,7 +138,7 @@ it can be verified with Salt:
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
salt newinstance test.ping
|
||||
salt newinstance test.version
|
||||
|
||||
|
||||
Profile Options
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -91,7 +91,7 @@ it can be verified with Salt:
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
# salt myubuntu test.ping
|
||||
# salt myubuntu test.version
|
||||
|
||||
|
||||
Required Settings
|
||||
|
|
|
@ -91,7 +91,7 @@ it can be verified with Salt:
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
# salt myubuntu test.ping
|
||||
# salt myubuntu test.version
|
||||
|
||||
|
||||
Required Settings
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
~~~~~~~~~~~~~~
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -160,7 +160,7 @@ it can be verified with Salt:
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
salt xenvm02 test.ping
|
||||
salt xenvm02 test.version
|
||||
|
||||
|
||||
Listing Sizes
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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``.
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
-------------
|
||||
|
|
|
@ -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}``
|
||||
|
||||
|
|
|
@ -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``
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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::
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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::
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
========
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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``.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
||||
|
|
20
noxfile.py
20
noxfile.py
|
@ -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()
|
||||
|
||||
|
|
34
requirements/static/arch.in
Normal file
34
requirements/static/arch.in
Normal 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
|
109
requirements/static/arch.txt
Normal file
109
requirements/static/arch.txt
Normal 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
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
37
requirements/static/windows.in
Normal file
37
requirements/static/windows.in
Normal 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
|
88
requirements/static/windows.txt
Normal file
88
requirements/static/windows.txt
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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.'
|
||||
|
|
|
@ -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'])
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'])
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
|
|
|
@ -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(',')
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 {
|
||||
|
|
3
tests/integration/files/conf/master.d/peers.conf
Normal file
3
tests/integration/files/conf/master.d/peers.conf
Normal file
|
@ -0,0 +1,3 @@
|
|||
peer:
|
||||
.*:
|
||||
- x509.sign_remote_certificate
|
65
tests/integration/files/file/base/test_cert.sls
Normal file
65
tests/integration/files/file/base/test_cert.sls
Normal 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
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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': {}})
|
||||
|
|
|
@ -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):
|
||||
'''
|
||||
|
|
|
@ -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']
|
||||
|
|
|
@ -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)
|
|
@ -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):
|
||||
'''
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
Loading…
Add table
Reference in a new issue