123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935 |
- # -*- coding: utf-8 -*-
- """
- unit tests for the grains state
- """
- from __future__ import absolute_import, print_function, unicode_literals
- import contextlib
- # Import Python libs
- import os
- import salt.modules.grains as grainsmod
- import salt.states.grains as grains
- # Import salt libs
- import salt.utils.files
- import salt.utils.stringutils
- import salt.utils.yaml
- from salt.ext import six
- from tests.support.mixins import LoaderModuleMockMixin
- from tests.support.mock import MagicMock, patch
- # Import Salt Testing libs
- from tests.support.runtests import RUNTIME_VARS
- from tests.support.unit import TestCase
- class GrainsTestCase(TestCase, LoaderModuleMockMixin):
- def setup_loader_modules(self):
- grains_test_dir = "__salt_test_state_grains"
- if not os.path.exists(os.path.join(RUNTIME_VARS.TMP, grains_test_dir)):
- os.makedirs(os.path.join(RUNTIME_VARS.TMP, grains_test_dir))
- loader_globals = {
- "__opts__": {
- "test": False,
- "conf_file": os.path.join(RUNTIME_VARS.TMP, grains_test_dir, "minion"),
- "cachedir": os.path.join(RUNTIME_VARS.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"], {})
- # 'make_hashable' function tests: 1
- def test_make_hashable(self):
- with self.setGrains({"cmplx_lst_grain": [{"a": "aval"}, {"foo": "bar"}]}):
- hashable_list = {"cmplx_lst_grain": [{"a": "aval"}, {"foo": "bar"}]}
- self.assertEqual(
- grains.make_hashable(grains.__grains__).issubset(
- grains.make_hashable(hashable_list)
- ),
- True,
- )
- # '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")
|