Move state-related utils to salt.utils.state.py

Moves the following functions from `salt.utils` to `salt.utils.state`:
- gen_state_tag
- search_onfail_requisites
- check_onfail_requisites
- check_state_result

Original functions have a deprecation warning added and all references
in Salt code were updated to use the new function path, including moving
some unit tests.
This commit is contained in:
rallytime 2017-08-30 17:31:23 -04:00
parent 0e262b8c0d
commit 4a86f23bf1
12 changed files with 705 additions and 585 deletions

View File

@ -122,7 +122,7 @@ This example, simplified from the pkg state, shows how to create mod_aggregate f
for chunk in chunks:
# The state runtime uses "tags" to track completed jobs, it may
# look familiar with the _|-
tag = salt.utils.gen_state_tag(chunk)
tag = salt.utils.state.gen_state_tag(chunk)
if tag in running:
# Already ran the pkg state, skip aggregation
continue

View File

@ -16,7 +16,8 @@ import copy as pycopy
# Import Salt libs
import salt.exceptions
import salt.minion
import salt.utils
import salt.utils # Can be removed once daemonize, get_specific_user, format_call are moved
import salt.utils.args
import salt.utils.doc
import salt.utils.error
import salt.utils.event
@ -25,6 +26,7 @@ import salt.utils.job
import salt.utils.lazy
import salt.utils.platform
import salt.utils.process
import salt.utils.state
import salt.utils.versions
import salt.transport
import salt.log.setup
@ -396,7 +398,7 @@ class SyncClientMixin(object):
data[u'success'] = True
if isinstance(data[u'return'], dict) and u'data' in data[u'return']:
# some functions can return boolean values
data[u'success'] = salt.utils.check_state_result(data[u'return'][u'data'])
data[u'success'] = salt.utils.state.check_state_result(data[u'return'][u'data'])
except (Exception, SystemExit) as ex:
if isinstance(ex, salt.exceptions.NotImplemented):
data[u'return'] = str(ex)

View File

