Skip to content

Commit

Permalink
Merge pull request #52969 from mchugh19/unless_doc
Browse files Browse the repository at this point in the history
support args in unless and onlyif
  • Loading branch information
Ch3LL authored May 14, 2019
2 parents 35a4647 + d4460a8 commit 21552ac
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 7 deletions.
31 changes: 27 additions & 4 deletions doc/ref/states/requisites.rst
Original file line number Diff line number Diff line change
Expand Up @@ -852,8 +852,8 @@ In the above case, ``some_check`` will be run prior to _each_ name -- once for
.. versionchanged:: Neon
The ``unless`` requisite can take a module as a dictionary field in unless.
The dictionary must contain an argument ``fun`` which is the module that is
being run, and everything else passed in will be kwargs passed to the module
function.
being run, and everything else must be passed in under the args key or will
be passed as individual kwargs to the module function.

.. code-block:: yaml
Expand All @@ -865,6 +865,18 @@ In the above case, ``some_check`` will be run prior to _each_ name -- once for
- fun: file.file_exists
path: /usr/local/bin/whatever
.. code-block:: yaml
set mysql root password:
debconf.set:
- name: mysql-server-5.7
- data:
'mysql-server/root_password': {'type': 'password', 'value': {{pillar['mysql.pass']}} }
- unless:
- fun: pkg.version
args:
- mysql-server-5.7
.. _onlyif-requisite:

onlyif
Expand Down Expand Up @@ -908,8 +920,8 @@ if the gluster commands return a 0 ret value.
.. versionchanged:: Neon
The ``onlyif`` requisite can take a module as a dictionary field in onlyif.
The dictionary must contain an argument ``fun`` which is the module that is
being run, and everything else passed in will be kwargs passed to the module
function.
being run, and everything else must be passed in under the args key or will
be passed as individual kwargs to the module function.

.. code-block:: yaml
Expand All @@ -927,6 +939,17 @@ if the gluster commands return a 0 ret value.
- fun: match.grain
tgt: 'os_family: Debian'
.. code-block:: yaml
arbitrary file example:
file.touch:
- name: /path/to/file
- onlyif:
- fun: file.search
args:
- /etc/crontab
- 'entry1'
runas
~~~~~

Expand Down
30 changes: 30 additions & 0 deletions doc/topics/releases/neon.rst
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,36 @@ New output:
Skipped:
0
Unless and onlyif Enhancements
==============================

The ``unless`` and ``onlyif`` requisites can now be operated with salt modules.
The dictionary must contain an argument ``fun`` which is the module that is
being run, and everything else must be passed in under the args key or will be
passed as individual kwargs to the module function.

.. code-block:: yaml
install apache on debian based distros:
cmd.run:
- name: make install
- cwd: /path/to/dir/whatever-2.1.5/
- unless:
- fun: file.file_exists
path: /usr/local/bin/whatever
.. code-block:: yaml
set mysql root password:
debconf.set:
- name: mysql-server-5.7
- data:
'mysql-server/root_password': {'type': 'password', 'value': {{pillar['mysql.pass']}} }
- unless:
- fun: pkg.version
args:
- mysql-server-5.7
Keystore State and Module
=========================
Expand Down
14 changes: 11 additions & 3 deletions salt/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -905,7 +905,11 @@ def _check_cmd(cmd):
ret['comment'] = 'no `fun` argument in onlyif: {0}'.format(entry)
log.warning(ret['comment'])
return ret
result = self.functions[entry.pop('fun')](**entry)

if 'args' in entry:
result = self.functions[entry.pop('fun')](*entry.pop('args'), **entry)
else:
result = self.functions[entry.pop('fun')](**entry)
if self.state_con.get('retcode', 0):
_check_cmd(self.state_con['retcode'])
elif not result:
Expand Down Expand Up @@ -946,10 +950,14 @@ def _check_cmd(cmd):
_check_cmd(cmd)
elif isinstance(entry, dict):
if 'fun' not in entry:
ret['comment'] = 'no `fun` argument in onlyif: {0}'.format(entry)
ret['comment'] = 'no `fun` argument in unless: {0}'.format(entry)
log.warning(ret['comment'])
return ret
result = self.functions[entry.pop('fun')](**entry)

if 'args' in entry:
result = self.functions[entry.pop('fun')](*entry.pop('args'), **entry)
else:
result = self.functions[entry.pop('fun')](**entry)
if self.state_con.get('retcode', 0):
_check_cmd(self.state_con['retcode'])
elif result:
Expand Down
66 changes: 66 additions & 0 deletions tests/unit/test_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,72 @@ def test_render_requisite_require_in_disabled(self):
run_num = ret['test_|-step_one_|-step_one_|-succeed_with_changes']['__run_num__']
self.assertEqual(run_num, 0)

def test_verify_onlyif_parse(self):
low_data = {
"onlyif": [
{
"fun": "file.search",
"args": [
"/etc/crontab",
"run-parts"
]
}
],
"name": "mysql-server-5.7",
"state": "debconf",
"__id__": "set root password",
"fun": "set",
"__env__": "base",
"__sls__": "debconf",
"data": {
"mysql-server/root_password": {
"type": "password",
"value": "temp123"
}
},
"order": 10000
}
expected_result = {'comment': 'onlyif condition is true', 'result': False}

with patch('salt.state.State._gather_pillar') as state_patch:
minion_opts = self.get_temp_config('minion')
state_obj = salt.state.State(minion_opts)
return_result = state_obj._run_check_onlyif(low_data, '')
self.assertEqual(expected_result, return_result)

def test_verify_unless_parse(self):
low_data = {
"unless": [
{
"fun": "file.search",
"args": [
"/etc/crontab",
"run-parts"
]
}
],
"name": "mysql-server-5.7",
"state": "debconf",
"__id__": "set root password",
"fun": "set",
"__env__": "base",
"__sls__": "debconf",
"data": {
"mysql-server/root_password": {
"type": "password",
"value": "temp123"
}
},
"order": 10000
}
expected_result = {'comment': 'unless condition is true', 'result': True, 'skip_watch': True}

with patch('salt.state.State._gather_pillar') as state_patch:
minion_opts = self.get_temp_config('minion')
state_obj = salt.state.State(minion_opts)
return_result = state_obj._run_check_unless(low_data, '')
self.assertEqual(expected_result, return_result)


class HighStateTestCase(TestCase, AdaptedConfigurationTestCaseMixin):
def setUp(self):
Expand Down

0 comments on commit 21552ac

Please sign in to comment.