mirror of
https://github.com/valitydev/salt.git
synced 2024-11-08 09:23:56 +00:00
Merge branch 'develop' into bbczeuz-patch-phusion-initd
This commit is contained in:
commit
f967a54dc2
4
.github/stale.yml
vendored
4
.github/stale.yml
vendored
@ -1,8 +1,8 @@
|
|||||||
# Probot Stale configuration file
|
# Probot Stale configuration file
|
||||||
|
|
||||||
# Number of days of inactivity before an issue becomes stale
|
# Number of days of inactivity before an issue becomes stale
|
||||||
# 875 is approximately 2 years and 5 months
|
# 860 is approximately 2 years and 4 months
|
||||||
daysUntilStale: 875
|
daysUntilStale: 860
|
||||||
|
|
||||||
# Number of days of inactivity before a stale issue is closed
|
# Number of days of inactivity before a stale issue is closed
|
||||||
daysUntilClose: 7
|
daysUntilClose: 7
|
||||||
|
@ -1725,9 +1725,15 @@ enabled and can be disabled by changing this value to ``False``.
|
|||||||
If ``extmod_whitelist`` is specified, modules which are not whitelisted will also be cleaned here.
|
If ``extmod_whitelist`` is specified, modules which are not whitelisted will also be cleaned here.
|
||||||
|
|
||||||
.. conf_minion:: environment
|
.. conf_minion:: environment
|
||||||
|
.. conf_minion:: saltenv
|
||||||
|
|
||||||
``environment``
|
``saltenv``
|
||||||
---------------
|
-----------
|
||||||
|
|
||||||
|
.. versionchanged:: Oxygen
|
||||||
|
Renamed from ``environment`` to ``saltenv``. If ``environment`` is used,
|
||||||
|
``saltenv`` will take its value. If both are used, ``environment`` will be
|
||||||
|
ignored and ``saltenv`` will be used.
|
||||||
|
|
||||||
Normally the minion is not isolated to any single environment on the master
|
Normally the minion is not isolated to any single environment on the master
|
||||||
when running states, but the environment can be isolated on the minion side
|
when running states, but the environment can be isolated on the minion side
|
||||||
@ -1736,7 +1742,25 @@ environments is to isolate via the top file.
|
|||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
environment: dev
|
saltenv: dev
|
||||||
|
|
||||||
|
.. conf_minion:: lock_saltenv
|
||||||
|
|
||||||
|
``lock_saltenv``
|
||||||
|
----------------
|
||||||
|
|
||||||
|
.. versionadded:: Oxygen
|
||||||
|
|
||||||
|
Default: ``False``
|
||||||
|
|
||||||
|
For purposes of running states, this option prevents using the ``saltenv``
|
||||||
|
argument to manually set the environment. This is useful to keep a minion which
|
||||||
|
has the :conf_minion:`saltenv` option set to ``dev`` from running states from
|
||||||
|
an environment other than ``dev``.
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
lock_saltenv: True
|
||||||
|
|
||||||
.. conf_minion:: snapper_states
|
.. conf_minion:: snapper_states
|
||||||
|
|
||||||
|
@ -137,6 +137,43 @@ can specify the "name" argument to avoid conflicting IDs:
|
|||||||
- kwarg:
|
- kwarg:
|
||||||
remove_existing: true
|
remove_existing: true
|
||||||
|
|
||||||
|
.. _orchestrate-runner-fail-functions:
|
||||||
|
|
||||||
|
Fail Functions
|
||||||
|
**************
|
||||||
|
|
||||||
|
When running a remote execution function in orchestration, certain return
|
||||||
|
values for those functions may indicate failure, while the function itself
|
||||||
|
doesn't set a return code. For those circumstances, using a "fail function"
|
||||||
|
allows for a more flexible means of assessing success or failure.
|
||||||
|
|
||||||
|
A fail function can be written as part of a :ref:`custom execution module
|
||||||
|
<writing-execution-modules>`. The function should accept one argument, and
|
||||||
|
return a boolean result. For example:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def check_func_result(retval):
|
||||||
|
if some_condition:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
The function can then be referenced in orchestration SLS like so:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
do_stuff:
|
||||||
|
salt.function:
|
||||||
|
- name: modname.funcname
|
||||||
|
- tgt: '*'
|
||||||
|
- fail_function: mymod.check_func_result
|
||||||
|
|
||||||
|
.. important::
|
||||||
|
Fail functions run *on the master*, so they must be synced using ``salt-run
|
||||||
|
saltutil.sync_modules``.
|
||||||
|
|
||||||
State
|
State
|
||||||
^^^^^
|
^^^^^
|
||||||
|
|
||||||
@ -221,6 +258,7 @@ To execute with pillar data.
|
|||||||
salt-run state.orch orch.deploy pillar='{"servers": "newsystem1",
|
salt-run state.orch orch.deploy pillar='{"servers": "newsystem1",
|
||||||
"master": "mymaster"}'
|
"master": "mymaster"}'
|
||||||
|
|
||||||
|
.. _orchestrate-runner-return-codes-runner-wheel:
|
||||||
|
|
||||||
Return Codes in Runner/Wheel Jobs
|
Return Codes in Runner/Wheel Jobs
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@ -298,3 +336,270 @@ Given the above setup, the orchestration will be carried out as follows:
|
|||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Remember, salt-run is always executed on the master.
|
Remember, salt-run is always executed on the master.
|
||||||
|
|
||||||
|
.. _orchestrate-runner-parsing-results-programatically:
|
||||||
|
|
||||||
|
Parsing Results Programatically
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
Orchestration jobs return output in a specific data structure. That data
|
||||||
|
structure is represented differently depending on the outputter used. With the
|
||||||
|
default outputter for orchestration, you get a nice human-readable output.
|
||||||
|
Assume the following orchestration SLS:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
good_state:
|
||||||
|
salt.state:
|
||||||
|
- tgt: myminion
|
||||||
|
- sls:
|
||||||
|
- succeed_with_changes
|
||||||
|
|
||||||
|
bad_state:
|
||||||
|
salt.state:
|
||||||
|
- tgt: myminion
|
||||||
|
- sls:
|
||||||
|
- fail_with_changes
|
||||||
|
|
||||||
|
mymod.myfunc:
|
||||||
|
salt.function:
|
||||||
|
- tgt: myminion
|
||||||
|
|
||||||
|
mymod.myfunc_false_result:
|
||||||
|
salt.function:
|
||||||
|
- tgt: myminion
|
||||||
|
|
||||||
|
|
||||||
|
Running this using the default outputter would produce output which looks like
|
||||||
|
this:
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
fa5944a73aa8_master:
|
||||||
|
----------
|
||||||
|
ID: good_state
|
||||||
|
Function: salt.state
|
||||||
|
Result: True
|
||||||
|
Comment: States ran successfully. Updating myminion.
|
||||||
|
Started: 21:08:02.681604
|
||||||
|
Duration: 265.565 ms
|
||||||
|
Changes:
|
||||||
|
myminion:
|
||||||
|
----------
|
||||||
|
ID: test succeed with changes
|
||||||
|
Function: test.succeed_with_changes
|
||||||
|
Result: True
|
||||||
|
Comment: Success!
|
||||||
|
Started: 21:08:02.835893
|
||||||
|
Duration: 0.375 ms
|
||||||
|
Changes:
|
||||||
|
----------
|
||||||
|
testing:
|
||||||
|
----------
|
||||||
|
new:
|
||||||
|
Something pretended to change
|
||||||
|
old:
|
||||||
|
Unchanged
|
||||||
|
|
||||||
|
Summary for myminion
|
||||||
|
------------
|
||||||
|
Succeeded: 1 (changed=1)
|
||||||
|
Failed: 0
|
||||||
|
------------
|
||||||
|
Total states run: 1
|
||||||
|
Total run time: 0.375 ms
|
||||||
|
----------
|
||||||
|
ID: bad_state
|
||||||
|
Function: salt.state
|
||||||
|
Result: False
|
||||||
|
Comment: Run failed on minions: myminion
|
||||||
|
Started: 21:08:02.947702
|
||||||
|
Duration: 177.01 ms
|
||||||
|
Changes:
|
||||||
|
myminion:
|
||||||
|
----------
|
||||||
|
ID: test fail with changes
|
||||||
|
Function: test.fail_with_changes
|
||||||
|
Result: False
|
||||||
|
Comment: Failure!
|
||||||
|
Started: 21:08:03.116634
|
||||||
|
Duration: 0.502 ms
|
||||||
|
Changes:
|
||||||
|
----------
|
||||||
|
testing:
|
||||||
|
----------
|
||||||
|
new:
|
||||||
|
Something pretended to change
|
||||||
|
old:
|
||||||
|
Unchanged
|
||||||
|
|
||||||
|
Summary for myminion
|
||||||
|
------------
|
||||||
|
Succeeded: 0 (changed=1)
|
||||||
|
Failed: 1
|
||||||
|
------------
|
||||||
|
Total states run: 1
|
||||||
|
Total run time: 0.502 ms
|
||||||
|
----------
|
||||||
|
ID: mymod.myfunc
|
||||||
|
Function: salt.function
|
||||||
|
Result: True
|
||||||
|
Comment: Function ran successfully. Function mymod.myfunc ran on myminion.
|
||||||
|
Started: 21:08:03.125011
|
||||||
|
Duration: 159.488 ms
|
||||||
|
Changes:
|
||||||
|
myminion:
|
||||||
|
True
|
||||||
|
----------
|
||||||
|
ID: mymod.myfunc_false_result
|
||||||
|
Function: salt.function
|
||||||
|
Result: False
|
||||||
|
Comment: Running function mymod.myfunc_false_result failed on minions: myminion. Function mymod.myfunc_false_result ran on myminion.
|
||||||
|
Started: 21:08:03.285148
|
||||||
|
Duration: 176.787 ms
|
||||||
|
Changes:
|
||||||
|
myminion:
|
||||||
|
False
|
||||||
|
|
||||||
|
Summary for fa5944a73aa8_master
|
||||||
|
------------
|
||||||
|
Succeeded: 2 (changed=4)
|
||||||
|
Failed: 2
|
||||||
|
------------
|
||||||
|
Total states run: 4
|
||||||
|
Total run time: 778.850 ms
|
||||||
|
|
||||||
|
|
||||||
|
However, using the ``json`` outputter, you can get the output in an easily
|
||||||
|
loadable and parsable format:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
salt-run state.orchestrate test --out=json
|
||||||
|
|
||||||
|
.. code-block:: json
|
||||||
|
|
||||||
|
{
|
||||||
|
"outputter": "highstate",
|
||||||
|
"data": {
|
||||||
|
"fa5944a73aa8_master": {
|
||||||
|
"salt_|-good_state_|-good_state_|-state": {
|
||||||
|
"comment": "States ran successfully. Updating myminion.",
|
||||||
|
"name": "good_state",
|
||||||
|
"start_time": "21:35:16.868345",
|
||||||
|
"result": true,
|
||||||
|
"duration": 267.299,
|
||||||
|
"__run_num__": 0,
|
||||||
|
"__jid__": "20171130213516897392",
|
||||||
|
"__sls__": "test",
|
||||||
|
"changes": {
|
||||||
|
"ret": {
|
||||||
|
"myminion": {
|
||||||
|
"test_|-test succeed with changes_|-test succeed with changes_|-succeed_with_changes": {
|
||||||
|
"comment": "Success!",
|
||||||
|
"name": "test succeed with changes",
|
||||||
|
"start_time": "21:35:17.022592",
|
||||||
|
"result": true,
|
||||||
|
"duration": 0.362,
|
||||||
|
"__run_num__": 0,
|
||||||
|
"__sls__": "succeed_with_changes",
|
||||||
|
"changes": {
|
||||||
|
"testing": {
|
||||||
|
"new": "Something pretended to change",
|
||||||
|
"old": "Unchanged"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"__id__": "test succeed with changes"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"out": "highstate"
|
||||||
|
},
|
||||||
|
"__id__": "good_state"
|
||||||
|
},
|
||||||
|
"salt_|-bad_state_|-bad_state_|-state": {
|
||||||
|
"comment": "Run failed on minions: test",
|
||||||
|
"name": "bad_state",
|
||||||
|
"start_time": "21:35:17.136511",
|
||||||
|
"result": false,
|
||||||
|
"duration": 197.635,
|
||||||
|
"__run_num__": 1,
|
||||||
|
"__jid__": "20171130213517202203",
|
||||||
|
"__sls__": "test",
|
||||||
|
"changes": {
|
||||||
|
"ret": {
|
||||||
|
"myminion": {
|
||||||
|
"test_|-test fail with changes_|-test fail with changes_|-fail_with_changes": {
|
||||||
|
"comment": "Failure!",
|
||||||
|
"name": "test fail with changes",
|
||||||
|
"start_time": "21:35:17.326268",
|
||||||
|
"result": false,
|
||||||
|
"duration": 0.509,
|
||||||
|
"__run_num__": 0,
|
||||||
|
"__sls__": "fail_with_changes",
|
||||||
|
"changes": {
|
||||||
|
"testing": {
|
||||||
|
"new": "Something pretended to change",
|
||||||
|
"old": "Unchanged"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"__id__": "test fail with changes"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"out": "highstate"
|
||||||
|
},
|
||||||
|
"__id__": "bad_state"
|
||||||
|
},
|
||||||
|
"salt_|-mymod.myfunc_|-mymod.myfunc_|-function": {
|
||||||
|
"comment": "Function ran successfully. Function mymod.myfunc ran on myminion.",
|
||||||
|
"name": "mymod.myfunc",
|
||||||
|
"start_time": "21:35:17.334373",
|
||||||
|
"result": true,
|
||||||
|
"duration": 151.716,
|
||||||
|
"__run_num__": 2,
|
||||||
|
"__jid__": "20171130213517361706",
|
||||||
|
"__sls__": "test",
|
||||||
|
"changes": {
|
||||||
|
"ret": {
|
||||||
|
"myminion": true
|
||||||
|
},
|
||||||
|
"out": "highstate"
|
||||||
|
},
|
||||||
|
"__id__": "mymod.myfunc"
|
||||||
|
},
|
||||||
|
"salt_|-mymod.myfunc_false_result-mymod.myfunc_false_result-function": {
|
||||||
|
"comment": "Running function mymod.myfunc_false_result failed on minions: myminion. Function mymod.myfunc_false_result ran on myminion.",
|
||||||
|
"name": "mymod.myfunc_false_result",
|
||||||
|
"start_time": "21:35:17.486625",
|
||||||
|
"result": false,
|
||||||
|
"duration": 174.241,
|
||||||
|
"__run_num__": 3,
|
||||||
|
"__jid__": "20171130213517536270",
|
||||||
|
"__sls__": "test",
|
||||||
|
"changes": {
|
||||||
|
"ret": {
|
||||||
|
"myminion": false
|
||||||
|
},
|
||||||
|
"out": "highstate"
|
||||||
|
},
|
||||||
|
"__id__": "mymod.myfunc_false_result"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"retcode": 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
The Oxygen release includes a couple fixes to make parsing this data easier and
|
||||||
|
more accurate. The first is the ability to set a :ref:`return code
|
||||||
|
<orchestrate-runner-return-codes-runner-wheel>` in a custom runner or wheel
|
||||||
|
function, as noted above. The second is a change to how failures are included
|
||||||
|
in the return data. Prior to the Oxygen release, minions that failed a
|
||||||
|
``salt.state`` orchestration job would show up in the ``comment`` field of the
|
||||||
|
return data, in a human-readable string that was not easily parsed. They are
|
||||||
|
now included in the ``changes`` dictionary alongside the minions that
|
||||||
|
succeeded. In addition, ``salt.function`` jobs which failed because the
|
||||||
|
:ref:`fail function <orchestrate-runner-fail-functions>` returned ``False``
|
||||||
|
used to handle their failures in the same way ``salt.state`` jobs did, and this
|
||||||
|
has likewise been corrected.
|
||||||
|
@ -65,6 +65,37 @@ noon PST so the Stormpath external authentication module has been removed.
|
|||||||
|
|
||||||
https://stormpath.com/oktaplusstormpath
|
https://stormpath.com/oktaplusstormpath
|
||||||
|
|
||||||
|
:conf_minion:`environment` config option renamed to :conf_minion:`saltenv`
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
The :conf_minion:`environment` config option predates referring to a salt
|
||||||
|
fileserver environment as a **saltenv**. To pin a minion to a single
|
||||||
|
environment for running states, one would use :conf_minion:`environment`, but
|
||||||
|
overriding that environment would be done with the ``saltenv`` argument. For
|
||||||
|
consistency, :conf_minion:`environment` is now simply referred to as
|
||||||
|
:conf_minion:`saltenv`. There are no plans to deprecate or remove
|
||||||
|
:conf_minion:`environment`, if used it will log a warning and its value will be
|
||||||
|
used as :conf_minion:`saltenv`.
|
||||||
|
|
||||||
|
:conf_minion:`lock_saltenv` config option added
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
If set to ``True``, this option will prevent a minion from allowing the
|
||||||
|
``saltenv`` argument to override the value set in :conf_minion:`saltenv` when
|
||||||
|
running states.
|
||||||
|
|
||||||
|
Failed Minions for State/Function Orchestration Jobs Added to Changes Dictionary
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
For orchestration jobs which run states (or run remote execution functions and
|
||||||
|
also use a :ref:`fail function <orchestrate-runner-fail-functions>` to indicate
|
||||||
|
success or failure), minions which have ``False`` results were previously
|
||||||
|
included as a formatted string in the comment field of the return for that
|
||||||
|
orchestration job. This made the failed returns difficult to :ref:`parse
|
||||||
|
programatically <orchestrate-runner-parsing-results-programatically>`. The
|
||||||
|
failed returns in these cases are now included in the changes dictionary,
|
||||||
|
making for much easier parsing.
|
||||||
|
|
||||||
New Grains
|
New Grains
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
@ -1050,7 +1050,7 @@ class Single(object):
|
|||||||
popts,
|
popts,
|
||||||
opts_pkg[u'grains'],
|
opts_pkg[u'grains'],
|
||||||
opts_pkg[u'id'],
|
opts_pkg[u'id'],
|
||||||
opts_pkg.get(u'environment', u'base')
|
opts_pkg.get(u'saltenv', u'base')
|
||||||
)
|
)
|
||||||
pillar_data = pillar.compile_pillar()
|
pillar_data = pillar.compile_pillar()
|
||||||
|
|
||||||
|
@ -246,7 +246,10 @@ VALID_OPTS = {
|
|||||||
'autoload_dynamic_modules': bool,
|
'autoload_dynamic_modules': bool,
|
||||||
|
|
||||||
# Force the minion into a single environment when it fetches files from the master
|
# Force the minion into a single environment when it fetches files from the master
|
||||||
'environment': str,
|
'saltenv': str,
|
||||||
|
|
||||||
|
# Prevent saltenv from being overriden on the command line
|
||||||
|
'lock_saltenv': bool,
|
||||||
|
|
||||||
# Force the minion into a single pillar root when it fetches pillar data from the master
|
# Force the minion into a single pillar root when it fetches pillar data from the master
|
||||||
'pillarenv': str,
|
'pillarenv': str,
|
||||||
@ -1181,7 +1184,8 @@ DEFAULT_MINION_OPTS = {
|
|||||||
'random_startup_delay': 0,
|
'random_startup_delay': 0,
|
||||||
'failhard': False,
|
'failhard': False,
|
||||||
'autoload_dynamic_modules': True,
|
'autoload_dynamic_modules': True,
|
||||||
'environment': None,
|
'saltenv': None,
|
||||||
|
'lock_saltenv': False,
|
||||||
'pillarenv': None,
|
'pillarenv': None,
|
||||||
'pillarenv_from_saltenv': False,
|
'pillarenv_from_saltenv': False,
|
||||||
'pillar_opts': False,
|
'pillar_opts': False,
|
||||||
@ -1458,7 +1462,8 @@ DEFAULT_MASTER_OPTS = {
|
|||||||
},
|
},
|
||||||
'top_file_merging_strategy': 'merge',
|
'top_file_merging_strategy': 'merge',
|
||||||
'env_order': [],
|
'env_order': [],
|
||||||
'environment': None,
|
'saltenv': None,
|
||||||
|
'lock_saltenv': False,
|
||||||
'default_top': 'base',
|
'default_top': 'base',
|
||||||
'file_client': 'local',
|
'file_client': 'local',
|
||||||
'git_pillar_base': 'master',
|
'git_pillar_base': 'master',
|
||||||
@ -3596,6 +3601,24 @@ def apply_minion_config(overrides=None,
|
|||||||
if overrides:
|
if overrides:
|
||||||
opts.update(overrides)
|
opts.update(overrides)
|
||||||
|
|
||||||
|
if u'environment' in opts:
|
||||||
|
if u'saltenv' in opts:
|
||||||
|
log.warning(
|
||||||
|
u'The \'saltenv\' and \'environment\' minion config options '
|
||||||
|
u'cannot both be used. Ignoring \'environment\' in favor of '
|
||||||
|
u'\'saltenv\'.',
|
||||||
|
)
|
||||||
|
# Set environment to saltenv in case someone's custom module is
|
||||||
|
# refrencing __opts__['environment']
|
||||||
|
opts[u'environment'] = opts[u'saltenv']
|
||||||
|
else:
|
||||||
|
log.warning(
|
||||||
|
u'The \'environment\' minion config option has been renamed '
|
||||||
|
u'to \'saltenv\'. Using %s as the \'saltenv\' config value.',
|
||||||
|
opts[u'environment']
|
||||||
|
)
|
||||||
|
opts[u'saltenv'] = opts[u'environment']
|
||||||
|
|
||||||
opts['__cli'] = os.path.basename(sys.argv[0])
|
opts['__cli'] = os.path.basename(sys.argv[0])
|
||||||
|
|
||||||
# No ID provided. Will getfqdn save us?
|
# No ID provided. Will getfqdn save us?
|
||||||
@ -3748,6 +3771,24 @@ def apply_master_config(overrides=None, defaults=None):
|
|||||||
if overrides:
|
if overrides:
|
||||||
opts.update(overrides)
|
opts.update(overrides)
|
||||||
|
|
||||||
|
if u'environment' in opts:
|
||||||
|
if u'saltenv' in opts:
|
||||||
|
log.warning(
|
||||||
|
u'The \'saltenv\' and \'environment\' master config options '
|
||||||
|
u'cannot both be used. Ignoring \'environment\' in favor of '
|
||||||
|
u'\'saltenv\'.',
|
||||||
|
)
|
||||||
|
# Set environment to saltenv in case someone's custom runner is
|
||||||
|
# refrencing __opts__['environment']
|
||||||
|
opts[u'environment'] = opts[u'saltenv']
|
||||||
|
else:
|
||||||
|
log.warning(
|
||||||
|
u'The \'environment\' master config option has been renamed '
|
||||||
|
u'to \'saltenv\'. Using %s as the \'saltenv\' config value.',
|
||||||
|
opts[u'environment']
|
||||||
|
)
|
||||||
|
opts[u'saltenv'] = opts[u'environment']
|
||||||
|
|
||||||
if len(opts['sock_dir']) > len(opts['cachedir']) + 10:
|
if len(opts['sock_dir']) > len(opts['cachedir']) + 10:
|
||||||
opts['sock_dir'] = os.path.join(opts['cachedir'], '.salt-unix')
|
opts['sock_dir'] = os.path.join(opts['cachedir'], '.salt-unix')
|
||||||
|
|
||||||
|
@ -737,7 +737,7 @@ class SaltLoadPillar(ioflo.base.deeding.Deed):
|
|||||||
'dst': (master.name, None, 'remote_cmd')}
|
'dst': (master.name, None, 'remote_cmd')}
|
||||||
load = {'id': self.opts.value['id'],
|
load = {'id': self.opts.value['id'],
|
||||||
'grains': self.grains.value,
|
'grains': self.grains.value,
|
||||||
'saltenv': self.opts.value['environment'],
|
'saltenv': self.opts.value['saltenv'],
|
||||||
'ver': '2',
|
'ver': '2',
|
||||||
'cmd': '_pillar'}
|
'cmd': '_pillar'}
|
||||||
self.road_stack.value.transmit({'route': route, 'load': load},
|
self.road_stack.value.transmit({'route': route, 'load': load},
|
||||||
|
@ -1593,8 +1593,10 @@ class LazyLoader(salt.utils.lazy.LazyDict):
|
|||||||
Load a single item if you have it
|
Load a single item if you have it
|
||||||
'''
|
'''
|
||||||
# if the key doesn't have a '.' then it isn't valid for this mod dict
|
# if the key doesn't have a '.' then it isn't valid for this mod dict
|
||||||
if not isinstance(key, six.string_types) or u'.' not in key:
|
if not isinstance(key, six.string_types):
|
||||||
raise KeyError
|
raise KeyError(u'The key must be a string.')
|
||||||
|
if u'.' not in key:
|
||||||
|
raise KeyError(u'The key \'%s\' should contain a \'.\'', key)
|
||||||
mod_name, _ = key.split(u'.', 1)
|
mod_name, _ = key.split(u'.', 1)
|
||||||
if mod_name in self.missing_modules:
|
if mod_name in self.missing_modules:
|
||||||
return True
|
return True
|
||||||
|
@ -736,8 +736,8 @@ class SMinion(MinionBase):
|
|||||||
if not os.path.isdir(pdir):
|
if not os.path.isdir(pdir):
|
||||||
os.makedirs(pdir, 0o700)
|
os.makedirs(pdir, 0o700)
|
||||||
ptop = os.path.join(pdir, u'top.sls')
|
ptop = os.path.join(pdir, u'top.sls')
|
||||||
if self.opts[u'environment'] is not None:
|
if self.opts[u'saltenv'] is not None:
|
||||||
penv = self.opts[u'environment']
|
penv = self.opts[u'saltenv']
|
||||||
else:
|
else:
|
||||||
penv = u'base'
|
penv = u'base'
|
||||||
cache_top = {penv: {self.opts[u'id']: [u'cache']}}
|
cache_top = {penv: {self.opts[u'id']: [u'cache']}}
|
||||||
@ -773,7 +773,7 @@ class SMinion(MinionBase):
|
|||||||
self.opts,
|
self.opts,
|
||||||
self.opts[u'grains'],
|
self.opts[u'grains'],
|
||||||
self.opts[u'id'],
|
self.opts[u'id'],
|
||||||
self.opts[u'environment'],
|
self.opts[u'saltenv'],
|
||||||
pillarenv=self.opts.get(u'pillarenv'),
|
pillarenv=self.opts.get(u'pillarenv'),
|
||||||
).compile_pillar()
|
).compile_pillar()
|
||||||
|
|
||||||
@ -1144,7 +1144,7 @@ class Minion(MinionBase):
|
|||||||
self.opts,
|
self.opts,
|
||||||
self.opts[u'grains'],
|
self.opts[u'grains'],
|
||||||
self.opts[u'id'],
|
self.opts[u'id'],
|
||||||
self.opts[u'environment'],
|
self.opts[u'saltenv'],
|
||||||
pillarenv=self.opts.get(u'pillarenv')
|
pillarenv=self.opts.get(u'pillarenv')
|
||||||
).compile_pillar()
|
).compile_pillar()
|
||||||
|
|
||||||
@ -2032,7 +2032,7 @@ class Minion(MinionBase):
|
|||||||
self.opts,
|
self.opts,
|
||||||
self.opts[u'grains'],
|
self.opts[u'grains'],
|
||||||
self.opts[u'id'],
|
self.opts[u'id'],
|
||||||
self.opts[u'environment'],
|
self.opts[u'saltenv'],
|
||||||
pillarenv=self.opts.get(u'pillarenv'),
|
pillarenv=self.opts.get(u'pillarenv'),
|
||||||
).compile_pillar()
|
).compile_pillar()
|
||||||
except SaltClientError:
|
except SaltClientError:
|
||||||
@ -3353,7 +3353,7 @@ class ProxyMinion(Minion):
|
|||||||
self.opts,
|
self.opts,
|
||||||
self.opts[u'grains'],
|
self.opts[u'grains'],
|
||||||
self.opts[u'id'],
|
self.opts[u'id'],
|
||||||
saltenv=self.opts[u'environment'],
|
saltenv=self.opts[u'saltenv'],
|
||||||
pillarenv=self.opts.get(u'pillarenv'),
|
pillarenv=self.opts.get(u'pillarenv'),
|
||||||
).compile_pillar()
|
).compile_pillar()
|
||||||
|
|
||||||
@ -3395,7 +3395,7 @@ class ProxyMinion(Minion):
|
|||||||
# we can then sync any proxymodules down from the master
|
# we can then sync any proxymodules down from the master
|
||||||
# we do a sync_all here in case proxy code was installed by
|
# we do a sync_all here in case proxy code was installed by
|
||||||
# SPM or was manually placed in /srv/salt/_modules etc.
|
# SPM or was manually placed in /srv/salt/_modules etc.
|
||||||
self.functions[u'saltutil.sync_all'](saltenv=self.opts[u'environment'])
|
self.functions[u'saltutil.sync_all'](saltenv=self.opts[u'saltenv'])
|
||||||
|
|
||||||
# Pull in the utils
|
# Pull in the utils
|
||||||
self.utils = salt.loader.utils(self.opts)
|
self.utils = salt.loader.utils(self.opts)
|
||||||
|
@ -219,7 +219,7 @@ def _gather_pillar(pillarenv, pillar_override):
|
|||||||
__opts__,
|
__opts__,
|
||||||
__grains__,
|
__grains__,
|
||||||
__opts__['id'],
|
__opts__['id'],
|
||||||
__opts__['environment'],
|
__opts__['saltenv'],
|
||||||
pillar_override=pillar_override,
|
pillar_override=pillar_override,
|
||||||
pillarenv=pillarenv
|
pillarenv=pillarenv
|
||||||
)
|
)
|
||||||
@ -589,11 +589,17 @@ def _run(cmd,
|
|||||||
out = proc.stdout.decode(__salt_system_encoding__)
|
out = proc.stdout.decode(__salt_system_encoding__)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
out = u''
|
out = u''
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
log.error('UnicodeDecodeError while decoding output of cmd {0}'.format(cmd))
|
||||||
|
out = proc.stdout.decode(__salt_system_encoding__, 'replace')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
err = proc.stderr.decode(__salt_system_encoding__)
|
err = proc.stderr.decode(__salt_system_encoding__)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
err = u''
|
err = u''
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
log.error('UnicodeDecodeError while decoding error of cmd {0}'.format(cmd))
|
||||||
|
err = proc.stderr.decode(__salt_system_encoding__, 'replace')
|
||||||
|
|
||||||
if rstrip:
|
if rstrip:
|
||||||
if out is not None:
|
if out is not None:
|
||||||
|
@ -49,7 +49,7 @@ def _gather_pillar(pillarenv, pillar_override):
|
|||||||
__opts__,
|
__opts__,
|
||||||
__grains__,
|
__grains__,
|
||||||
__opts__['id'],
|
__opts__['id'],
|
||||||
__opts__['environment'],
|
__opts__['saltenv'],
|
||||||
pillar_override=pillar_override,
|
pillar_override=pillar_override,
|
||||||
pillarenv=pillarenv
|
pillarenv=pillarenv
|
||||||
)
|
)
|
||||||
|
@ -5290,7 +5290,7 @@ def _gather_pillar(pillarenv, pillar_override, **grains):
|
|||||||
grains,
|
grains,
|
||||||
# Not sure if these two are correct
|
# Not sure if these two are correct
|
||||||
__opts__['id'],
|
__opts__['id'],
|
||||||
__opts__['environment'],
|
__opts__['saltenv'],
|
||||||
pillar_override=pillar_override,
|
pillar_override=pillar_override,
|
||||||
pillarenv=pillarenv
|
pillarenv=pillarenv
|
||||||
)
|
)
|
||||||
|
@ -225,7 +225,7 @@ def send(tag,
|
|||||||
data_dict['pillar'] = __pillar__
|
data_dict['pillar'] = __pillar__
|
||||||
|
|
||||||
if with_env_opts:
|
if with_env_opts:
|
||||||
data_dict['saltenv'] = __opts__.get('environment', 'base')
|
data_dict['saltenv'] = __opts__.get('saltenv', 'base')
|
||||||
data_dict['pillarenv'] = __opts__.get('pillarenv')
|
data_dict['pillarenv'] = __opts__.get('pillarenv')
|
||||||
|
|
||||||
if kwargs:
|
if kwargs:
|
||||||
|
@ -237,7 +237,7 @@ def items(*args, **kwargs):
|
|||||||
pillarenv = kwargs.get('pillarenv')
|
pillarenv = kwargs.get('pillarenv')
|
||||||
if pillarenv is None:
|
if pillarenv is None:
|
||||||
if __opts__.get('pillarenv_from_saltenv', False):
|
if __opts__.get('pillarenv_from_saltenv', False):
|
||||||
pillarenv = kwargs.get('saltenv') or __opts__['environment']
|
pillarenv = kwargs.get('saltenv') or __opts__['saltenv']
|
||||||
else:
|
else:
|
||||||
pillarenv = __opts__['pillarenv']
|
pillarenv = __opts__['pillarenv']
|
||||||
|
|
||||||
@ -468,7 +468,7 @@ def ext(external, pillar=None):
|
|||||||
__opts__,
|
__opts__,
|
||||||
__grains__,
|
__grains__,
|
||||||
__opts__['id'],
|
__opts__['id'],
|
||||||
__opts__['environment'],
|
__opts__['saltenv'],
|
||||||
ext=external,
|
ext=external,
|
||||||
pillar_override=pillar)
|
pillar_override=pillar)
|
||||||
|
|
||||||
|
@ -509,7 +509,7 @@ class SaltCheck(object):
|
|||||||
# state cache should be updated before running this method
|
# state cache should be updated before running this method
|
||||||
search_list = []
|
search_list = []
|
||||||
cachedir = __opts__.get('cachedir', None)
|
cachedir = __opts__.get('cachedir', None)
|
||||||
environment = __opts__['environment']
|
environment = __opts__['saltenv']
|
||||||
if environment:
|
if environment:
|
||||||
path = cachedir + os.sep + "files" + os.sep + environment
|
path = cachedir + os.sep + "files" + os.sep + environment
|
||||||
search_list.append(path)
|
search_list.append(path)
|
||||||
|
@ -364,10 +364,14 @@ def _get_opts(**kwargs):
|
|||||||
|
|
||||||
if 'saltenv' in kwargs:
|
if 'saltenv' in kwargs:
|
||||||
saltenv = kwargs['saltenv']
|
saltenv = kwargs['saltenv']
|
||||||
if saltenv is not None and not isinstance(saltenv, six.string_types):
|
if saltenv is not None:
|
||||||
opts['environment'] = str(kwargs['saltenv'])
|
if not isinstance(saltenv, six.string_types):
|
||||||
else:
|
saltenv = six.text_type(saltenv)
|
||||||
opts['environment'] = kwargs['saltenv']
|
if opts['lock_saltenv'] and saltenv != opts['saltenv']:
|
||||||
|
raise CommandExecutionError(
|
||||||
|
'lock_saltenv is enabled, saltenv cannot be changed'
|
||||||
|
)
|
||||||
|
opts['saltenv'] = kwargs['saltenv']
|
||||||
|
|
||||||
if 'pillarenv' in kwargs or opts.get('pillarenv_from_saltenv', False):
|
if 'pillarenv' in kwargs or opts.get('pillarenv_from_saltenv', False):
|
||||||
pillarenv = kwargs.get('pillarenv') or kwargs.get('saltenv')
|
pillarenv = kwargs.get('pillarenv') or kwargs.get('saltenv')
|
||||||
@ -934,7 +938,7 @@ def highstate(test=None, queue=False, **kwargs):
|
|||||||
kwargs.pop('env')
|
kwargs.pop('env')
|
||||||
|
|
||||||
if 'saltenv' in kwargs:
|
if 'saltenv' in kwargs:
|
||||||
opts['environment'] = kwargs['saltenv']
|
opts['saltenv'] = kwargs['saltenv']
|
||||||
|
|
||||||
if 'pillarenv' in kwargs:
|
if 'pillarenv' in kwargs:
|
||||||
opts['pillarenv'] = kwargs['pillarenv']
|
opts['pillarenv'] = kwargs['pillarenv']
|
||||||
@ -1126,8 +1130,8 @@ def sls(mods, test=None, exclude=None, queue=False, **kwargs):
|
|||||||
|
|
||||||
# Since this is running a specific SLS file (or files), fall back to the
|
# Since this is running a specific SLS file (or files), fall back to the
|
||||||
# 'base' saltenv if none is configured and none was passed.
|
# 'base' saltenv if none is configured and none was passed.
|
||||||
if opts['environment'] is None:
|
if opts['saltenv'] is None:
|
||||||
opts['environment'] = 'base'
|
opts['saltenv'] = 'base'
|
||||||
|
|
||||||
pillar_override = kwargs.get('pillar')
|
pillar_override = kwargs.get('pillar')
|
||||||
pillar_enc = kwargs.get('pillar_enc')
|
pillar_enc = kwargs.get('pillar_enc')
|
||||||
@ -1183,7 +1187,7 @@ def sls(mods, test=None, exclude=None, queue=False, **kwargs):
|
|||||||
st_.push_active()
|
st_.push_active()
|
||||||
ret = {}
|
ret = {}
|
||||||
try:
|
try:
|
||||||
high_, errors = st_.render_highstate({opts['environment']: mods})
|
high_, errors = st_.render_highstate({opts['saltenv']: mods})
|
||||||
|
|
||||||
if errors:
|
if errors:
|
||||||
__context__['retcode'] = 1
|
__context__['retcode'] = 1
|
||||||
@ -1505,8 +1509,8 @@ def sls_id(id_, mods, test=None, queue=False, **kwargs):
|
|||||||
|
|
||||||
# Since this is running a specific ID within a specific SLS file, fall back
|
# Since this is running a specific ID within a specific SLS file, fall back
|
||||||
# to the 'base' saltenv if none is configured and none was passed.
|
# to the 'base' saltenv if none is configured and none was passed.
|
||||||
if opts['environment'] is None:
|
if opts['saltenv'] is None:
|
||||||
opts['environment'] = 'base'
|
opts['saltenv'] = 'base'
|
||||||
|
|
||||||
pillar_override = kwargs.get('pillar')
|
pillar_override = kwargs.get('pillar')
|
||||||
pillar_enc = kwargs.get('pillar_enc')
|
pillar_enc = kwargs.get('pillar_enc')
|
||||||
@ -1540,7 +1544,7 @@ def sls_id(id_, mods, test=None, queue=False, **kwargs):
|
|||||||
split_mods = mods.split(',')
|
split_mods = mods.split(',')
|
||||||
st_.push_active()
|
st_.push_active()
|
||||||
try:
|
try:
|
||||||
high_, errors = st_.render_highstate({opts['environment']: split_mods})
|
high_, errors = st_.render_highstate({opts['saltenv']: split_mods})
|
||||||
finally:
|
finally:
|
||||||
st_.pop_active()
|
st_.pop_active()
|
||||||
errors += st_.state.verify_high(high_)
|
errors += st_.state.verify_high(high_)
|
||||||
@ -1566,7 +1570,7 @@ def sls_id(id_, mods, test=None, queue=False, **kwargs):
|
|||||||
if not ret:
|
if not ret:
|
||||||
raise SaltInvocationError(
|
raise SaltInvocationError(
|
||||||
'No matches for ID \'{0}\' found in SLS \'{1}\' within saltenv '
|
'No matches for ID \'{0}\' found in SLS \'{1}\' within saltenv '
|
||||||
'\'{2}\''.format(id_, mods, opts['environment'])
|
'\'{2}\''.format(id_, mods, opts['saltenv'])
|
||||||
)
|
)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@ -1617,8 +1621,8 @@ def show_low_sls(mods, test=None, queue=False, **kwargs):
|
|||||||
|
|
||||||
# Since this is dealing with a specific SLS file (or files), fall back to
|
# Since this is dealing with a specific SLS file (or files), fall back to
|
||||||
# the 'base' saltenv if none is configured and none was passed.
|
# the 'base' saltenv if none is configured and none was passed.
|
||||||
if opts['environment'] is None:
|
if opts['saltenv'] is None:
|
||||||
opts['environment'] = 'base'
|
opts['saltenv'] = 'base'
|
||||||
|
|
||||||
pillar_override = kwargs.get('pillar')
|
pillar_override = kwargs.get('pillar')
|
||||||
pillar_enc = kwargs.get('pillar_enc')
|
pillar_enc = kwargs.get('pillar_enc')
|
||||||
@ -1649,7 +1653,7 @@ def show_low_sls(mods, test=None, queue=False, **kwargs):
|
|||||||
mods = mods.split(',')
|
mods = mods.split(',')
|
||||||
st_.push_active()
|
st_.push_active()
|
||||||
try:
|
try:
|
||||||
high_, errors = st_.render_highstate({opts['environment']: mods})
|
high_, errors = st_.render_highstate({opts['saltenv']: mods})
|
||||||
finally:
|
finally:
|
||||||
st_.pop_active()
|
st_.pop_active()
|
||||||
errors += st_.state.verify_high(high_)
|
errors += st_.state.verify_high(high_)
|
||||||
@ -1688,7 +1692,7 @@ def show_sls(mods, test=None, queue=False, **kwargs):
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
salt '*' state.show_sls core,edit.vim dev
|
salt '*' state.show_sls core,edit.vim saltenv=dev
|
||||||
'''
|
'''
|
||||||
if 'env' in kwargs:
|
if 'env' in kwargs:
|
||||||
# "env" is not supported; Use "saltenv".
|
# "env" is not supported; Use "saltenv".
|
||||||
@ -1704,8 +1708,8 @@ def show_sls(mods, test=None, queue=False, **kwargs):
|
|||||||
|
|
||||||
# Since this is dealing with a specific SLS file (or files), fall back to
|
# Since this is dealing with a specific SLS file (or files), fall back to
|
||||||
# the 'base' saltenv if none is configured and none was passed.
|
# the 'base' saltenv if none is configured and none was passed.
|
||||||
if opts['environment'] is None:
|
if opts['saltenv'] is None:
|
||||||
opts['environment'] = 'base'
|
opts['saltenv'] = 'base'
|
||||||
|
|
||||||
pillar_override = kwargs.get('pillar')
|
pillar_override = kwargs.get('pillar')
|
||||||
pillar_enc = kwargs.get('pillar_enc')
|
pillar_enc = kwargs.get('pillar_enc')
|
||||||
@ -1738,7 +1742,7 @@ def show_sls(mods, test=None, queue=False, **kwargs):
|
|||||||
mods = mods.split(',')
|
mods = mods.split(',')
|
||||||
st_.push_active()
|
st_.push_active()
|
||||||
try:
|
try:
|
||||||
high_, errors = st_.render_highstate({opts['environment']: mods})
|
high_, errors = st_.render_highstate({opts['saltenv']: mods})
|
||||||
finally:
|
finally:
|
||||||
st_.pop_active()
|
st_.pop_active()
|
||||||
errors += st_.state.verify_high(high_)
|
errors += st_.state.verify_high(high_)
|
||||||
@ -1904,6 +1908,7 @@ def pkg(pkg_path,
|
|||||||
salt '*' state.pkg /tmp/salt_state.tgz 760a9353810e36f6d81416366fc426dc md5
|
salt '*' state.pkg /tmp/salt_state.tgz 760a9353810e36f6d81416366fc426dc md5
|
||||||
'''
|
'''
|
||||||
# TODO - Add ability to download from salt master or other source
|
# TODO - Add ability to download from salt master or other source
|
||||||
|
popts = _get_opts(**kwargs)
|
||||||
if not os.path.isfile(pkg_path):
|
if not os.path.isfile(pkg_path):
|
||||||
return {}
|
return {}
|
||||||
if not salt.utils.hashutils.get_hash(pkg_path, hash_type) == pkg_sum:
|
if not salt.utils.hashutils.get_hash(pkg_path, hash_type) == pkg_sum:
|
||||||
@ -1938,7 +1943,6 @@ def pkg(pkg_path,
|
|||||||
with salt.utils.files.fopen(roster_grains_json, 'r') as fp_:
|
with salt.utils.files.fopen(roster_grains_json, 'r') as fp_:
|
||||||
roster_grains = json.load(fp_, object_hook=salt.utils.data.decode_dict)
|
roster_grains = json.load(fp_, object_hook=salt.utils.data.decode_dict)
|
||||||
|
|
||||||
popts = _get_opts(**kwargs)
|
|
||||||
if os.path.isfile(roster_grains_json):
|
if os.path.isfile(roster_grains_json):
|
||||||
popts['grains'] = roster_grains
|
popts['grains'] = roster_grains
|
||||||
popts['fileclient'] = 'local'
|
popts['fileclient'] = 'local'
|
||||||
|
@ -399,6 +399,14 @@ def _systemd_scope():
|
|||||||
and __salt__['config.get']('systemd.scope', True)
|
and __salt__['config.get']('systemd.scope', True)
|
||||||
|
|
||||||
|
|
||||||
|
def _clean_cache():
|
||||||
|
'''
|
||||||
|
Clean cached results
|
||||||
|
'''
|
||||||
|
for cache_name in ['pkg.list_pkgs', 'pkg.list_provides']:
|
||||||
|
__context__.pop(cache_name, None)
|
||||||
|
|
||||||
|
|
||||||
def list_upgrades(refresh=True, **kwargs):
|
def list_upgrades(refresh=True, **kwargs):
|
||||||
'''
|
'''
|
||||||
List all available package upgrades on this system
|
List all available package upgrades on this system
|
||||||
@ -1049,6 +1057,10 @@ def install(name=None,
|
|||||||
operator (<, >, <=, >=, =) and a version number (ex. '>1.2.3-4').
|
operator (<, >, <=, >=, =) and a version number (ex. '>1.2.3-4').
|
||||||
This parameter is ignored if ``pkgs`` or ``sources`` is passed.
|
This parameter is ignored if ``pkgs`` or ``sources`` is passed.
|
||||||
|
|
||||||
|
resolve_capabilities
|
||||||
|
If this option is set to True zypper will take capabilites into
|
||||||
|
account. In this case names which are just provided by a package
|
||||||
|
will get installed. Default is False.
|
||||||
|
|
||||||
Multiple Package Installation Options:
|
Multiple Package Installation Options:
|
||||||
|
|
||||||
@ -1164,7 +1176,10 @@ def install(name=None,
|
|||||||
log.info('Targeting repo \'{0}\''.format(fromrepo))
|
log.info('Targeting repo \'{0}\''.format(fromrepo))
|
||||||
else:
|
else:
|
||||||
fromrepoopt = ''
|
fromrepoopt = ''
|
||||||
cmd_install = ['install', '--name', '--auto-agree-with-licenses']
|
cmd_install = ['install', '--auto-agree-with-licenses']
|
||||||
|
|
||||||
|
cmd_install.append(kwargs.get('resolve_capabilities') and '--capability' or '--name')
|
||||||
|
|
||||||
if not refresh:
|
if not refresh:
|
||||||
cmd_install.insert(0, '--no-refresh')
|
cmd_install.insert(0, '--no-refresh')
|
||||||
if skip_verify:
|
if skip_verify:
|
||||||
@ -1194,7 +1209,7 @@ def install(name=None,
|
|||||||
downgrades = downgrades[500:]
|
downgrades = downgrades[500:]
|
||||||
__zypper__(no_repo_failure=ignore_repo_failure).call(*cmd)
|
__zypper__(no_repo_failure=ignore_repo_failure).call(*cmd)
|
||||||
|
|
||||||
__context__.pop('pkg.list_pkgs', None)
|
_clean_cache()
|
||||||
new = list_pkgs(attr=diff_attr) if not downloadonly else list_downloaded()
|
new = list_pkgs(attr=diff_attr) if not downloadonly else list_downloaded()
|
||||||
|
|
||||||
# Handle packages which report multiple new versions
|
# Handle packages which report multiple new versions
|
||||||
@ -1311,7 +1326,7 @@ def upgrade(refresh=True,
|
|||||||
old = list_pkgs()
|
old = list_pkgs()
|
||||||
|
|
||||||
__zypper__(systemd_scope=_systemd_scope()).noraise.call(*cmd_update)
|
__zypper__(systemd_scope=_systemd_scope()).noraise.call(*cmd_update)
|
||||||
__context__.pop('pkg.list_pkgs', None)
|
_clean_cache()
|
||||||
new = list_pkgs()
|
new = list_pkgs()
|
||||||
|
|
||||||
# Handle packages which report multiple new versions
|
# Handle packages which report multiple new versions
|
||||||
@ -1360,7 +1375,7 @@ def _uninstall(name=None, pkgs=None):
|
|||||||
__zypper__(systemd_scope=systemd_scope).call('remove', *targets[:500])
|
__zypper__(systemd_scope=systemd_scope).call('remove', *targets[:500])
|
||||||
targets = targets[500:]
|
targets = targets[500:]
|
||||||
|
|
||||||
__context__.pop('pkg.list_pkgs', None)
|
_clean_cache()
|
||||||
ret = salt.utils.data.compare_dicts(old, list_pkgs())
|
ret = salt.utils.data.compare_dicts(old, list_pkgs())
|
||||||
|
|
||||||
if errors:
|
if errors:
|
||||||
@ -1750,7 +1765,7 @@ def list_installed_patterns():
|
|||||||
return _get_patterns(installed_only=True)
|
return _get_patterns(installed_only=True)
|
||||||
|
|
||||||
|
|
||||||
def search(criteria, refresh=False):
|
def search(criteria, refresh=False, **kwargs):
|
||||||
'''
|
'''
|
||||||
List known packags, available to the system.
|
List known packags, available to the system.
|
||||||
|
|
||||||
@ -1759,26 +1774,94 @@ def search(criteria, refresh=False):
|
|||||||
If set to False (default) it depends on zypper if a refresh is
|
If set to False (default) it depends on zypper if a refresh is
|
||||||
executed.
|
executed.
|
||||||
|
|
||||||
|
match (str)
|
||||||
|
One of `exact`, `words`, `substrings`. Search for an `exact` match
|
||||||
|
or for the whole `words` only. Default to `substrings` to patch
|
||||||
|
partial words.
|
||||||
|
|
||||||
|
provides (bool)
|
||||||
|
Search for packages which provide the search strings.
|
||||||
|
|
||||||
|
recommends (bool)
|
||||||
|
Search for packages which recommend the search strings.
|
||||||
|
|
||||||
|
requires (bool)
|
||||||
|
Search for packages which require the search strings.
|
||||||
|
|
||||||
|
suggests (bool)
|
||||||
|
Search for packages which suggest the search strings.
|
||||||
|
|
||||||
|
conflicts (bool)
|
||||||
|
Search packages conflicting with search strings.
|
||||||
|
|
||||||
|
obsoletes (bool)
|
||||||
|
Search for packages which obsolete the search strings.
|
||||||
|
|
||||||
|
file_list (bool)
|
||||||
|
Search for a match in the file list of packages.
|
||||||
|
|
||||||
|
search_descriptions (bool)
|
||||||
|
Search also in package summaries and descriptions.
|
||||||
|
|
||||||
|
case_sensitive (bool)
|
||||||
|
Perform case-sensitive search.
|
||||||
|
|
||||||
|
installed_only (bool)
|
||||||
|
Show only installed packages.
|
||||||
|
|
||||||
|
not_installed_only (bool)
|
||||||
|
Show only packages which are not installed.
|
||||||
|
|
||||||
|
details (bool)
|
||||||
|
Show version and repository
|
||||||
|
|
||||||
CLI Examples:
|
CLI Examples:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
salt '*' pkg.search <criteria>
|
salt '*' pkg.search <criteria>
|
||||||
'''
|
'''
|
||||||
|
ALLOWED_SEARCH_OPTIONS = {
|
||||||
|
'provides': '--provides',
|
||||||
|
'recommends': '--recommends',
|
||||||
|
'requires': '--requires',
|
||||||
|
'suggests': '--suggests',
|
||||||
|
'conflicts': '--conflicts',
|
||||||
|
'obsoletes': '--obsoletes',
|
||||||
|
'file_list': '--file-list',
|
||||||
|
'search_descriptions': '--search-descriptions',
|
||||||
|
'case_sensitive': '--case-sensitive',
|
||||||
|
'installed_only': '--installed-only',
|
||||||
|
'not_installed_only': '-u',
|
||||||
|
'details': '--details'
|
||||||
|
}
|
||||||
if refresh:
|
if refresh:
|
||||||
refresh_db()
|
refresh_db()
|
||||||
|
|
||||||
solvables = __zypper__.nolock.xml.call('se', criteria).getElementsByTagName('solvable')
|
cmd = ['search']
|
||||||
|
if kwargs.get('match') == 'exact':
|
||||||
|
cmd.append('--match-exact')
|
||||||
|
elif kwargs.get('match') == 'words':
|
||||||
|
cmd.append('--match-words')
|
||||||
|
elif kwargs.get('match') == 'substrings':
|
||||||
|
cmd.append('--match-substrings')
|
||||||
|
|
||||||
|
for opt in kwargs:
|
||||||
|
if opt in ALLOWED_SEARCH_OPTIONS:
|
||||||
|
cmd.append(ALLOWED_SEARCH_OPTIONS.get(opt))
|
||||||
|
|
||||||
|
cmd.append(criteria)
|
||||||
|
solvables = __zypper__.nolock.noraise.xml.call(*cmd).getElementsByTagName('solvable')
|
||||||
if not solvables:
|
if not solvables:
|
||||||
raise CommandExecutionError(
|
raise CommandExecutionError(
|
||||||
'No packages found matching \'{0}\''.format(criteria)
|
'No packages found matching \'{0}\''.format(criteria)
|
||||||
)
|
)
|
||||||
|
|
||||||
out = {}
|
out = {}
|
||||||
for solvable in [slv for slv in solvables
|
for solvable in solvables:
|
||||||
if slv.getAttribute('status') == 'not-installed'
|
out[solvable.getAttribute('name')] = dict()
|
||||||
and slv.getAttribute('kind') == 'package']:
|
for k, v in solvable.attributes.items():
|
||||||
out[solvable.getAttribute('name')] = {'summary': solvable.getAttribute('summary')}
|
out[solvable.getAttribute('name')][k] = v
|
||||||
|
|
||||||
return out
|
return out
|
||||||
|
|
||||||
@ -2033,3 +2116,97 @@ def list_installed_patches():
|
|||||||
salt '*' pkg.list_installed_patches
|
salt '*' pkg.list_installed_patches
|
||||||
'''
|
'''
|
||||||
return _get_patches(installed_only=True)
|
return _get_patches(installed_only=True)
|
||||||
|
|
||||||
|
|
||||||
|
def list_provides(**kwargs):
|
||||||
|
'''
|
||||||
|
.. versionadded:: Oxygen
|
||||||
|
|
||||||
|
List package provides of installed packages as a dict.
|
||||||
|
{'<provided_name>': ['<package_name>', '<package_name>', ...]}
|
||||||
|
|
||||||
|
CLI Examples:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
salt '*' pkg.list_provides
|
||||||
|
'''
|
||||||
|
ret = __context__.get('pkg.list_provides')
|
||||||
|
if not ret:
|
||||||
|
cmd = ['rpm', '-qa', '--queryformat', '[%{PROVIDES}_|-%{NAME}\n]']
|
||||||
|
ret = dict()
|
||||||
|
for line in __salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False).splitlines():
|
||||||
|
provide, realname = line.split('_|-')
|
||||||
|
|
||||||
|
if provide == realname:
|
||||||
|
continue
|
||||||
|
if provide not in ret:
|
||||||
|
ret[provide] = list()
|
||||||
|
ret[provide].append(realname)
|
||||||
|
|
||||||
|
__context__['pkg.list_provides'] = ret
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_capabilities(pkgs, refresh, **kwargs):
|
||||||
|
'''
|
||||||
|
.. versionadded:: Oxygen
|
||||||
|
|
||||||
|
Convert name provides in ``pkgs`` into real package names if
|
||||||
|
``resolve_capabilities`` parameter is set to True. In case of
|
||||||
|
``resolve_capabilities`` is set to False the package list
|
||||||
|
is returned unchanged.
|
||||||
|
|
||||||
|
refresh
|
||||||
|
force a refresh if set to True.
|
||||||
|
If set to False (default) it depends on zypper if a refresh is
|
||||||
|
executed.
|
||||||
|
|
||||||
|
resolve_capabilities
|
||||||
|
If this option is set to True the input will be checked if
|
||||||
|
a package with this name exists. If not, this function will
|
||||||
|
search for a package which provides this name. If one is found
|
||||||
|
the output is exchanged with the real package name.
|
||||||
|
In case this option is set to False (Default) the input will
|
||||||
|
be returned unchanged.
|
||||||
|
|
||||||
|
CLI Examples:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
salt '*' pkg.resolve_capabilities resolve_capabilities=True w3m_ssl
|
||||||
|
'''
|
||||||
|
if refresh:
|
||||||
|
refresh_db()
|
||||||
|
|
||||||
|
ret = list()
|
||||||
|
for pkg in pkgs:
|
||||||
|
if isinstance(pkg, dict):
|
||||||
|
name = next(iter(pkg))
|
||||||
|
version = pkg[name]
|
||||||
|
else:
|
||||||
|
name = pkg
|
||||||
|
version = None
|
||||||
|
|
||||||
|
if kwargs.get('resolve_capabilities', False):
|
||||||
|
try:
|
||||||
|
search(name, match='exact')
|
||||||
|
except CommandExecutionError:
|
||||||
|
# no package this such a name found
|
||||||
|
# search for a package which provides this name
|
||||||
|
try:
|
||||||
|
result = search(name, provides=True, match='exact')
|
||||||
|
if len(result) == 1:
|
||||||
|
name = result.keys()[0]
|
||||||
|
elif len(result) > 1:
|
||||||
|
log.warn("Found ambiguous match for capability '{0}'.".format(pkg))
|
||||||
|
except CommandExecutionError as exc:
|
||||||
|
# when search throws an exception stay with original name and version
|
||||||
|
log.debug("Search failed with: {0}".format(exc))
|
||||||
|
|
||||||
|
if version:
|
||||||
|
ret.append({name: version})
|
||||||
|
else:
|
||||||
|
ret.append(name)
|
||||||
|
return ret
|
||||||
|
@ -138,7 +138,7 @@ class AsyncRemotePillar(RemotePillarMixin):
|
|||||||
def __init__(self, opts, grains, minion_id, saltenv, ext=None, functions=None,
|
def __init__(self, opts, grains, minion_id, saltenv, ext=None, functions=None,
|
||||||
pillar_override=None, pillarenv=None, extra_minion_data=None):
|
pillar_override=None, pillarenv=None, extra_minion_data=None):
|
||||||
self.opts = opts
|
self.opts = opts
|
||||||
self.opts['environment'] = saltenv
|
self.opts['saltenv'] = saltenv
|
||||||
self.ext = ext
|
self.ext = ext
|
||||||
self.grains = grains
|
self.grains = grains
|
||||||
self.minion_id = minion_id
|
self.minion_id = minion_id
|
||||||
@ -165,7 +165,7 @@ class AsyncRemotePillar(RemotePillarMixin):
|
|||||||
'''
|
'''
|
||||||
load = {'id': self.minion_id,
|
load = {'id': self.minion_id,
|
||||||
'grains': self.grains,
|
'grains': self.grains,
|
||||||
'saltenv': self.opts['environment'],
|
'saltenv': self.opts['saltenv'],
|
||||||
'pillarenv': self.opts['pillarenv'],
|
'pillarenv': self.opts['pillarenv'],
|
||||||
'pillar_override': self.pillar_override,
|
'pillar_override': self.pillar_override,
|
||||||
'extra_minion_data': self.extra_minion_data,
|
'extra_minion_data': self.extra_minion_data,
|
||||||
@ -198,7 +198,7 @@ class RemotePillar(RemotePillarMixin):
|
|||||||
def __init__(self, opts, grains, minion_id, saltenv, ext=None, functions=None,
|
def __init__(self, opts, grains, minion_id, saltenv, ext=None, functions=None,
|
||||||
pillar_override=None, pillarenv=None, extra_minion_data=None):
|
pillar_override=None, pillarenv=None, extra_minion_data=None):
|
||||||
self.opts = opts
|
self.opts = opts
|
||||||
self.opts['environment'] = saltenv
|
self.opts['saltenv'] = saltenv
|
||||||
self.ext = ext
|
self.ext = ext
|
||||||
self.grains = grains
|
self.grains = grains
|
||||||
self.minion_id = minion_id
|
self.minion_id = minion_id
|
||||||
@ -224,7 +224,7 @@ class RemotePillar(RemotePillarMixin):
|
|||||||
'''
|
'''
|
||||||
load = {'id': self.minion_id,
|
load = {'id': self.minion_id,
|
||||||
'grains': self.grains,
|
'grains': self.grains,
|
||||||
'saltenv': self.opts['environment'],
|
'saltenv': self.opts['saltenv'],
|
||||||
'pillarenv': self.opts['pillarenv'],
|
'pillarenv': self.opts['pillarenv'],
|
||||||
'pillar_override': self.pillar_override,
|
'pillar_override': self.pillar_override,
|
||||||
'extra_minion_data': self.extra_minion_data,
|
'extra_minion_data': self.extra_minion_data,
|
||||||
@ -445,9 +445,9 @@ class Pillar(object):
|
|||||||
else:
|
else:
|
||||||
opts['grains'] = grains
|
opts['grains'] = grains
|
||||||
# Allow minion/CLI saltenv/pillarenv to take precedence over master
|
# Allow minion/CLI saltenv/pillarenv to take precedence over master
|
||||||
opts['environment'] = saltenv \
|
opts['saltenv'] = saltenv \
|
||||||
if saltenv is not None \
|
if saltenv is not None \
|
||||||
else opts.get('environment')
|
else opts.get('saltenv')
|
||||||
opts['pillarenv'] = pillarenv \
|
opts['pillarenv'] = pillarenv \
|
||||||
if pillarenv is not None \
|
if pillarenv is not None \
|
||||||
else opts.get('pillarenv')
|
else opts.get('pillarenv')
|
||||||
|
@ -404,7 +404,7 @@ def ext_pillar(minion_id, pillar, *repos): # pylint: disable=unused-argument
|
|||||||
# Map env if env == '__env__' before checking the env value
|
# Map env if env == '__env__' before checking the env value
|
||||||
if env == '__env__':
|
if env == '__env__':
|
||||||
env = opts.get('pillarenv') \
|
env = opts.get('pillarenv') \
|
||||||
or opts.get('environment') \
|
or opts.get('saltenv') \
|
||||||
or opts.get('git_pillar_base')
|
or opts.get('git_pillar_base')
|
||||||
log.debug('__env__ maps to %s', env)
|
log.debug('__env__ maps to %s', env)
|
||||||
|
|
||||||
|
@ -763,7 +763,7 @@ class State(object):
|
|||||||
self.opts,
|
self.opts,
|
||||||
self.opts[u'grains'],
|
self.opts[u'grains'],
|
||||||
self.opts[u'id'],
|
self.opts[u'id'],
|
||||||
self.opts[u'environment'],
|
self.opts[u'saltenv'],
|
||||||
pillar_override=self._pillar_override,
|
pillar_override=self._pillar_override,
|
||||||
pillarenv=self.opts.get(u'pillarenv'))
|
pillarenv=self.opts.get(u'pillarenv'))
|
||||||
return pillar.compile_pillar()
|
return pillar.compile_pillar()
|
||||||
@ -1892,20 +1892,27 @@ class State(object):
|
|||||||
(u'onlyif' in low and u'{0[state]}.mod_run_check'.format(low) not in self.states):
|
(u'onlyif' in low and u'{0[state]}.mod_run_check'.format(low) not in self.states):
|
||||||
ret.update(self._run_check(low))
|
ret.update(self._run_check(low))
|
||||||
|
|
||||||
if u'saltenv' in low:
|
if not self.opts.get(u'lock_saltenv', False):
|
||||||
inject_globals[u'__env__'] = six.text_type(low[u'saltenv'])
|
# NOTE: Overriding the saltenv when lock_saltenv is blocked in
|
||||||
elif isinstance(cdata[u'kwargs'].get(u'env', None), six.string_types):
|
# salt/modules/state.py, before we ever get here, but this
|
||||||
# User is using a deprecated env setting which was parsed by
|
# additional check keeps use of the State class outside of the
|
||||||
# format_call.
|
# salt/modules/state.py from getting around this setting.
|
||||||
# We check for a string type since module functions which
|
if u'saltenv' in low:
|
||||||
# allow setting the OS environ also make use of the "env"
|
inject_globals[u'__env__'] = six.text_type(low[u'saltenv'])
|
||||||
# keyword argument, which is not a string
|
elif isinstance(cdata[u'kwargs'].get(u'env', None), six.string_types):
|
||||||
inject_globals[u'__env__'] = six.text_type(cdata[u'kwargs'][u'env'])
|
# User is using a deprecated env setting which was parsed by
|
||||||
elif u'__env__' in low:
|
# format_call.
|
||||||
# The user is passing an alternative environment using __env__
|
# We check for a string type since module functions which
|
||||||
# which is also not the appropriate choice, still, handle it
|
# allow setting the OS environ also make use of the "env"
|
||||||
inject_globals[u'__env__'] = six.text_type(low[u'__env__'])
|
# keyword argument, which is not a string
|
||||||
else:
|
inject_globals[u'__env__'] = six.text_type(cdata[u'kwargs'][u'env'])
|
||||||
|
elif u'__env__' in low:
|
||||||
|
# The user is passing an alternative environment using
|
||||||
|
# __env__ which is also not the appropriate choice, still,
|
||||||
|
# handle it
|
||||||
|
inject_globals[u'__env__'] = six.text_type(low[u'__env__'])
|
||||||
|
|
||||||
|
if u'__env__' not in inject_globals:
|
||||||
# Let's use the default environment
|
# Let's use the default environment
|
||||||
inject_globals[u'__env__'] = u'base'
|
inject_globals[u'__env__'] = u'base'
|
||||||
|
|
||||||
@ -2952,32 +2959,32 @@ class BaseHighState(object):
|
|||||||
found = 0 # did we find any contents in the top files?
|
found = 0 # did we find any contents in the top files?
|
||||||
# Gather initial top files
|
# Gather initial top files
|
||||||
merging_strategy = self.opts[u'top_file_merging_strategy']
|
merging_strategy = self.opts[u'top_file_merging_strategy']
|
||||||
if merging_strategy == u'same' and not self.opts[u'environment']:
|
if merging_strategy == u'same' and not self.opts[u'saltenv']:
|
||||||
if not self.opts[u'default_top']:
|
if not self.opts[u'default_top']:
|
||||||
raise SaltRenderError(
|
raise SaltRenderError(
|
||||||
u'top_file_merging_strategy set to \'same\', but no '
|
u'top_file_merging_strategy set to \'same\', but no '
|
||||||
u'default_top configuration option was set'
|
u'default_top configuration option was set'
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.opts[u'environment']:
|
if self.opts[u'saltenv']:
|
||||||
contents = self.client.cache_file(
|
contents = self.client.cache_file(
|
||||||
self.opts[u'state_top'],
|
self.opts[u'state_top'],
|
||||||
self.opts[u'environment']
|
self.opts[u'saltenv']
|
||||||
)
|
)
|
||||||
if contents:
|
if contents:
|
||||||
found = 1
|
found = 1
|
||||||
tops[self.opts[u'environment']] = [
|
tops[self.opts[u'saltenv']] = [
|
||||||
compile_template(
|
compile_template(
|
||||||
contents,
|
contents,
|
||||||
self.state.rend,
|
self.state.rend,
|
||||||
self.state.opts[u'renderer'],
|
self.state.opts[u'renderer'],
|
||||||
self.state.opts[u'renderer_blacklist'],
|
self.state.opts[u'renderer_blacklist'],
|
||||||
self.state.opts[u'renderer_whitelist'],
|
self.state.opts[u'renderer_whitelist'],
|
||||||
saltenv=self.opts[u'environment']
|
saltenv=self.opts[u'saltenv']
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
tops[self.opts[u'environment']] = [{}]
|
tops[self.opts[u'saltenv']] = [{}]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
found = 0
|
found = 0
|
||||||
@ -3309,8 +3316,8 @@ class BaseHighState(object):
|
|||||||
matches = DefaultOrderedDict(OrderedDict)
|
matches = DefaultOrderedDict(OrderedDict)
|
||||||
# pylint: disable=cell-var-from-loop
|
# pylint: disable=cell-var-from-loop
|
||||||
for saltenv, body in six.iteritems(top):
|
for saltenv, body in six.iteritems(top):
|
||||||
if self.opts[u'environment']:
|
if self.opts[u'saltenv']:
|
||||||
if saltenv != self.opts[u'environment']:
|
if saltenv != self.opts[u'saltenv']:
|
||||||
continue
|
continue
|
||||||
for match, data in six.iteritems(body):
|
for match, data in six.iteritems(body):
|
||||||
def _filter_matches(_match, _data, _opts):
|
def _filter_matches(_match, _data, _opts):
|
||||||
|
@ -508,8 +508,10 @@ def _find_install_targets(name=None,
|
|||||||
# add it to the kwargs.
|
# add it to the kwargs.
|
||||||
kwargs['refresh'] = refresh
|
kwargs['refresh'] = refresh
|
||||||
|
|
||||||
|
resolve_capabilities = kwargs.get('resolve_capabilities', False) and 'pkg.list_provides' in __salt__
|
||||||
try:
|
try:
|
||||||
cur_pkgs = __salt__['pkg.list_pkgs'](versions_as_list=True, **kwargs)
|
cur_pkgs = __salt__['pkg.list_pkgs'](versions_as_list=True, **kwargs)
|
||||||
|
cur_prov = resolve_capabilities and __salt__['pkg.list_provides'](**kwargs) or dict()
|
||||||
except CommandExecutionError as exc:
|
except CommandExecutionError as exc:
|
||||||
return {'name': name,
|
return {'name': name,
|
||||||
'changes': {},
|
'changes': {},
|
||||||
@ -669,6 +671,9 @@ def _find_install_targets(name=None,
|
|||||||
failed_verify = False
|
failed_verify = False
|
||||||
for key, val in six.iteritems(desired):
|
for key, val in six.iteritems(desired):
|
||||||
cver = cur_pkgs.get(key, [])
|
cver = cur_pkgs.get(key, [])
|
||||||
|
if resolve_capabilities and not cver and key in cur_prov:
|
||||||
|
cver = cur_pkgs.get(cur_prov.get(key)[0], [])
|
||||||
|
|
||||||
# Package not yet installed, so add to targets
|
# Package not yet installed, so add to targets
|
||||||
if not cver:
|
if not cver:
|
||||||
targets[key] = val
|
targets[key] = val
|
||||||
@ -786,13 +791,15 @@ def _find_install_targets(name=None,
|
|||||||
warnings, was_refreshed)
|
warnings, was_refreshed)
|
||||||
|
|
||||||
|
|
||||||
def _verify_install(desired, new_pkgs, ignore_epoch=False):
|
def _verify_install(desired, new_pkgs, ignore_epoch=False, new_caps=None):
|
||||||
'''
|
'''
|
||||||
Determine whether or not the installed packages match what was requested in
|
Determine whether or not the installed packages match what was requested in
|
||||||
the SLS file.
|
the SLS file.
|
||||||
'''
|
'''
|
||||||
ok = []
|
ok = []
|
||||||
failed = []
|
failed = []
|
||||||
|
if not new_caps:
|
||||||
|
new_caps = dict()
|
||||||
for pkgname, pkgver in desired.items():
|
for pkgname, pkgver in desired.items():
|
||||||
# FreeBSD pkg supports `openjdk` and `java/openjdk7` package names.
|
# FreeBSD pkg supports `openjdk` and `java/openjdk7` package names.
|
||||||
# Homebrew for Mac OSX does something similar with tap names
|
# Homebrew for Mac OSX does something similar with tap names
|
||||||
@ -809,6 +816,8 @@ def _verify_install(desired, new_pkgs, ignore_epoch=False):
|
|||||||
cver = new_pkgs.get(pkgname.split('=')[0])
|
cver = new_pkgs.get(pkgname.split('=')[0])
|
||||||
else:
|
else:
|
||||||
cver = new_pkgs.get(pkgname)
|
cver = new_pkgs.get(pkgname)
|
||||||
|
if not cver and pkgname in new_caps:
|
||||||
|
cver = new_pkgs.get(new_caps.get(pkgname)[0])
|
||||||
|
|
||||||
if not cver:
|
if not cver:
|
||||||
failed.append(pkgname)
|
failed.append(pkgname)
|
||||||
@ -873,6 +882,26 @@ def _nested_output(obj):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def _resolve_capabilities(pkgs, refresh=False, **kwargs):
|
||||||
|
'''
|
||||||
|
Resolve capabilities in ``pkgs`` and exchange them with real package
|
||||||
|
names, when the result is distinct.
|
||||||
|
This feature can be turned on while setting the paramter
|
||||||
|
``resolve_capabilities`` to True.
|
||||||
|
|
||||||
|
Return the input dictionary with replaced capability names and as
|
||||||
|
second return value a bool which say if a refresh need to be run.
|
||||||
|
|
||||||
|
In case of ``resolve_capabilities`` is False (disabled) or not
|
||||||
|
supported by the implementation the input is returned unchanged.
|
||||||
|
'''
|
||||||
|
if not pkgs or 'pkg.resolve_capabilities' not in __salt__:
|
||||||
|
return pkgs, refresh
|
||||||
|
|
||||||
|
ret = __salt__['pkg.resolve_capabilities'](pkgs, refresh=refresh, **kwargs)
|
||||||
|
return ret, False
|
||||||
|
|
||||||
|
|
||||||
def installed(
|
def installed(
|
||||||
name,
|
name,
|
||||||
version=None,
|
version=None,
|
||||||
@ -1105,6 +1134,11 @@ def installed(
|
|||||||
|
|
||||||
.. versionadded:: 2014.1.1
|
.. versionadded:: 2014.1.1
|
||||||
|
|
||||||
|
:param bool resolve_capabilities:
|
||||||
|
Turn on resolving capabilities. This allow to name "provides" or alias names for packages.
|
||||||
|
|
||||||
|
.. versionadded:: Oxygen
|
||||||
|
|
||||||
:param bool allow_updates:
|
:param bool allow_updates:
|
||||||
Allow the package to be updated outside Salt's control (e.g. auto
|
Allow the package to be updated outside Salt's control (e.g. auto
|
||||||
updates on Windows). This means a package on the Minion can have a
|
updates on Windows). This means a package on the Minion can have a
|
||||||
@ -1448,6 +1482,12 @@ def installed(
|
|||||||
|
|
||||||
kwargs['saltenv'] = __env__
|
kwargs['saltenv'] = __env__
|
||||||
refresh = salt.utils.pkg.check_refresh(__opts__, refresh)
|
refresh = salt.utils.pkg.check_refresh(__opts__, refresh)
|
||||||
|
|
||||||
|
# check if capabilities should be checked and modify the requested packages
|
||||||
|
# accordingly.
|
||||||
|
if pkgs:
|
||||||
|
pkgs, refresh = _resolve_capabilities(pkgs, refresh=refresh, **kwargs)
|
||||||
|
|
||||||
if not isinstance(pkg_verify, list):
|
if not isinstance(pkg_verify, list):
|
||||||
pkg_verify = pkg_verify is True
|
pkg_verify = pkg_verify is True
|
||||||
if (pkg_verify or isinstance(pkg_verify, list)) \
|
if (pkg_verify or isinstance(pkg_verify, list)) \
|
||||||
@ -1707,8 +1747,13 @@ def installed(
|
|||||||
if __grains__['os'] == 'FreeBSD':
|
if __grains__['os'] == 'FreeBSD':
|
||||||
kwargs['with_origin'] = True
|
kwargs['with_origin'] = True
|
||||||
new_pkgs = __salt__['pkg.list_pkgs'](versions_as_list=True, **kwargs)
|
new_pkgs = __salt__['pkg.list_pkgs'](versions_as_list=True, **kwargs)
|
||||||
|
if kwargs.get('resolve_capabilities', False) and 'pkg.list_provides' in __salt__:
|
||||||
|
new_caps = __salt__['pkg.list_provides'](**kwargs)
|
||||||
|
else:
|
||||||
|
new_caps = {}
|
||||||
ok, failed = _verify_install(desired, new_pkgs,
|
ok, failed = _verify_install(desired, new_pkgs,
|
||||||
ignore_epoch=ignore_epoch)
|
ignore_epoch=ignore_epoch,
|
||||||
|
new_caps=new_caps)
|
||||||
modified = [x for x in ok if x in targets]
|
modified = [x for x in ok if x in targets]
|
||||||
not_modified = [x for x in ok
|
not_modified = [x for x in ok
|
||||||
if x not in targets
|
if x not in targets
|
||||||
@ -1927,6 +1972,11 @@ def downloaded(name,
|
|||||||
- dos2unix
|
- dos2unix
|
||||||
- salt-minion: 2015.8.5-1.el6
|
- salt-minion: 2015.8.5-1.el6
|
||||||
|
|
||||||
|
:param bool resolve_capabilities:
|
||||||
|
Turn on resolving capabilities. This allow to name "provides" or alias names for packages.
|
||||||
|
|
||||||
|
.. versionadded:: Oxygen
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
@ -1952,11 +2002,22 @@ def downloaded(name,
|
|||||||
ret['comment'] = 'No packages to download provided'
|
ret['comment'] = 'No packages to download provided'
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
# If just a name (and optionally a version) is passed, just pack them into
|
||||||
|
# the pkgs argument.
|
||||||
|
if name and not pkgs:
|
||||||
|
if version:
|
||||||
|
pkgs = [{name: version}]
|
||||||
|
version = None
|
||||||
|
else:
|
||||||
|
pkgs = [name]
|
||||||
|
|
||||||
# It doesn't make sense here to received 'downloadonly' as kwargs
|
# It doesn't make sense here to received 'downloadonly' as kwargs
|
||||||
# as we're explicitely passing 'downloadonly=True' to execution module.
|
# as we're explicitely passing 'downloadonly=True' to execution module.
|
||||||
if 'downloadonly' in kwargs:
|
if 'downloadonly' in kwargs:
|
||||||
del kwargs['downloadonly']
|
del kwargs['downloadonly']
|
||||||
|
|
||||||
|
pkgs, _refresh = _resolve_capabilities(pkgs, **kwargs)
|
||||||
|
|
||||||
# Only downloading not yet downloaded packages
|
# Only downloading not yet downloaded packages
|
||||||
targets = _find_download_targets(name,
|
targets = _find_download_targets(name,
|
||||||
version,
|
version,
|
||||||
@ -2203,6 +2264,10 @@ def latest(
|
|||||||
This parameter is available only on Debian based distributions and
|
This parameter is available only on Debian based distributions and
|
||||||
has no effect on the rest.
|
has no effect on the rest.
|
||||||
|
|
||||||
|
:param bool resolve_capabilities:
|
||||||
|
Turn on resolving capabilities. This allow to name "provides" or alias names for packages.
|
||||||
|
|
||||||
|
.. versionadded:: Oxygen
|
||||||
|
|
||||||
Multiple Package Installation Options:
|
Multiple Package Installation Options:
|
||||||
|
|
||||||
@ -2300,6 +2365,10 @@ def latest(
|
|||||||
|
|
||||||
kwargs['saltenv'] = __env__
|
kwargs['saltenv'] = __env__
|
||||||
|
|
||||||
|
# check if capabilities should be checked and modify the requested packages
|
||||||
|
# accordingly.
|
||||||
|
desired_pkgs, refresh = _resolve_capabilities(desired_pkgs, refresh=refresh, **kwargs)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
avail = __salt__['pkg.latest_version'](*desired_pkgs,
|
avail = __salt__['pkg.latest_version'](*desired_pkgs,
|
||||||
fromrepo=fromrepo,
|
fromrepo=fromrepo,
|
||||||
@ -2822,6 +2891,11 @@ def uptodate(name, refresh=False, pkgs=None, **kwargs):
|
|||||||
This parameter available only on Debian based distributions, and
|
This parameter available only on Debian based distributions, and
|
||||||
have no effect on the rest.
|
have no effect on the rest.
|
||||||
|
|
||||||
|
:param bool resolve_capabilities:
|
||||||
|
Turn on resolving capabilities. This allow to name "provides" or alias names for packages.
|
||||||
|
|
||||||
|
.. versionadded:: Oxygen
|
||||||
|
|
||||||
kwargs
|
kwargs
|
||||||
Any keyword arguments to pass through to ``pkg.upgrade``.
|
Any keyword arguments to pass through to ``pkg.upgrade``.
|
||||||
|
|
||||||
@ -2842,6 +2916,7 @@ def uptodate(name, refresh=False, pkgs=None, **kwargs):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
if isinstance(refresh, bool):
|
if isinstance(refresh, bool):
|
||||||
|
pkgs, refresh = _resolve_capabilities(pkgs, refresh=refresh, **kwargs)
|
||||||
try:
|
try:
|
||||||
packages = __salt__['pkg.list_upgrades'](refresh=refresh, **kwargs)
|
packages = __salt__['pkg.list_upgrades'](refresh=refresh, **kwargs)
|
||||||
if isinstance(pkgs, list):
|
if isinstance(pkgs, list):
|
||||||
|
@ -351,7 +351,6 @@ def state(name,
|
|||||||
|
|
||||||
changes = {}
|
changes = {}
|
||||||
fail = set()
|
fail = set()
|
||||||
failures = {}
|
|
||||||
no_change = set()
|
no_change = set()
|
||||||
|
|
||||||
if fail_minions is None:
|
if fail_minions is None:
|
||||||
@ -393,7 +392,7 @@ def state(name,
|
|||||||
if not m_state:
|
if not m_state:
|
||||||
if minion not in fail_minions:
|
if minion not in fail_minions:
|
||||||
fail.add(minion)
|
fail.add(minion)
|
||||||
failures[minion] = m_ret or 'Minion did not respond'
|
changes[minion] = m_ret
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
for state_item in six.itervalues(m_ret):
|
for state_item in six.itervalues(m_ret):
|
||||||
@ -418,18 +417,6 @@ def state(name,
|
|||||||
state_ret['comment'] += ' Updating {0}.'.format(', '.join(changes))
|
state_ret['comment'] += ' Updating {0}.'.format(', '.join(changes))
|
||||||
if no_change:
|
if no_change:
|
||||||
state_ret['comment'] += ' No changes made to {0}.'.format(', '.join(no_change))
|
state_ret['comment'] += ' No changes made to {0}.'.format(', '.join(no_change))
|
||||||
if failures:
|
|
||||||
state_ret['comment'] += '\nFailures:\n'
|
|
||||||
for minion, failure in six.iteritems(failures):
|
|
||||||
state_ret['comment'] += '\n'.join(
|
|
||||||
(' ' * 4 + l)
|
|
||||||
for l in salt.output.out_format(
|
|
||||||
{minion: failure},
|
|
||||||
'highstate',
|
|
||||||
__opts__,
|
|
||||||
).splitlines()
|
|
||||||
)
|
|
||||||
state_ret['comment'] += '\n'
|
|
||||||
if test or __opts__.get('test'):
|
if test or __opts__.get('test'):
|
||||||
if state_ret['changes'] and state_ret['result'] is True:
|
if state_ret['changes'] and state_ret['result'] is True:
|
||||||
# Test mode with changes is the only case where result should ever be none
|
# Test mode with changes is the only case where result should ever be none
|
||||||
@ -570,7 +557,6 @@ def function(
|
|||||||
|
|
||||||
changes = {}
|
changes = {}
|
||||||
fail = set()
|
fail = set()
|
||||||
failures = {}
|
|
||||||
|
|
||||||
if fail_minions is None:
|
if fail_minions is None:
|
||||||
fail_minions = ()
|
fail_minions = ()
|
||||||
@ -598,7 +584,7 @@ def function(
|
|||||||
if not m_func:
|
if not m_func:
|
||||||
if minion not in fail_minions:
|
if minion not in fail_minions:
|
||||||
fail.add(minion)
|
fail.add(minion)
|
||||||
failures[minion] = m_ret and m_ret or 'Minion did not respond'
|
changes[minion] = m_ret
|
||||||
continue
|
continue
|
||||||
changes[minion] = m_ret
|
changes[minion] = m_ret
|
||||||
if not cmd_ret:
|
if not cmd_ret:
|
||||||
@ -614,18 +600,6 @@ def function(
|
|||||||
func_ret['comment'] = 'Function ran successfully.'
|
func_ret['comment'] = 'Function ran successfully.'
|
||||||
if changes:
|
if changes:
|
||||||
func_ret['comment'] += ' Function {0} ran on {1}.'.format(name, ', '.join(changes))
|
func_ret['comment'] += ' Function {0} ran on {1}.'.format(name, ', '.join(changes))
|
||||||
if failures:
|
|
||||||
func_ret['comment'] += '\nFailures:\n'
|
|
||||||
for minion, failure in six.iteritems(failures):
|
|
||||||
func_ret['comment'] += '\n'.join(
|
|
||||||
(' ' * 4 + l)
|
|
||||||
for l in salt.output.out_format(
|
|
||||||
{minion: failure},
|
|
||||||
'highstate',
|
|
||||||
__opts__,
|
|
||||||
).splitlines()
|
|
||||||
)
|
|
||||||
func_ret['comment'] += '\n'
|
|
||||||
return func_ret
|
return func_ret
|
||||||
|
|
||||||
|
|
||||||
|
@ -910,7 +910,7 @@ class GitProvider(object):
|
|||||||
'''
|
'''
|
||||||
if self.branch == '__env__':
|
if self.branch == '__env__':
|
||||||
target = self.opts.get('pillarenv') \
|
target = self.opts.get('pillarenv') \
|
||||||
or self.opts.get('environment') \
|
or self.opts.get('saltenv') \
|
||||||
or 'base'
|
or 'base'
|
||||||
return self.opts['{0}_base'.format(self.role)] \
|
return self.opts['{0}_base'.format(self.role)] \
|
||||||
if target == 'base' \
|
if target == 'base' \
|
||||||
|
@ -125,3 +125,26 @@ def modules_available(*names):
|
|||||||
if not fnmatch.filter(list(__salt__), name):
|
if not fnmatch.filter(list(__salt__), name):
|
||||||
not_found.append(name)
|
not_found.append(name)
|
||||||
return not_found
|
return not_found
|
||||||
|
|
||||||
|
|
||||||
|
def nonzero_retcode_return_true():
|
||||||
|
'''
|
||||||
|
Sets a nonzero retcode before returning. Designed to test orchestration.
|
||||||
|
'''
|
||||||
|
__context__['retcode'] = 1
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def nonzero_retcode_return_false():
|
||||||
|
'''
|
||||||
|
Sets a nonzero retcode before returning. Designed to test orchestration.
|
||||||
|
'''
|
||||||
|
__context__['retcode'] = 1
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def fail_function(*args, **kwargs): # pylint: disable=unused-argument
|
||||||
|
'''
|
||||||
|
Return False no matter what is passed to it
|
||||||
|
'''
|
||||||
|
return False
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
test fail with changes:
|
||||||
|
test.fail_with_changes
|
11
tests/integration/files/file/base/orch/issue43204/init.sls
Normal file
11
tests/integration/files/file/base/orch/issue43204/init.sls
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
Step01:
|
||||||
|
salt.state:
|
||||||
|
- tgt: 'minion'
|
||||||
|
- sls:
|
||||||
|
- orch.issue43204.fail_with_changes
|
||||||
|
|
||||||
|
Step02:
|
||||||
|
salt.function:
|
||||||
|
- name: runtests_helpers.nonzero_retcode_return_false
|
||||||
|
- tgt: 'minion'
|
||||||
|
- fail_function: runtests_helpers.fail_function
|
@ -6,6 +6,7 @@ Tests for the state runner
|
|||||||
# Import Python Libs
|
# Import Python Libs
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
import errno
|
import errno
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import signal
|
import signal
|
||||||
@ -81,6 +82,58 @@ class StateRunnerTest(ShellCase):
|
|||||||
self.assertFalse(os.path.exists('/tmp/ewu-2016-12-13'))
|
self.assertFalse(os.path.exists('/tmp/ewu-2016-12-13'))
|
||||||
self.assertNotEqual(code, 0)
|
self.assertNotEqual(code, 0)
|
||||||
|
|
||||||
|
def test_orchestrate_state_and_function_failure(self):
|
||||||
|
'''
|
||||||
|
Ensure that returns from failed minions are in the changes dict where
|
||||||
|
they belong, so they can be programatically analyzed.
|
||||||
|
|
||||||
|
See https://github.com/saltstack/salt/issues/43204
|
||||||
|
'''
|
||||||
|
self.run_run('saltutil.sync_modules')
|
||||||
|
ret = json.loads(
|
||||||
|
'\n'.join(
|
||||||
|
self.run_run(u'state.orchestrate orch.issue43204 --out=json')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# Drill down to the changes dict
|
||||||
|
state_ret = ret[u'data'][u'master'][u'salt_|-Step01_|-Step01_|-state'][u'changes']
|
||||||
|
func_ret = ret[u'data'][u'master'][u'salt_|-Step02_|-runtests_helpers.nonzero_retcode_return_false_|-function'][u'changes']
|
||||||
|
|
||||||
|
# Remove duration and start time from the results, since they would
|
||||||
|
# vary with each run and that would make it impossible to test.
|
||||||
|
for item in ('duration', 'start_time'):
|
||||||
|
state_ret['ret']['minion']['test_|-test fail with changes_|-test fail with changes_|-fail_with_changes'].pop(item)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
state_ret,
|
||||||
|
{
|
||||||
|
u'out': u'highstate',
|
||||||
|
u'ret': {
|
||||||
|
u'minion': {
|
||||||
|
u'test_|-test fail with changes_|-test fail with changes_|-fail_with_changes': {
|
||||||
|
u'__id__': u'test fail with changes',
|
||||||
|
u'__run_num__': 0,
|
||||||
|
u'__sls__': u'orch.issue43204.fail_with_changes',
|
||||||
|
u'changes': {
|
||||||
|
u'testing': {
|
||||||
|
u'new': u'Something pretended to change',
|
||||||
|
u'old': u'Unchanged'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
u'comment': u'Failure!',
|
||||||
|
u'name': u'test fail with changes',
|
||||||
|
u'result': False,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
func_ret,
|
||||||
|
{u'out': u'highstate', u'ret': {u'minion': False}}
|
||||||
|
)
|
||||||
|
|
||||||
def test_orchestrate_target_exists(self):
|
def test_orchestrate_target_exists(self):
|
||||||
'''
|
'''
|
||||||
test orchestration when target exists
|
test orchestration when target exists
|
||||||
|
@ -37,11 +37,15 @@ _PKG_TARGETS = {
|
|||||||
'Debian': ['python-plist', 'apg'],
|
'Debian': ['python-plist', 'apg'],
|
||||||
'RedHat': ['units', 'zsh-html'],
|
'RedHat': ['units', 'zsh-html'],
|
||||||
'FreeBSD': ['aalib', 'pth'],
|
'FreeBSD': ['aalib', 'pth'],
|
||||||
'Suse': ['aalib', 'python-pssh'],
|
'Suse': ['aalib', 'rpm-python'],
|
||||||
'MacOS': ['libpng', 'jpeg'],
|
'MacOS': ['libpng', 'jpeg'],
|
||||||
'Windows': ['firefox', '7zip'],
|
'Windows': ['firefox', '7zip'],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_PKG_CAP_TARGETS = {
|
||||||
|
'Suse': [('w3m_ssl', 'w3m')],
|
||||||
|
}
|
||||||
|
|
||||||
_PKG_TARGETS_32 = {
|
_PKG_TARGETS_32 = {
|
||||||
'CentOS': 'xz-devel.i686'
|
'CentOS': 'xz-devel.i686'
|
||||||
}
|
}
|
||||||
@ -793,3 +797,260 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin):
|
|||||||
self.assertEqual(ret_comment, 'An error was encountered while installing/updating group '
|
self.assertEqual(ret_comment, 'An error was encountered while installing/updating group '
|
||||||
'\'handle_missing_pkg_group\': Group \'handle_missing_pkg_group\' '
|
'\'handle_missing_pkg_group\': Group \'handle_missing_pkg_group\' '
|
||||||
'not found.')
|
'not found.')
|
||||||
|
|
||||||
|
@skipIf(salt.utils.platform.is_windows(), 'minion is windows')
|
||||||
|
@requires_system_grains
|
||||||
|
def test_pkg_cap_001_installed(self, grains=None):
|
||||||
|
'''
|
||||||
|
This is a destructive test as it installs and then removes a package
|
||||||
|
'''
|
||||||
|
# Skip test if package manager not available
|
||||||
|
if not pkgmgr_avail(self.run_function, self.run_function('grains.items')):
|
||||||
|
self.skipTest('Package manager is not available')
|
||||||
|
|
||||||
|
os_family = grains.get('os_family', '')
|
||||||
|
pkg_cap_targets = _PKG_CAP_TARGETS.get(os_family, [])
|
||||||
|
if not len(pkg_cap_targets) > 0:
|
||||||
|
self.skipTest('Capability not provided')
|
||||||
|
|
||||||
|
target, realpkg = pkg_cap_targets[0]
|
||||||
|
version = self.run_function('pkg.version', [target])
|
||||||
|
realver = self.run_function('pkg.version', [realpkg])
|
||||||
|
|
||||||
|
# If this assert fails, we need to find new targets, this test needs to
|
||||||
|
# be able to test successful installation of packages, so this package
|
||||||
|
# needs to not be installed before we run the states below
|
||||||
|
self.assertFalse(version)
|
||||||
|
self.assertFalse(realver)
|
||||||
|
|
||||||
|
ret = self.run_state('pkg.installed', name=target, refresh=False, resolve_capabilities=True, test=True)
|
||||||
|
self.assertInSaltComment("The following packages would be installed/updated: {0}".format(realpkg), ret)
|
||||||
|
ret = self.run_state('pkg.installed', name=target, refresh=False, resolve_capabilities=True)
|
||||||
|
self.assertSaltTrueReturn(ret)
|
||||||
|
ret = self.run_state('pkg.removed', name=realpkg)
|
||||||
|
self.assertSaltTrueReturn(ret)
|
||||||
|
|
||||||
|
@skipIf(salt.utils.platform.is_windows(), 'minion is windows')
|
||||||
|
@requires_system_grains
|
||||||
|
def test_pkg_cap_002_already_installed(self, grains=None):
|
||||||
|
'''
|
||||||
|
This is a destructive test as it installs and then removes a package
|
||||||
|
'''
|
||||||
|
# Skip test if package manager not available
|
||||||
|
if not pkgmgr_avail(self.run_function, self.run_function('grains.items')):
|
||||||
|
self.skipTest('Package manager is not available')
|
||||||
|
|
||||||
|
os_family = grains.get('os_family', '')
|
||||||
|
pkg_cap_targets = _PKG_CAP_TARGETS.get(os_family, [])
|
||||||
|
if not len(pkg_cap_targets) > 0:
|
||||||
|
self.skipTest('Capability not provided')
|
||||||
|
|
||||||
|
target, realpkg = pkg_cap_targets[0]
|
||||||
|
version = self.run_function('pkg.version', [target])
|
||||||
|
realver = self.run_function('pkg.version', [realpkg])
|
||||||
|
|
||||||
|
# If this assert fails, we need to find new targets, this test needs to
|
||||||
|
# be able to test successful installation of packages, so this package
|
||||||
|
# needs to not be installed before we run the states below
|
||||||
|
self.assertFalse(version)
|
||||||
|
self.assertFalse(realver)
|
||||||
|
|
||||||
|
# install the package already
|
||||||
|
ret = self.run_state('pkg.installed', name=realpkg, refresh=False)
|
||||||
|
|
||||||
|
ret = self.run_state('pkg.installed', name=target, refresh=False, resolve_capabilities=True, test=True)
|
||||||
|
self.assertInSaltComment("All specified packages are already installed", ret)
|
||||||
|
|
||||||
|
ret = self.run_state('pkg.installed', name=target, refresh=False, resolve_capabilities=True)
|
||||||
|
self.assertSaltTrueReturn(ret)
|
||||||
|
|
||||||
|
self.assertInSaltComment("packages are already installed", ret)
|
||||||
|
ret = self.run_state('pkg.removed', name=realpkg)
|
||||||
|
self.assertSaltTrueReturn(ret)
|
||||||
|
|
||||||
|
@skipIf(salt.utils.platform.is_windows(), 'minion is windows')
|
||||||
|
@requires_system_grains
|
||||||
|
def test_pkg_cap_003_installed_multipkg_with_version(self, grains=None):
|
||||||
|
'''
|
||||||
|
This is a destructive test as it installs and then removes two packages
|
||||||
|
'''
|
||||||
|
# Skip test if package manager not available
|
||||||
|
if not pkgmgr_avail(self.run_function, self.run_function('grains.items')):
|
||||||
|
self.skipTest('Package manager is not available')
|
||||||
|
|
||||||
|
os_family = grains.get('os_family', '')
|
||||||
|
pkg_cap_targets = _PKG_CAP_TARGETS.get(os_family, [])
|
||||||
|
if not len(pkg_cap_targets) > 0:
|
||||||
|
self.skipTest('Capability not provided')
|
||||||
|
pkg_targets = _PKG_TARGETS.get(os_family, [])
|
||||||
|
|
||||||
|
# Don't perform this test on FreeBSD since version specification is not
|
||||||
|
# supported.
|
||||||
|
if os_family == 'FreeBSD':
|
||||||
|
return
|
||||||
|
|
||||||
|
# Make sure that we have targets that match the os_family. If this
|
||||||
|
# fails then the _PKG_TARGETS dict above needs to have an entry added,
|
||||||
|
# with two packages that are not installed before these tests are run
|
||||||
|
self.assertTrue(bool(pkg_cap_targets))
|
||||||
|
self.assertTrue(bool(pkg_targets))
|
||||||
|
|
||||||
|
if os_family == 'Arch':
|
||||||
|
for idx in range(13):
|
||||||
|
if idx == 12:
|
||||||
|
raise Exception('Package database locked after 60 seconds, '
|
||||||
|
'bailing out')
|
||||||
|
if not os.path.isfile('/var/lib/pacman/db.lck'):
|
||||||
|
break
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
capability, realpkg = pkg_cap_targets[0]
|
||||||
|
version = latest_version(self.run_function, pkg_targets[0])
|
||||||
|
realver = latest_version(self.run_function, realpkg)
|
||||||
|
|
||||||
|
# If this assert fails, we need to find new targets, this test needs to
|
||||||
|
# be able to test successful installation of packages, so these
|
||||||
|
# packages need to not be installed before we run the states below
|
||||||
|
self.assertTrue(bool(version))
|
||||||
|
self.assertTrue(bool(realver))
|
||||||
|
|
||||||
|
pkgs = [{pkg_targets[0]: version}, pkg_targets[1], {capability: realver}]
|
||||||
|
ret = self.run_state('pkg.installed',
|
||||||
|
name='test_pkg_cap_003_installed_multipkg_with_version-install',
|
||||||
|
pkgs=pkgs,
|
||||||
|
refresh=False)
|
||||||
|
self.assertSaltFalseReturn(ret)
|
||||||
|
|
||||||
|
ret = self.run_state('pkg.installed',
|
||||||
|
name='test_pkg_cap_003_installed_multipkg_with_version-install-capability',
|
||||||
|
pkgs=pkgs,
|
||||||
|
refresh=False, resolve_capabilities=True, test=True)
|
||||||
|
self.assertInSaltComment("packages would be installed/updated", ret)
|
||||||
|
self.assertInSaltComment("{0}={1}".format(realpkg, realver), ret)
|
||||||
|
|
||||||
|
ret = self.run_state('pkg.installed',
|
||||||
|
name='test_pkg_cap_003_installed_multipkg_with_version-install-capability',
|
||||||
|
pkgs=pkgs,
|
||||||
|
refresh=False, resolve_capabilities=True)
|
||||||
|
self.assertSaltTrueReturn(ret)
|
||||||
|
cleanup_pkgs = pkg_targets
|
||||||
|
cleanup_pkgs.append(realpkg)
|
||||||
|
ret = self.run_state('pkg.removed',
|
||||||
|
name='test_pkg_cap_003_installed_multipkg_with_version-remove',
|
||||||
|
pkgs=cleanup_pkgs)
|
||||||
|
self.assertSaltTrueReturn(ret)
|
||||||
|
|
||||||
|
@skipIf(salt.utils.platform.is_windows(), 'minion is windows')
|
||||||
|
@requires_system_grains
|
||||||
|
def test_pkg_cap_004_latest(self, grains=None):
|
||||||
|
'''
|
||||||
|
This tests pkg.latest with a package that has no epoch (or a zero
|
||||||
|
epoch).
|
||||||
|
'''
|
||||||
|
# Skip test if package manager not available
|
||||||
|
if not pkgmgr_avail(self.run_function, self.run_function('grains.items')):
|
||||||
|
self.skipTest('Package manager is not available')
|
||||||
|
|
||||||
|
os_family = grains.get('os_family', '')
|
||||||
|
pkg_cap_targets = _PKG_CAP_TARGETS.get(os_family, [])
|
||||||
|
if not len(pkg_cap_targets) > 0:
|
||||||
|
self.skipTest('Capability not provided')
|
||||||
|
|
||||||
|
target, realpkg = pkg_cap_targets[0]
|
||||||
|
version = self.run_function('pkg.version', [target])
|
||||||
|
realver = self.run_function('pkg.version', [realpkg])
|
||||||
|
|
||||||
|
# If this assert fails, we need to find new targets, this test needs to
|
||||||
|
# be able to test successful installation of packages, so this package
|
||||||
|
# needs to not be installed before we run the states below
|
||||||
|
self.assertFalse(version)
|
||||||
|
self.assertFalse(realver)
|
||||||
|
|
||||||
|
ret = self.run_state('pkg.latest', name=target, refresh=False, resolve_capabilities=True, test=True)
|
||||||
|
self.assertInSaltComment("The following packages would be installed/upgraded: {0}".format(realpkg), ret)
|
||||||
|
ret = self.run_state('pkg.latest', name=target, refresh=False, resolve_capabilities=True)
|
||||||
|
self.assertSaltTrueReturn(ret)
|
||||||
|
|
||||||
|
ret = self.run_state('pkg.latest', name=target, refresh=False, resolve_capabilities=True)
|
||||||
|
self.assertSaltTrueReturn(ret)
|
||||||
|
self.assertInSaltComment("is already up-to-date", ret)
|
||||||
|
|
||||||
|
ret = self.run_state('pkg.removed', name=realpkg)
|
||||||
|
self.assertSaltTrueReturn(ret)
|
||||||
|
|
||||||
|
@skipIf(salt.utils.platform.is_windows(), 'minion is windows')
|
||||||
|
@requires_system_grains
|
||||||
|
def test_pkg_cap_005_downloaded(self, grains=None):
|
||||||
|
'''
|
||||||
|
This is a destructive test as it installs and then removes a package
|
||||||
|
'''
|
||||||
|
# Skip test if package manager not available
|
||||||
|
if not pkgmgr_avail(self.run_function, self.run_function('grains.items')):
|
||||||
|
self.skipTest('Package manager is not available')
|
||||||
|
|
||||||
|
os_family = grains.get('os_family', '')
|
||||||
|
pkg_cap_targets = _PKG_CAP_TARGETS.get(os_family, [])
|
||||||
|
if not len(pkg_cap_targets) > 0:
|
||||||
|
self.skipTest('Capability not provided')
|
||||||
|
|
||||||
|
target, realpkg = pkg_cap_targets[0]
|
||||||
|
version = self.run_function('pkg.version', [target])
|
||||||
|
realver = self.run_function('pkg.version', [realpkg])
|
||||||
|
|
||||||
|
# If this assert fails, we need to find new targets, this test needs to
|
||||||
|
# be able to test successful installation of packages, so this package
|
||||||
|
# needs to not be installed before we run the states below
|
||||||
|
self.assertFalse(version)
|
||||||
|
self.assertFalse(realver)
|
||||||
|
|
||||||
|
ret = self.run_state('pkg.downloaded', name=target, refresh=False)
|
||||||
|
self.assertSaltFalseReturn(ret)
|
||||||
|
|
||||||
|
ret = self.run_state('pkg.downloaded', name=target, refresh=False, resolve_capabilities=True, test=True)
|
||||||
|
self.assertInSaltComment("The following packages would be downloaded: {0}".format(realpkg), ret)
|
||||||
|
|
||||||
|
ret = self.run_state('pkg.downloaded', name=target, refresh=False, resolve_capabilities=True)
|
||||||
|
self.assertSaltTrueReturn(ret)
|
||||||
|
|
||||||
|
@skipIf(salt.utils.platform.is_windows(), 'minion is windows')
|
||||||
|
@requires_system_grains
|
||||||
|
def test_pkg_cap_006_uptodate(self, grains=None):
|
||||||
|
'''
|
||||||
|
This is a destructive test as it installs and then removes a package
|
||||||
|
'''
|
||||||
|
# Skip test if package manager not available
|
||||||
|
if not pkgmgr_avail(self.run_function, self.run_function('grains.items')):
|
||||||
|
self.skipTest('Package manager is not available')
|
||||||
|
|
||||||
|
os_family = grains.get('os_family', '')
|
||||||
|
pkg_cap_targets = _PKG_CAP_TARGETS.get(os_family, [])
|
||||||
|
if not len(pkg_cap_targets) > 0:
|
||||||
|
self.skipTest('Capability not provided')
|
||||||
|
|
||||||
|
target, realpkg = pkg_cap_targets[0]
|
||||||
|
version = self.run_function('pkg.version', [target])
|
||||||
|
realver = self.run_function('pkg.version', [realpkg])
|
||||||
|
|
||||||
|
# If this assert fails, we need to find new targets, this test needs to
|
||||||
|
# be able to test successful installation of packages, so this package
|
||||||
|
# needs to not be installed before we run the states below
|
||||||
|
self.assertFalse(version)
|
||||||
|
self.assertFalse(realver)
|
||||||
|
|
||||||
|
ret = self.run_state('pkg.installed', name=target,
|
||||||
|
refresh=False, resolve_capabilities=True)
|
||||||
|
self.assertSaltTrueReturn(ret)
|
||||||
|
ret = self.run_state('pkg.uptodate',
|
||||||
|
name='test_pkg_cap_006_uptodate',
|
||||||
|
pkgs=[target],
|
||||||
|
refresh=False,
|
||||||
|
resolve_capabilities=True)
|
||||||
|
self.assertSaltTrueReturn(ret)
|
||||||
|
self.assertInSaltComment("System is already up-to-date", ret)
|
||||||
|
ret = self.run_state('pkg.removed', name=realpkg)
|
||||||
|
self.assertSaltTrueReturn(ret)
|
||||||
|
ret = self.run_state('pkg.uptodate',
|
||||||
|
name='test_pkg_cap_006_uptodate',
|
||||||
|
refresh=False,
|
||||||
|
test=True)
|
||||||
|
self.assertInSaltComment("System update will be performed", ret)
|
||||||
|
@ -90,7 +90,7 @@ def get_salt_vars():
|
|||||||
__opts__,
|
__opts__,
|
||||||
__grains__,
|
__grains__,
|
||||||
__opts__.get('id'),
|
__opts__.get('id'),
|
||||||
__opts__.get('environment'),
|
__opts__.get('saltenv'),
|
||||||
).compile_pillar()
|
).compile_pillar()
|
||||||
else:
|
else:
|
||||||
__pillar__ = {}
|
__pillar__ = {}
|
||||||
|
@ -278,6 +278,38 @@ class LazyLoaderWhitelistTest(TestCase):
|
|||||||
self.assertNotIn('grains.get', self.loader)
|
self.assertNotIn('grains.get', self.loader)
|
||||||
|
|
||||||
|
|
||||||
|
class LazyLoaderSingleItem(TestCase):
|
||||||
|
'''
|
||||||
|
Test loading a single item via the _load() function
|
||||||
|
'''
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.opts = salt.config.minion_config(None)
|
||||||
|
cls.opts['grains'] = grains(cls.opts)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.loader = LazyLoader(_module_dirs(copy.deepcopy(self.opts), 'modules', 'module'),
|
||||||
|
copy.deepcopy(self.opts),
|
||||||
|
tag='module')
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
del self.loader
|
||||||
|
|
||||||
|
def test_single_item_no_dot(self):
|
||||||
|
'''
|
||||||
|
Checks that a KeyError is raised when the function key does not contain a '.'
|
||||||
|
'''
|
||||||
|
with self.assertRaises(KeyError) as err:
|
||||||
|
inspect.isfunction(self.loader['testing_no_dot'])
|
||||||
|
|
||||||
|
if six.PY2:
|
||||||
|
self.assertEqual(err.exception[0],
|
||||||
|
'The key \'%s\' should contain a \'.\'')
|
||||||
|
else:
|
||||||
|
self.assertEqual(str(err.exception),
|
||||||
|
str(("The key '%s' should contain a '.'", 'testing_no_dot')))
|
||||||
|
|
||||||
|
|
||||||
module_template = '''
|
module_template = '''
|
||||||
__load__ = ['test', 'test_alias']
|
__load__ = ['test', 'test_alias']
|
||||||
__func_alias__ = dict(test_alias='working_alias')
|
__func_alias__ = dict(test_alias='working_alias')
|
||||||
|
@ -25,7 +25,7 @@ import salt.utils.hashutils
|
|||||||
import salt.utils.odict
|
import salt.utils.odict
|
||||||
import salt.utils.platform
|
import salt.utils.platform
|
||||||
import salt.modules.state as state
|
import salt.modules.state as state
|
||||||
from salt.exceptions import SaltInvocationError
|
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
||||||
from salt.ext import six
|
from salt.ext import six
|
||||||
|
|
||||||
|
|
||||||
@ -362,7 +362,7 @@ class StateTestCase(TestCase, LoaderModuleMockMixin):
|
|||||||
state: {
|
state: {
|
||||||
'__opts__': {
|
'__opts__': {
|
||||||
'cachedir': '/D',
|
'cachedir': '/D',
|
||||||
'environment': None,
|
'saltenv': None,
|
||||||
'__cli': 'salt',
|
'__cli': 'salt',
|
||||||
},
|
},
|
||||||
'__utils__': utils,
|
'__utils__': utils,
|
||||||
@ -632,7 +632,7 @@ class StateTestCase(TestCase, LoaderModuleMockMixin):
|
|||||||
with patch.dict(state.__opts__, {"test": "A"}):
|
with patch.dict(state.__opts__, {"test": "A"}):
|
||||||
mock = MagicMock(
|
mock = MagicMock(
|
||||||
return_value={'test': True,
|
return_value={'test': True,
|
||||||
'environment': None}
|
'saltenv': None}
|
||||||
)
|
)
|
||||||
with patch.object(state, '_get_opts', mock):
|
with patch.object(state, '_get_opts', mock):
|
||||||
mock = MagicMock(return_value=True)
|
mock = MagicMock(return_value=True)
|
||||||
@ -659,7 +659,7 @@ class StateTestCase(TestCase, LoaderModuleMockMixin):
|
|||||||
with patch.dict(state.__opts__, {"test": "A"}):
|
with patch.dict(state.__opts__, {"test": "A"}):
|
||||||
mock = MagicMock(
|
mock = MagicMock(
|
||||||
return_value={'test': True,
|
return_value={'test': True,
|
||||||
'environment': None}
|
'saltenv': None}
|
||||||
)
|
)
|
||||||
with patch.object(state, '_get_opts', mock):
|
with patch.object(state, '_get_opts', mock):
|
||||||
MockState.State.flag = True
|
MockState.State.flag = True
|
||||||
@ -681,7 +681,7 @@ class StateTestCase(TestCase, LoaderModuleMockMixin):
|
|||||||
with patch.dict(state.__opts__, {"test": "A"}):
|
with patch.dict(state.__opts__, {"test": "A"}):
|
||||||
mock = MagicMock(
|
mock = MagicMock(
|
||||||
return_value={'test': True,
|
return_value={'test': True,
|
||||||
'environment': None}
|
'saltenv': None}
|
||||||
)
|
)
|
||||||
with patch.object(state, '_get_opts', mock):
|
with patch.object(state, '_get_opts', mock):
|
||||||
mock = MagicMock(return_value=True)
|
mock = MagicMock(return_value=True)
|
||||||
@ -881,7 +881,7 @@ class StateTestCase(TestCase, LoaderModuleMockMixin):
|
|||||||
|
|
||||||
with patch.dict(state.__opts__, {"test": None}):
|
with patch.dict(state.__opts__, {"test": None}):
|
||||||
mock = MagicMock(return_value={"test": "",
|
mock = MagicMock(return_value={"test": "",
|
||||||
"environment": None})
|
"saltenv": None})
|
||||||
with patch.object(state, '_get_opts', mock):
|
with patch.object(state, '_get_opts', mock):
|
||||||
mock = MagicMock(return_value=True)
|
mock = MagicMock(return_value=True)
|
||||||
with patch.object(salt.utils,
|
with patch.object(salt.utils,
|
||||||
@ -993,3 +993,82 @@ class StateTestCase(TestCase, LoaderModuleMockMixin):
|
|||||||
else:
|
else:
|
||||||
with patch('salt.utils.files.fopen', mock_open()):
|
with patch('salt.utils.files.fopen', mock_open()):
|
||||||
self.assertTrue(state.pkg(tar_file, 0, "md5"))
|
self.assertTrue(state.pkg(tar_file, 0, "md5"))
|
||||||
|
|
||||||
|
def test_lock_saltenv(self):
|
||||||
|
'''
|
||||||
|
Tests lock_saltenv in each function which accepts saltenv on the CLI
|
||||||
|
'''
|
||||||
|
lock_msg = 'lock_saltenv is enabled, saltenv cannot be changed'
|
||||||
|
empty_list_mock = MagicMock(return_value=[])
|
||||||
|
with patch.dict(state.__opts__, {'lock_saltenv': True}), \
|
||||||
|
patch.dict(state.__salt__, {'grains.get': empty_list_mock}), \
|
||||||
|
patch.object(state, 'running', empty_list_mock):
|
||||||
|
|
||||||
|
# Test high
|
||||||
|
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
|
||||||
|
state.high(
|
||||||
|
[{"vim": {"pkg": ["installed"]}}], saltenv='base')
|
||||||
|
|
||||||
|
# Test template
|
||||||
|
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
|
||||||
|
state.template('foo', saltenv='base')
|
||||||
|
|
||||||
|
# Test template_str
|
||||||
|
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
|
||||||
|
state.template_str('foo', saltenv='base')
|
||||||
|
|
||||||
|
# Test apply_ with SLS
|
||||||
|
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
|
||||||
|
state.apply_('foo', saltenv='base')
|
||||||
|
|
||||||
|
# Test apply_ with Highstate
|
||||||
|
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
|
||||||
|
state.apply_(saltenv='base')
|
||||||
|
|
||||||
|
# Test highstate
|
||||||
|
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
|
||||||
|
state.highstate(saltenv='base')
|
||||||
|
|
||||||
|
# Test sls
|
||||||
|
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
|
||||||
|
state.sls('foo', saltenv='base')
|
||||||
|
|
||||||
|
# Test top
|
||||||
|
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
|
||||||
|
state.top('foo.sls', saltenv='base')
|
||||||
|
|
||||||
|
# Test show_highstate
|
||||||
|
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
|
||||||
|
state.show_highstate(saltenv='base')
|
||||||
|
|
||||||
|
# Test show_lowstate
|
||||||
|
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
|
||||||
|
state.show_lowstate(saltenv='base')
|
||||||
|
|
||||||
|
# Test sls_id
|
||||||
|
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
|
||||||
|
state.sls_id('foo', 'bar', saltenv='base')
|
||||||
|
|
||||||
|
# Test show_low_sls
|
||||||
|
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
|
||||||
|
state.show_low_sls('foo', saltenv='base')
|
||||||
|
|
||||||
|
# Test show_sls
|
||||||
|
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
|
||||||
|
state.show_sls('foo', saltenv='base')
|
||||||
|
|
||||||
|
# Test show_top
|
||||||
|
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
|
||||||
|
state.show_top(saltenv='base')
|
||||||
|
|
||||||
|
# Test single
|
||||||
|
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
|
||||||
|
state.single('foo.bar', name='baz', saltenv='base')
|
||||||
|
|
||||||
|
# Test pkg
|
||||||
|
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
|
||||||
|
state.pkg(
|
||||||
|
'/tmp/salt_state.tgz',
|
||||||
|
'760a9353810e36f6d81416366fc426dc',
|
||||||
|
'md5',
|
||||||
|
saltenv='base')
|
||||||
|
@ -669,8 +669,8 @@ Repository 'DUMMY' not found by its alias, number, or URI.
|
|||||||
zypper_mock.assert_called_once_with(
|
zypper_mock.assert_called_once_with(
|
||||||
'--no-refresh',
|
'--no-refresh',
|
||||||
'install',
|
'install',
|
||||||
'--name',
|
|
||||||
'--auto-agree-with-licenses',
|
'--auto-agree-with-licenses',
|
||||||
|
'--name',
|
||||||
'--download-only',
|
'--download-only',
|
||||||
'vim'
|
'vim'
|
||||||
)
|
)
|
||||||
@ -699,8 +699,8 @@ Repository 'DUMMY' not found by its alias, number, or URI.
|
|||||||
zypper_mock.assert_called_once_with(
|
zypper_mock.assert_called_once_with(
|
||||||
'--no-refresh',
|
'--no-refresh',
|
||||||
'install',
|
'install',
|
||||||
'--name',
|
|
||||||
'--auto-agree-with-licenses',
|
'--auto-agree-with-licenses',
|
||||||
|
'--name',
|
||||||
'--download-only',
|
'--download-only',
|
||||||
'vim'
|
'vim'
|
||||||
)
|
)
|
||||||
@ -724,8 +724,8 @@ Repository 'DUMMY' not found by its alias, number, or URI.
|
|||||||
zypper_mock.assert_called_once_with(
|
zypper_mock.assert_called_once_with(
|
||||||
'--no-refresh',
|
'--no-refresh',
|
||||||
'install',
|
'install',
|
||||||
'--name',
|
|
||||||
'--auto-agree-with-licenses',
|
'--auto-agree-with-licenses',
|
||||||
|
'--name',
|
||||||
'patch:SUSE-PATCH-1234'
|
'patch:SUSE-PATCH-1234'
|
||||||
)
|
)
|
||||||
self.assertDictEqual(ret, {"vim": {"old": "1.1", "new": "1.2"}})
|
self.assertDictEqual(ret, {"vim": {"old": "1.1", "new": "1.2"}})
|
||||||
|
@ -55,7 +55,7 @@ class PillarTestCase(TestCase):
|
|||||||
'os': 'Ubuntu',
|
'os': 'Ubuntu',
|
||||||
}
|
}
|
||||||
pillar = salt.pillar.Pillar(opts, grains, 'mocked-minion', 'dev')
|
pillar = salt.pillar.Pillar(opts, grains, 'mocked-minion', 'dev')
|
||||||
self.assertEqual(pillar.opts['environment'], 'dev')
|
self.assertEqual(pillar.opts['saltenv'], 'dev')
|
||||||
self.assertEqual(pillar.opts['pillarenv'], 'dev')
|
self.assertEqual(pillar.opts['pillarenv'], 'dev')
|
||||||
|
|
||||||
def test_ext_pillar_no_extra_minion_data_val_dict(self):
|
def test_ext_pillar_no_extra_minion_data_val_dict(self):
|
||||||
@ -416,7 +416,7 @@ class PillarTestCase(TestCase):
|
|||||||
'state_top': '',
|
'state_top': '',
|
||||||
'pillar_roots': [],
|
'pillar_roots': [],
|
||||||
'extension_modules': '',
|
'extension_modules': '',
|
||||||
'environment': 'base',
|
'saltenv': 'base',
|
||||||
'file_roots': [],
|
'file_roots': [],
|
||||||
}
|
}
|
||||||
grains = {
|
grains = {
|
||||||
@ -584,7 +584,7 @@ class RemotePillarTestCase(TestCase):
|
|||||||
|
|
||||||
salt.pillar.RemotePillar({}, self.grains, 'mocked-minion', 'dev')
|
salt.pillar.RemotePillar({}, self.grains, 'mocked-minion', 'dev')
|
||||||
mock_get_extra_minion_data.assert_called_once_with(
|
mock_get_extra_minion_data.assert_called_once_with(
|
||||||
{'environment': 'dev'})
|
{'saltenv': 'dev'})
|
||||||
|
|
||||||
def test_multiple_keys_in_opts_added_to_pillar(self):
|
def test_multiple_keys_in_opts_added_to_pillar(self):
|
||||||
opts = {
|
opts = {
|
||||||
@ -702,7 +702,7 @@ class AsyncRemotePillarTestCase(TestCase):
|
|||||||
|
|
||||||
salt.pillar.RemotePillar({}, self.grains, 'mocked-minion', 'dev')
|
salt.pillar.RemotePillar({}, self.grains, 'mocked-minion', 'dev')
|
||||||
mock_get_extra_minion_data.assert_called_once_with(
|
mock_get_extra_minion_data.assert_called_once_with(
|
||||||
{'environment': 'dev'})
|
{'saltenv': 'dev'})
|
||||||
|
|
||||||
def test_pillar_send_extra_minion_data_from_config(self):
|
def test_pillar_send_extra_minion_data_from_config(self):
|
||||||
opts = {
|
opts = {
|
||||||
|
Loading…
Reference in New Issue
Block a user