K8sService class (#307)

K8sService class

SUMMARY

This refactors the perform_action() logic from common.py into a separate K8sService class.
TODO:

 Unit tests.

ISSUE TYPE

New Module Pull Request

COMPONENT NAME

service.py

Reviewed-by: Abhijeet Kasurde <None>
Reviewed-by: Mike Graves <mgraves@redhat.com>
Reviewed-by: Alina Buzachis <None>
Reviewed-by: None <None>
This commit is contained in:
Alina Buzachis
2022-01-13 16:08:47 +01:00
committed by Mike Graves
parent f168a3f67f
commit e2f54d3431
6 changed files with 1029 additions and 8 deletions

View File

@@ -0,0 +1,373 @@
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,
)
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():
svc = K8sService(Mock(), Mock())
match, diff = svc.diff_objects(pod_definition, pod_definition)
assert match is True
assert diff == {}
def test_diff_objects_meta_diff():
svc = K8sService(Mock(), Mock())
match, diff = svc.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"],
}
]
},
}
svc = K8sService(Mock(), Mock())
match, diff = svc.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 = {"resources.get.side_effect": [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()
module.params = {}
module.check_mode = False
svc = K8sService(client, module)
results = svc.delete(Mock(), pod_definition, mock_pod_resource_instance)
assert isinstance(results, dict)
assert results["changed"] is True
assert results["result"] == pod_definition
def test_service_delete_no_existing_resource():
module = Mock()
module.params = {}
module.check_mode = False
svc = K8sService(Mock(), module)
results = svc.delete(Mock(), pod_definition)
assert isinstance(results, dict)
assert results["changed"] is False
assert results["result"] == {}
def test_service_delete_existing_resource_check_mode(mock_pod_resource_instance):
module = Mock()
module.params = {"wait": False}
module.check_mode = True
svc = K8sService(Mock(), module)
results = svc.delete(Mock(), pod_definition, mock_pod_resource_instance)
assert isinstance(results, dict)
assert results["changed"] is True
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)
results = svc.create(Mock(), pod_definition)
assert isinstance(results, dict)
assert results["changed"] is True
assert results["result"] == pod_definition
def test_service_create_resource_check_mode():
client = Mock()
client.dry_run = False
module = Mock()
module.params = {}
module.check_mode = True
svc = K8sService(client, module)
results = svc.create(Mock(), pod_definition)
assert isinstance(results, dict)
assert results["changed"] is True
assert results["result"] == pod_definition
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, dict)
assert results["changed"] is False
assert results["result"] == 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 isinstance(results, dict)
assert results["changed"] is False
assert results["result"] == {}
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": [ResourceInstance(None, pod_definition_updated)]}
client = Mock(**spec)
module = Mock()
module.params = {"apply": True}
module.check_mode = False
svc = K8sService(client, module)
results = svc.apply(Mock(), pod_definition_updated, mock_pod_resource_instance)
assert isinstance(results, dict)
assert results["changed"] is True
assert results["diff"] is not {}
assert results["result"] == pod_definition_updated
def test_service_apply_existing_resource_no_diff(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)
results = svc.apply(Mock(), pod_definition, mock_pod_resource_instance)
assert isinstance(results, dict)
assert results["changed"] is False
assert results["diff"] == {}
assert results["result"] == pod_definition
def test_service_apply_existing_resource_no_apply(mock_pod_resource_instance):
spec = {"apply.side_effect": [mock_pod_resource_instance]}
client = Mock(**spec)
module = Mock()
module.params = {"apply": False}
module.check_mode = False
svc = K8sService(client, module)
results = svc.apply(Mock(), pod_definition, mock_pod_resource_instance)
assert isinstance(results, dict)
assert results["changed"] is False
assert results["result"] == {}
def test_service_replace_existing_resource_no_diff(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)
results = svc.replace(Mock(), pod_definition, mock_pod_resource_instance)
assert isinstance(results, dict)
assert results["changed"] is False
assert results["diff"] == {}
assert results["result"] == pod_definition
def test_service_replace_existing_resource(
mock_pod_resource_instance, mock_pod_updated_resource_instance
):
spec = {"replace.side_effect": [mock_pod_updated_resource_instance]}
client = Mock(**spec)
module = Mock()
module.params = {}
module.check_mode = False
svc = K8sService(client, module)
results = svc.replace(Mock(), pod_definition_updated, mock_pod_resource_instance)
assert isinstance(results, dict)
assert results["changed"] is True
assert results["result"] == pod_definition_updated
assert results["diff"] != {}
assert results["diff"]["before"] is not {}
assert results["diff"]["after"] is not {}
def test_service_update_existing_resource(
mock_pod_resource_instance, mock_pod_updated_resource_instance
):
spec = {"replace.side_effect": [mock_pod_updated_resource_instance]}
client = Mock(**spec)
module = Mock()
module.params = {}
module.check_mode = False
svc = K8sService(client, module)
results = svc.replace(Mock(), pod_definition_updated, mock_pod_resource_instance)
assert isinstance(results, dict)
assert results["changed"] is True
assert results["result"] == pod_definition_updated
assert results["diff"] != {}
assert results["diff"]["before"] is not {}
assert results["diff"]["after"] is not {}
def test_service_update_existing_resource_no_diff(mock_pod_updated_resource_instance):
spec = {"replace.side_effect": [mock_pod_updated_resource_instance]}
client = Mock(**spec)
module = Mock()
module.params = {}
module.check_mode = False
svc = K8sService(client, module)
results = svc.replace(
Mock(), pod_definition_updated, mock_pod_updated_resource_instance
)
assert isinstance(results, dict)
assert results["changed"] is False
assert results["result"] == pod_definition_updated
assert results["diff"] == {}
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"] == []