mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 17:09:03 +00:00
1111 lines
47 KiB
Python
1111 lines
47 KiB
Python
# -*- coding: utf-8 -*-
|
|
'''
|
|
unit tests for the grains state
|
|
'''
|
|
|
|
from __future__ import absolute_import, print_function, unicode_literals
|
|
|
|
# Import Python libs
|
|
import os
|
|
import contextlib
|
|
|
|
# Import Salt Testing libs
|
|
from tests.support.mixins import LoaderModuleMockMixin
|
|
from tests.support.paths import TMP
|
|
from tests.support.unit import TestCase, skipIf
|
|
from tests.support.mock import NO_MOCK, NO_MOCK_REASON, MagicMock, patch
|
|
|
|
# Import salt libs
|
|
import salt.utils.files
|
|
import salt.utils.stringutils
|
|
import salt.utils.yaml
|
|
import salt.modules.grains as grainsmod
|
|
import salt.states.grains as grains
|
|
from salt.ext import six
|
|
|
|
|
|
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
|
class GrainsTestCase(TestCase, LoaderModuleMockMixin):
|
|
|
|
def setup_loader_modules(self):
|
|
grains_test_dir = '__salt_test_state_grains'
|
|
if not os.path.exists(os.path.join(TMP, grains_test_dir)):
|
|
os.makedirs(os.path.join(TMP, grains_test_dir))
|
|
loader_globals = {
|
|
'__opts__': {
|
|
'test': False,
|
|
'conf_file': os.path.join(TMP, grains_test_dir, 'minion'),
|
|
'cachedir': os.path.join(TMP, grains_test_dir),
|
|
'local': True,
|
|
},
|
|
'__salt__': {
|
|
'cmd.run_all': MagicMock(return_value={
|
|
'pid': 5,
|
|
'retcode': 0,
|
|
'stderr': '',
|
|
'stdout': ''}),
|
|
'grains.get': grainsmod.get,
|
|
'grains.set': grainsmod.set,
|
|
'grains.setval': grainsmod.setval,
|
|
'grains.delval': grainsmod.delval,
|
|
'grains.append': grainsmod.append,
|
|
'grains.remove': grainsmod.remove,
|
|
'saltutil.sync_grains': MagicMock()
|
|
}
|
|
}
|
|
return {grains: loader_globals, grainsmod: loader_globals}
|
|
|
|
def assertGrainFileContent(self, grains_string):
|
|
if os.path.isdir(grains.__opts__['conf_file']):
|
|
grains_file = os.path.join(
|
|
grains.__opts__['conf_file'],
|
|
'grains')
|
|
else:
|
|
grains_file = os.path.join(
|
|
os.path.dirname(grains.__opts__['conf_file']),
|
|
'grains')
|
|
with salt.utils.files.fopen(grains_file, "r") as grf:
|
|
grains_data = salt.utils.stringutils.to_unicode(grf.read())
|
|
self.assertMultiLineEqual(grains_string, grains_data)
|
|
|
|
@contextlib.contextmanager
|
|
def setGrains(self, grains_data):
|
|
with patch.dict(grains.__grains__, grains_data):
|
|
with patch.dict(grainsmod.__grains__, grains_data):
|
|
if os.path.isdir(grains.__opts__['conf_file']):
|
|
grains_file = os.path.join(
|
|
grains.__opts__['conf_file'],
|
|
'grains')
|
|
else:
|
|
grains_file = os.path.join(
|
|
os.path.dirname(grains.__opts__['conf_file']), 'grains')
|
|
with salt.utils.files.fopen(grains_file, "w+") as grf:
|
|
salt.utils.yaml.safe_dump(grains_data, grf, default_flow_style=False)
|
|
yield
|
|
|
|
# 'exists' function tests: 2
|
|
|
|
def test_exists_missing(self):
|
|
with self.setGrains({'a': 'aval'}):
|
|
ret = grains.exists(name='foo')
|
|
self.assertEqual(ret['result'], False)
|
|
self.assertEqual(ret['comment'], 'Grain does not exist')
|
|
self.assertEqual(ret['changes'], {})
|
|
|
|
def test_exists_found(self):
|
|
with self.setGrains({'a': 'aval', 'foo': 'bar'}):
|
|
# Grain already set
|
|
ret = grains.exists(name='foo')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Grain exists')
|
|
self.assertEqual(ret['changes'], {})
|
|
|
|
# 'present' function tests: 12
|
|
|
|
def test_present_add(self):
|
|
# Set a non existing grain
|
|
with self.setGrains({'a': 'aval'}):
|
|
ret = grains.present(name='foo', value='bar')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['changes'], {'foo': 'bar'})
|
|
self.assertEqual(grains.__grains__, {'a': 'aval', 'foo': 'bar'})
|
|
self.assertGrainFileContent("a: aval\nfoo: bar\n")
|
|
|
|
# Set a non existing nested grain
|
|
with self.setGrains({'a': 'aval'}):
|
|
ret = grains.present(name='foo:is:nested', value='bar')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['changes'], {'foo': {'is': {'nested': 'bar'}}})
|
|
self.assertEqual(grains.__grains__, {'a': 'aval', 'foo': {'is': {'nested': 'bar'}}})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
"foo:\n"
|
|
" is:\n"
|
|
" nested: bar\n"
|
|
)
|
|
|
|
# Set a non existing nested dict grain
|
|
with self.setGrains({'a': 'aval'}):
|
|
ret = grains.present(
|
|
name='foo:is:nested',
|
|
value={'bar': 'is a dict'})
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['changes'], {'foo': {'is': {'nested': {'bar': 'is a dict'}}}})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'is': {'nested': {'bar': 'is a dict'}}}})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ " is:\n"
|
|
+ " nested:\n"
|
|
+ " bar: is a dict\n"
|
|
)
|
|
|
|
def test_present_add_key_to_existing(self):
|
|
with self.setGrains({'a': 'aval', 'foo': {'k1': 'v1'}}):
|
|
# Fails setting a grain to a dict
|
|
ret = grains.present(
|
|
name='foo:k2',
|
|
value='v2')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Set grain foo:k2 to v2')
|
|
self.assertEqual(ret['changes'], {'foo': {'k2': 'v2', 'k1': 'v1'}})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'k1': 'v1', 'k2': 'v2'}})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ " k1: v1\n"
|
|
+ " k2: v2\n"
|
|
)
|
|
|
|
def test_present_already_set(self):
|
|
with self.setGrains({'a': 'aval', 'foo': 'bar'}):
|
|
# Grain already set
|
|
ret = grains.present(
|
|
name='foo',
|
|
value='bar')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Grain is already set')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': 'bar'})
|
|
|
|
with self.setGrains({'a': 'aval', 'foo': {'is': {'nested': 'bar'}}}):
|
|
# Nested grain already set
|
|
ret = grains.present(
|
|
name='foo:is:nested',
|
|
value='bar')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Grain is already set')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'is': {'nested': 'bar'}}})
|
|
|
|
with self.setGrains({'a': 'aval', 'foo': {'is': {'nested': 'bar'}}}):
|
|
# Nested dict grain already set
|
|
ret = grains.present(
|
|
name='foo:is',
|
|
value={'nested': 'bar'})
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Grain is already set')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'is': {'nested': 'bar'}}})
|
|
|
|
def test_present_overwrite(self):
|
|
with self.setGrains({'a': 'aval', 'foo': 'bar'}):
|
|
# Overwrite an existing grain
|
|
ret = grains.present(
|
|
name='foo',
|
|
value='newbar')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['changes'], {'foo': 'newbar'})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': 'newbar'})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo: newbar\n"
|
|
)
|
|
|
|
with self.setGrains({'a': 'aval', 'foo': 'bar'}):
|
|
# Clear a grain (set to None)
|
|
ret = grains.present(
|
|
name='foo',
|
|
value=None)
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['changes'], {'foo': None})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': None})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo: null\n"
|
|
)
|
|
|
|
with self.setGrains({'a': 'aval', 'foo': {'is': {'nested': 'bar'}}}):
|
|
# Overwrite an existing nested grain
|
|
ret = grains.present(
|
|
name='foo:is:nested',
|
|
value='newbar')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['changes'], {'foo': {'is': {'nested': 'newbar'}}})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'is': {'nested': 'newbar'}}})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ " is:\n"
|
|
+ " nested: newbar\n"
|
|
)
|
|
|
|
with self.setGrains({'a': 'aval', 'foo': {'is': {'nested': 'bar'}}}):
|
|
# Clear a nested grain (set to None)
|
|
ret = grains.present(
|
|
name='foo:is:nested',
|
|
value=None)
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['changes'], {'foo': {'is': {'nested': None}}})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'is': {'nested': None}}})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ " is:\n"
|
|
+ " nested: null\n"
|
|
)
|
|
|
|
def test_present_fail_overwrite(self):
|
|
with self.setGrains({'a': 'aval', 'foo': {'is': {'nested': 'val'}}}):
|
|
# Overwrite an existing grain
|
|
ret = grains.present(
|
|
name='foo:is',
|
|
value='newbar')
|
|
self.assertEqual(ret['result'], False)
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(ret['comment'], 'The key \'foo:is\' exists but is a dict or a list. Use \'force=True\' to overwrite.')
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'is': {'nested': 'val'}}})
|
|
|
|
with self.setGrains({'a': 'aval', 'foo': {'is': {'nested': 'val'}}}):
|
|
# Clear a grain (set to None)
|
|
ret = grains.present(
|
|
name='foo:is',
|
|
value=None)
|
|
self.assertEqual(ret['result'], False)
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(ret['comment'], 'The key \'foo:is\' exists but is a dict or a list. Use \'force=True\' to overwrite.')
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'is': {'nested': 'val'}}})
|
|
|
|
def test_present_fails_to_set_dict_or_list(self):
|
|
with self.setGrains({'a': 'aval', 'foo': 'bar'}):
|
|
# Fails to overwrite a grain to a list
|
|
ret = grains.present(
|
|
name='foo',
|
|
value=['l1', 'l2'])
|
|
self.assertEqual(ret['result'], False)
|
|
self.assertEqual(ret['comment'], 'The key \'foo\' exists and the '
|
|
+ 'given value is a dict or a list. '
|
|
+ 'Use \'force=True\' to overwrite.')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': 'bar'})
|
|
|
|
with self.setGrains({'a': 'aval', 'foo': 'bar'}):
|
|
# Fails setting a grain to a dict
|
|
ret = grains.present(
|
|
name='foo',
|
|
value={'k1': 'v1'})
|
|
self.assertEqual(ret['result'], False)
|
|
self.assertEqual(ret['comment'], 'The key \'foo\' exists and the given '
|
|
+ 'value is a dict or a list. Use '
|
|
+ '\'force=True\' to overwrite.')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': 'bar'})
|
|
|
|
with self.setGrains({'a': 'aval', 'foo': {'is': {'nested': 'bar'}}}):
|
|
# Fails to overwrite a nested grain to a list
|
|
ret = grains.present(
|
|
name='foo,is,nested',
|
|
value=['l1', 'l2'],
|
|
delimiter=',')
|
|
self.assertEqual(ret['result'], False)
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(ret['comment'], 'The key \'foo:is:nested\' exists and the '
|
|
+ 'given value is a dict or a list. '
|
|
+ 'Use \'force=True\' to overwrite.')
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'is': {'nested': 'bar'}}})
|
|
|
|
with self.setGrains({'a': 'aval', 'foo': {'is': {'nested': 'bar'}}}):
|
|
# Fails setting a nested grain to a dict
|
|
ret = grains.present(
|
|
name='foo:is:nested',
|
|
value={'k1': 'v1'})
|
|
self.assertEqual(ret['result'], False)
|
|
self.assertEqual(ret['comment'], 'The key \'foo:is:nested\' exists and the '
|
|
+ 'given value is a dict or a list. '
|
|
+ 'Use \'force=True\' to overwrite.')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'is': {'nested': 'bar'}}})
|
|
|
|
def test_present_fail_merge_dict(self):
|
|
with self.setGrains({'a': 'aval', 'foo': {'k1': 'v1'}}):
|
|
# Fails setting a grain to a dict
|
|
ret = grains.present(
|
|
name='foo',
|
|
value={'k2': 'v2'})
|
|
self.assertEqual(ret['result'], False)
|
|
self.assertEqual(ret['comment'], 'The key \'foo\' exists but '
|
|
+ 'is a dict or a list. '
|
|
+ 'Use \'force=True\' to overwrite.')
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'k1': 'v1'}})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ " k1: v1\n"
|
|
)
|
|
|
|
def test_present_force_to_set_dict_or_list(self):
|
|
with self.setGrains({'a': 'aval', 'foo': 'bar'}):
|
|
# Force to overwrite a grain to a list
|
|
ret = grains.present(
|
|
name='foo',
|
|
value=['l1', 'l2'],
|
|
force=True)
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(
|
|
ret['comment'],
|
|
"Set grain foo to ['l1', 'l2']" if six.PY3
|
|
else "Set grain foo to [u'l1', u'l2']"
|
|
)
|
|
self.assertEqual(ret['changes'], {'foo': ['l1', 'l2']})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': ['l1', 'l2']})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ "- l1\n"
|
|
+ "- l2\n"
|
|
)
|
|
|
|
with self.setGrains({'a': 'aval', 'foo': 'bar'}):
|
|
# Force setting a grain to a dict
|
|
ret = grains.present(
|
|
name='foo',
|
|
value={'k1': 'v1'},
|
|
force=True)
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(
|
|
ret['comment'],
|
|
"Set grain foo to {'k1': 'v1'}" if six.PY3
|
|
else "Set grain foo to {u'k1': u'v1'}"
|
|
)
|
|
self.assertEqual(ret['changes'], {'foo': {'k1': 'v1'}})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'k1': 'v1'}})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ " k1: v1\n"
|
|
)
|
|
|
|
with self.setGrains({'a': 'aval', 'foo': {'is': {'nested': 'bar'}}}):
|
|
# Force to overwrite a nested grain to a list
|
|
ret = grains.present(
|
|
name='foo,is,nested',
|
|
value=['l1', 'l2'],
|
|
delimiter=',',
|
|
force=True)
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['changes'], {'foo': {'is': {'nested': ['l1', 'l2']}}})
|
|
self.assertEqual(
|
|
ret['comment'],
|
|
"Set grain foo:is:nested to ['l1', 'l2']" if six.PY3
|
|
else "Set grain foo:is:nested to [u'l1', u'l2']"
|
|
)
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'is': {'nested': ['l1', 'l2']}}})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ " is:\n"
|
|
+ " nested:\n"
|
|
+ " - l1\n"
|
|
+ " - l2\n"
|
|
)
|
|
|
|
with self.setGrains({'a': 'aval', 'foo': {'is': {'nested': 'bar'}, 'and': 'other'}}):
|
|
# Force setting a nested grain to a dict
|
|
ret = grains.present(
|
|
name='foo:is:nested',
|
|
value={'k1': 'v1'},
|
|
force=True)
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(
|
|
ret['comment'],
|
|
"Set grain foo:is:nested to {'k1': 'v1'}" if six.PY3
|
|
else "Set grain foo:is:nested to {u'k1': u'v1'}"
|
|
)
|
|
self.assertEqual(ret['changes'], {'foo': {'is': {'nested': {'k1': 'v1'}}, 'and': 'other'}})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'is': {'nested': {'k1': 'v1'}}, 'and': 'other'}})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ " and: other\n"
|
|
+ " is:\n"
|
|
+ " nested:\n"
|
|
+ " k1: v1\n"
|
|
)
|
|
|
|
def test_present_fails_to_convert_value_to_key(self):
|
|
with self.setGrains({'a': 'aval', 'foo': 'bar'}):
|
|
# Fails converting a value to a nested grain key
|
|
ret = grains.present(
|
|
name='foo:is:nested',
|
|
value={'k1': 'v1'})
|
|
self.assertEqual(ret['result'], False)
|
|
self.assertEqual(ret['comment'], 'The key \'foo\' value is \'bar\', '
|
|
+ 'which is different from the provided '
|
|
+ 'key \'is\'. Use \'force=True\' to overwrite.')
|
|
self.assertEqual(ret['changes'], {})
|
|
|
|
def test_present_overwrite_test(self):
|
|
with patch.dict(grains.__opts__, {'test': True}):
|
|
with self.setGrains({'a': 'aval', 'foo': 'bar'}):
|
|
# Overwrite an existing grain
|
|
ret = grains.present(
|
|
name='foo',
|
|
value='newbar')
|
|
self.assertEqual(ret['result'], None)
|
|
self.assertEqual(ret['changes'], {'changed': {'foo': 'newbar'}})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': 'bar'})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo: bar\n"
|
|
)
|
|
|
|
def test_present_convert_value_to_key(self):
|
|
with self.setGrains({'a': 'aval', 'foo': 'is'}):
|
|
# Converts a value to a nested grain key
|
|
ret = grains.present(
|
|
name='foo:is:nested',
|
|
value={'k1': 'v1'})
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(
|
|
ret['comment'],
|
|
"Set grain foo:is:nested to {'k1': 'v1'}" if six.PY3
|
|
else "Set grain foo:is:nested to {u'k1': u'v1'}"
|
|
)
|
|
self.assertEqual(ret['changes'], {'foo': {'is': {'nested': {'k1': 'v1'}}}})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'is': {'nested': {'k1': 'v1'}}}})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ " is:\n"
|
|
+ " nested:\n"
|
|
+ " k1: v1\n"
|
|
)
|
|
|
|
with self.setGrains({'a': 'aval', 'foo': ['one', 'is', 'correct']}):
|
|
# Converts a list element to a nested grain key
|
|
ret = grains.present(
|
|
name='foo:is:nested',
|
|
value={'k1': 'v1'})
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(
|
|
ret['comment'],
|
|
"Set grain foo:is:nested to {'k1': 'v1'}" if six.PY3
|
|
else "Set grain foo:is:nested to {u'k1': u'v1'}"
|
|
)
|
|
self.assertEqual(ret['changes'], {'foo': ['one', {'is': {'nested': {'k1': 'v1'}}}, 'correct']})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': ['one', {'is': {'nested': {'k1': 'v1'}}}, 'correct']})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ "- one\n"
|
|
+ "- is:\n"
|
|
+ " nested:\n"
|
|
+ " k1: v1\n"
|
|
+ "- correct\n"
|
|
)
|
|
|
|
def test_present_unknown_failure(self):
|
|
with patch('salt.modules.grains.setval') as mocked_setval:
|
|
mocked_setval.return_value = 'Failed to set grain foo'
|
|
with self.setGrains({'a': 'aval', 'foo': 'bar'}):
|
|
# Unknown reason failure
|
|
ret = grains.present(
|
|
name='foo',
|
|
value='baz')
|
|
self.assertEqual(ret['result'], False)
|
|
self.assertEqual(ret['comment'], 'Failed to set grain foo')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': 'bar'})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo: bar\n"
|
|
)
|
|
|
|
# 'absent' function tests: 6
|
|
|
|
def test_absent_already(self):
|
|
# Unset a non existent grain
|
|
with self.setGrains({'a': 'aval'}):
|
|
ret = grains.absent(
|
|
name='foo')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Grain foo does not exist')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval'})
|
|
self.assertGrainFileContent("a: aval\n")
|
|
|
|
# Unset a non existent nested grain
|
|
with self.setGrains({'a': 'aval'}):
|
|
ret = grains.absent(
|
|
name='foo:is:nested')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Grain foo:is:nested does not exist')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval'})
|
|
self.assertGrainFileContent("a: aval\n")
|
|
|
|
def test_absent_unset(self):
|
|
# Unset a grain
|
|
with self.setGrains({'a': 'aval', 'foo': 'bar'}):
|
|
ret = grains.absent(
|
|
name='foo')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Value for grain foo was set to None')
|
|
self.assertEqual(ret['changes'], {'grain': 'foo', 'value': None})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': None})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo: null\n"
|
|
)
|
|
|
|
# Unset grain when its value is False
|
|
with self.setGrains({'a': 'aval', 'foo': False}):
|
|
ret = grains.absent(
|
|
name='foo')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Value for grain foo was set to None')
|
|
self.assertEqual(ret['changes'], {'grain': 'foo', 'value': None})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': None})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo: null\n"
|
|
)
|
|
|
|
# Unset a nested grain
|
|
with self.setGrains({'a': 'aval', 'foo': ['order', {'is': {'nested': 'bar'}}, 'correct']}):
|
|
ret = grains.absent(
|
|
name='foo,is,nested',
|
|
delimiter=',')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Value for grain foo:is:nested was set to None')
|
|
self.assertEqual(ret['changes'], {'grain': 'foo:is:nested', 'value': None})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': ['order', {'is': {'nested': None}}, 'correct']})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ "- order\n"
|
|
+ "- is:\n"
|
|
+ " nested: null\n"
|
|
+ "- correct\n"
|
|
)
|
|
|
|
# Unset a nested value don't change anything
|
|
with self.setGrains({'a': 'aval', 'foo': ['order', {'is': 'nested'}, 'correct']}):
|
|
ret = grains.absent(
|
|
name='foo:is:nested')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Grain foo:is:nested does not exist')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': ['order', {'is': 'nested'}, 'correct']})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ "- order\n"
|
|
+ "- is: nested\n"
|
|
+ "- correct\n"
|
|
)
|
|
|
|
def test_absent_unset_test(self):
|
|
with patch.dict(grains.__opts__, {'test': True}):
|
|
with self.setGrains({'a': 'aval', 'foo': 'bar'}):
|
|
# Overwrite an existing grain
|
|
ret = grains.absent(name='foo')
|
|
self.assertEqual(ret['result'], None)
|
|
self.assertEqual(ret['changes'], {'grain': 'foo', 'value': None})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': 'bar'})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo: bar\n"
|
|
)
|
|
|
|
def test_absent_fails_nested_complex_grain(self):
|
|
# Unset a nested complex grain
|
|
with self.setGrains({'a': 'aval', 'foo': ['order', {'is': {'nested': 'bar'}}, 'correct']}):
|
|
ret = grains.absent(
|
|
name='foo:is')
|
|
self.assertEqual(ret['result'], False)
|
|
self.assertEqual(ret['comment'], 'The key \'foo:is\' exists but is a dict or a list. Use \'force=True\' to overwrite.')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': ['order', {'is': {'nested': 'bar'}}, 'correct']})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ "- order\n"
|
|
+ "- is:\n"
|
|
+ " nested: bar\n"
|
|
+ "- correct\n"
|
|
)
|
|
|
|
def test_absent_force_nested_complex_grain(self):
|
|
# Unset a nested complex grain
|
|
with self.setGrains({'a': 'aval', 'foo': ['order', {'is': {'nested': 'bar'}}, 'correct']}):
|
|
ret = grains.absent(
|
|
name='foo:is',
|
|
force=True)
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Value for grain foo:is was set to None')
|
|
self.assertEqual(ret['changes'], {'grain': 'foo:is', 'value': None})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': ['order', {'is': None}, 'correct']})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ "- order\n"
|
|
+ "- is: null\n"
|
|
+ "- correct\n"
|
|
)
|
|
|
|
def test_absent_delete(self):
|
|
# Delete a grain
|
|
with self.setGrains({'a': 'aval', 'foo': 'bar'}):
|
|
ret = grains.absent(
|
|
name='foo',
|
|
destructive=True)
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Grain foo was deleted')
|
|
self.assertEqual(ret['changes'], {'deleted': 'foo'})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval'})
|
|
self.assertGrainFileContent("a: aval\n")
|
|
|
|
# Delete a previously unset grain
|
|
with self.setGrains({'a': 'aval', 'foo': None}):
|
|
ret = grains.absent(
|
|
name='foo',
|
|
destructive=True)
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Grain foo was deleted')
|
|
self.assertEqual(ret['changes'], {'deleted': 'foo'})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval'})
|
|
self.assertGrainFileContent("a: aval\n")
|
|
|
|
# Delete a nested grain
|
|
with self.setGrains({'a': 'aval', 'foo': ['order', {'is': {'nested': 'bar', 'other': 'value'}}, 'correct']}):
|
|
ret = grains.absent(
|
|
name='foo:is:nested',
|
|
destructive=True)
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Grain foo:is:nested was deleted')
|
|
self.assertEqual(ret['changes'], {'deleted': 'foo:is:nested'})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': ['order', {'is': {'other': 'value'}}, 'correct']})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ "- order\n"
|
|
+ "- is:\n"
|
|
+ " other: value\n"
|
|
+ "- correct\n"
|
|
)
|
|
|
|
# 'append' function tests: 6
|
|
|
|
def test_append(self):
|
|
# Append to an existing list
|
|
with self.setGrains({'a': 'aval', 'foo': ['bar']}):
|
|
ret = grains.append(
|
|
name='foo',
|
|
value='baz')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Value baz was added to grain foo')
|
|
self.assertEqual(ret['changes'], {'added': 'baz'})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': ['bar', 'baz']})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ "- bar\n"
|
|
+ "- baz\n"
|
|
)
|
|
|
|
def test_append_nested(self):
|
|
# Append to an existing nested list
|
|
with self.setGrains({'a': 'aval', 'foo': {'list': ['bar']}}):
|
|
ret = grains.append(
|
|
name='foo,list',
|
|
value='baz',
|
|
delimiter=',')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Value baz was added to grain foo:list')
|
|
self.assertEqual(ret['changes'], {'added': 'baz'})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'list': ['bar', 'baz']}})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ " list:\n"
|
|
+ " - bar\n"
|
|
+ " - baz\n"
|
|
)
|
|
|
|
def test_append_already(self):
|
|
# Append to an existing list
|
|
with self.setGrains({'a': 'aval', 'foo': ['bar']}):
|
|
ret = grains.append(
|
|
name='foo',
|
|
value='bar')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Value bar is already in the list '
|
|
+ 'for grain foo')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': ['bar']})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ "- bar\n"
|
|
)
|
|
|
|
def test_append_fails_not_a_list(self):
|
|
# Fail to append to an existing grain, not a list
|
|
with self.setGrains({'a': 'aval', 'foo': {'bar': 'val'}}):
|
|
ret = grains.append(
|
|
name='foo',
|
|
value='baz')
|
|
self.assertEqual(ret['result'], False)
|
|
self.assertEqual(ret['comment'], 'Grain foo is not a valid list')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'bar': 'val'}})
|
|
|
|
def test_append_convert_to_list(self):
|
|
# Append to an existing grain, converting to a list
|
|
with self.setGrains({'a': 'aval', 'foo': {'bar': 'val'}}):
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ " bar: val\n"
|
|
)
|
|
ret = grains.append(
|
|
name='foo',
|
|
value='baz',
|
|
convert=True)
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Value baz was added to grain foo')
|
|
self.assertEqual(ret['changes'], {'added': 'baz'})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': [{'bar': 'val'}, 'baz']})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ "- bar: val\n"
|
|
+ "- baz\n"
|
|
)
|
|
|
|
# Append to an existing grain, converting to a list a multi-value dict
|
|
with self.setGrains({'a': 'aval', 'foo': {'bar': 'val', 'other': 'value'}}):
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ " bar: val\n"
|
|
+ " other: value\n"
|
|
)
|
|
ret = grains.append(
|
|
name='foo',
|
|
value='baz',
|
|
convert=True)
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Value baz was added to grain foo')
|
|
self.assertEqual(ret['changes'], {'added': 'baz'})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': [{'bar': 'val', 'other': 'value'}, 'baz']})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ "- bar: val\n"
|
|
+ " other: value\n"
|
|
+ "- baz\n"
|
|
)
|
|
|
|
def test_append_fails_inexistent(self):
|
|
# Append to a non existing grain
|
|
with self.setGrains({'a': 'aval'}):
|
|
ret = grains.append(
|
|
name='foo',
|
|
value='bar')
|
|
self.assertEqual(ret['result'], False)
|
|
self.assertEqual(ret['comment'], 'Grain foo does not exist')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval'})
|
|
|
|
def test_append_convert_to_list_empty(self):
|
|
# Append to an existing list
|
|
with self.setGrains({'foo': None}):
|
|
ret = grains.append(name='foo',
|
|
value='baz',
|
|
convert=True)
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Value baz was added to grain foo')
|
|
self.assertEqual(ret['changes'], {'added': 'baz'})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'foo': ['baz']})
|
|
self.assertGrainFileContent("foo:\n"
|
|
+ "- baz\n")
|
|
|
|
# 'list_present' function tests: 7
|
|
|
|
def test_list_present(self):
|
|
with self.setGrains({'a': 'aval', 'foo': ['bar']}):
|
|
ret = grains.list_present(
|
|
name='foo',
|
|
value='baz')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Append value baz to grain foo')
|
|
self.assertEqual(ret['changes'], {'new': {'foo': ['bar', 'baz']}})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': ['bar', 'baz']})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ "- bar\n"
|
|
+ "- baz\n"
|
|
)
|
|
|
|
def test_list_present_nested(self):
|
|
with self.setGrains({'a': 'aval', 'foo': {'is': {'nested': ['bar']}}}):
|
|
ret = grains.list_present(
|
|
name='foo,is,nested',
|
|
value='baz',
|
|
delimiter=',')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Append value baz to grain foo:is:nested')
|
|
self.assertEqual(ret['changes'], {'new': {'foo': {'is': {'nested': ['bar', 'baz']}}}})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'is': {'nested': ['bar', 'baz']}}})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ " is:\n"
|
|
+ " nested:\n"
|
|
+ " - bar\n"
|
|
+ " - baz\n"
|
|
)
|
|
|
|
def test_list_present_inexistent(self):
|
|
with self.setGrains({'a': 'aval'}):
|
|
ret = grains.list_present(
|
|
name='foo',
|
|
value='baz')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Append value baz to grain foo')
|
|
self.assertEqual(ret['changes'], {'new': {'foo': ['baz']}})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': ['baz']})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ "- baz\n"
|
|
)
|
|
|
|
def test_list_present_inexistent_nested(self):
|
|
with self.setGrains({'a': 'aval'}):
|
|
ret = grains.list_present(
|
|
name='foo:is:nested',
|
|
value='baz')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Append value baz to grain foo:is:nested')
|
|
self.assertEqual(ret['changes'], {'new': {'foo': {'is': {'nested': ['baz']}}}})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'is': {'nested': ['baz']}}})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ " is:\n"
|
|
+ " nested:\n"
|
|
+ " - baz\n"
|
|
)
|
|
|
|
def test_list_present_not_a_list(self):
|
|
with self.setGrains({'a': 'aval', 'foo': 'bar'}):
|
|
ret = grains.list_present(
|
|
name='foo',
|
|
value='baz')
|
|
self.assertEqual(ret['result'], False)
|
|
self.assertEqual(ret['comment'], 'Grain foo is not a valid list')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': 'bar'})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo: bar\n"
|
|
)
|
|
|
|
def test_list_present_nested_already(self):
|
|
with self.setGrains({'a': 'aval', 'b': {'foo': ['bar']}}):
|
|
ret = grains.list_present(
|
|
name='b:foo',
|
|
value='bar')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Value bar is already in grain b:foo')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'b': {'foo': ['bar']}})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "b:\n"
|
|
+ " foo:\n"
|
|
+ " - bar\n"
|
|
)
|
|
|
|
def test_list_present_already(self):
|
|
with self.setGrains({'a': 'aval', 'foo': ['bar']}):
|
|
ret = grains.list_present(
|
|
name='foo',
|
|
value='bar')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Value bar is already in grain foo')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': ['bar']})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ "- bar\n"
|
|
)
|
|
|
|
def test_list_present_unknown_failure(self):
|
|
with self.setGrains({'a': 'aval', 'foo': ['bar']}):
|
|
# Unknown reason failure
|
|
|
|
with patch.dict(grainsmod.__salt__, {'grains.append': MagicMock()}):
|
|
ret = grains.list_present(
|
|
name='foo',
|
|
value='baz')
|
|
self.assertEqual(ret['result'], False)
|
|
self.assertEqual(ret['comment'], 'Failed append value baz to grain foo')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': ['bar']})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ "- bar\n"
|
|
)
|
|
|
|
# 'list_absent' function tests: 6
|
|
|
|
def test_list_absent(self):
|
|
with self.setGrains({'a': 'aval', 'foo': ['bar']}):
|
|
ret = grains.list_absent(
|
|
name='foo',
|
|
value='bar')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Value bar was deleted from grain foo')
|
|
self.assertEqual(ret['changes'], {'deleted': ['bar']})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': []})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo: []\n"
|
|
)
|
|
|
|
def test_list_absent_nested(self):
|
|
with self.setGrains({'a': 'aval', 'foo': {'list': ['bar']}}):
|
|
ret = grains.list_absent(
|
|
name='foo:list',
|
|
value='bar')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Value bar was deleted from grain foo:list')
|
|
self.assertEqual(ret['changes'], {'deleted': ['bar']})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': {'list': []}})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ " list: []\n"
|
|
)
|
|
|
|
def test_list_absent_inexistent(self):
|
|
with self.setGrains({'a': 'aval'}):
|
|
ret = grains.list_absent(
|
|
name='foo',
|
|
value='baz')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Grain foo does not exist')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval'})
|
|
self.assertGrainFileContent("a: aval\n")
|
|
|
|
def test_list_absent_inexistent_nested(self):
|
|
with self.setGrains({'a': 'aval'}):
|
|
ret = grains.list_absent(
|
|
name='foo:list',
|
|
value='baz')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Grain foo:list does not exist')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval'})
|
|
self.assertGrainFileContent("a: aval\n")
|
|
|
|
def test_list_absent_not_a_list(self):
|
|
with self.setGrains({'a': 'aval', 'foo': 'bar'}):
|
|
ret = grains.list_absent(
|
|
name='foo',
|
|
value='bar')
|
|
self.assertEqual(ret['result'], False)
|
|
self.assertEqual(ret['comment'], 'Grain foo is not a valid list')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': 'bar'})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo: bar\n"
|
|
)
|
|
|
|
def test_list_absent_already(self):
|
|
with self.setGrains({'a': 'aval', 'foo': ['bar']}):
|
|
ret = grains.list_absent(
|
|
name='foo',
|
|
value='baz')
|
|
self.assertEqual(ret['result'], True)
|
|
self.assertEqual(ret['comment'], 'Value baz is absent from grain foo')
|
|
self.assertEqual(ret['changes'], {})
|
|
self.assertEqual(
|
|
grains.__grains__,
|
|
{'a': 'aval', 'foo': ['bar']})
|
|
self.assertGrainFileContent("a: aval\n"
|
|
+ "foo:\n"
|
|
+ "- bar\n"
|
|
)
|