migrate unit_states_test_kubernetes to pytest

This commit is contained in:
Frode Gundersen 2023-02-23 20:17:27 +00:00 committed by Megan Wilhite
parent 507fbf9de7
commit a5a26b8066
2 changed files with 811 additions and 897 deletions

View file

@ -0,0 +1,811 @@
"""
:codeauthor: :email:`Jeff Schroeder <jeffschroeder@computer.org>`
Test cases for salt.states.kubernetes
"""
import base64
from contextlib import contextmanager
import pytest
import salt.modules.kubernetesmod as kubernetesmod
import salt.states.kubernetes as kubernetes
import salt.utils.stringutils
from tests.support.mock import MagicMock, patch
pytestmark = [
pytest.mark.skipif(
kubernetesmod.HAS_LIBS is False,
reason="Kubernetes client lib is not installed. Skipping test_kubernetes.py",
)
]
@pytest.fixture
def configure_loader_modules():
return {kubernetes: {"__env__": "base"}}
@contextmanager
def mock_func(func_name, return_value, test=False):
"""
Mock any of the kubernetes state function return values and set
the test options.
"""
name = "kubernetes.{}".format(func_name)
mocked = {name: MagicMock(return_value=return_value)}
with patch.dict(kubernetes.__salt__, mocked) as patched:
with patch.dict(kubernetes.__opts__, {"test": test}):
yield patched
def make_configmap(name, namespace="default", data=None):
return make_ret_dict(
kind="ConfigMap",
name=name,
namespace=namespace,
data=data,
)
def make_secret(name, namespace="default", data=None):
secret_data = make_ret_dict(
kind="Secret",
name=name,
namespace=namespace,
data=data,
)
# Base64 all of the values just like kubectl does
for key, value in secret_data["data"].items():
secret_data["data"][key] = base64.b64encode(
salt.utils.stringutils.to_bytes(value)
)
return secret_data
def make_node_labels(name="minikube"):
return {
"kubernetes.io/hostname": name,
"beta.kubernetes.io/os": "linux",
"beta.kubernetes.io/arch": "amd64",
"failure-domain.beta.kubernetes.io/region": "us-west-1",
}
def make_node(name="minikube"):
node_data = make_ret_dict(kind="Node", name="minikube")
node_data.update(
{
"api_version": "v1",
"kind": "Node",
"metadata": {
"annotations": {"node.alpha.kubernetes.io/ttl": "0"},
"labels": make_node_labels(name=name),
"name": name,
"namespace": None,
"link": "/api/v1/nodes/{name}".format(name=name),
"uid": "7811b8ae-c1a1-11e7-a55a-0800279fb61e",
},
"spec": {"external_id": name},
"status": {},
}
)
return node_data
def make_namespace(name="default"):
namespace_data = make_ret_dict(kind="Namespace", name=name)
del namespace_data["data"]
namespace_data.update(
{
"status": {"phase": "Active"},
"spec": {"finalizers": ["kubernetes"]},
"metadata": {
"name": name,
"namespace": None,
"labels": None,
"link": "/api/v1/namespaces/{namespace}".format(
namespace=name,
),
"annotations": None,
"uid": "752fceeb-c1a1-11e7-a55a-0800279fb61e",
},
}
)
return namespace_data
def make_ret_dict(kind, name, namespace=None, data=None):
"""
Make a minimal example configmap or secret for using in mocks
"""
assert kind in ("Secret", "ConfigMap", "Namespace", "Node")
if data is None:
data = {}
link = "/api/v1/namespaces/{namespace}/{kind}s/{name}".format(
namespace=namespace,
kind=kind.lower(),
name=name,
)
return_data = {
"kind": kind,
"data": data,
"api_version": "v1",
"metadata": {
"name": name,
"labels": None,
"namespace": namespace,
"link": link,
"annotations": {"kubernetes.io/change-cause": "salt-call state.apply"},
},
}
return return_data
def test_configmap_present__fail():
error = kubernetes.configmap_present(
name="testme",
data={1: 1},
source="salt://beyond/oblivion.jinja",
)
assert {
"changes": {},
"result": False,
"name": "testme",
"comment": "'source' cannot be used in combination with 'data'",
} == error
def test_configmap_present__create_test_true():
# Create a new configmap with test=True
with mock_func("show_configmap", return_value=None, test=True):
ret = kubernetes.configmap_present(
name="example",
data={"example.conf": "# empty config file"},
)
assert {
"comment": "The configmap is going to be created",
"changes": {},
"name": "example",
"result": None,
} == ret
def test_configmap_present__create():
# Create a new configmap
with mock_func("show_configmap", return_value=None):
cm = make_configmap(
name="test",
namespace="default",
data={"foo": "bar"},
)
with mock_func("create_configmap", return_value=cm):
actual = kubernetes.configmap_present(
name="test",
data={"foo": "bar"},
)
assert {
"comment": "",
"changes": {"data": {"foo": "bar"}},
"name": "test",
"result": True,
} == actual
def test_configmap_present__create_no_data():
# Create a new configmap with no 'data' attribute
with mock_func("show_configmap", return_value=None):
cm = make_configmap(
name="test",
namespace="default",
)
with mock_func("create_configmap", return_value=cm):
actual = kubernetes.configmap_present(name="test")
assert {
"comment": "",
"changes": {"data": {}},
"name": "test",
"result": True,
} == actual
def test_configmap_present__replace_test_true():
cm = make_configmap(
name="settings",
namespace="saltstack",
data={"foobar.conf": "# Example configuration"},
)
with mock_func("show_configmap", return_value=cm, test=True):
ret = kubernetes.configmap_present(
name="settings",
namespace="saltstack",
data={"foobar.conf": "# Example configuration"},
)
assert {
"comment": "The configmap is going to be replaced",
"changes": {},
"name": "settings",
"result": None,
} == ret
def test_configmap_present__replace():
cm = make_configmap(name="settings", data={"action": "make=war"})
# Replace an existing configmap
with mock_func("show_configmap", return_value=cm):
new_cm = cm.copy()
new_cm.update({"data": {"action": "make=peace"}})
with mock_func("replace_configmap", return_value=new_cm):
actual = kubernetes.configmap_present(
name="settings",
data={"action": "make=peace"},
)
assert {
"comment": ("The configmap is already present. Forcing recreation"),
"changes": {"data": {"action": "make=peace"}},
"name": "settings",
"result": True,
} == actual
def test_configmap_absent__noop_test_true():
# Nothing to delete with test=True
with mock_func("show_configmap", return_value=None, test=True):
actual = kubernetes.configmap_absent(name="NOT_FOUND")
assert {
"comment": "The configmap does not exist",
"changes": {},
"name": "NOT_FOUND",
"result": None,
} == actual
def test_configmap_absent__test_true():
# Configmap exists with test=True
cm = make_configmap(name="deleteme", namespace="default")
with mock_func("show_configmap", return_value=cm, test=True):
actual = kubernetes.configmap_absent(name="deleteme")
assert {
"comment": "The configmap is going to be deleted",
"changes": {},
"name": "deleteme",
"result": None,
} == actual
def test_configmap_absent__noop():
# Nothing to delete
with mock_func("show_configmap", return_value=None):
actual = kubernetes.configmap_absent(name="NOT_FOUND")
assert {
"comment": "The configmap does not exist",
"changes": {},
"name": "NOT_FOUND",
"result": True,
} == actual
def test_configmap_absent():
# Configmap exists, delete it!
cm = make_configmap(name="deleteme", namespace="default")
with mock_func("show_configmap", return_value=cm):
# The return from this module isn't used in the state
with mock_func("delete_configmap", return_value={}):
actual = kubernetes.configmap_absent(name="deleteme")
assert {
"comment": "ConfigMap deleted",
"changes": {
"kubernetes.configmap": {
"new": "absent",
"old": "present",
},
},
"name": "deleteme",
"result": True,
} == actual
def test_secret_present__fail():
actual = kubernetes.secret_present(
name="sekret",
data={"password": "monk3y"},
source="salt://nope.jinja",
)
assert {
"changes": {},
"result": False,
"name": "sekret",
"comment": "'source' cannot be used in combination with 'data'",
} == actual
def test_secret_present__exists_test_true():
secret = make_secret(name="sekret")
new_secret = secret.copy()
new_secret.update({"data": {"password": "uncle"}})
# Secret exists already and needs replacing with test=True
with mock_func("show_secret", return_value=secret):
with mock_func("replace_secret", return_value=new_secret, test=True):
actual = kubernetes.secret_present(
name="sekret",
data={"password": "uncle"},
)
assert {
"changes": {},
"result": None,
"name": "sekret",
"comment": "The secret is going to be replaced",
} == actual
def test_secret_present__exists():
# Secret exists and gets replaced
secret = make_secret(name="sekret", data={"password": "booyah"})
with mock_func("show_secret", return_value=secret):
with mock_func("replace_secret", return_value=secret):
actual = kubernetes.secret_present(
name="sekret",
data={"password": "booyah"},
)
assert {
"changes": {"data": ["password"]},
"result": True,
"name": "sekret",
"comment": "The secret is already present. Forcing recreation",
} == actual
def test_secret_present__create():
# Secret exists and gets replaced
secret = make_secret(name="sekret", data={"password": "booyah"})
with mock_func("show_secret", return_value=None):
with mock_func("create_secret", return_value=secret):
actual = kubernetes.secret_present(
name="sekret",
data={"password": "booyah"},
)
assert {
"changes": {"data": ["password"]},
"result": True,
"name": "sekret",
"comment": "",
} == actual
def test_secret_present__create_no_data():
# Secret exists and gets replaced
secret = make_secret(name="sekret")
with mock_func("show_secret", return_value=None):
with mock_func("create_secret", return_value=secret):
actual = kubernetes.secret_present(name="sekret")
assert {
"changes": {"data": []},
"result": True,
"name": "sekret",
"comment": "",
} == actual
def test_secret_present__create_test_true():
# Secret exists and gets replaced with test=True
secret = make_secret(name="sekret")
with mock_func("show_secret", return_value=None):
with mock_func("create_secret", return_value=secret, test=True):
actual = kubernetes.secret_present(name="sekret")
assert {
"changes": {},
"result": None,
"name": "sekret",
"comment": "The secret is going to be created",
} == actual
def test_secret_absent__noop_test_true():
with mock_func("show_secret", return_value=None, test=True):
actual = kubernetes.secret_absent(name="sekret")
assert {
"changes": {},
"result": None,
"name": "sekret",
"comment": "The secret does not exist",
} == actual
def test_secret_absent__noop():
with mock_func("show_secret", return_value=None):
actual = kubernetes.secret_absent(name="passwords")
assert {
"changes": {},
"result": True,
"name": "passwords",
"comment": "The secret does not exist",
} == actual
def test_secret_absent__delete_test_true():
secret = make_secret(name="credentials", data={"redis": "letmein"})
with mock_func("show_secret", return_value=secret):
with mock_func("delete_secret", return_value=secret, test=True):
actual = kubernetes.secret_absent(name="credentials")
assert {
"changes": {},
"result": None,
"name": "credentials",
"comment": "The secret is going to be deleted",
} == actual
def test_secret_absent__delete():
secret = make_secret(name="foobar", data={"redis": "letmein"})
deleted = {
"status": None,
"kind": "Secret",
"code": None,
"reason": None,
"details": None,
"message": None,
"api_version": "v1",
"metadata": {
"link": "/api/v1/namespaces/default/secrets/foobar",
"resource_version": "30292",
},
}
with mock_func("show_secret", return_value=secret):
with mock_func("delete_secret", return_value=deleted):
actual = kubernetes.secret_absent(name="foobar")
assert {
"changes": {
"kubernetes.secret": {"new": "absent", "old": "present"},
},
"result": True,
"name": "foobar",
"comment": "Secret deleted",
} == actual
def test_node_label_present__add_test_true():
labels = make_node_labels()
with mock_func("node_labels", return_value=labels, test=True):
actual = kubernetes.node_label_present(
name="com.zoo-animal",
node="minikube",
value="monkey",
)
assert {
"changes": {},
"result": None,
"name": "com.zoo-animal",
"comment": "The label is going to be set",
} == actual
def test_node_label_present__add():
node_data = make_node()
# Remove some of the defaults to make it simpler
node_data["metadata"]["labels"] = {
"beta.kubernetes.io/os": "linux",
}
labels = node_data["metadata"]["labels"]
with mock_func("node_labels", return_value=labels):
with mock_func("node_add_label", return_value=node_data):
actual = kubernetes.node_label_present(
name="failure-domain.beta.kubernetes.io/zone",
node="minikube",
value="us-central1-a",
)
assert {
"comment": "",
"changes": {
"minikube.failure-domain.beta.kubernetes.io/zone": {
"new": {
"failure-domain.beta.kubernetes.io/zone": ("us-central1-a"),
"beta.kubernetes.io/os": "linux",
},
"old": {"beta.kubernetes.io/os": "linux"},
},
},
"name": "failure-domain.beta.kubernetes.io/zone",
"result": True,
} == actual
def test_node_label_present__already_set():
node_data = make_node()
labels = node_data["metadata"]["labels"]
with mock_func("node_labels", return_value=labels):
with mock_func("node_add_label", return_value=node_data):
actual = kubernetes.node_label_present(
name="failure-domain.beta.kubernetes.io/region",
node="minikube",
value="us-west-1",
)
assert {
"changes": {},
"result": True,
"name": "failure-domain.beta.kubernetes.io/region",
"comment": ("The label is already set and has the specified value"),
} == actual
def test_node_label_present__update_test_true():
node_data = make_node()
labels = node_data["metadata"]["labels"]
with mock_func("node_labels", return_value=labels):
with mock_func("node_add_label", return_value=node_data, test=True):
actual = kubernetes.node_label_present(
name="failure-domain.beta.kubernetes.io/region",
node="minikube",
value="us-east-1",
)
assert {
"changes": {},
"result": None,
"name": "failure-domain.beta.kubernetes.io/region",
"comment": "The label is going to be updated",
} == actual
def test_node_label_present__update():
node_data = make_node()
# Remove some of the defaults to make it simpler
node_data["metadata"]["labels"] = {
"failure-domain.beta.kubernetes.io/region": "us-west-1",
}
labels = node_data["metadata"]["labels"]
with mock_func("node_labels", return_value=labels):
with mock_func("node_add_label", return_value=node_data):
actual = kubernetes.node_label_present(
name="failure-domain.beta.kubernetes.io/region",
node="minikube",
value="us-east-1",
)
assert {
"changes": {
"minikube.failure-domain.beta.kubernetes.io/region": {
"new": {
"failure-domain.beta.kubernetes.io/region": ("us-east-1")
},
"old": {
"failure-domain.beta.kubernetes.io/region": ("us-west-1")
},
}
},
"result": True,
"name": "failure-domain.beta.kubernetes.io/region",
"comment": "The label is already set, changing the value",
} == actual
def test_node_label_absent__noop_test_true():
labels = make_node_labels()
with mock_func("node_labels", return_value=labels, test=True):
actual = kubernetes.node_label_absent(
name="non-existent-label",
node="minikube",
)
assert {
"changes": {},
"result": None,
"name": "non-existent-label",
"comment": "The label does not exist",
} == actual
def test_node_label_absent__noop():
labels = make_node_labels()
with mock_func("node_labels", return_value=labels):
actual = kubernetes.node_label_absent(
name="non-existent-label",
node="minikube",
)
assert {
"changes": {},
"result": True,
"name": "non-existent-label",
"comment": "The label does not exist",
} == actual
def test_node_label_absent__delete_test_true():
labels = make_node_labels()
with mock_func("node_labels", return_value=labels, test=True):
actual = kubernetes.node_label_absent(
name="failure-domain.beta.kubernetes.io/region",
node="minikube",
)
assert {
"changes": {},
"result": None,
"name": "failure-domain.beta.kubernetes.io/region",
"comment": "The label is going to be deleted",
} == actual
def test_node_label_absent__delete():
node_data = make_node()
labels = node_data["metadata"]["labels"].copy()
node_data["metadata"]["labels"].pop("failure-domain.beta.kubernetes.io/region")
with mock_func("node_labels", return_value=labels):
with mock_func("node_remove_label", return_value=node_data):
actual = kubernetes.node_label_absent(
name="failure-domain.beta.kubernetes.io/region",
node="minikube",
)
assert {
"result": True,
"changes": {
"kubernetes.node_label": {
"new": "absent",
"old": "present",
}
},
"comment": "Label removed from node",
"name": "failure-domain.beta.kubernetes.io/region",
} == actual
def test_namespace_present__create_test_true():
with mock_func("show_namespace", return_value=None, test=True):
actual = kubernetes.namespace_present(name="saltstack")
assert {
"changes": {},
"result": None,
"name": "saltstack",
"comment": "The namespace is going to be created",
} == actual
def test_namespace_present__create():
namespace_data = make_namespace(name="saltstack")
with mock_func("show_namespace", return_value=None):
with mock_func("create_namespace", return_value=namespace_data):
actual = kubernetes.namespace_present(name="saltstack")
assert {
"changes": {"namespace": {"new": namespace_data, "old": {}}},
"result": True,
"name": "saltstack",
"comment": "",
} == actual
def test_namespace_present__noop_test_true():
namespace_data = make_namespace(name="saltstack")
with mock_func("show_namespace", return_value=namespace_data, test=True):
actual = kubernetes.namespace_present(name="saltstack")
assert {
"changes": {},
"result": None,
"name": "saltstack",
"comment": "The namespace already exists",
} == actual
def test_namespace_present__noop():
namespace_data = make_namespace(name="saltstack")
with mock_func("show_namespace", return_value=namespace_data):
actual = kubernetes.namespace_present(name="saltstack")
assert {
"changes": {},
"result": True,
"name": "saltstack",
"comment": "The namespace already exists",
} == actual
def test_namespace_absent__noop_test_true():
with mock_func("show_namespace", return_value=None, test=True):
actual = kubernetes.namespace_absent(name="salt")
assert {
"changes": {},
"result": None,
"name": "salt",
"comment": "The namespace does not exist",
} == actual
def test_namespace_absent__noop():
with mock_func("show_namespace", return_value=None):
actual = kubernetes.namespace_absent(name="salt")
assert {
"changes": {},
"result": True,
"name": "salt",
"comment": "The namespace does not exist",
} == actual
def test_namespace_absent__delete_test_true():
namespace_data = make_namespace(name="salt")
with mock_func("show_namespace", return_value=namespace_data, test=True):
actual = kubernetes.namespace_absent(name="salt")
assert {
"changes": {},
"result": None,
"name": "salt",
"comment": "The namespace is going to be deleted",
} == actual
def test_namespace_absent__delete_code_200():
namespace_data = make_namespace(name="salt")
deleted = namespace_data.copy()
deleted["code"] = 200
deleted.update({"code": 200, "message": None})
with mock_func("show_namespace", return_value=namespace_data):
with mock_func("delete_namespace", return_value=deleted):
actual = kubernetes.namespace_absent(name="salt")
assert {
"changes": {
"kubernetes.namespace": {"new": "absent", "old": "present"}
},
"result": True,
"name": "salt",
"comment": "Terminating",
} == actual
def test_namespace_absent__delete_status_terminating():
namespace_data = make_namespace(name="salt")
deleted = namespace_data.copy()
deleted.update(
{
"code": None,
"status": "Terminating namespace",
"message": "Terminating this shizzzle yo",
}
)
with mock_func("show_namespace", return_value=namespace_data):
with mock_func("delete_namespace", return_value=deleted):
actual = kubernetes.namespace_absent(name="salt")
assert {
"changes": {
"kubernetes.namespace": {"new": "absent", "old": "present"}
},
"result": True,
"name": "salt",
"comment": "Terminating this shizzzle yo",
} == actual
def test_namespace_absent__delete_status_phase_terminating():
# This is what kubernetes 1.8.0 looks like when deleting namespaces
namespace_data = make_namespace(name="salt")
deleted = namespace_data.copy()
deleted.update({"code": None, "message": None, "status": {"phase": "Terminating"}})
with mock_func("show_namespace", return_value=namespace_data):
with mock_func("delete_namespace", return_value=deleted):
actual = kubernetes.namespace_absent(name="salt")
assert {
"changes": {
"kubernetes.namespace": {"new": "absent", "old": "present"}
},
"result": True,
"name": "salt",
"comment": "Terminating",
} == actual
def test_namespace_absent__delete_error():
namespace_data = make_namespace(name="salt")
deleted = namespace_data.copy()
deleted.update({"code": 418, "message": "I' a teapot!", "status": None})
with mock_func("show_namespace", return_value=namespace_data):
with mock_func("delete_namespace", return_value=deleted):
actual = kubernetes.namespace_absent(name="salt")
assert {
"changes": {},
"result": False,
"name": "salt",
"comment": "Something went wrong, response: {}".format(
deleted,
),
} == actual