@ -207,6 +207,7 @@ import salt.utils.decorators
import salt.utils.docker
import salt.utils.files
import salt.utils.path
import salt.utils.state
import salt.utils.stringutils
import salt.utils.thin
import salt.pillar
@ -5420,7 +5421,7 @@ def sls(name, mods=None, saltenv='base', **kwargs):
)
if not isinstance(ret, dict):
__context__['retcode'] = 1
elif not salt.utils.check_state_result(ret):
elif not salt.utils.state.check_state_result(ret):
__context__['retcode'] = 2
else:
__context__['retcode'] = 0
@ -5494,7 +5495,7 @@ def sls_build(name, base='opensuse/python', mods=None, saltenv='base',
# Now execute the state into the container
ret = sls(id_, mods, saltenv, **kwargs)
# fail if the state was not successful
if not dryrun and not salt.utils.check_state_result(ret):
if not dryrun and not salt.utils.state.check_state_result(ret):
raise CommandExecutionError(ret)
if dryrun is False:
ret = commit(id_, name)

View File

@ -33,6 +33,7 @@ import salt.utils.event
import salt.utils.files
import salt.utils.jid
import salt.utils.platform
import salt.utils.state
import salt.utils.url
import salt.utils.versions
from salt.exceptions import CommandExecutionError, SaltInvocationError
@ -98,7 +99,7 @@ def _set_retcode(ret, highstate=None):
if isinstance(ret, list):
__context__['retcode'] = 1
return
if not salt.utils.check_state_result(ret, highstate=highstate):
if not salt.utils.state.check_state_result(ret, highstate=highstate):
__context__['retcode'] = 2
@ -316,7 +317,7 @@ def low(data, queue=False, **kwargs):
ret = st_.call(data)
if isinstance(ret, list):
__context__['retcode'] = 1
if salt.utils.check_state_result(ret):
if salt.utils.state.check_state_result(ret):
__context__['retcode'] = 2
return ret

View File

@ -10,6 +10,7 @@ import logging
import salt.loader
import salt.utils
import salt.utils.event
import salt.utils.state
from salt.exceptions import SaltInvocationError
LOGGER = logging.getLogger(__name__)
@ -81,7 +82,7 @@ def orchestrate(mods,
pillar_enc=pillar_enc,
orchestration_jid=orchestration_jid)
ret = {'data': {minion.opts['id']: running}, 'outputter': 'highstate'}
res = salt.utils.check_state_result(ret['data'])
res = salt.utils.state.check_state_result(ret['data'])
if res:
ret['retcode'] = 0
else:

View File

@ -194,7 +194,7 @@ at some point be deprecated in favor of a more generic ``firewall`` state.
from __future__ import absolute_import
# Import salt libs
import salt.utils
import salt.utils.state
from salt.state import STATE_INTERNAL_KEYWORDS as _STATE_INTERNAL_KEYWORDS
@ -810,7 +810,7 @@ def mod_aggregate(low, chunks, running):
if low.get('fun') not in agg_enabled:
return low
for chunk in chunks:
tag = salt.utils.gen_state_tag(chunk)
tag = salt.utils.state.gen_state_tag(chunk)
if tag in running:
# Already ran the iptables state, skip aggregation
continue

View File

@ -81,9 +81,9 @@ import os
import re
# Import Salt libs
import salt.utils # Can be removed once gen_state_tag is moved
import salt.utils.pkg
import salt.utils.platform
import salt.utils.state
import salt.utils.versions
from salt.output import nested
from salt.utils import namespaced_function as _namespaced_function
@ -3071,7 +3071,7 @@ def mod_aggregate(low, chunks, running):
if low.get('fun') not in agg_enabled:
return low
for chunk in chunks:
tag = salt.utils.gen_state_tag(chunk)
tag = salt.utils.state.gen_state_tag(chunk)
if tag in running:
# Already ran the pkg state, skip aggregation
continue

View File

@ -30,8 +30,8 @@ import time
# Import salt libs
import salt.syspaths
import salt.utils # Can be removed once check_state_result is moved
import salt.utils.event
import salt.utils.state
import salt.utils.versions
from salt.ext import six
@ -342,7 +342,7 @@ def state(name,
except KeyError:
m_state = False
if m_state:
m_state = salt.utils.check_state_result(m_ret, recurse=True)
m_state = salt.utils.state.check_state_result(m_ret, recurse=True)
if not m_state:
if minion not in fail_minions:

View File

@ -19,9 +19,7 @@ import fnmatch
import hashlib
import json
import logging
import numbers
import os
import posixpath
import random
import re
import shlex
@ -29,10 +27,8 @@ import shutil
import socket
import sys
import pstats
import tempfile
import time
import types
import warnings
import string
import subprocess
import getpass
@ -40,7 +36,6 @@ import getpass
# Import 3rd-party libs
from salt.ext import six
# pylint: disable=import-error
from salt.ext.six.moves.urllib.parse import urlparse # pylint: disable=no-name-in-module
# pylint: disable=redefined-builtin
from salt.ext.six.moves import range
from salt.ext.six.moves import zip
@ -134,7 +129,6 @@ from salt.exceptions import (
log = logging.getLogger(__name__)
_empty = object()
def get_context(template, line, num_lines=5, marker=None):
@ -1376,148 +1370,6 @@ def check_include_exclude(path_str, include_pat=None, exclude_pat=None):
return ret
def gen_state_tag(low):
'''
Generate the running dict tag string from the low data structure
'''
return '{0[state]}_|-{0[__id__]}_|-{0[name]}_|-{0[fun]}'.format(low)
def search_onfail_requisites(sid, highstate):
"""
For a particular low chunk, search relevant onfail related
states
"""
onfails = []
if '_|-' in sid:
st = salt.state.split_low_tag(sid)
else:
st = {'__id__': sid}
for fstate, fchunks in six.iteritems(highstate):
if fstate == st['__id__']:
continue
else:
for mod_, fchunk in six.iteritems(fchunks):
if (
not isinstance(mod_, six.string_types) or
mod_.startswith('__')
):
continue
else:
if not isinstance(fchunk, list):
continue
else:
# bydefault onfail will fail, but you can
# set onfail_stop: False to prevent the highstate
# to stop if you handle it
onfail_handled = False
for fdata in fchunk:
if not isinstance(fdata, dict):
continue
onfail_handled = (fdata.get('onfail_stop', True)
is False)
if onfail_handled:
break
if not onfail_handled:
continue
for fdata in fchunk:
if not isinstance(fdata, dict):
continue
for knob, fvalue in six.iteritems(fdata):
if knob != 'onfail':
continue
for freqs in fvalue:
for fmod, fid in six.iteritems(freqs):
if not (
fid == st['__id__'] and
fmod == st.get('state', fmod)
):
continue
onfails.append((fstate, mod_, fchunk))
return onfails
def check_onfail_requisites(state_id, state_result, running, highstate):
'''
When a state fail and is part of a highstate, check
if there is onfail requisites.
When we find onfail requisites, we will consider the state failed
only if at least one of those onfail requisites also failed
Returns:
True: if onfail handlers suceeded
False: if one on those handler failed
None: if the state does not have onfail requisites
'''
nret = None
if (
state_id and state_result and
highstate and isinstance(highstate, dict)
):
onfails = search_onfail_requisites(state_id, highstate)
if onfails:
for handler in onfails:
fstate, mod_, fchunk = handler
ofresult = True
for rstateid, rstate in six.iteritems(running):
if '_|-' in rstateid:
st = salt.state.split_low_tag(rstateid)
# in case of simple state, try to guess
else:
id_ = rstate.get('__id__', rstateid)
if not id_:
raise ValueError('no state id')
st = {'__id__': id_, 'state': mod_}
if mod_ == st['state'] and fstate == st['__id__']:
ofresult = rstate.get('result', _empty)
if ofresult in [False, True]:
nret = ofresult
if ofresult is False:
# as soon as we find an errored onfail, we stop
break
# consider that if we parsed onfailes without changing
# the ret, that we have failed
if nret is None:
nret = False
return nret
def check_state_result(running, recurse=False, highstate=None):
'''
Check the total return value of the run and determine if the running
dict has any issues
'''
if not isinstance(running, dict):
return False
if not running:
return False
ret = True
for state_id, state_result in six.iteritems(running):
if not recurse and not isinstance(state_result, dict):
ret = False
if ret and isinstance(state_result, dict):
result = state_result.get('result', _empty)
if result is False:
ret = False
# only override return value if we are not already failed
elif result is _empty and isinstance(state_result, dict) and ret:
ret = check_state_result(
state_result, recurse=True, highstate=highstate)
# if we detect a fail, check for onfail requisites
if not ret:
# ret can be None in case of no onfail reqs, recast it to bool
ret = bool(check_onfail_requisites(state_id, state_result,
running, highstate))
# return as soon as we got a failure
if not ret:
break
return ret
def st_mode_to_octal(mode):
'''
Convert the st_mode value from a stat(2) call (as returned from os.stat())
@ -3403,3 +3255,89 @@ def get_colors(use=True, theme=None):
'Oxygen. This warning will be removed in Salt Neon.'
)
return salt.utils.color.get_colors(use=use, theme=theme)
def gen_state_tag(low):
'''
Generate the running dict tag string from the low data structure
.. deprecated:: Oxygen
'''
# Late import to avoid circular import.
import salt.utils.versions
import salt.utils.state
salt.utils.versions.warn_until(
'Neon',
'Use of \'salt.utils.gen_state_tag\' detected. This function has been '
'moved to \'salt.utils.state.gen_state_tag\' as of Salt Oxygen. This '
'warning will be removed in Salt Neon.'
)
return salt.utils.state.gen_state_tag(low)
def search_onfail_requisites(sid, highstate):
'''
For a particular low chunk, search relevant onfail related states
.. deprecated:: Oxygen
'''
# Late import to avoid circular import.
import salt.utils.versions
import salt.utils.state
salt.utils.versions.warn_until(
'Neon',
'Use of \'salt.utils.search_onfail_requisites\' detected. This function'
'has been moved to \'salt.utils.state.search_onfail_requisites\' as of '
'Salt Oxygen. This warning will be removed in Salt Neon.'
)
return salt.utils.state.search_onfail_requisites(sid, highstate)
def check_onfail_requisites(state_id, state_result, running, highstate):
'''
When a state fail and is part of a highstate, check
if there is onfail requisites.
When we find onfail requisites, we will consider the state failed
only if at least one of those onfail requisites also failed
Returns:
True: if onfail handlers suceeded
False: if one on those handler failed
None: if the state does not have onfail requisites
.. deprecated:: Oxygen
'''
# Late import to avoid circular import.
import salt.utils.versions
import salt.utils.state
salt.utils.versions.warn_until(
'Neon',
'Use of \'salt.utils.check_onfail_requisites\' detected. This function'
'has been moved to \'salt.utils.state.check_onfail_requisites\' as of '
'Salt Oxygen. This warning will be removed in Salt Neon.'
)
return salt.utils.state.check_onfail_requisites(
state_id, state_result, running, highstate
)
def check_state_result(running, recurse=False, highstate=None):
'''
Check the total return value of the run and determine if the running
dict has any issues
.. deprecated:: Oxygen
'''
# Late import to avoid circular import.
import salt.utils.versions
import salt.utils.state
salt.utils.versions.warn_until(
'Neon',
'Use of \'salt.utils.check_state_result\' detected. This function'
'has been moved to \'salt.utils.state.check_state_result\' as of '
'Salt Oxygen. This warning will be removed in Salt Neon.'
)
return salt.utils.state.check_state_result(
running, recurse=recurse, highstate=highstate
)

155
salt/utils/state.py Normal file
View File

@ -0,0 +1,155 @@
# -*- coding: utf-8 -*-
'''
Utility functions for state functions
.. versionadded:: Oxygen
'''
# Import Python Libs
from __future__ import absolute_import
# Import Salt libs
from salt.ext import six
import salt.state
_empty = object()
def gen_state_tag(low):
'''
Generate the running dict tag string from the low data structure
'''
return '{0[state]}_|-{0[__id__]}_|-{0[name]}_|-{0[fun]}'.format(low)
def search_onfail_requisites(sid, highstate):
'''
For a particular low chunk, search relevant onfail related states
'''
onfails = []
if '_|-' in sid:
st = salt.state.split_low_tag(sid)
else:
st = {'__id__': sid}
for fstate, fchunks in six.iteritems(highstate):
if fstate == st['__id__']:
continue
else:
for mod_, fchunk in six.iteritems(fchunks):
if (
not isinstance(mod_, six.string_types) or
mod_.startswith('__')
):
continue
else:
if not isinstance(fchunk, list):
continue
else:
# bydefault onfail will fail, but you can
# set onfail_stop: False to prevent the highstate
# to stop if you handle it
onfail_handled = False
for fdata in fchunk:
if not isinstance(fdata, dict):
continue
onfail_handled = (fdata.get('onfail_stop', True)
is False)
if onfail_handled:
break
if not onfail_handled:
continue
for fdata in fchunk:
if not isinstance(fdata, dict):
continue
for knob, fvalue in six.iteritems(fdata):
if knob != 'onfail':
continue
for freqs in fvalue:
for fmod, fid in six.iteritems(freqs):
if not (
fid == st['__id__'] and
fmod == st.get('state', fmod)
):
continue
onfails.append((fstate, mod_, fchunk))
return onfails
def check_onfail_requisites(state_id, state_result, running, highstate):
'''
When a state fail and is part of a highstate, check
if there is onfail requisites.
When we find onfail requisites, we will consider the state failed
only if at least one of those onfail requisites also failed
Returns:
True: if onfail handlers suceeded
False: if one on those handler failed
None: if the state does not have onfail requisites
'''
nret = None
if (
state_id and state_result and
highstate and isinstance(highstate, dict)
):
onfails = search_onfail_requisites(state_id, highstate)
if onfails:
for handler in onfails:
fstate, mod_, fchunk = handler
for rstateid, rstate in six.iteritems(running):
if '_|-' in rstateid:
st = salt.state.split_low_tag(rstateid)
# in case of simple state, try to guess
else:
id_ = rstate.get('__id__', rstateid)
if not id_:
raise ValueError('no state id')
st = {'__id__': id_, 'state': mod_}
if mod_ == st['state'] and fstate == st['__id__']:
ofresult = rstate.get('result', _empty)
if ofresult in [False, True]:
nret = ofresult
if ofresult is False:
# as soon as we find an errored onfail, we stop
break
# consider that if we parsed onfailes without changing
# the ret, that we have failed
if nret is None:
nret = False
return nret
def check_state_result(running, recurse=False, highstate=None):
'''
Check the total return value of the run and determine if the running
dict has any issues
'''
if not isinstance(running, dict):
return False
if not running:
return False
ret = True
for state_id, state_result in six.iteritems(running):
if not recurse and not isinstance(state_result, dict):
ret = False
if ret and isinstance(state_result, dict):
result = state_result.get('result', _empty)
if result is False:
ret = False
# only override return value if we are not already failed
elif result is _empty and isinstance(state_result, dict) and ret:
ret = check_state_result(
state_result, recurse=True, highstate=highstate)
# if we detect a fail, check for onfail requisites
if not ret:
# ret can be None in case of no onfail reqs, recast it to bool
ret = bool(check_onfail_requisites(state_id, state_result,
running, highstate))
# return as soon as we got a failure
if not ret:
break
return ret

View File

@ -0,0 +1,445 @@
# -*- coding: utf-8 -*-
'''
Unit Tests for functions located in salt.utils.state.py.
'''
# Import python libs
from __future__ import absolute_import
# Import Salt libs
from salt.ext import six
import salt.utils.odict
import salt.utils.state
# Import Salt Testing libs
from tests.support.unit import TestCase
class StateUtilTestCase(TestCase):
'''
Test case for state util.
'''
def test_check_state_result(self):
self.assertFalse(salt.utils.state.check_state_result(None),
'Failed to handle None as an invalid data type.')
self.assertFalse(salt.utils.state.check_state_result([]),
'Failed to handle an invalid data type.')
self.assertFalse(salt.utils.state.check_state_result({}),
'Failed to handle an empty dictionary.')
self.assertFalse(salt.utils.state.check_state_result({'host1': []}),
'Failed to handle an invalid host data structure.')
test_valid_state = {'host1': {'test_state': {'result': 'We have liftoff!'}}}
self.assertTrue(salt.utils.state.check_state_result(test_valid_state))
test_valid_false_states = {
'test1': salt.utils.odict.OrderedDict([
('host1',
salt.utils.odict.OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': False}),
])),
]),
'test2': salt.utils.odict.OrderedDict([
('host1',
salt.utils.odict.OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': True}),
])),
('host2',
salt.utils.odict.OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': False}),
])),
]),
'test3': ['a'],
'test4': salt.utils.odict.OrderedDict([
('asup', salt.utils.odict.OrderedDict([
('host1',
salt.utils.odict.OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': True}),
])),
('host2',
salt.utils.odict.OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': False}),
]))
]))
]),
'test5': salt.utils.odict.OrderedDict([
('asup', salt.utils.odict.OrderedDict([
('host1',
salt.utils.odict.OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': True}),
])),
('host2', salt.utils.odict.OrderedDict([]))
]))
])
}
for test, data in six.iteritems(test_valid_false_states):
self.assertFalse(
salt.utils.state.check_state_result(data),
msg='{0} failed'.format(test))
test_valid_true_states = {
'test1': salt.utils.odict.OrderedDict([
('host1',
salt.utils.odict.OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': True}),
])),
]),
'test3': salt.utils.odict.OrderedDict([
('host1',
salt.utils.odict.OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': True}),
])),
('host2',
salt.utils.odict.OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': True}),
])),
]),
'test4': salt.utils.odict.OrderedDict([
('asup', salt.utils.odict.OrderedDict([
('host1',
salt.utils.odict.OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': True}),
])),
('host2',
salt.utils.odict.OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': True}),
]))
]))
]),
'test2': salt.utils.odict.OrderedDict([
('host1',
salt.utils.odict.OrderedDict([
('test_state0', {'result': None}),
('test_state', {'result': True}),
])),
('host2',
salt.utils.odict.OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': 'abc'}),
]))
])
}
for test, data in six.iteritems(test_valid_true_states):
self.assertTrue(
salt.utils.state.check_state_result(data),
msg='{0} failed'.format(test))
test_invalid_true_ht_states = {
'test_onfail_simple2': (
salt.utils.odict.OrderedDict([
('host1',
salt.utils.odict.OrderedDict([
('test_vstate0', {'result': False}),
('test_vstate1', {'result': True}),
])),
]),
{
'test_vstate0': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}]},
'test_vstate1': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
salt.utils.odict.OrderedDict([
('onfail_stop', True),
('onfail',
[salt.utils.odict.OrderedDict([('cmd', 'test_vstate0')])])
]),
'run',
{'order': 10004}]},
}
),
'test_onfail_integ2': (
salt.utils.odict.OrderedDict([
('host1',
salt.utils.odict.OrderedDict([
('t_|-test_ivstate0_|-echo_|-run', {
'result': False}),
('cmd_|-test_ivstate0_|-echo_|-run', {
'result': False}),
('cmd_|-test_ivstate1_|-echo_|-run', {
'result': False}),
])),
]),
{
'test_ivstate0': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}],
't': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}]},
'test_ivstate1': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
salt.utils.odict.OrderedDict([
('onfail_stop', False),
('onfail',
[salt.utils.odict.OrderedDict([('cmd', 'test_ivstate0')])])
]),
'run',
{'order': 10004}]},
}
),
'test_onfail_integ3': (
salt.utils.odict.OrderedDict([
('host1',
salt.utils.odict.OrderedDict([
('t_|-test_ivstate0_|-echo_|-run', {
'result': True}),
('cmd_|-test_ivstate0_|-echo_|-run', {
'result': False}),
('cmd_|-test_ivstate1_|-echo_|-run', {
'result': False}),
])),
]),
{
'test_ivstate0': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}],
't': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}]},
'test_ivstate1': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
salt.utils.odict.OrderedDict([
('onfail_stop', False),
('onfail',
[salt.utils.odict.OrderedDict([('cmd', 'test_ivstate0')])])
]),
'run',
{'order': 10004}]},
}
),
'test_onfail_integ4': (
salt.utils.odict.OrderedDict([
('host1',
salt.utils.odict.OrderedDict([
('t_|-test_ivstate0_|-echo_|-run', {
'result': False}),
('cmd_|-test_ivstate0_|-echo_|-run', {
'result': False}),
('cmd_|-test_ivstate1_|-echo_|-run', {
'result': True}),
])),
]),
{
'test_ivstate0': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}],
't': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}]},
'test_ivstate1': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
salt.utils.odict.OrderedDict([
('onfail_stop', False),
('onfail',
[salt.utils.odict.OrderedDict([('cmd', 'test_ivstate0')])])
]),
'run',
{'order': 10004}]},
'test_ivstate2': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
salt.utils.odict.OrderedDict([
('onfail_stop', True),
('onfail',
[salt.utils.odict.OrderedDict([('cmd', 'test_ivstate0')])])
]),
'run',
{'order': 10004}]},
}
),
'test_onfail': (
salt.utils.odict.OrderedDict([
('host1',
salt.utils.odict.OrderedDict([
('test_state0', {'result': False}),
('test_state', {'result': True}),
])),
]),
None
),
'test_onfail_d': (
salt.utils.odict.OrderedDict([
('host1',
salt.utils.odict.OrderedDict([
('test_state0', {'result': False}),
('test_state', {'result': True}),
])),
]),
{}
)
}
for test, testdata in six.iteritems(test_invalid_true_ht_states):
data, ht = testdata
for t_ in [a for a in data['host1']]:
tdata = data['host1'][t_]
if '_|-' in t_:
t_ = t_.split('_|-')[1]
tdata['__id__'] = t_
self.assertFalse(
salt.utils.state.check_state_result(data, highstate=ht),
msg='{0} failed'.format(test))
test_valid_true_ht_states = {
'test_onfail_integ': (
salt.utils.odict.OrderedDict([
('host1',
salt.utils.odict.OrderedDict([
('cmd_|-test_ivstate0_|-echo_|-run', {
'result': False}),
('cmd_|-test_ivstate1_|-echo_|-run', {
'result': True}),
])),
]),
{
'test_ivstate0': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}]},
'test_ivstate1': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
salt.utils.odict.OrderedDict([
('onfail_stop', False),
('onfail',
[salt.utils.odict.OrderedDict([('cmd', 'test_ivstate0')])])
]),
'run',
{'order': 10004}]},
}
),
'test_onfail_intega3': (
salt.utils.odict.OrderedDict([
('host1',
salt.utils.odict.OrderedDict([
('t_|-test_ivstate0_|-echo_|-run', {
'result': True}),
('cmd_|-test_ivstate0_|-echo_|-run', {
'result': False}),
('cmd_|-test_ivstate1_|-echo_|-run', {
'result': True}),
])),
]),
{
'test_ivstate0': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}],
't': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}]},
'test_ivstate1': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
salt.utils.odict.OrderedDict([
('onfail_stop', False),
('onfail',
[salt.utils.odict.OrderedDict([('cmd', 'test_ivstate0')])])
]),
'run',
{'order': 10004}]},
}
),
'test_onfail_simple': (
salt.utils.odict.OrderedDict([
('host1',
salt.utils.odict.OrderedDict([
('test_vstate0', {'result': False}),
('test_vstate1', {'result': True}),
])),
]),
{
'test_vstate0': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}]},
'test_vstate1': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
salt.utils.odict.OrderedDict([
('onfail_stop', False),
('onfail',
[salt.utils.odict.OrderedDict([('cmd', 'test_vstate0')])])
]),
'run',
{'order': 10004}]},
}
), # order is different
'test_onfail_simple_rev': (
salt.utils.odict.OrderedDict([
('host1',
salt.utils.odict.OrderedDict([
('test_vstate0', {'result': False}),
('test_vstate1', {'result': True}),
])),
]),
{
'test_vstate0': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}]},
'test_vstate1': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
salt.utils.odict.OrderedDict([
('onfail',
[salt.utils.odict.OrderedDict([('cmd', 'test_vstate0')])])
]),
salt.utils.odict.OrderedDict([('onfail_stop', False)]),
'run',
{'order': 10004}]},
}
)
}
for test, testdata in six.iteritems(test_valid_true_ht_states):
data, ht = testdata
for t_ in [a for a in data['host1']]:
tdata = data['host1'][t_]
if '_|-' in t_:
t_ = t_.split('_|-')[1]
tdata['__id__'] = t_
self.assertTrue(
salt.utils.state.check_state_result(data, highstate=ht),
msg='{0} failed'.format(test))
test_valid_false_state = {'host1': {'test_state': {'result': False}}}
self.assertFalse(salt.utils.check_state_result(test_valid_false_state))

View File

@ -20,7 +20,6 @@ import salt.utils
import salt.utils.jid
import salt.utils.yamlencoding
import salt.utils.zeromq
from salt.utils.odict import OrderedDict
from salt.exceptions import (SaltInvocationError, SaltSystemExit, CommandNotFoundError)
# Import Python libraries
@ -30,7 +29,6 @@ import zmq
from collections import namedtuple
# Import 3rd-party libs
from salt.ext import six
try:
import timelib # pylint: disable=import-error,unused-import
HAS_TIMELIB = True
@ -290,427 +288,6 @@ class UtilsTestCase(TestCase):
self.assertEqual(salt.utils.sanitize_win_path_string('\\windows\\system'), '\\windows\\system')
self.assertEqual(salt.utils.sanitize_win_path_string('\\bo:g|us\\p?at*h>'), '\\bo_g_us\\p_at_h_')
def test_check_state_result(self):
self.assertFalse(salt.utils.check_state_result(None), "Failed to handle None as an invalid data type.")
self.assertFalse(salt.utils.check_state_result([]), "Failed to handle an invalid data type.")
self.assertFalse(salt.utils.check_state_result({}), "Failed to handle an empty dictionary.")
self.assertFalse(salt.utils.check_state_result({'host1': []}), "Failed to handle an invalid host data structure.")
test_valid_state = {'host1': {'test_state': {'result': 'We have liftoff!'}}}
self.assertTrue(salt.utils.check_state_result(test_valid_state))
test_valid_false_states = {
'test1': OrderedDict([
('host1',
OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': False}),
])),
]),
'test2': OrderedDict([
('host1',
OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': True}),
])),
('host2',
OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': False}),
])),
]),
'test3': ['a'],
'test4': OrderedDict([
('asup', OrderedDict([
('host1',
OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': True}),
])),
('host2',
OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': False}),
]))
]))
]),
'test5': OrderedDict([
('asup', OrderedDict([
('host1',
OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': True}),
])),
('host2', OrderedDict([]))
]))
])
}
for test, data in six.iteritems(test_valid_false_states):
self.assertFalse(
salt.utils.check_state_result(data),
msg='{0} failed'.format(test))
test_valid_true_states = {
'test1': OrderedDict([
('host1',
OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': True}),
])),
]),
'test3': OrderedDict([
('host1',
OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': True}),
])),
('host2',
OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': True}),
])),
]),
'test4': OrderedDict([
('asup', OrderedDict([
('host1',
OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': True}),
])),
('host2',
OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': True}),
]))
]))
]),
'test2': OrderedDict([
('host1',
OrderedDict([
('test_state0', {'result': None}),
('test_state', {'result': True}),
])),
('host2',
OrderedDict([
('test_state0', {'result': True}),
('test_state', {'result': 'abc'}),
]))
])
}
for test, data in six.iteritems(test_valid_true_states):
self.assertTrue(
salt.utils.check_state_result(data),
msg='{0} failed'.format(test))
test_invalid_true_ht_states = {
'test_onfail_simple2': (
OrderedDict([
('host1',
OrderedDict([
('test_vstate0', {'result': False}),
('test_vstate1', {'result': True}),
])),
]),
{
'test_vstate0': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}]},
'test_vstate1': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [OrderedDict([('name', '/bin/true')]),
OrderedDict([
('onfail_stop', True),
('onfail',
[OrderedDict([('cmd', 'test_vstate0')])])
]),
'run',
{'order': 10004}]},
}
),
'test_onfail_integ2': (
OrderedDict([
('host1',
OrderedDict([
('t_|-test_ivstate0_|-echo_|-run', {
'result': False}),
('cmd_|-test_ivstate0_|-echo_|-run', {
'result': False}),
('cmd_|-test_ivstate1_|-echo_|-run', {
'result': False}),
])),
]),
{
'test_ivstate0': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}],
't': [OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}]},
'test_ivstate1': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [OrderedDict([('name', '/bin/true')]),
OrderedDict([
('onfail_stop', False),
('onfail',
[OrderedDict([('cmd', 'test_ivstate0')])])
]),
'run',
{'order': 10004}]},
}
),
'test_onfail_integ3': (
OrderedDict([
('host1',
OrderedDict([
('t_|-test_ivstate0_|-echo_|-run', {
'result': True}),
('cmd_|-test_ivstate0_|-echo_|-run', {
'result': False}),
('cmd_|-test_ivstate1_|-echo_|-run', {
'result': False}),
])),
]),
{
'test_ivstate0': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}],
't': [OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}]},
'test_ivstate1': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [OrderedDict([('name', '/bin/true')]),
OrderedDict([
('onfail_stop', False),
('onfail',
[OrderedDict([('cmd', 'test_ivstate0')])])
]),
'run',
{'order': 10004}]},
}
),
'test_onfail_integ4': (
OrderedDict([
('host1',
OrderedDict([
('t_|-test_ivstate0_|-echo_|-run', {
'result': False}),
('cmd_|-test_ivstate0_|-echo_|-run', {
'result': False}),
('cmd_|-test_ivstate1_|-echo_|-run', {
'result': True}),
])),
]),
{
'test_ivstate0': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}],
't': [OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}]},
'test_ivstate1': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [OrderedDict([('name', '/bin/true')]),
OrderedDict([
('onfail_stop', False),
('onfail',
[OrderedDict([('cmd', 'test_ivstate0')])])
]),
'run',
{'order': 10004}]},
'test_ivstate2': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [OrderedDict([('name', '/bin/true')]),
OrderedDict([
('onfail_stop', True),
('onfail',
[OrderedDict([('cmd', 'test_ivstate0')])])
]),
'run',
{'order': 10004}]},
}
),
'test_onfail': (
OrderedDict([
('host1',
OrderedDict([
('test_state0', {'result': False}),
('test_state', {'result': True}),
])),
]),
None
),
'test_onfail_d': (
OrderedDict([
('host1',
OrderedDict([
('test_state0', {'result': False}),
('test_state', {'result': True}),
])),
]),
{}
)
}
for test, testdata in six.iteritems(test_invalid_true_ht_states):
data, ht = testdata
for t_ in [a for a in data['host1']]:
tdata = data['host1'][t_]
if '_|-' in t_:
t_ = t_.split('_|-')[1]
tdata['__id__'] = t_
self.assertFalse(
salt.utils.check_state_result(data, highstate=ht),
msg='{0} failed'.format(test))
test_valid_true_ht_states = {
'test_onfail_integ': (
OrderedDict([
('host1',
OrderedDict([
('cmd_|-test_ivstate0_|-echo_|-run', {
'result': False}),
('cmd_|-test_ivstate1_|-echo_|-run', {
'result': True}),
])),
]),
{
'test_ivstate0': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}]},
'test_ivstate1': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [OrderedDict([('name', '/bin/true')]),
OrderedDict([
('onfail_stop', False),
('onfail',
[OrderedDict([('cmd', 'test_ivstate0')])])
]),
'run',
{'order': 10004}]},
}
),
'test_onfail_intega3': (
OrderedDict([
('host1',
OrderedDict([
('t_|-test_ivstate0_|-echo_|-run', {
'result': True}),
('cmd_|-test_ivstate0_|-echo_|-run', {
'result': False}),
('cmd_|-test_ivstate1_|-echo_|-run', {
'result': True}),
])),
]),
{
'test_ivstate0': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}],
't': [OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}]},
'test_ivstate1': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [OrderedDict([('name', '/bin/true')]),
OrderedDict([
('onfail_stop', False),
('onfail',
[OrderedDict([('cmd', 'test_ivstate0')])])
]),
'run',
{'order': 10004}]},
}
),
'test_onfail_simple': (
OrderedDict([
('host1',
OrderedDict([
('test_vstate0', {'result': False}),
('test_vstate1', {'result': True}),
])),
]),
{
'test_vstate0': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}]},
'test_vstate1': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [OrderedDict([('name', '/bin/true')]),
OrderedDict([
('onfail_stop', False),
('onfail',
[OrderedDict([('cmd', 'test_vstate0')])])
]),
'run',
{'order': 10004}]},
}
), # order is different
'test_onfail_simple_rev': (
OrderedDict([
('host1',
OrderedDict([
('test_vstate0', {'result': False}),
('test_vstate1', {'result': True}),
])),
]),
{
'test_vstate0': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [OrderedDict([('name', '/bin/true')]),
'run',
{'order': 10002}]},
'test_vstate1': {
'__env__': 'base',
'__sls__': u'a',
'cmd': [OrderedDict([('name', '/bin/true')]),
OrderedDict([
('onfail',
[OrderedDict([('cmd', 'test_vstate0')])])
]),
OrderedDict([('onfail_stop', False)]),
'run',
{'order': 10004}]},
}
)
}
for test, testdata in six.iteritems(test_valid_true_ht_states):
data, ht = testdata
for t_ in [a for a in data['host1']]:
tdata = data['host1'][t_]
if '_|-' in t_:
t_ = t_.split('_|-')[1]
tdata['__id__'] = t_
self.assertTrue(
salt.utils.check_state_result(data, highstate=ht),
msg='{0} failed'.format(test))
test_valid_false_state = {'host1': {'test_state': {'result': False}}}
self.assertFalse(salt.utils.check_state_result(test_valid_false_state))
@skipIf(NO_MOCK, NO_MOCK_REASON)
@skipIf(not hasattr(zmq, 'IPC_PATH_MAX_LEN'), "ZMQ does not have max length support.")
def test_check_ipc_length(self):