From 13d08d280188433de7feee8be82c4e3ecbade667 Mon Sep 17 00:00:00 2001 From: "stu126940@mail.uni-kiel.de" <stu126940@mail.uni-kiel.de> Date: Mon, 21 Jun 2021 22:47:27 +0200 Subject: [PATCH] add tests add unit test for K8sManager, add unit test for K8sResourceLoader, introduce a K8s mock server --- theodolite-quarkus/build.gradle | 4 + .../theodolite/k8s/K8sResourceLoader.kt | 11 ++ .../theodolite/k8s/ServiceMonitorWrapper.kt | 2 +- .../kotlin/theodolite/k8s/K8sManagerTest.kt | 151 ++++++++++++++++++ .../theodolite/k8s/K8sResourceLoaderTest.kt | 86 ++++++++++ .../k8s-resource-files/test-configmap.yaml | 6 + .../k8s-resource-files/test-deployment.yaml | 17 ++ .../test-service-monitor.yaml | 7 + .../k8s-resource-files/test-service.yaml | 9 ++ .../k8s-resource-files/test-statefulset.yaml | 16 ++ 10 files changed, 308 insertions(+), 1 deletion(-) create mode 100644 theodolite-quarkus/src/test/kotlin/theodolite/k8s/K8sManagerTest.kt create mode 100644 theodolite-quarkus/src/test/kotlin/theodolite/k8s/K8sResourceLoaderTest.kt create mode 100644 theodolite-quarkus/src/test/resources/k8s-resource-files/test-configmap.yaml create mode 100644 theodolite-quarkus/src/test/resources/k8s-resource-files/test-deployment.yaml create mode 100644 theodolite-quarkus/src/test/resources/k8s-resource-files/test-service-monitor.yaml create mode 100644 theodolite-quarkus/src/test/resources/k8s-resource-files/test-service.yaml create mode 100644 theodolite-quarkus/src/test/resources/k8s-resource-files/test-statefulset.yaml diff --git a/theodolite-quarkus/build.gradle b/theodolite-quarkus/build.gradle index 8c0a13d1f..0062fecd9 100644 --- a/theodolite-quarkus/build.gradle +++ b/theodolite-quarkus/build.gradle @@ -31,6 +31,10 @@ dependencies { testImplementation 'io.quarkus:quarkus-junit5' testImplementation 'io.rest-assured:rest-assured' testImplementation 'org.junit-pioneer:junit-pioneer:1.4.0' + testImplementation group: 'io.fabric8', name: 'kubernetes-server-mock', version: '4.6.0' + + + } group 'theodolite' diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/K8sResourceLoader.kt b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/K8sResourceLoader.kt index fd5ec3b2e..784114d27 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/K8sResourceLoader.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/K8sResourceLoader.kt @@ -60,6 +60,16 @@ class K8sResourceLoader(private val client: NamespacedKubernetesClient) { return loadGenericResource(path) { x: String -> client.configMaps().load(x).get() } } + /** + * Parses a StatefulSet from a StatefulSet yaml + * @param path of the yaml file + * @return StatefulSet from fabric8 + */ + private fun loadStatefulSet(path: String): KubernetesResource { + return loadGenericResource(path) { x: String -> client.apps().statefulSets().load(x).get() } + + } + /** * Generic helper function to load a resource. * @param path of the resource @@ -96,6 +106,7 @@ class K8sResourceLoader(private val client: NamespacedKubernetesClient) { "Service" -> loadService(path) "ServiceMonitor" -> loadServiceMonitor(path) "ConfigMap" -> loadConfigmap(path) + "StatefulSet" -> loadStatefulSet(path) else -> { logger.error { "Error during loading of unspecified resource Kind" } throw java.lang.IllegalArgumentException("error while loading resource with kind: $kind") diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/ServiceMonitorWrapper.kt b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/ServiceMonitorWrapper.kt index 56452d749..a1d33dc73 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/ServiceMonitorWrapper.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/ServiceMonitorWrapper.kt @@ -49,7 +49,7 @@ class ServiceMonitorWrapper(private val serviceMonitor: Map<String, String>) : C /** * @throws NullPointerException if name or metadata is null */ - private fun getServiceMonitorName(): String { + fun getServiceMonitorName(): String { val smAsMap = this.serviceMonitor["metadata"]!! as Map<String, String> return smAsMap["name"]!! } diff --git a/theodolite-quarkus/src/test/kotlin/theodolite/k8s/K8sManagerTest.kt b/theodolite-quarkus/src/test/kotlin/theodolite/k8s/K8sManagerTest.kt new file mode 100644 index 000000000..cb52e0ae1 --- /dev/null +++ b/theodolite-quarkus/src/test/kotlin/theodolite/k8s/K8sManagerTest.kt @@ -0,0 +1,151 @@ +package theodolite.k8s + +import io.fabric8.kubernetes.api.model.* +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder +import io.fabric8.kubernetes.api.model.apps.StatefulSet +import io.fabric8.kubernetes.api.model.apps.StatefulSetBuilder +import io.fabric8.kubernetes.client.server.mock.KubernetesServer +import io.quarkus.test.junit.QuarkusTest +import mu.KotlinLogging +import org.json.JSONObject +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test + + +private val logger = KotlinLogging.logger {} + +@QuarkusTest +class K8sManagerTest { + private final val server = KubernetesServer(false,true) + private final val testResourcePath = "./src/test/resources/k8s-resource-files/" + + private final val resourceName = "test-resource" + private final val metadata: ObjectMeta = ObjectMetaBuilder().withName(resourceName).build() + + + val defaultDeployment: Deployment = DeploymentBuilder() + .withMetadata(metadata) + .withNewSpec() + .editOrNewSelector() + .withMatchLabels(mapOf("app" to "test")) + .endSelector() + .endSpec() + .build() + + val defaultStatefulSet: StatefulSet = StatefulSetBuilder() + .withMetadata(metadata) + .withNewSpec() + .editOrNewSelector() + .withMatchLabels(mapOf("app" to "test")) + .endSelector() + .endSpec() + .build() + + val defaultService: Service = ServiceBuilder() + .withMetadata(metadata) + .build() + + val defaultConfigMap: ConfigMap = ConfigMapBuilder() + .withMetadata(metadata) + .build() + + @BeforeEach + fun setUp() { + server.before() + + } + + @AfterEach + fun tearDown() { + server.after() + + } + + @Test + @DisplayName("Test handling of Deployments") + fun handleDeploymentTest() { + val manager = K8sManager(server.client) + + manager.deploy(defaultDeployment) + assertEquals(1, server.client.apps().deployments().list().items.size) + assertEquals(resourceName, server.client.apps().deployments().list().items.first().metadata.name) + + manager.remove(defaultDeployment) + assertEquals(0, server.client.apps().deployments().list().items.size) + } + + @Test + @DisplayName("Test handling of StatefulSets") + fun handleStatefulSetTest() { + val manager = K8sManager(server.client) + + manager.deploy(defaultStatefulSet) + assertEquals(1, server.client.apps().statefulSets().list().items.size) + assertEquals(resourceName, server.client.apps().statefulSets().list().items.first().metadata.name) + + manager.remove(defaultStatefulSet) + assertEquals(0, server.client.apps().statefulSets().list().items.size) + } + + @Test + @DisplayName("Test handling of Services") + fun handleServiceTest() { + val manager = K8sManager(server.client) + + manager.deploy(defaultService) + assertEquals(1, server.client.services().list().items.size) + assertEquals(resourceName, server.client.services().list().items.first().metadata.name) + + manager.remove(defaultService) + assertEquals(0, server.client.services().list().items.size) + } + + + @Test + @DisplayName("Test handling of ConfigMaps") + fun handleConfigMapTest() { + val manager = K8sManager(server.client) + + manager.deploy(defaultConfigMap) + assertEquals(1, server.client.configMaps().list().items.size) + assertEquals(resourceName, server.client.configMaps().list().items.first().metadata.name) + + manager.remove(defaultConfigMap) + assertEquals(0, server.client.configMaps().list().items.size) + } + + @Test + @DisplayName("Test handling of ServiceMontors") + fun handleServiceMonitorTest() { + val manager = K8sManager(server.client) + val servicemonitor = K8sResourceLoader(server.client) + .loadK8sResource("ServiceMonitor", testResourcePath + "test-service-monitor.yaml") + + val serviceMonitorContext = K8sContextFactory().create( + api = "v1", + scope = "Namespaced", + group = "monitoring.coreos.com", + plural = "servicemonitors" + ) + manager.deploy(servicemonitor) + + var serviceMonitors = JSONObject(server.client.customResource(serviceMonitorContext).list()) + .getJSONArray("items") + + assertEquals(1,serviceMonitors.length()) + assertEquals("test-service-monitor", serviceMonitors.getJSONObject(0).getJSONObject("metadata").getString("name")) + + manager.remove(servicemonitor) + + serviceMonitors = JSONObject(server.client.customResource(serviceMonitorContext).list()) + .getJSONArray("items") + + assertEquals(0,serviceMonitors.length()) + } + + +} \ No newline at end of file diff --git a/theodolite-quarkus/src/test/kotlin/theodolite/k8s/K8sResourceLoaderTest.kt b/theodolite-quarkus/src/test/kotlin/theodolite/k8s/K8sResourceLoaderTest.kt new file mode 100644 index 000000000..0531782bf --- /dev/null +++ b/theodolite-quarkus/src/test/kotlin/theodolite/k8s/K8sResourceLoaderTest.kt @@ -0,0 +1,86 @@ +package theodolite.k8s + +import io.fabric8.kubernetes.api.model.ConfigMap +import io.fabric8.kubernetes.api.model.Service +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.fabric8.kubernetes.api.model.apps.StatefulSet +import io.fabric8.kubernetes.client.server.mock.KubernetesServer +import io.quarkus.test.junit.QuarkusTest +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test + +@QuarkusTest +class K8sResourceLoaderTest { + private final val server = KubernetesServer(false,true) + private final val testResourcePath = "./src/test/resources/k8s-resource-files/" + + @BeforeEach + fun setUp() { + server.before() + + } + + @AfterEach + fun tearDown() { + server.after() + + } + + @Test + @DisplayName("Test loading of Deployments") + fun loadDeploymentTest() { + val loader = K8sResourceLoader(server.client) + val resource = loader.loadK8sResource("Deployment", testResourcePath + "test-deployment.yaml") + + assertTrue(resource is Deployment) + assertTrue(resource.toString().contains("name=test-deployment")) + } + + @Test + @DisplayName("Test loading of StatefulSet") + fun loadStatefulSetTest() { + val loader = K8sResourceLoader(server.client) + val resource = loader.loadK8sResource("StatefulSet", testResourcePath + "test-statefulset.yaml") + + assertTrue(resource is StatefulSet) + assertTrue(resource.toString().contains("name=test-statefulset")) + } + + @Test + @DisplayName("Test loading of Service") + fun loadServiceTest() { + val loader = K8sResourceLoader(server.client) + val resource = loader.loadK8sResource("Service", testResourcePath + "test-service.yaml") + + assertTrue(resource is Service) + assertTrue(resource.toString().contains("name=test-service")) + } + + @Test + @DisplayName("Test loading of ConfigMap") + fun loadConfigMapTest() { + val loader = K8sResourceLoader(server.client) + val resource = loader.loadK8sResource("ConfigMap", testResourcePath + "test-configmap.yaml") + + assertTrue(resource is ConfigMap) + assertTrue(resource.toString().contains("name=test-configmap")) + } + + @Test + @DisplayName("Test loading of ServiceMonitors") + fun loadServiceMonitorTest() { + val loader = K8sResourceLoader(server.client) + val resource = loader.loadK8sResource("ServiceMonitor", testResourcePath + "test-service-monitor.yaml") + + assertTrue(resource is ServiceMonitorWrapper) + if (resource is ServiceMonitorWrapper) { + assertEquals(resource.getServiceMonitorName(),"test-service-monitor") + + } + } + +} \ No newline at end of file diff --git a/theodolite-quarkus/src/test/resources/k8s-resource-files/test-configmap.yaml b/theodolite-quarkus/src/test/resources/k8s-resource-files/test-configmap.yaml new file mode 100644 index 000000000..dce11c991 --- /dev/null +++ b/theodolite-quarkus/src/test/resources/k8s-resource-files/test-configmap.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: test-configmap +data: + test: test \ No newline at end of file diff --git a/theodolite-quarkus/src/test/resources/k8s-resource-files/test-deployment.yaml b/theodolite-quarkus/src/test/resources/k8s-resource-files/test-deployment.yaml new file mode 100644 index 000000000..e9c4bda12 --- /dev/null +++ b/theodolite-quarkus/src/test/resources/k8s-resource-files/test-deployment.yaml @@ -0,0 +1,17 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-deployment +spec: + selector: + matchLabels: + app: titan-ccp-aggregation + template: + metadata: + labels: + app: titan-ccp-aggregation + spec: + containers: + - name: uc-application + image: ghcr.io/cau-se/theodolite-uc1-kstreams-app:latest + diff --git a/theodolite-quarkus/src/test/resources/k8s-resource-files/test-service-monitor.yaml b/theodolite-quarkus/src/test/resources/k8s-resource-files/test-service-monitor.yaml new file mode 100644 index 000000000..e8a0e52e1 --- /dev/null +++ b/theodolite-quarkus/src/test/resources/k8s-resource-files/test-service-monitor.yaml @@ -0,0 +1,7 @@ +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + labels: + app: titan-ccp-aggregation + appScope: titan-ccp + name: test-service-monitor \ No newline at end of file diff --git a/theodolite-quarkus/src/test/resources/k8s-resource-files/test-service.yaml b/theodolite-quarkus/src/test/resources/k8s-resource-files/test-service.yaml new file mode 100644 index 000000000..471b6db83 --- /dev/null +++ b/theodolite-quarkus/src/test/resources/k8s-resource-files/test-service.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Service +metadata: + name: test-service + labels: + app: titan-ccp-aggregation +spec: + selector: + app: titan-ccp-aggregation \ No newline at end of file diff --git a/theodolite-quarkus/src/test/resources/k8s-resource-files/test-statefulset.yaml b/theodolite-quarkus/src/test/resources/k8s-resource-files/test-statefulset.yaml new file mode 100644 index 000000000..6a8810e9e --- /dev/null +++ b/theodolite-quarkus/src/test/resources/k8s-resource-files/test-statefulset.yaml @@ -0,0 +1,16 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: test-statefulset +spec: + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: k8s.gcr.io/nginx-slim:0.8 -- GitLab