123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638 |
- # -*- coding: utf-8 -*-
- '''
- Unit Tests for functions located in salt.utils.state.py.
- '''
- # Import python libs
- from __future__ import absolute_import, print_function, unicode_literals
- import copy
- import textwrap
- # 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_result(self):
- self.assertFalse(salt.utils.state.check_result(None),
- 'Failed to handle None as an invalid data type.')
- self.assertFalse(salt.utils.state.check_result([]),
- 'Failed to handle an invalid data type.')
- self.assertFalse(salt.utils.state.check_result({}),
- 'Failed to handle an empty dictionary.')
- self.assertFalse(salt.utils.state.check_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_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_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_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__': 'a',
- 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
- 'run',
- {'order': 10002}]},
- 'test_vstate1': {
- '__env__': 'base',
- '__sls__': '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__': '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__': '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__': '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__': '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__': '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__': '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__': '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_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__': 'a',
- 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
- 'run',
- {'order': 10002}]},
- 'test_ivstate1': {
- '__env__': 'base',
- '__sls__': '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__': '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__': '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__': 'a',
- 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
- 'run',
- {'order': 10002}]},
- 'test_vstate1': {
- '__env__': 'base',
- '__sls__': '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__': 'a',
- 'cmd': [salt.utils.odict.OrderedDict([('name', '/bin/true')]),
- 'run',
- {'order': 10002}]},
- 'test_vstate1': {
- '__env__': 'base',
- '__sls__': '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_result(data, highstate=ht),
- msg='{0} failed'.format(test))
- test_valid_false_state = {'host1': {'test_state': {'result': False}}}
- self.assertFalse(salt.utils.state.check_result(test_valid_false_state))
- class UtilStateMergeSubreturnTestcase(TestCase):
- '''
- Test cases for salt.utils.state.merge_subreturn function.
- '''
- main_ret = {
- 'name': 'primary',
- # result may be missing, as primarysalt.utils.state is still in progress
- 'comment': '',
- 'changes': {},
- }
- sub_ret = {
- 'name': 'secondary',
- 'result': True,
- 'comment': '',
- 'changes': {},
- }
- def test_merge_result(self):
- # result not created if not needed
- for no_effect_result in [True, None]:
- m = copy.deepcopy(self.main_ret)
- s = copy.deepcopy(self.sub_ret)
- s['result'] = no_effect_result
- res = salt.utils.state.merge_subreturn(m, s)
- self.assertNotIn('result', res)
- # False subresult is propagated to existing result
- for original_result in [True, None, False]:
- m = copy.deepcopy(self.main_ret)
- m['result'] = original_result
- s = copy.deepcopy(self.sub_ret)
- s['result'] = False
- res = salt.utils.state.merge_subreturn(m, s)
- self.assertFalse(res['result'])
- # False result cannot be overridden
- for any_result in [True, None, False]:
- m = copy.deepcopy(self.main_ret)
- m['result'] = False
- s = copy.deepcopy(self.sub_ret)
- s['result'] = any_result
- res = salt.utils.state.merge_subreturn(m, s)
- self.assertFalse(res['result'])
- def test_merge_changes(self):
- # The main changes dict should always already exist,
- # and there should always be a changes dict in the secondary.
- primary_changes = {'old': None, 'new': 'my_resource'}
- secondary_changes = {'old': None, 'new': ['alarm-1', 'alarm-2']}
- # No changes case
- m = copy.deepcopy(self.main_ret)
- s = copy.deepcopy(self.sub_ret)
- res = salt.utils.state.merge_subreturn(m, s)
- self.assertDictEqual(res['changes'], {})
- # New changes don't get rid of existing changes
- m = copy.deepcopy(self.main_ret)
- m['changes'] = copy.deepcopy(primary_changes)
- s = copy.deepcopy(self.sub_ret)
- s['changes'] = copy.deepcopy(secondary_changes)
- res = salt.utils.state.merge_subreturn(m, s)
- self.assertDictEqual(res['changes'], {
- 'old': None,
- 'new': 'my_resource',
- 'secondary': secondary_changes,
- })
- # The subkey parameter is respected
- m = copy.deepcopy(self.main_ret)
- m['changes'] = copy.deepcopy(primary_changes)
- s = copy.deepcopy(self.sub_ret)
- s['changes'] = copy.deepcopy(secondary_changes)
- res = salt.utils.state.merge_subreturn(m, s, subkey='alarms')
- self.assertDictEqual(res['changes'], {
- 'old': None,
- 'new': 'my_resource',
- 'alarms': secondary_changes,
- })
- def test_merge_comments(self):
- main_comment_1 = 'First primary comment.'
- main_comment_2 = 'Second primary comment.'
- sub_comment_1 = 'First secondary comment,\nwhich spans two lines.'
- sub_comment_2 = 'Second secondary comment: {0}'.format(
- 'some error\n And a traceback',
- )
- final_comment = textwrap.dedent('''\
- First primary comment.
- Second primary comment.
- First secondary comment,
- which spans two lines.
- Second secondary comment: some error
- And a traceback
- '''.rstrip())
- # Joining two strings
- m = copy.deepcopy(self.main_ret)
- m['comment'] = main_comment_1 + '\n' + main_comment_2
- s = copy.deepcopy(self.sub_ret)
- s['comment'] = sub_comment_1 + '\n' + sub_comment_2
- res = salt.utils.state.merge_subreturn(m, s)
- self.assertMultiLineEqual(res['comment'], final_comment)
- # Joining string and a list
- m = copy.deepcopy(self.main_ret)
- m['comment'] = main_comment_1 + '\n' + main_comment_2
- s = copy.deepcopy(self.sub_ret)
- s['comment'] = [sub_comment_1, sub_comment_2]
- res = salt.utils.state.merge_subreturn(m, s)
- self.assertMultiLineEqual(res['comment'], final_comment)
- # For tests where output is a list,
- # also test that final joined output will match
- # Joining list and a string
- m = copy.deepcopy(self.main_ret)
- m['comment'] = [main_comment_1, main_comment_2]
- s = copy.deepcopy(self.sub_ret)
- s['comment'] = sub_comment_1 + '\n' + sub_comment_2
- res = salt.utils.state.merge_subreturn(m, s)
- self.assertEqual(res['comment'], [
- main_comment_1,
- main_comment_2,
- sub_comment_1 + '\n' + sub_comment_2,
- ])
- self.assertMultiLineEqual('\n'.join(res['comment']), final_comment)
- # Joining two lists
- m = copy.deepcopy(self.main_ret)
- m['comment'] = [main_comment_1, main_comment_2]
- s = copy.deepcopy(self.sub_ret)
- s['comment'] = [sub_comment_1, sub_comment_2]
- res = salt.utils.state.merge_subreturn(m, s)
- self.assertEqual(res['comment'], [
- main_comment_1,
- main_comment_2,
- sub_comment_1,
- sub_comment_2,
- ])
- self.assertMultiLineEqual('\n'.join(res['comment']), final_comment)
- def test_merge_empty_comments(self):
- # Since the primarysalt.utils.state is in progress,
- # the main comment may be empty, either '' or [].
- # Note that [''] is a degenerate case and should never happen,
- # hence the behavior is left unspecified in that case.
- # The secondary comment should never be empty,
- # because thatsalt.utils.state has already returned,
- # so we leave the behavior unspecified in that case.
- sub_comment_1 = 'Secondary comment about changes:'
- sub_comment_2 = 'A diff that goes with the previous comment'
- # No contributions from primary
- final_comment = sub_comment_1 + '\n' + sub_comment_2
- # Joining empty string and a string
- m = copy.deepcopy(self.main_ret)
- m['comment'] = ''
- s = copy.deepcopy(self.sub_ret)
- s['comment'] = sub_comment_1 + '\n' + sub_comment_2
- res = salt.utils.state.merge_subreturn(m, s)
- self.assertEqual(res['comment'], final_comment)
- # Joining empty string and a list
- m = copy.deepcopy(self.main_ret)
- m['comment'] = ''
- s = copy.deepcopy(self.sub_ret)
- s['comment'] = [sub_comment_1, sub_comment_2]
- res = salt.utils.state.merge_subreturn(m, s)
- self.assertEqual(res['comment'], final_comment)
- # For tests where output is a list,
- # also test that final joined output will match
- # Joining empty list and a string
- m = copy.deepcopy(self.main_ret)
- m['comment'] = []
- s = copy.deepcopy(self.sub_ret)
- s['comment'] = sub_comment_1 + '\n' + sub_comment_2
- res = salt.utils.state.merge_subreturn(m, s)
- self.assertEqual(res['comment'], [final_comment])
- self.assertEqual('\n'.join(res['comment']), final_comment)
- # Joining empty list and a list
- m = copy.deepcopy(self.main_ret)
- m['comment'] = []
- s = copy.deepcopy(self.sub_ret)
- s['comment'] = [sub_comment_1, sub_comment_2]
- res = salt.utils.state.merge_subreturn(m, s)
- self.assertEqual(res['comment'], [sub_comment_1, sub_comment_2])
- self.assertEqual('\n'.join(res['comment']), final_comment)
|