View file

@ -1,897 +0,0 @@
"""
:codeauthor: :email:`Jeff Schroeder <jeffschroeder@computer.org>`
"""
import base64
from contextlib import contextmanager
import pytest
import salt.modules.kubernetesmod as kubernetesmod
import salt.states.kubernetes as kubernetes
import salt.utils.stringutils
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.mock import MagicMock, patch
from tests.support.unit import TestCase
@pytest.mark.skipif(
kubernetesmod.HAS_LIBS is False,
reason="Probably Kubernetes client lib is not installed. Skipping test_kubernetes.py",
)
class KubernetesTestCase(TestCase, LoaderModuleMockMixin):
"""
Test cases for salt.states.kubernetes
"""
def setup_loader_modules(self):
return {kubernetes: {"__env__": "base"}}
@contextmanager
def mock_func(self, func_name, return_value, test=False):
"""
Mock any of the kubernetes state function return values and set
the test options.
"""
name = "kubernetes.{}".format(func_name)
mocked = {name: MagicMock(return_value=return_value)}
with patch.dict(kubernetes.__salt__, mocked) as patched:
with patch.dict(kubernetes.__opts__, {"test": test}):
yield patched
def make_configmap(self, name, namespace="default", data=None):
return self.make_ret_dict(
kind="ConfigMap",
name=name,
namespace=namespace,
data=data,
)
def make_secret(self, name, namespace="default", data=None):
secret_data = self.make_ret_dict(
kind="Secret",
name=name,
namespace=namespace,
data=data,
)
# Base64 all of the values just like kubectl does
for key, value in secret_data["data"].items():
secret_data["data"][key] = base64.b64encode(
salt.utils.stringutils.to_bytes(value)
)
return secret_data
def make_node_labels(self, name="minikube"):
return {
"kubernetes.io/hostname": name,
"beta.kubernetes.io/os": "linux",
"beta.kubernetes.io/arch": "amd64",
"failure-domain.beta.kubernetes.io/region": "us-west-1",
}
def make_node(self, name="minikube"):
node_data = self.make_ret_dict(kind="Node", name="minikube")
node_data.update(
{
"api_version": "v1",
"kind": "Node",
"metadata": {
"annotations": {"node.alpha.kubernetes.io/ttl": "0"},
"labels": self.make_node_labels(name=name),
"name": name,
"namespace": None,
"self_link": "/api/v1/nodes/{name}".format(name=name),
"uid": "7811b8ae-c1a1-11e7-a55a-0800279fb61e",
},
"spec": {"external_id": name},
"status": {},
}
)
return node_data
def make_namespace(self, name="default"):
namespace_data = self.make_ret_dict(kind="Namespace", name=name)
del namespace_data["data"]
namespace_data.update(
{
"status": {"phase": "Active"},
"spec": {"finalizers": ["kubernetes"]},
"metadata": {
"name": name,
"namespace": None,
"labels": None,
"self_link": "/api/v1/namespaces/{namespace}".format(
namespace=name,
),
"annotations": None,
"uid": "752fceeb-c1a1-11e7-a55a-0800279fb61e",
},
}
)
return namespace_data
def make_ret_dict(self, kind, name, namespace=None, data=None):
"""
Make a minimal example configmap or secret for using in mocks
"""
assert kind in ("Secret", "ConfigMap", "Namespace", "Node")
if data is None:
data = {}
self_link = "/api/v1/namespaces/{namespace}/{kind}s/{name}".format(
namespace=namespace,
kind=kind.lower(),
name=name,
)
return_data = {
"kind": kind,
"data": data,
"api_version": "v1",
"metadata": {
"name": name,
"labels": None,
"namespace": namespace,
"self_link": self_link,
"annotations": {"kubernetes.io/change-cause": "salt-call state.apply"},
},
}
return return_data
def test_configmap_present__fail(self):
error = kubernetes.configmap_present(
name="testme",
data={1: 1},
source="salt://beyond/oblivion.jinja",
)
self.assertDictEqual(
{
"changes": {},
"result": False,
"name": "testme",
"comment": "'source' cannot be used in combination with 'data'",
},
error,
)
def test_configmap_present__create_test_true(self):
# Create a new configmap with test=True
with self.mock_func("show_configmap", return_value=None, test=True):
ret = kubernetes.configmap_present(
name="example",
data={"example.conf": "# empty config file"},
)
self.assertDictEqual(
{
"comment": "The configmap is going to be created",
"changes": {},
"name": "example",
"result": None,
},
ret,
)
def test_configmap_present__create(self):
# Create a new configmap
with self.mock_func("show_configmap", return_value=None):
cm = self.make_configmap(
name="test",
namespace="default",
data={"foo": "bar"},
)
with self.mock_func("create_configmap", return_value=cm):
actual = kubernetes.configmap_present(
name="test",
data={"foo": "bar"},
)
self.assertDictEqual(
{
"comment": "",
"changes": {"data": {"foo": "bar"}},
"name": "test",
"result": True,
},
actual,
)
def test_configmap_present__create_no_data(self):
# Create a new configmap with no 'data' attribute
with self.mock_func("show_configmap", return_value=None):
cm = self.make_configmap(
name="test",
namespace="default",
)
with self.mock_func("create_configmap", return_value=cm):
actual = kubernetes.configmap_present(name="test")
self.assertDictEqual(
{
"comment": "",
"changes": {"data": {}},
"name": "test",
"result": True,
},
actual,
)
def test_configmap_present__replace_test_true(self):
cm = self.make_configmap(
name="settings",
namespace="saltstack",
data={"foobar.conf": "# Example configuration"},
)
with self.mock_func("show_configmap", return_value=cm, test=True):
ret = kubernetes.configmap_present(
name="settings",
namespace="saltstack",
data={"foobar.conf": "# Example configuration"},
)
self.assertDictEqual(
{
"comment": "The configmap is going to be replaced",
"changes": {},
"name": "settings",
"result": None,
},
ret,
)
def test_configmap_present__replace(self):
cm = self.make_configmap(name="settings", data={"action": "make=war"})
# Replace an existing configmap
with self.mock_func("show_configmap", return_value=cm):
new_cm = cm.copy()
new_cm.update({"data": {"action": "make=peace"}})
with self.mock_func("replace_configmap", return_value=new_cm):
actual = kubernetes.configmap_present(
name="settings",
data={"action": "make=peace"},
)
self.assertDictEqual(
{
"comment": (
"The configmap is already present. Forcing recreation"
),
"changes": {"data": {"action": "make=peace"}},
"name": "settings",
"result": True,
},
actual,
)
def test_configmap_absent__noop_test_true(self):
# Nothing to delete with test=True
with self.mock_func("show_configmap", return_value=None, test=True):
actual = kubernetes.configmap_absent(name="NOT_FOUND")
self.assertDictEqual(
{
"comment": "The configmap does not exist",
"changes": {},
"name": "NOT_FOUND",
"result": None,
},
actual,
)
def test_configmap_absent__test_true(self):
# Configmap exists with test=True
cm = self.make_configmap(name="deleteme", namespace="default")
with self.mock_func("show_configmap", return_value=cm, test=True):
actual = kubernetes.configmap_absent(name="deleteme")
self.assertDictEqual(
{
"comment": "The configmap is going to be deleted",
"changes": {},
"name": "deleteme",
"result": None,
},
actual,
)
def test_configmap_absent__noop(self):
# Nothing to delete
with self.mock_func("show_configmap", return_value=None):
actual = kubernetes.configmap_absent(name="NOT_FOUND")
self.assertDictEqual(
{
"comment": "The configmap does not exist",
"changes": {},
"name": "NOT_FOUND",
"result": True,
},
actual,
)
def test_configmap_absent(self):
# Configmap exists, delete it!
cm = self.make_configmap(name="deleteme", namespace="default")
with self.mock_func("show_configmap", return_value=cm):
# The return from this module isn't used in the state
with self.mock_func("delete_configmap", return_value={}):
actual = kubernetes.configmap_absent(name="deleteme")
self.assertDictEqual(
{
"comment": "ConfigMap deleted",
"changes": {
"kubernetes.configmap": {
"new": "absent",
"old": "present",
},
},
"name": "deleteme",
"result": True,
},
actual,
)
def test_secret_present__fail(self):
actual = kubernetes.secret_present(
name="sekret",
data={"password": "monk3y"},
source="salt://nope.jinja",
)
self.assertDictEqual(
{
"changes": {},
"result": False,
"name": "sekret",
"comment": "'source' cannot be used in combination with 'data'",
},
actual,
)
def test_secret_present__exists_test_true(self):
secret = self.make_secret(name="sekret")
new_secret = secret.copy()
new_secret.update({"data": {"password": "uncle"}})
# Secret exists already and needs replacing with test=True
with self.mock_func("show_secret", return_value=secret):
with self.mock_func("replace_secret", return_value=new_secret, test=True):
actual = kubernetes.secret_present(
name="sekret",
data={"password": "uncle"},
)
self.assertDictEqual(
{
"changes": {},
"result": None,
"name": "sekret",
"comment": "The secret is going to be replaced",
},
actual,
)
def test_secret_present__exists(self):
# Secret exists and gets replaced
secret = self.make_secret(name="sekret", data={"password": "booyah"})
with self.mock_func("show_secret", return_value=secret):
with self.mock_func("replace_secret", return_value=secret):
actual = kubernetes.secret_present(
name="sekret",
data={"password": "booyah"},
)
self.assertDictEqual(
{
"changes": {"data": ["password"]},
"result": True,
"name": "sekret",
"comment": "The secret is already present. Forcing recreation",
},
actual,
)
def test_secret_present__create(self):
# Secret exists and gets replaced
secret = self.make_secret(name="sekret", data={"password": "booyah"})
with self.mock_func("show_secret", return_value=None):
with self.mock_func("create_secret", return_value=secret):
actual = kubernetes.secret_present(
name="sekret",
data={"password": "booyah"},
)
self.assertDictEqual(
{
"changes": {"data": ["password"]},
"result": True,
"name": "sekret",
"comment": "",
},
actual,
)
def test_secret_present__create_no_data(self):
# Secret exists and gets replaced
secret = self.make_secret(name="sekret")
with self.mock_func("show_secret", return_value=None):
with self.mock_func("create_secret", return_value=secret):
actual = kubernetes.secret_present(name="sekret")
self.assertDictEqual(
{
"changes": {"data": []},
"result": True,
"name": "sekret",
"comment": "",
},
actual,
)
def test_secret_present__create_test_true(self):
# Secret exists and gets replaced with test=True
secret = self.make_secret(name="sekret")
with self.mock_func("show_secret", return_value=None):
with self.mock_func("create_secret", return_value=secret, test=True):
actual = kubernetes.secret_present(name="sekret")
self.assertDictEqual(
{
"changes": {},
"result": None,
"name": "sekret",
"comment": "The secret is going to be created",
},
actual,
)
def test_secret_absent__noop_test_true(self):
with self.mock_func("show_secret", return_value=None, test=True):
actual = kubernetes.secret_absent(name="sekret")
self.assertDictEqual(
{
"changes": {},
"result": None,
"name": "sekret",
"comment": "The secret does not exist",
},
actual,
)
def test_secret_absent__noop(self):
with self.mock_func("show_secret", return_value=None):
actual = kubernetes.secret_absent(name="passwords")
self.assertDictEqual(
{
"changes": {},
"result": True,
"name": "passwords",
"comment": "The secret does not exist",
},
actual,
)
def test_secret_absent__delete_test_true(self):
secret = self.make_secret(name="credentials", data={"redis": "letmein"})
with self.mock_func("show_secret", return_value=secret):
with self.mock_func("delete_secret", return_value=secret, test=True):
actual = kubernetes.secret_absent(name="credentials")
self.assertDictEqual(
{
"changes": {},
"result": None,
"name": "credentials",
"comment": "The secret is going to be deleted",
},
actual,
)
def test_secret_absent__delete(self):
secret = self.make_secret(name="foobar", data={"redis": "letmein"})
deleted = {
"status": None,
"kind": "Secret",
"code": None,
"reason": None,
"details": None,
"message": None,
"api_version": "v1",
"metadata": {
"self_link": "/api/v1/namespaces/default/secrets/foobar",
"resource_version": "30292",
},
}
with self.mock_func("show_secret", return_value=secret):
with self.mock_func("delete_secret", return_value=deleted):
actual = kubernetes.secret_absent(name="foobar")
self.assertDictEqual(
{
"changes": {
"kubernetes.secret": {"new": "absent", "old": "present"},
},
"result": True,
"name": "foobar",
"comment": "Secret deleted",
},
actual,
)
def test_node_label_present__add_test_true(self):
labels = self.make_node_labels()
with self.mock_func("node_labels", return_value=labels, test=True):
actual = kubernetes.node_label_present(
name="com.zoo-animal",
node="minikube",
value="monkey",
)
self.assertDictEqual(
{
"changes": {},
"result": None,
"name": "com.zoo-animal",
"comment": "The label is going to be set",
},
actual,
)
def test_node_label_present__add(self):
node_data = self.make_node()
# Remove some of the defaults to make it simpler
node_data["metadata"]["labels"] = {
"beta.kubernetes.io/os": "linux",
}
labels = node_data["metadata"]["labels"]
with self.mock_func("node_labels", return_value=labels):
with self.mock_func("node_add_label", return_value=node_data):
actual = kubernetes.node_label_present(
name="failure-domain.beta.kubernetes.io/zone",
node="minikube",
value="us-central1-a",
)
self.assertDictEqual(
{
"comment": "",
"changes": {
"minikube.failure-domain.beta.kubernetes.io/zone": {
"new": {
"failure-domain.beta.kubernetes.io/zone": (
"us-central1-a"
),
"beta.kubernetes.io/os": "linux",
},
"old": {"beta.kubernetes.io/os": "linux"},
},
},
"name": "failure-domain.beta.kubernetes.io/zone",
"result": True,
},
actual,
)
def test_node_label_present__already_set(self):
node_data = self.make_node()
labels = node_data["metadata"]["labels"]
with self.mock_func("node_labels", return_value=labels):
with self.mock_func("node_add_label", return_value=node_data):
actual = kubernetes.node_label_present(
name="failure-domain.beta.kubernetes.io/region",
node="minikube",
value="us-west-1",
)
self.assertDictEqual(
{
"changes": {},
"result": True,
"name": "failure-domain.beta.kubernetes.io/region",
"comment": (
"The label is already set and has the specified value"
),
},
actual,
)
def test_node_label_present__update_test_true(self):
node_data = self.make_node()
labels = node_data["metadata"]["labels"]
with self.mock_func("node_labels", return_value=labels):
with self.mock_func("node_add_label", return_value=node_data, test=True):
actual = kubernetes.node_label_present(
name="failure-domain.beta.kubernetes.io/region",
node="minikube",
value="us-east-1",
)
self.assertDictEqual(
{
"changes": {},
"result": None,
"name": "failure-domain.beta.kubernetes.io/region",
"comment": "The label is going to be updated",
},
actual,
)
def test_node_label_present__update(self):
node_data = self.make_node()
# Remove some of the defaults to make it simpler
node_data["metadata"]["labels"] = {
"failure-domain.beta.kubernetes.io/region": "us-west-1",
}
labels = node_data["metadata"]["labels"]
with self.mock_func("node_labels", return_value=labels):
with self.mock_func("node_add_label", return_value=node_data):
actual = kubernetes.node_label_present(
name="failure-domain.beta.kubernetes.io/region",
node="minikube",
value="us-east-1",
)
self.assertDictEqual(
{
"changes": {
"minikube.failure-domain.beta.kubernetes.io/region": {
"new": {
"failure-domain.beta.kubernetes.io/region": (
"us-east-1"
)
},
"old": {
"failure-domain.beta.kubernetes.io/region": (
"us-west-1"
)
},
}
},
"result": True,
"name": "failure-domain.beta.kubernetes.io/region",
"comment": "The label is already set, changing the value",
},
actual,
)
def test_node_label_absent__noop_test_true(self):
labels = self.make_node_labels()
with self.mock_func("node_labels", return_value=labels, test=True):
actual = kubernetes.node_label_absent(
name="non-existent-label",
node="minikube",
)
self.assertDictEqual(
{
"changes": {},
"result": None,
"name": "non-existent-label",
"comment": "The label does not exist",
},
actual,
)
def test_node_label_absent__noop(self):
labels = self.make_node_labels()
with self.mock_func("node_labels", return_value=labels):
actual = kubernetes.node_label_absent(
name="non-existent-label",
node="minikube",
)
self.assertDictEqual(
{
"changes": {},
"result": True,
"name": "non-existent-label",
"comment": "The label does not exist",
},
actual,
)
def test_node_label_absent__delete_test_true(self):
labels = self.make_node_labels()
with self.mock_func("node_labels", return_value=labels, test=True):
actual = kubernetes.node_label_absent(
name="failure-domain.beta.kubernetes.io/region",
node="minikube",
)
self.assertDictEqual(
{
"changes": {},
"result": None,
"name": "failure-domain.beta.kubernetes.io/region",
"comment": "The label is going to be deleted",
},
actual,
)
def test_node_label_absent__delete(self):
node_data = self.make_node()
labels = node_data["metadata"]["labels"].copy()
node_data["metadata"]["labels"].pop("failure-domain.beta.kubernetes.io/region")
with self.mock_func("node_labels", return_value=labels):
with self.mock_func("node_remove_label", return_value=node_data):
actual = kubernetes.node_label_absent(
name="failure-domain.beta.kubernetes.io/region",
node="minikube",
)
self.assertDictEqual(
{
"result": True,
"changes": {
"kubernetes.node_label": {
"new": "absent",
"old": "present",
}
},
"comment": "Label removed from node",
"name": "failure-domain.beta.kubernetes.io/region",
},
actual,
)
def test_namespace_present__create_test_true(self):
with self.mock_func("show_namespace", return_value=None, test=True):
actual = kubernetes.namespace_present(name="saltstack")
self.assertDictEqual(
{
"changes": {},
"result": None,
"name": "saltstack",
"comment": "The namespace is going to be created",
},
actual,
)
def test_namespace_present__create(self):
namespace_data = self.make_namespace(name="saltstack")
with self.mock_func("show_namespace", return_value=None):
with self.mock_func("create_namespace", return_value=namespace_data):
actual = kubernetes.namespace_present(name="saltstack")
self.assertDictEqual(
{
"changes": {"namespace": {"new": namespace_data, "old": {}}},
"result": True,
"name": "saltstack",
"comment": "",
},
actual,
)
def test_namespace_present__noop_test_true(self):
namespace_data = self.make_namespace(name="saltstack")
with self.mock_func("show_namespace", return_value=namespace_data, test=True):
actual = kubernetes.namespace_present(name="saltstack")
self.assertDictEqual(
{
"changes": {},
"result": None,
"name": "saltstack",
"comment": "The namespace already exists",
},
actual,
)
def test_namespace_present__noop(self):
namespace_data = self.make_namespace(name="saltstack")
with self.mock_func("show_namespace", return_value=namespace_data):
actual = kubernetes.namespace_present(name="saltstack")
self.assertDictEqual(
{
"changes": {},
"result": True,
"name": "saltstack",
"comment": "The namespace already exists",
},
actual,
)
def test_namespace_absent__noop_test_true(self):
with self.mock_func("show_namespace", return_value=None, test=True):
actual = kubernetes.namespace_absent(name="salt")
self.assertDictEqual(
{
"changes": {},
"result": None,
"name": "salt",
"comment": "The namespace does not exist",
},
actual,
)
def test_namespace_absent__noop(self):
with self.mock_func("show_namespace", return_value=None):
actual = kubernetes.namespace_absent(name="salt")
self.assertDictEqual(
{
"changes": {},
"result": True,
"name": "salt",
"comment": "The namespace does not exist",
},
actual,
)
def test_namespace_absent__delete_test_true(self):
namespace_data = self.make_namespace(name="salt")
with self.mock_func("show_namespace", return_value=namespace_data, test=True):
actual = kubernetes.namespace_absent(name="salt")
self.assertDictEqual(
{
"changes": {},
"result": None,
"name": "salt",
"comment": "The namespace is going to be deleted",
},
actual,
)
def test_namespace_absent__delete_code_200(self):
namespace_data = self.make_namespace(name="salt")
deleted = namespace_data.copy()
deleted["code"] = 200
deleted.update({"code": 200, "message": None})
with self.mock_func("show_namespace", return_value=namespace_data):
with self.mock_func("delete_namespace", return_value=deleted):
actual = kubernetes.namespace_absent(name="salt")
self.assertDictEqual(
{
"changes": {
"kubernetes.namespace": {"new": "absent", "old": "present"}
},
"result": True,
"name": "salt",
"comment": "Terminating",
},
actual,
)
def test_namespace_absent__delete_status_terminating(self):
namespace_data = self.make_namespace(name="salt")
deleted = namespace_data.copy()
deleted.update(
{
"code": None,
"status": "Terminating namespace",
"message": "Terminating this shizzzle yo",
}
)
with self.mock_func("show_namespace", return_value=namespace_data):
with self.mock_func("delete_namespace", return_value=deleted):
actual = kubernetes.namespace_absent(name="salt")
self.assertDictEqual(
{
"changes": {
"kubernetes.namespace": {"new": "absent", "old": "present"}
},
"result": True,
"name": "salt",
"comment": "Terminating this shizzzle yo",
},
actual,
)
def test_namespace_absent__delete_status_phase_terminating(self):
# This is what kubernetes 1.8.0 looks like when deleting namespaces
namespace_data = self.make_namespace(name="salt")
deleted = namespace_data.copy()
deleted.update(
{"code": None, "message": None, "status": {"phase": "Terminating"}}
)
with self.mock_func("show_namespace", return_value=namespace_data):
with self.mock_func("delete_namespace", return_value=deleted):
actual = kubernetes.namespace_absent(name="salt")
self.assertDictEqual(
{
"changes": {
"kubernetes.namespace": {"new": "absent", "old": "present"}
},
"result": True,
"name": "salt",
"comment": "Terminating",
},
actual,
)
def test_namespace_absent__delete_error(self):
namespace_data = self.make_namespace(name="salt")
deleted = namespace_data.copy()
deleted.update({"code": 418, "message": "I' a teapot!", "status": None})
with self.mock_func("show_namespace", return_value=namespace_data):
with self.mock_func("delete_namespace", return_value=deleted):
actual = kubernetes.namespace_absent(name="salt")
self.assertDictEqual(
{
"changes": {},
"result": False,
"name": "salt",
"comment": "Something went wrong, response: {}".format(
deleted,
),
},
actual,
)