mirror of
https://github.com/ansible-collections/kubernetes.core.git
synced 2026-03-26 21:33:02 +00:00
This primarily moves the diff and wait logic from the various service methods to perform_action to eliminate code duplication. I also moved the diff_objects function out of the service object and moved most of the find_resource logic to a new resource client method. We ended up with several modules creating a service object just to use one of these methods, so it seemed to make sense to make these more accessible.
293 lines
8.6 KiB
Python
293 lines
8.6 KiB
Python
from unittest.mock import Mock
|
|
|
|
import pytest
|
|
from kubernetes.dynamic.resource import ResourceInstance, Resource
|
|
|
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
|
|
K8sService,
|
|
diff_objects,
|
|
)
|
|
|
|
from kubernetes.dynamic.exceptions import NotFoundError
|
|
|
|
pod_definition = {
|
|
"apiVersion": "v1",
|
|
"kind": "Pod",
|
|
"metadata": {
|
|
"name": "foo",
|
|
"labels": {"environment": "production", "app": "nginx"},
|
|
"namespace": "foo",
|
|
},
|
|
"spec": {
|
|
"containers": [
|
|
{
|
|
"name": "nginx",
|
|
"image": "nginx:1.14.2",
|
|
"command": ["/bin/sh", "-c", "sleep 10"],
|
|
}
|
|
]
|
|
},
|
|
}
|
|
|
|
pod_definition_updated = {
|
|
"apiVersion": "v1",
|
|
"kind": "Pod",
|
|
"metadata": {
|
|
"name": "foo",
|
|
"labels": {"environment": "testing", "app": "nginx"},
|
|
"namespace": "bar",
|
|
},
|
|
"spec": {
|
|
"containers": [
|
|
{
|
|
"name": "nginx",
|
|
"image": "nginx:1.14.2",
|
|
"command": ["/bin/sh", "-c", "sleep 10"],
|
|
}
|
|
]
|
|
},
|
|
}
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def mock_pod_resource_instance():
|
|
return ResourceInstance(None, pod_definition)
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def mock_pod_updated_resource_instance():
|
|
return ResourceInstance(None, pod_definition_updated)
|
|
|
|
|
|
def test_diff_objects_no_diff():
|
|
match, diff = diff_objects(pod_definition, pod_definition)
|
|
|
|
assert match is True
|
|
assert diff == {}
|
|
|
|
|
|
def test_diff_objects_meta_diff():
|
|
match, diff = diff_objects(pod_definition, pod_definition_updated)
|
|
|
|
assert match is False
|
|
assert diff["before"] == {
|
|
"metadata": {"labels": {"environment": "production"}, "namespace": "foo"}
|
|
}
|
|
assert diff["after"] == {
|
|
"metadata": {"labels": {"environment": "testing"}, "namespace": "bar"}
|
|
}
|
|
|
|
|
|
def test_diff_objects_spec_diff():
|
|
pod_definition_updated = {
|
|
"apiVersion": "v1",
|
|
"kind": "Pod",
|
|
"metadata": {
|
|
"name": "foo",
|
|
"labels": {"environment": "production", "app": "nginx"},
|
|
"namespace": "foo",
|
|
},
|
|
"spec": {
|
|
"containers": [
|
|
{
|
|
"name": "busybox",
|
|
"image": "busybox",
|
|
"command": ["/bin/sh", "-c", "sleep 3600"],
|
|
}
|
|
]
|
|
},
|
|
}
|
|
match, diff = diff_objects(pod_definition, pod_definition_updated)
|
|
|
|
assert match is False
|
|
assert diff["before"]["spec"] == pod_definition["spec"]
|
|
assert diff["after"]["spec"] == pod_definition_updated["spec"]
|
|
|
|
|
|
def test_find_resource():
|
|
mock_pod_resource = Resource(
|
|
api_version="v1", kind="Pod", namespaced=False, preferred=True, prefix="api"
|
|
)
|
|
spec = {"resource.return_value": mock_pod_resource}
|
|
client = Mock(**spec)
|
|
svc = K8sService(client, Mock())
|
|
resource = svc.find_resource("Pod", "v1")
|
|
|
|
assert isinstance(resource, Resource)
|
|
assert resource.to_dict().items() <= mock_pod_resource.to_dict().items()
|
|
|
|
|
|
def test_service_delete_existing_resource(mock_pod_resource_instance):
|
|
spec = {"delete.side_effect": [mock_pod_resource_instance]}
|
|
client = Mock(**spec)
|
|
module = Mock(
|
|
params={"delete_options": {"gracePeriodSeconds": 2}}, check_mode=False
|
|
)
|
|
resource = Mock()
|
|
svc = K8sService(client, module)
|
|
result = svc.delete(resource, pod_definition, mock_pod_resource_instance)
|
|
|
|
assert isinstance(result, dict)
|
|
assert result == mock_pod_resource_instance.to_dict()
|
|
client.delete.assert_called_with(
|
|
resource,
|
|
name=pod_definition["metadata"]["name"],
|
|
namespace=pod_definition["metadata"]["namespace"],
|
|
body={"apiVersion": "v1", "kind": "DeleteOptions", "gracePeriodSeconds": 2},
|
|
)
|
|
|
|
|
|
def test_service_delete_no_existing_resource():
|
|
module = Mock()
|
|
module.params = {}
|
|
module.check_mode = False
|
|
client = Mock()
|
|
client.delete.return_value = mock_pod_resource_instance
|
|
svc = K8sService(client, module)
|
|
result = svc.delete(Mock(), pod_definition)
|
|
|
|
assert result == {}
|
|
client.delete.assert_not_called()
|
|
|
|
|
|
def test_service_delete_existing_resource_check_mode(mock_pod_resource_instance):
|
|
module = Mock(params={}, check_mode=True)
|
|
client = Mock(dry_run=False)
|
|
client.delete.return_value = mock_pod_resource_instance
|
|
svc = K8sService(client, module)
|
|
result = svc.delete(Mock(), pod_definition, mock_pod_resource_instance)
|
|
|
|
assert result == {}
|
|
client.delete.assert_not_called()
|
|
|
|
|
|
def test_service_create_resource(mock_pod_resource_instance):
|
|
spec = {"create.side_effect": [mock_pod_resource_instance]}
|
|
client = Mock(**spec)
|
|
module = Mock()
|
|
module.params = {}
|
|
module.check_mode = False
|
|
svc = K8sService(client, module)
|
|
result = svc.create(Mock(), pod_definition)
|
|
|
|
assert result == mock_pod_resource_instance.to_dict()
|
|
|
|
|
|
def test_service_create_resource_check_mode():
|
|
client = Mock(dry_run=False)
|
|
client.create.return_value = mock_pod_resource_instance
|
|
module = Mock(params={}, check_mode=True)
|
|
svc = K8sService(client, module)
|
|
result = svc.create(Mock(), pod_definition)
|
|
|
|
assert result == pod_definition
|
|
client.create.assert_not_called()
|
|
|
|
|
|
def test_service_retrieve_existing_resource(mock_pod_resource_instance):
|
|
spec = {"get.side_effect": [mock_pod_resource_instance]}
|
|
client = Mock(**spec)
|
|
module = Mock()
|
|
module.params = {}
|
|
svc = K8sService(client, module)
|
|
results = svc.retrieve(Mock(), pod_definition)
|
|
|
|
assert isinstance(results, ResourceInstance)
|
|
assert results.to_dict() == pod_definition
|
|
|
|
|
|
def test_service_retrieve_no_existing_resource():
|
|
spec = {"get.side_effect": [NotFoundError(Mock())]}
|
|
client = Mock(**spec)
|
|
module = Mock()
|
|
module.params = {}
|
|
svc = K8sService(client, module)
|
|
results = svc.retrieve(Mock(), pod_definition)
|
|
|
|
assert results is None
|
|
|
|
|
|
def test_create_project_request():
|
|
project_definition = {
|
|
"apiVersion": "v1",
|
|
"kind": "ProjectRequest",
|
|
"metadata": {"name": "test"},
|
|
}
|
|
spec = {"create.side_effect": [ResourceInstance(None, project_definition)]}
|
|
client = Mock(**spec)
|
|
module = Mock()
|
|
module.check_mode = False
|
|
module.params = {"state": "present"}
|
|
svc = K8sService(client, module)
|
|
results = svc.create_project_request(project_definition)
|
|
|
|
assert isinstance(results, dict)
|
|
assert results["changed"] is True
|
|
assert results["result"] == project_definition
|
|
|
|
|
|
def test_service_apply_existing_resource(mock_pod_resource_instance):
|
|
spec = {"apply.side_effect": [mock_pod_resource_instance]}
|
|
client = Mock(**spec)
|
|
module = Mock()
|
|
module.params = {"apply": True}
|
|
module.check_mode = False
|
|
svc = K8sService(client, module)
|
|
result = svc.apply(Mock(), pod_definition_updated, mock_pod_resource_instance)
|
|
|
|
assert result == mock_pod_resource_instance.to_dict()
|
|
|
|
|
|
def test_service_replace_existing_resource(mock_pod_resource_instance):
|
|
spec = {"replace.side_effect": [mock_pod_resource_instance]}
|
|
client = Mock(**spec)
|
|
module = Mock()
|
|
module.params = {}
|
|
module.check_mode = False
|
|
svc = K8sService(client, module)
|
|
result = svc.replace(Mock(), pod_definition, mock_pod_resource_instance)
|
|
|
|
assert result == mock_pod_resource_instance.to_dict()
|
|
|
|
|
|
def test_service_update_existing_resource(mock_pod_resource_instance):
|
|
spec = {"replace.side_effect": [mock_pod_resource_instance]}
|
|
client = Mock(**spec)
|
|
module = Mock()
|
|
module.params = {}
|
|
module.check_mode = False
|
|
svc = K8sService(client, module)
|
|
result = svc.replace(Mock(), pod_definition, mock_pod_resource_instance)
|
|
|
|
assert result == mock_pod_resource_instance.to_dict()
|
|
|
|
|
|
def test_service_find(mock_pod_resource_instance):
|
|
spec = {"get.side_effect": [mock_pod_resource_instance]}
|
|
client = Mock(**spec)
|
|
module = Mock()
|
|
module.params = {}
|
|
module.check_mode = False
|
|
svc = K8sService(client, module)
|
|
results = svc.find("Pod", "v1", name="foo", namespace="foo")
|
|
|
|
assert isinstance(results, dict)
|
|
assert results["api_found"] is True
|
|
assert results["resources"] is not []
|
|
assert len(results["resources"]) == 1
|
|
assert results["resources"][0] == pod_definition
|
|
|
|
|
|
def test_service_find_error():
|
|
spec = {"get.side_effect": [NotFoundError(Mock())]}
|
|
client = Mock(**spec)
|
|
module = Mock()
|
|
module.params = {}
|
|
module.check_mode = False
|
|
svc = K8sService(client, module)
|
|
results = svc.find("Pod", "v1", name="foo", namespace="foo")
|
|
|
|
assert isinstance(results, dict)
|
|
assert results["api_found"] is True
|
|
assert results["resources"] == []
|