Merge remote-tracking branch 'saltstack/3006.x' into merge-forward

This commit is contained in:
Daniel A. Wozniak 2023-12-16 15:35:16 -07:00
commit 412178e48a
10 changed files with 1044 additions and 959 deletions

View file

@ -163,13 +163,16 @@ def renderer(path=None, string=None, default_renderer="jinja|yaml", **kwargs):
if not path and not string:
raise salt.exceptions.SaltInvocationError("Must pass either path or string")
if path and string:
raise salt.exceptions.SaltInvocationError("Must not pass both path and string")
renderers = salt.loader.render(__opts__, __salt__)
if path:
path_or_string = __salt__["cp.get_url"](
path, saltenv=kwargs.get("saltenv", "base")
)
elif string:
if string:
path_or_string = ":string:"
kwargs["input_data"] = string

View file

@ -55,7 +55,7 @@ def test_publish_retry(salt_master, salt_minion_retry, salt_cli, salt_run_cli):
@pytest.mark.slow_test
def test_pillar_timeout(salt_master_factory):
cmd = """
python -c "import time; time.sleep(2.5); print('{\\"foo\\": \\"bar\\"}');\"
python -c "import time; time.sleep(3.0); print('{\\"foo\\": \\"bar\\"}');\"
""".strip()
master_overrides = {
"ext_pillar": [

View file

@ -256,6 +256,9 @@ def setup_redhat_family(
):
arch = os.environ.get("SALT_REPO_ARCH") or "x86_64"
if os_name == "photon":
os_version = f"{os_version}.0"
if repo_subpath == "minor":
repo_url_base = (
f"{root_url}/{os_name}/{os_version}/{arch}/{repo_subpath}/{salt_release}"

View file

@ -1,4 +1,5 @@
import asyncio
import os
import pytest
@ -24,6 +25,7 @@ def minion_opts(tmp_path):
dirpath.mkdir(parents=True)
opts[name] = str(dirpath)
opts["log_file"] = "logs/minion.log"
opts["conf_file"] = os.path.join(opts["conf_dir"], "minion")
return opts
@ -41,6 +43,7 @@ def master_opts(tmp_path):
dirpath.mkdir(parents=True)
opts[name] = str(dirpath)
opts["log_file"] = "logs/master.log"
opts["conf_file"] = os.path.join(opts["conf_dir"], "master")
return opts
@ -59,6 +62,7 @@ def syndic_opts(tmp_path):
dirpath.mkdir(parents=True)
opts[name] = str(dirpath)
opts["log_file"] = "logs/syndic.log"
opts["conf_file"] = os.path.join(opts["conf_dir"], "syndic")
return opts

View file

@ -1,18 +1,20 @@
import logging
from io import StringIO
import pytest
import salt.exceptions
import salt.modules.slsutil as slsutil
from tests.support.mock import MagicMock
from tests.support.mock import MagicMock, patch
log = logging.getLogger(__name__)
@pytest.fixture
def configure_loader_modules(master_dirs, master_files):
def configure_loader_modules(master_dirs, master_files, minion_opts):
return {
slsutil: {
"__opts__": minion_opts,
"__salt__": {
"cp.list_master": MagicMock(return_value=master_files),
"cp.list_master_dirs": MagicMock(return_value=master_dirs),
@ -47,6 +49,21 @@ def test_banner():
check_banner(commentchar="//", borderchar="-")
check_banner(title="title here", text="text here")
check_banner(commentchar=" *")
check_banner(commentchar=" *", newline=False)
# Test when width result in a raised exception
with pytest.raises(salt.exceptions.ArgumentValueError):
slsutil.banner(width=4)
ret = slsutil.banner(
title="title here", text="text here", blockstart="/*", blockend="*/"
)
lines = ret.splitlines()
# test blockstart
assert lines[0] == "/*"
# test blockend
assert lines[-1] == "*/"
def check_banner(
@ -125,3 +142,159 @@ def test_findup():
with pytest.raises(salt.exceptions.CommandExecutionError):
slsutil.findup("red", "default.conf")
with pytest.raises(salt.exceptions.SaltInvocationError):
with patch.object(slsutil, "path_exists", return_value=False):
slsutil.findup("red", "default.conf")
with pytest.raises(salt.exceptions.SaltInvocationError):
slsutil.findup("red", {"file": "default.conf"})
def test_update():
"""
Test update function
"""
ret = slsutil.update({"foo": "Foo"}, {"bar": "Bar"})
assert ret == {"foo": "Foo", "bar": "Bar"}
ret = slsutil.update({"foo": "Foo"}, {"foo": "Bar"}, merge_lists=False)
assert ret == {"foo": "Bar"}
def test_merge():
"""
Test merge function
"""
ret = slsutil.merge({"foo": "Foo"}, {"bar": "Bar"}, strategy="smart")
assert ret == {"foo": "Foo", "bar": "Bar"}
ret = slsutil.merge({"foo": "Foo"}, {"foo": "Bar"}, strategy="aggregate")
assert ret == {"foo": "Bar"}
ret = slsutil.merge({"foo": "Foo"}, {"foo": "Bar"}, strategy="list")
assert ret == {"foo": ["Foo", "Bar"]}
ret = slsutil.merge({"foo": "Foo"}, {"foo": "Bar"}, strategy="overwrite")
assert ret == {"foo": "Bar"}
ret = slsutil.merge(
{"foo": {"Foo": "Bar"}}, {"foo": {"Foo": "Baz"}}, strategy="recurse"
)
assert ret == {"foo": {"Foo": "Baz"}}
def test_merge_all():
"""
Test merge_all function
"""
ret = slsutil.merge_all([{"foo": "Foo"}, {"bar": "Bar"}], strategy="smart")
assert ret == {"foo": "Foo", "bar": "Bar"}
ret = slsutil.merge_all([{"foo": "Foo"}, {"foo": "Bar"}], strategy="aggregate")
assert ret == {"foo": "Bar"}
ret = slsutil.merge_all([{"foo": "Foo"}, {"foo": "Bar"}], strategy="overwrite")
assert ret == {"foo": "Bar"}
ret = slsutil.merge_all(
[{"foo": {"Foo": "Bar"}}, {"foo": {"Foo": "Baz"}}], strategy="recurse"
)
assert ret == {"foo": {"Foo": "Baz"}}
def test_renderer():
"""
Test renderer function
"""
with patch.dict(
slsutil.__utils__, {"stringio.is_readable": MagicMock(return_value=False)}
):
ret = slsutil.renderer(string="Hello, {{ name }}.", name="world")
assert ret == "Hello, world."
with pytest.raises(salt.exceptions.SaltInvocationError) as exc:
slsutil.renderer()
assert str(exc.value) == "Must pass path or string."
with pytest.raises(salt.exceptions.SaltInvocationError) as exc:
slsutil.renderer(path="/path/to/file", string="Hello world")
assert str(exc.value) == "Must not pass both path and string."
with patch.dict(
slsutil.__salt__, {"cp.get_url": MagicMock(return_value="/path/to/file")}
):
with patch.dict(
slsutil.__utils__, {"stringio.is_readable": MagicMock(return_value=True)}
):
rendered_file = "Hello, world."
with patch(
"salt.template.compile_template",
MagicMock(return_value=StringIO(rendered_file)),
):
ret = slsutil.renderer(path="/path/to/file")
assert ret == "Hello, world."
def test_serialize():
"""
Test serialize function
"""
ret = slsutil.serialize("json", obj={"foo": "Foo!"})
assert ret == '{"foo": "Foo!"}'
def test_deserialize():
"""
Test serialize function
"""
ret = slsutil.deserialize("json", '{"foo": "Foo!"}')
assert ret == {"foo": "Foo!"}
def dummy_function(args=None, kwargs=None):
return True
def test__set_context():
"""
Test _set_context
"""
with patch.dict(slsutil.__context__, {}):
slsutil._set_context(
["level_one", "level_two", "level_three"], dummy_function, force=True
)
assert slsutil.__context__ == {
"level_one": {"level_two": {"level_three": True}}
}
with patch.dict(slsutil.__context__, {}):
slsutil._set_context(
["level_one", "level_two", "level_three"],
dummy_function,
fun_kwargs={"key_one": "arg_one"},
force=True,
)
assert slsutil.__context__ == {
"level_one": {"level_two": {"level_three": True}}
}
def test__get_serializer_fn():
"""
Test _set_context
"""
# Invalid serializer
with pytest.raises(salt.exceptions.CommandExecutionError) as exc:
slsutil._get_serialize_fn("bad_yaml", "badfunc")
assert str(exc.value) == "Serializer 'bad_yaml' not found."
# Invalid serializer function
with pytest.raises(salt.exceptions.CommandExecutionError) as exc:
slsutil._get_serialize_fn("yaml", "foobar")
assert str(exc.value) == "Serializer 'yaml' does not implement foobar."

View file

@ -0,0 +1,58 @@
"""
Tests cases for salt.modules.tomcat
"""
import io
import urllib.request
import pytest
import salt.modules.tomcat as tomcat
from tests.support.mock import MagicMock, patch
@pytest.fixture
def configure_loader_modules():
return {tomcat: {}}
def test_tomcat_wget_no_bytestring():
responses = {
"string": io.StringIO("Best response ever\r\nAnd you know it!"),
"bytes": io.BytesIO(b"Best response ever\r\nAnd you know it!"),
}
string_mock = MagicMock(return_value=responses["string"])
bytes_mock = MagicMock(return_value=responses["bytes"])
with patch(
"salt.modules.tomcat._auth",
MagicMock(
return_value=urllib.request.build_opener(
urllib.request.HTTPBasicAuthHandler(),
urllib.request.HTTPDigestAuthHandler(),
)
),
):
with patch("urllib.request.urlopen", string_mock):
response = tomcat._wget("tomcat.wait", url="http://localhost:8080/nofail")
for line in response["msg"]:
assert isinstance(line, str)
with patch("urllib.request.urlopen", bytes_mock):
try:
response = tomcat._wget(
"tomcat.wait", url="http://localhost:8080/nofail"
)
except TypeError as type_error:
if (
type_error.args[0]
== "startswith first arg must be bytes or a tuple of bytes,"
" not str"
):
print("Got back a byte string, should've been a string")
else:
raise type_error
for line in response["msg"]:
assert isinstance(line, str)

View file

@ -0,0 +1,796 @@
"""
unit tests for the grains state
"""
import contextlib
import os
import pytest
import salt.modules.grains as grainsmod
import salt.states.grains as grains
import salt.utils.files
import salt.utils.stringutils
import salt.utils.yaml
from tests.support.mock import MagicMock, patch
@pytest.fixture
def configure_loader_modules(minion_opts):
minion_opts["local"] = True
minion_opts["test"] = False
loader_globals = {
"__opts__": minion_opts,
"__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 assert_grain_file_content(grains_string):
grains_file = os.path.join(grains.__opts__["conf_dir"], "grains")
with salt.utils.files.fopen(grains_file, "r") as grf:
grains_data = salt.utils.stringutils.to_unicode(grf.read())
assert grains_string == grains_data
@contextlib.contextmanager
def set_grains(grains_data):
with patch.dict(grains.__grains__, grains_data):
with patch.dict(grainsmod.__grains__, grains_data):
grains_file = os.path.join(grains.__opts__["conf_dir"], "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():
with set_grains({"a": "aval"}):
ret = grains.exists(name="foo")
assert ret["result"] is False
assert ret["comment"] == "Grain does not exist"
assert ret["changes"] == {}
def test_exists_found():
with set_grains({"a": "aval", "foo": "bar"}):
# Grain already set
ret = grains.exists(name="foo")
assert ret["result"] is True
assert ret["comment"] == "Grain exists"
assert ret["changes"] == {}
# 'make_hashable' function tests: 1
def test_make_hashable():
with set_grains({"cmplx_lst_grain": [{"a": "aval"}, {"foo": "bar"}]}):
hashable_list = {"cmplx_lst_grain": [{"a": "aval"}, {"foo": "bar"}]}
assert grains.make_hashable(grains.__grains__).issubset(
grains.make_hashable(hashable_list)
)
# 'present' function tests: 12
def test_present_add():
# Set a non existing grain
with set_grains({"a": "aval"}):
ret = grains.present(name="foo", value="bar")
assert ret["result"] is True
assert ret["changes"] == {"foo": "bar"}
assert grains.__grains__ == {"a": "aval", "foo": "bar"}
assert_grain_file_content("a: aval\nfoo: bar\n")
# Set a non existing nested grain
with set_grains({"a": "aval"}):
ret = grains.present(name="foo:is:nested", value="bar")
assert ret["result"] is True
assert ret["changes"] == {"foo": {"is": {"nested": "bar"}}}
assert grains.__grains__ == {"a": "aval", "foo": {"is": {"nested": "bar"}}}
assert_grain_file_content("a: aval\nfoo:\n is:\n nested: bar\n")
# Set a non existing nested dict grain
with set_grains({"a": "aval"}):
ret = grains.present(name="foo:is:nested", value={"bar": "is a dict"})
assert ret["result"] is True
assert ret["changes"] == {"foo": {"is": {"nested": {"bar": "is a dict"}}}}
assert grains.__grains__ == {
"a": "aval",
"foo": {"is": {"nested": {"bar": "is a dict"}}},
}
assert_grain_file_content(
"a: aval\nfoo:\n is:\n nested:\n bar: is a dict\n"
)
def test_present_add_key_to_existing():
with set_grains({"a": "aval", "foo": {"k1": "v1"}}):
# Fails setting a grain to a dict
ret = grains.present(name="foo:k2", value="v2")
assert ret["result"] is True
assert ret["comment"] == "Set grain foo:k2 to v2"
assert ret["changes"] == {"foo": {"k2": "v2", "k1": "v1"}}
assert grains.__grains__ == {"a": "aval", "foo": {"k1": "v1", "k2": "v2"}}
assert_grain_file_content("a: aval\nfoo:\n k1: v1\n k2: v2\n")
def test_present_already_set():
with set_grains({"a": "aval", "foo": "bar"}):
# Grain already set
ret = grains.present(name="foo", value="bar")
assert ret["result"] is True
assert ret["comment"] == "Grain is already set"
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval", "foo": "bar"}
with set_grains({"a": "aval", "foo": {"is": {"nested": "bar"}}}):
# Nested grain already set
ret = grains.present(name="foo:is:nested", value="bar")
assert ret["result"] is True
assert ret["comment"] == "Grain is already set"
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval", "foo": {"is": {"nested": "bar"}}}
with set_grains({"a": "aval", "foo": {"is": {"nested": "bar"}}}):
# Nested dict grain already set
ret = grains.present(name="foo:is", value={"nested": "bar"})
assert ret["result"] is True
assert ret["comment"] == "Grain is already set"
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval", "foo": {"is": {"nested": "bar"}}}
def test_present_overwrite():
with set_grains({"a": "aval", "foo": "bar"}):
# Overwrite an existing grain
ret = grains.present(name="foo", value="newbar")
assert ret["result"] is True
assert ret["changes"] == {"foo": "newbar"}
assert grains.__grains__ == {"a": "aval", "foo": "newbar"}
assert_grain_file_content("a: aval\nfoo: newbar\n")
with set_grains({"a": "aval", "foo": "bar"}):
# Clear a grain (set to None)
ret = grains.present(name="foo", value=None)
assert ret["result"] is True
assert ret["changes"] == {"foo": None}
assert grains.__grains__ == {"a": "aval", "foo": None}
assert_grain_file_content("a: aval\nfoo: null\n")
with set_grains({"a": "aval", "foo": {"is": {"nested": "bar"}}}):
# Overwrite an existing nested grain
ret = grains.present(name="foo:is:nested", value="newbar")
assert ret["result"] is True
assert ret["changes"] == {"foo": {"is": {"nested": "newbar"}}}
assert grains.__grains__ == {"a": "aval", "foo": {"is": {"nested": "newbar"}}}
assert_grain_file_content("a: aval\nfoo:\n is:\n nested: newbar\n")
with set_grains({"a": "aval", "foo": {"is": {"nested": "bar"}}}):
# Clear a nested grain (set to None)
ret = grains.present(name="foo:is:nested", value=None)
assert ret["result"] is True
assert ret["changes"] == {"foo": {"is": {"nested": None}}}
assert grains.__grains__ == {"a": "aval", "foo": {"is": {"nested": None}}}
assert_grain_file_content("a: aval\nfoo:\n is:\n nested: null\n")
def test_present_fail_overwrite():
with set_grains({"a": "aval", "foo": {"is": {"nested": "val"}}}):
# Overwrite an existing grain
ret = grains.present(name="foo:is", value="newbar")
assert ret["result"] is False
assert ret["changes"] == {}
assert (
ret["comment"]
== "The key 'foo:is' exists but is a dict or a list. Use 'force=True' to overwrite."
)
assert grains.__grains__ == {"a": "aval", "foo": {"is": {"nested": "val"}}}
with set_grains({"a": "aval", "foo": {"is": {"nested": "val"}}}):
# Clear a grain (set to None)
ret = grains.present(name="foo:is", value=None)
assert ret["result"] is False
assert ret["changes"] == {}
assert (
ret["comment"]
== "The key 'foo:is' exists but is a dict or a list. Use 'force=True' to overwrite."
)
assert grains.__grains__ == {"a": "aval", "foo": {"is": {"nested": "val"}}}
def test_present_fails_to_set_dict_or_list():
with set_grains({"a": "aval", "foo": "bar"}):
# Fails to overwrite a grain to a list
ret = grains.present(name="foo", value=["l1", "l2"])
assert ret["result"] is False
assert (
ret["comment"]
== "The key 'foo' exists and the given value is a dict or a list. Use 'force=True' to overwrite."
)
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval", "foo": "bar"}
with set_grains({"a": "aval", "foo": "bar"}):
# Fails setting a grain to a dict
ret = grains.present(name="foo", value={"k1": "v1"})
assert ret["result"] is False
assert (
ret["comment"]
== "The key 'foo' exists and the given value is a dict or a list. Use 'force=True' to overwrite."
)
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval", "foo": "bar"}
with set_grains({"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=",")
assert ret["result"] is False
assert ret["changes"] == {}
assert (
ret["comment"]
== "The key 'foo:is:nested' exists and the given value is a dict or a list. Use 'force=True' to overwrite."
)
assert grains.__grains__ == {"a": "aval", "foo": {"is": {"nested": "bar"}}}
with set_grains({"a": "aval", "foo": {"is": {"nested": "bar"}}}):
# Fails setting a nested grain to a dict
ret = grains.present(name="foo:is:nested", value={"k1": "v1"})
assert ret["result"] is False
assert (
ret["comment"]
== "The key 'foo:is:nested' exists and the given value is a dict or a list. Use 'force=True' to overwrite."
)
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval", "foo": {"is": {"nested": "bar"}}}
def test_present_fail_merge_dict():
with set_grains({"a": "aval", "foo": {"k1": "v1"}}):
# Fails setting a grain to a dict
ret = grains.present(name="foo", value={"k2": "v2"})
assert ret["result"] is False
assert (
ret["comment"]
== "The key 'foo' exists but is a dict or a list. Use 'force=True' to overwrite."
)
assert grains.__grains__ == {"a": "aval", "foo": {"k1": "v1"}}
assert_grain_file_content("a: aval\nfoo:\n k1: v1\n")
def test_present_force_to_set_dict_or_list():
with set_grains({"a": "aval", "foo": "bar"}):
# Force to overwrite a grain to a list
ret = grains.present(name="foo", value=["l1", "l2"], force=True)
assert ret["result"] is True
assert ret["comment"] == "Set grain foo to ['l1', 'l2']"
assert ret["changes"] == {"foo": ["l1", "l2"]}
assert grains.__grains__ == {"a": "aval", "foo": ["l1", "l2"]}
assert_grain_file_content("a: aval\nfoo:\n- l1\n- l2\n")
with set_grains({"a": "aval", "foo": "bar"}):
# Force setting a grain to a dict
ret = grains.present(name="foo", value={"k1": "v1"}, force=True)
assert ret["result"] is True
assert ret["comment"] == "Set grain foo to {'k1': 'v1'}"
assert ret["changes"] == {"foo": {"k1": "v1"}}
assert grains.__grains__ == {"a": "aval", "foo": {"k1": "v1"}}
assert_grain_file_content("a: aval\nfoo:\n k1: v1\n")
with set_grains({"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
)
assert ret["result"] is True
assert ret["changes"] == {"foo": {"is": {"nested": ["l1", "l2"]}}}
assert ret["comment"] == "Set grain foo:is:nested to ['l1', 'l2']"
assert grains.__grains__ == {
"a": "aval",
"foo": {"is": {"nested": ["l1", "l2"]}},
}
assert_grain_file_content(
"a: aval\nfoo:\n is:\n nested:\n - l1\n - l2\n"
)
with set_grains({"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)
assert ret["result"] is True
assert ret["comment"] == "Set grain foo:is:nested to {'k1': 'v1'}"
assert ret["changes"] == {
"foo": {"is": {"nested": {"k1": "v1"}}, "and": "other"}
}
assert grains.__grains__ == {
"a": "aval",
"foo": {"is": {"nested": {"k1": "v1"}}, "and": "other"},
}
assert_grain_file_content(
"a: aval\nfoo:\n and: other\n is:\n nested:\n k1: v1\n"
)
def test_present_fails_to_convert_value_to_key():
with set_grains({"a": "aval", "foo": "bar"}):
# Fails converting a value to a nested grain key
ret = grains.present(name="foo:is:nested", value={"k1": "v1"})
assert ret["result"] is False
assert (
ret["comment"]
== "The key 'foo' value is 'bar', which is different from the provided key 'is'. Use 'force=True' to overwrite."
)
assert ret["changes"] == {}
def test_present_overwrite_test():
with patch.dict(grains.__opts__, {"test": True}):
with set_grains({"a": "aval", "foo": "bar"}):
# Overwrite an existing grain
ret = grains.present(name="foo", value="newbar")
assert ret["result"] is None
assert ret["changes"] == {"changed": {"foo": "newbar"}}
assert grains.__grains__ == {"a": "aval", "foo": "bar"}
assert_grain_file_content("a: aval\nfoo: bar\n")
def test_present_convert_value_to_key():
with set_grains({"a": "aval", "foo": "is"}):
# Converts a value to a nested grain key
ret = grains.present(name="foo:is:nested", value={"k1": "v1"})
assert ret["result"] is True
assert ret["comment"] == "Set grain foo:is:nested to {'k1': 'v1'}"
assert ret["changes"] == {"foo": {"is": {"nested": {"k1": "v1"}}}}
assert grains.__grains__ == {
"a": "aval",
"foo": {"is": {"nested": {"k1": "v1"}}},
}
assert_grain_file_content("a: aval\nfoo:\n is:\n nested:\n k1: v1\n")
with set_grains({"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"})
assert ret["result"] is True
assert ret["comment"] == "Set grain foo:is:nested to {'k1': 'v1'}"
assert ret["changes"] == {
"foo": ["one", {"is": {"nested": {"k1": "v1"}}}, "correct"]
}
assert grains.__grains__ == {
"a": "aval",
"foo": ["one", {"is": {"nested": {"k1": "v1"}}}, "correct"],
}
assert_grain_file_content(
"a: aval\nfoo:\n- one\n- is:\n nested:\n k1: v1\n- correct\n"
)
def test_present_unknown_failure():
with patch("salt.modules.grains.setval") as mocked_setval:
mocked_setval.return_value = "Failed to set grain foo"
with set_grains({"a": "aval", "foo": "bar"}):
# Unknown reason failure
ret = grains.present(name="foo", value="baz")
assert ret["result"] is False
assert ret["comment"] == "Failed to set grain foo"
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval", "foo": "bar"}
assert_grain_file_content("a: aval\nfoo: bar\n")
# 'absent' function tests: 6
def test_absent_already():
# Unset a non existent grain
with set_grains({"a": "aval"}):
ret = grains.absent(name="foo")
assert ret["result"] is True
assert ret["comment"] == "Grain foo does not exist"
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval"}
assert_grain_file_content("a: aval\n")
# Unset a non existent nested grain
with set_grains({"a": "aval"}):
ret = grains.absent(name="foo:is:nested")
assert ret["result"] is True
assert ret["comment"] == "Grain foo:is:nested does not exist"
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval"}
assert_grain_file_content("a: aval\n")
def test_absent_unset():
# Unset a grain
with set_grains({"a": "aval", "foo": "bar"}):
ret = grains.absent(name="foo")
assert ret["result"] is True
assert ret["comment"] == "Value for grain foo was set to None"
assert ret["changes"] == {"grain": "foo", "value": None}
assert grains.__grains__ == {"a": "aval", "foo": None}
assert_grain_file_content("a: aval\nfoo: null\n")
# Unset grain when its value is False
with set_grains({"a": "aval", "foo": False}):
ret = grains.absent(name="foo")
assert ret["result"] is True
assert ret["comment"] == "Value for grain foo was set to None"
assert ret["changes"] == {"grain": "foo", "value": None}
assert grains.__grains__ == {"a": "aval", "foo": None}
assert_grain_file_content("a: aval\nfoo: null\n")
# Unset a nested grain
with set_grains(
{"a": "aval", "foo": ["order", {"is": {"nested": "bar"}}, "correct"]}
):
ret = grains.absent(name="foo,is,nested", delimiter=",")
assert ret["result"] is True
assert ret["comment"] == "Value for grain foo:is:nested was set to None"
assert ret["changes"] == {"grain": "foo:is:nested", "value": None}
assert grains.__grains__ == {
"a": "aval",
"foo": ["order", {"is": {"nested": None}}, "correct"],
}
assert_grain_file_content(
"a: aval\nfoo:\n- order\n- is:\n nested: null\n- correct\n"
)
# Unset a nested value don't change anything
with set_grains({"a": "aval", "foo": ["order", {"is": "nested"}, "correct"]}):
ret = grains.absent(name="foo:is:nested")
assert ret["result"] is True
assert ret["comment"] == "Grain foo:is:nested does not exist"
assert ret["changes"] == {}
assert grains.__grains__ == {
"a": "aval",
"foo": ["order", {"is": "nested"}, "correct"],
}
assert_grain_file_content("a: aval\nfoo:\n- order\n- is: nested\n- correct\n")
def test_absent_unset_test():
with patch.dict(grains.__opts__, {"test": True}):
with set_grains({"a": "aval", "foo": "bar"}):
# Overwrite an existing grain
ret = grains.absent(name="foo")
assert ret["result"] is None
assert ret["changes"] == {"grain": "foo", "value": None}
assert grains.__grains__ == {"a": "aval", "foo": "bar"}
assert_grain_file_content("a: aval\nfoo: bar\n")
def test_absent_fails_nested_complex_grain():
# Unset a nested complex grain
with set_grains(
{"a": "aval", "foo": ["order", {"is": {"nested": "bar"}}, "correct"]}
):
ret = grains.absent(name="foo:is")
assert ret["result"] is False
assert (
ret["comment"]
== "The key 'foo:is' exists but is a dict or a list. Use 'force=True' to overwrite."
)
assert ret["changes"] == {}
assert grains.__grains__ == {
"a": "aval",
"foo": ["order", {"is": {"nested": "bar"}}, "correct"],
}
assert_grain_file_content(
"a: aval\nfoo:\n- order\n- is:\n nested: bar\n- correct\n"
)
def test_absent_force_nested_complex_grain():
# Unset a nested complex grain
with set_grains(
{"a": "aval", "foo": ["order", {"is": {"nested": "bar"}}, "correct"]}
):
ret = grains.absent(name="foo:is", force=True)
assert ret["result"] is True
assert ret["comment"] == "Value for grain foo:is was set to None"
assert ret["changes"] == {"grain": "foo:is", "value": None}
assert grains.__grains__ == {
"a": "aval",
"foo": ["order", {"is": None}, "correct"],
}
assert_grain_file_content("a: aval\nfoo:\n- order\n- is: null\n- correct\n")
def test_absent_delete():
# Delete a grain
with set_grains({"a": "aval", "foo": "bar"}):
ret = grains.absent(name="foo", destructive=True)
assert ret["result"] is True
assert ret["comment"] == "Grain foo was deleted"
assert ret["changes"] == {"deleted": "foo"}
assert grains.__grains__ == {"a": "aval"}
assert_grain_file_content("a: aval\n")
# Delete a previously unset grain
with set_grains({"a": "aval", "foo": None}):
ret = grains.absent(name="foo", destructive=True)
assert ret["result"] is True
assert ret["comment"] == "Grain foo was deleted"
assert ret["changes"] == {"deleted": "foo"}
assert grains.__grains__ == {"a": "aval"}
assert_grain_file_content("a: aval\n")
# Delete a nested grain
with set_grains(
{
"a": "aval",
"foo": [
"order",
{"is": {"nested": "bar", "other": "value"}},
"correct",
],
}
):
ret = grains.absent(name="foo:is:nested", destructive=True)
assert ret["result"] is True
assert ret["comment"] == "Grain foo:is:nested was deleted"
assert ret["changes"] == {"deleted": "foo:is:nested"}
assert grains.__grains__ == {
"a": "aval",
"foo": ["order", {"is": {"other": "value"}}, "correct"],
}
assert_grain_file_content(
"a: aval\nfoo:\n- order\n- is:\n other: value\n- correct\n"
)
# 'append' function tests: 6
def test_append():
# Append to an existing list
with set_grains({"a": "aval", "foo": ["bar"]}):
ret = grains.append(name="foo", value="baz")
assert ret["result"] is True
assert ret["comment"] == "Value baz was added to grain foo"
assert ret["changes"] == {"added": "baz"}
assert grains.__grains__ == {"a": "aval", "foo": ["bar", "baz"]}
assert_grain_file_content("a: aval\nfoo:\n- bar\n- baz\n")
def test_append_nested():
# Append to an existing nested list
with set_grains({"a": "aval", "foo": {"list": ["bar"]}}):
ret = grains.append(name="foo,list", value="baz", delimiter=",")
assert ret["result"] is True
assert ret["comment"] == "Value baz was added to grain foo:list"
assert ret["changes"] == {"added": "baz"}
assert grains.__grains__ == {"a": "aval", "foo": {"list": ["bar", "baz"]}}
assert_grain_file_content("a: aval\nfoo:\n list:\n - bar\n - baz\n")
def test_append_already():
# Append to an existing list
with set_grains({"a": "aval", "foo": ["bar"]}):
ret = grains.append(name="foo", value="bar")
assert ret["result"] is True
assert ret["comment"] == "Value bar is already in the list " + "for grain foo"
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval", "foo": ["bar"]}
assert_grain_file_content("a: aval\nfoo:\n- bar\n")
def test_append_fails_not_a_list():
# Fail to append to an existing grain, not a list
with set_grains({"a": "aval", "foo": {"bar": "val"}}):
ret = grains.append(name="foo", value="baz")
assert ret["result"] is False
assert ret["comment"] == "Grain foo is not a valid list"
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval", "foo": {"bar": "val"}}
def test_append_convert_to_list():
# Append to an existing grain, converting to a list
with set_grains({"a": "aval", "foo": {"bar": "val"}}):
assert_grain_file_content("a: aval\nfoo:\n bar: val\n")
ret = grains.append(name="foo", value="baz", convert=True)
assert ret["result"] is True
assert ret["comment"] == "Value baz was added to grain foo"
assert ret["changes"] == {"added": "baz"}
assert grains.__grains__ == {"a": "aval", "foo": [{"bar": "val"}, "baz"]}
assert_grain_file_content("a: aval\nfoo:\n- bar: val\n- baz\n")
# Append to an existing grain, converting to a list a multi-value dict
with set_grains({"a": "aval", "foo": {"bar": "val", "other": "value"}}):
assert_grain_file_content("a: aval\nfoo:\n bar: val\n other: value\n")
ret = grains.append(name="foo", value="baz", convert=True)
assert ret["result"] is True
assert ret["comment"] == "Value baz was added to grain foo"
assert ret["changes"] == {"added": "baz"}
assert grains.__grains__ == {
"a": "aval",
"foo": [{"bar": "val", "other": "value"}, "baz"],
}
assert_grain_file_content("a: aval\nfoo:\n- bar: val\n other: value\n- baz\n")
def test_append_fails_inexistent():
# Append to a non existing grain
with set_grains({"a": "aval"}):
ret = grains.append(name="foo", value="bar")
assert ret["result"] is False
assert ret["comment"] == "Grain foo does not exist"
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval"}
def test_append_convert_to_list_empty():
# Append to an existing list
with set_grains({"foo": None}):
ret = grains.append(name="foo", value="baz", convert=True)
assert ret["result"] is True
assert ret["comment"] == "Value baz was added to grain foo"
assert ret["changes"] == {"added": "baz"}
assert grains.__grains__ == {"foo": ["baz"]}
assert_grain_file_content("foo:\n- baz\n")
# 'list_present' function tests: 7
def test_list_present():
with set_grains({"a": "aval", "foo": ["bar"]}):
ret = grains.list_present(name="foo", value="baz")
assert ret["result"] is True
assert ret["comment"] == "Append value baz to grain foo"
assert ret["changes"] == {"new": {"foo": ["bar", "baz"]}}
assert grains.__grains__ == {"a": "aval", "foo": ["bar", "baz"]}
assert_grain_file_content("a: aval\nfoo:\n- bar\n- baz\n")
def test_list_present_nested():
with set_grains({"a": "aval", "foo": {"is": {"nested": ["bar"]}}}):
ret = grains.list_present(name="foo,is,nested", value="baz", delimiter=",")
assert ret["result"] is True
assert ret["comment"] == "Append value baz to grain foo:is:nested"
assert ret["changes"] == {"new": {"foo": {"is": {"nested": ["bar", "baz"]}}}}
assert grains.__grains__ == {
"a": "aval",
"foo": {"is": {"nested": ["bar", "baz"]}},
}
assert_grain_file_content(
"a: aval\nfoo:\n is:\n nested:\n - bar\n - baz\n"
)
def test_list_present_inexistent():
with set_grains({"a": "aval"}):
ret = grains.list_present(name="foo", value="baz")
assert ret["result"] is True
assert ret["comment"] == "Append value baz to grain foo"
assert ret["changes"] == {"new": {"foo": ["baz"]}}
assert grains.__grains__ == {"a": "aval", "foo": ["baz"]}
assert_grain_file_content("a: aval\nfoo:\n- baz\n")
def test_list_present_inexistent_nested():
with set_grains({"a": "aval"}):
ret = grains.list_present(name="foo:is:nested", value="baz")
assert ret["result"] is True
assert ret["comment"] == "Append value baz to grain foo:is:nested"
assert ret["changes"] == {"new": {"foo": {"is": {"nested": ["baz"]}}}}
assert grains.__grains__ == {"a": "aval", "foo": {"is": {"nested": ["baz"]}}}
assert_grain_file_content("a: aval\nfoo:\n is:\n nested:\n - baz\n")
def test_list_present_not_a_list():
with set_grains({"a": "aval", "foo": "bar"}):
ret = grains.list_present(name="foo", value="baz")
assert ret["result"] is False
assert ret["comment"] == "Grain foo is not a valid list"
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval", "foo": "bar"}
assert_grain_file_content("a: aval\nfoo: bar\n")
def test_list_present_nested_already():
with set_grains({"a": "aval", "b": {"foo": ["bar"]}}):
ret = grains.list_present(name="b:foo", value="bar")
assert ret["result"] is True
assert ret["comment"] == "Value bar is already in grain b:foo"
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval", "b": {"foo": ["bar"]}}
assert_grain_file_content("a: aval\nb:\n foo:\n - bar\n")
def test_list_present_already():
with set_grains({"a": "aval", "foo": ["bar"]}):
ret = grains.list_present(name="foo", value="bar")
assert ret["result"] is True
assert ret["comment"] == "Value bar is already in grain foo"
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval", "foo": ["bar"]}
assert_grain_file_content("a: aval\nfoo:\n- bar\n")
def test_list_present_unknown_failure():
with set_grains({"a": "aval", "foo": ["bar"]}):
# Unknown reason failure
with patch.dict(grainsmod.__salt__, {"grains.append": MagicMock()}):
ret = grains.list_present(name="foo", value="baz")
assert ret["result"] is False
assert ret["comment"] == "Failed append value baz to grain foo"
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval", "foo": ["bar"]}
assert_grain_file_content("a: aval\nfoo:\n- bar\n")
# 'list_absent' function tests: 6
def test_list_absent():
with set_grains({"a": "aval", "foo": ["bar"]}):
ret = grains.list_absent(name="foo", value="bar")
assert ret["result"] is True
assert ret["comment"] == "Value bar was deleted from grain foo"
assert ret["changes"] == {"deleted": ["bar"]}
assert grains.__grains__ == {"a": "aval", "foo": []}
assert_grain_file_content("a: aval\nfoo: []\n")
def test_list_absent_nested():
with set_grains({"a": "aval", "foo": {"list": ["bar"]}}):
ret = grains.list_absent(name="foo:list", value="bar")
assert ret["result"] is True
assert ret["comment"] == "Value bar was deleted from grain foo:list"
assert ret["changes"] == {"deleted": ["bar"]}
assert grains.__grains__ == {"a": "aval", "foo": {"list": []}}
assert_grain_file_content("a: aval\nfoo:\n list: []\n")
def test_list_absent_inexistent():
with set_grains({"a": "aval"}):
ret = grains.list_absent(name="foo", value="baz")
assert ret["result"] is True
assert ret["comment"] == "Grain foo does not exist"
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval"}
assert_grain_file_content("a: aval\n")
def test_list_absent_inexistent_nested():
with set_grains({"a": "aval"}):
ret = grains.list_absent(name="foo:list", value="baz")
assert ret["result"] is True
assert ret["comment"] == "Grain foo:list does not exist"
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval"}
assert_grain_file_content("a: aval\n")
def test_list_absent_not_a_list():
with set_grains({"a": "aval", "foo": "bar"}):
ret = grains.list_absent(name="foo", value="bar")
assert ret["result"] is False
assert ret["comment"] == "Grain foo is not a valid list"
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval", "foo": "bar"}
assert_grain_file_content("a: aval\nfoo: bar\n")
def test_list_absent_already():
with set_grains({"a": "aval", "foo": ["bar"]}):
ret = grains.list_absent(name="foo", value="baz")
assert ret["result"] is True
assert ret["comment"] == "Value baz is absent from grain foo"
assert ret["changes"] == {}
assert grains.__grains__ == {"a": "aval", "foo": ["bar"]}
assert_grain_file_content("a: aval\nfoo:\n- bar\n")

View file

@ -1,58 +0,0 @@
import io
import urllib.request
import salt.modules.tomcat as tomcat
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.mock import MagicMock, patch
from tests.support.unit import TestCase
class TomcatTestCasse(TestCase, LoaderModuleMockMixin):
"""
Tests cases for salt.modules.tomcat
"""
def setup_loader_modules(self):
return {tomcat: {}}
def test_tomcat_wget_no_bytestring(self):
responses = {
"string": io.StringIO("Best response ever\r\nAnd you know it!"),
"bytes": io.BytesIO(b"Best response ever\r\nAnd you know it!"),
}
string_mock = MagicMock(return_value=responses["string"])
bytes_mock = MagicMock(return_value=responses["bytes"])
with patch(
"salt.modules.tomcat._auth",
MagicMock(
return_value=urllib.request.build_opener(
urllib.request.HTTPBasicAuthHandler(),
urllib.request.HTTPDigestAuthHandler(),
)
),
):
with patch("urllib.request.urlopen", string_mock):
response = tomcat._wget(
"tomcat.wait", url="http://localhost:8080/nofail"
)
for line in response["msg"]:
self.assertIsInstance(line, str)
with patch("urllib.request.urlopen", bytes_mock):
try:
response = tomcat._wget(
"tomcat.wait", url="http://localhost:8080/nofail"
)
except TypeError as type_error:
if (
type_error.args[0]
== "startswith first arg must be bytes or a tuple of bytes,"
" not str"
):
self.fail("Got back a byte string, should've been a string")
else:
raise type_error
for line in response["msg"]:
self.assertIsInstance(line, str)

View file

@ -1,897 +0,0 @@
"""
unit tests for the grains state
"""
import contextlib
import os
import salt.modules.grains as grainsmod
import salt.states.grains as grains
import salt.utils.files
import salt.utils.stringutils
import salt.utils.yaml
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.mock import MagicMock, patch
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\nfoo:\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']")
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'}")
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']")
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'}")
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'}")
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'}")
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")

View file

@ -380,6 +380,9 @@ def rpm(
assert incoming is not None
assert repo_path is not None
assert key_id is not None
if distro == "photon":
distro_version = f"{distro_version}.0"
display_name = f"{distro.capitalize()} {distro_version}"
if distro_version not in _rpm_distro_info[distro]:
ctx.error(f"Support for {display_name} is missing.")