diff --git a/theodolite/.gitignore b/theodolite/.gitignore
index a1eff0e1d4dddacdbcafa2c235b28616cb53e7bf..285b6baee527835a20f0b79f1ecece49b80f7d42 100644
--- a/theodolite/.gitignore
+++ b/theodolite/.gitignore
@@ -31,3 +31,6 @@ nb-configuration.xml
 # patch
 *.orig
 *.rej
+
+# Local environment
+.env
diff --git a/theodolite/README.md b/theodolite/README.md
index fe3b4f704a2c288aa56ef8067f6d4d86823d2989..96f56c20db1d0796ba692cc497b93532517526ff 100644
--- a/theodolite/README.md
+++ b/theodolite/README.md
@@ -12,14 +12,8 @@ You can run your application in dev mode using:
 ./gradlew quarkusDev
 ```
 
-### Hint for running with k3s (or k3d)
+> **_NOTE:_**  Quarkus now ships with a Dev UI, which is available in dev mode only at http://localhost:8080/q/dev/.
 
-You may need to add the following dependencies to the `build.gradle` file when running Theodolite with k3s.
-
-```
-implementation 'org.bouncycastle:bcprov-ext-jdk15on:1.68'
-implementation 'org.bouncycastle:bcpkix-jdk15on:1.68'
-```
 
 ## Packaging and running the application
 
@@ -59,7 +53,7 @@ Or, if you don't have GraalVM installed, you can run the native executable build
 You can then execute your native executable with:
 ```./build/theodolite-0.7.0-SNAPSHOT-runner```
 
-If you want to learn more about building native executables, please consult <https://quarkus.io/guides/gradle-tooling>.
+If you want to learn more about building native executables, please consult https://quarkus.io/guides/gradle-tooling.
 
 ## Build docker images
 
diff --git a/theodolite/build.gradle b/theodolite/build.gradle
index a758bfbae778b94a9ea5d6b6a9b49a9db75ba03d..06d451cc24395824650e88d2fe516eb4015a266e 100644
--- a/theodolite/build.gradle
+++ b/theodolite/build.gradle
@@ -1,9 +1,9 @@
 plugins {
-    id 'org.jetbrains.kotlin.jvm' version "1.3.72"
-    id "org.jetbrains.kotlin.plugin.allopen" version "1.3.72"
+    id 'org.jetbrains.kotlin.jvm' version "1.5.31"
+    id "org.jetbrains.kotlin.plugin.allopen" version "1.5.31"
     id 'io.quarkus'
-    id "io.gitlab.arturbosch.detekt" version "1.15.0"   //For code style
-    id "org.jlleitschuh.gradle.ktlint" version "10.0.0" // same as above
+    id "io.gitlab.arturbosch.detekt" version "1.15.0"
+    id "org.jlleitschuh.gradle.ktlint" version "10.0.0"
 }
 
 repositories {
@@ -18,21 +18,28 @@ dependencies {
     implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
     implementation 'io.quarkus:quarkus-arc'
     implementation 'io.quarkus:quarkus-resteasy'
-    implementation 'com.google.code.gson:gson:2.8.5'
-    implementation 'org.slf4j:slf4j-simple:1.7.29'
-    implementation 'io.github.microutils:kotlin-logging:1.12.0'
-    implementation('io.fabric8:kubernetes-client:5.4.1'){force = true}
-    implementation('io.fabric8:kubernetes-model-core:5.4.1'){force = true}
-    implementation('io.fabric8:kubernetes-model-common:5.4.1'){force = true}
-    implementation 'org.apache.kafka:kafka-clients:2.7.0'
+    implementation 'io.quarkus:quarkus-kubernetes-client'
+
+    implementation 'org.bouncycastle:bcprov-ext-jdk15on:1.69'
+    implementation 'org.bouncycastle:bcpkix-jdk15on:1.69'
+
+    implementation 'com.google.code.gson:gson:2.8.9'
+    implementation 'org.slf4j:slf4j-simple:1.7.32'
+    implementation 'io.github.microutils:kotlin-logging:2.1.16'
+    //implementation('io.fabric8:kubernetes-client:5.4.1'){force = true}
+    //implementation('io.fabric8:kubernetes-model-core:5.4.1'){force = true}
+    //implementation('io.fabric8:kubernetes-model-common:5.4.1'){force = true}
+    implementation 'org.apache.kafka:kafka-clients:2.8.0'
     implementation 'khttp:khttp:1.0.0'
 
-    compile 'junit:junit:4.12'
+    // compile 'junit:junit:4.12'
 
     testImplementation 'io.quarkus:quarkus-junit5'
+    testImplementation 'io.quarkus:quarkus-test-kubernetes-client'
     testImplementation 'io.rest-assured:rest-assured'
-    testImplementation 'org.junit-pioneer:junit-pioneer:1.4.0'
-    testImplementation ('io.fabric8:kubernetes-server-mock:5.4.1'){force = true}
+    testImplementation 'org.junit-pioneer:junit-pioneer:1.5.0'
+    //testImplementation 'io.fabric8:kubernetes-server-mock:5.10.1'
+    testImplementation "org.mockito.kotlin:mockito-kotlin:4.0.0"
 }
 
 group 'theodolite'
@@ -57,6 +64,7 @@ compileKotlin {
 compileTestKotlin {
     kotlinOptions.jvmTarget = JavaVersion.VERSION_11
 }
+
 detekt {
     failFast = true // fail build on any finding
     buildUponDefaultConfig = true
diff --git a/theodolite/gradle.properties b/theodolite/gradle.properties
index d7e4187c25e76dfb440650274b2d383f75a32242..76ed8f2136f14263460bc391d420c78de200d659 100644
--- a/theodolite/gradle.properties
+++ b/theodolite/gradle.properties
@@ -1,8 +1,8 @@
 #Gradle properties
+quarkusPluginVersion=2.5.2.Final
+quarkusPlatformArtifactId=quarkus-bom
 quarkusPluginId=io.quarkus
-quarkusPluginVersion=1.10.3.Final
-quarkusPlatformGroupId=io.quarkus
-quarkusPlatformArtifactId=quarkus-universe-bom
-quarkusPlatformVersion=1.10.3.Final
+quarkusPlatformGroupId=io.quarkus.platform
+quarkusPlatformVersion=2.5.2.Final
 
-org.gradle.logging.level=INFO
\ No newline at end of file
+#org.gradle.logging.level=INFO
\ No newline at end of file
diff --git a/theodolite/gradle/wrapper/gradle-wrapper.properties b/theodolite/gradle/wrapper/gradle-wrapper.properties
index bb8b2fc26b2e572c79d7212a4f6f11057c6787f7..e750102e09269a4ac558e10a6612998e5ca4c0f2 100644
--- a/theodolite/gradle/wrapper/gradle-wrapper.properties
+++ b/theodolite/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/theodolite/gradlew.bat b/theodolite/gradlew.bat
old mode 100755
new mode 100644
diff --git a/theodolite/src/main/docker/Dockerfile.jvm b/theodolite/src/main/docker/Dockerfile.jvm
index 4d51240e0225bb571cc4a625e40c9ec76fd8f10d..03035752038fee2e5ce4c477c61adc84991f3729 100644
--- a/theodolite/src/main/docker/Dockerfile.jvm
+++ b/theodolite/src/main/docker/Dockerfile.jvm
@@ -14,14 +14,14 @@
 # docker run -i --rm -p 8080:8080 quarkus/theodolite-jvm
 #
 # If you want to include the debug port into your docker image
-# you will have to expose the debug port (default 5005) like this :  EXPOSE 8080 5050
+# you will have to expose the debug port (default 5005) like this :  EXPOSE 8080 5005
 #
 # Then run the container using :
 #
 # docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/theodolite-jvm
 #
 ###
-FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3 
+FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4 
 
 ARG JAVA_PACKAGE=java-11-openjdk-headless
 ARG RUN_JAVA_VERSION=1.3.8
@@ -38,14 +38,18 @@ RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \
     && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \
     && chown 1001 /deployments/run-java.sh \
     && chmod 540 /deployments/run-java.sh \
-    && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security
+    && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/conf/security/java.security
 
 # Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
 ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
-COPY build/lib/* /deployments/lib/
-COPY build/*-runner.jar /deployments/app.jar
+# We make four distinct layers so if there are application changes the library layers can be re-used
+COPY --chown=1001 build/quarkus-app/lib/ /deployments/lib/
+COPY --chown=1001 build/quarkus-app/*.jar /deployments/
+COPY --chown=1001 build/quarkus-app/app/ /deployments/app/
+COPY --chown=1001 build/quarkus-app/quarkus/ /deployments/quarkus/
 
 EXPOSE 8080
 USER 1001
 
 ENTRYPOINT [ "/deployments/run-java.sh" ]
+
diff --git a/theodolite/src/main/docker/Dockerfile.fast-jar b/theodolite/src/main/docker/Dockerfile.legacy-jar
similarity index 67%
rename from theodolite/src/main/docker/Dockerfile.fast-jar
rename to theodolite/src/main/docker/Dockerfile.legacy-jar
index 16853dd8f064565ae017bee9dae3597b63085006..f9dffd188570c14087bafaec838b58b61a4e5912 100644
--- a/theodolite/src/main/docker/Dockerfile.fast-jar
+++ b/theodolite/src/main/docker/Dockerfile.legacy-jar
@@ -3,25 +3,25 @@
 #
 # Before building the container image run:
 #
-# ./gradlew build -Dquarkus.package.type=fast-jar
+# ./gradlew build -Dquarkus.package.type=legacy-jar
 #
 # Then, build the image with:
 #
-# docker build -f src/main/docker/Dockerfile.fast-jar -t quarkus/theodolite-fast-jar .
+# docker build -f src/main/docker/Dockerfile.legacy-jar -t quarkus/theodolite-legacy-jar .
 #
 # Then run the container using:
 #
-# docker run -i --rm -p 8080:8080 quarkus/theodolite-fast-jar
+# docker run -i --rm -p 8080:8080 quarkus/theodolite-legacy-jar
 #
 # If you want to include the debug port into your docker image
-# you will have to expose the debug port (default 5005) like this :  EXPOSE 8080 5050
+# you will have to expose the debug port (default 5005) like this :  EXPOSE 8080 5005
 #
 # Then run the container using :
 #
-# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/theodolite-fast-jar
+# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/theodolite-legacy-jar
 #
 ###
-FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3 
+FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4 
 
 ARG JAVA_PACKAGE=java-11-openjdk-headless
 ARG RUN_JAVA_VERSION=1.3.8
@@ -38,15 +38,12 @@ RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \
     && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \
     && chown 1001 /deployments/run-java.sh \
     && chmod 540 /deployments/run-java.sh \
-    && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security
+    && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/conf/security/java.security
 
 # Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
 ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
-# We make four distinct layers so if there are application changes the library layers can be re-used
-COPY --chown=1001 build/quarkus-app/lib/ /deployments/lib/
-COPY --chown=1001 build/quarkus-app/*.jar /deployments/
-COPY --chown=1001 build/quarkus-app/app/ /deployments/app/
-COPY --chown=1001 build/quarkus-app/quarkus/ /deployments/quarkus/
+COPY build/lib/* /deployments/lib/
+COPY build/*-runner.jar /deployments/app.jar
 
 EXPOSE 8080
 USER 1001
diff --git a/theodolite/src/main/docker/Dockerfile.native b/theodolite/src/main/docker/Dockerfile.native
index 95ef4fb51d7dc1ac520fb4c5a9af1b2d0a32fd09..04a1dd6f2b6cc99511bf705eed5d98be1da25b05 100644
--- a/theodolite/src/main/docker/Dockerfile.native
+++ b/theodolite/src/main/docker/Dockerfile.native
@@ -14,8 +14,8 @@
 # docker run -i --rm -p 8080:8080 quarkus/theodolite
 #
 ###
-FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3
-WORKDIR /deployments
+FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4
+WORKDIR /deployments/
 RUN chown 1001 /deployments \
     && chmod "g+rwX" /deployments \
     && chown 1001:root /deployments
diff --git a/theodolite/src/main/docker/Dockerfile.native-distroless b/theodolite/src/main/docker/Dockerfile.native-distroless
new file mode 100644
index 0000000000000000000000000000000000000000..1ed64110dd931bf3fea9100e3318318ad40b6966
--- /dev/null
+++ b/theodolite/src/main/docker/Dockerfile.native-distroless
@@ -0,0 +1,24 @@
+####
+# This Dockerfile is used in order to build a distroless container that runs the Quarkus application in native (no JVM) mode
+#
+# Before building the container image run:
+#
+# ./gradlew build -Dquarkus.package.type=native
+#
+# Then, build the image with:
+#
+# docker build -f src/main/docker/Dockerfile.native-distroless -t quarkus/theodolite .
+#
+# Then run the container using:
+#
+# docker run -i --rm -p 8080:8080 quarkus/theodolite
+#
+###
+FROM quay.io/quarkus/quarkus-distroless-image:1.0
+WORKDIR /deployments/
+COPY build/*-runner /deployments/application
+
+EXPOSE 8080
+USER nonroot
+
+CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/ConfigMapResourceSet.kt b/theodolite/src/main/kotlin/theodolite/benchmark/ConfigMapResourceSet.kt
index 273a13170e77ae9e2f5f09869ebbc5cc06185715..27e3206ad7b60d61cab94caaef8a3279d834fe65 100644
--- a/theodolite/src/main/kotlin/theodolite/benchmark/ConfigMapResourceSet.kt
+++ b/theodolite/src/main/kotlin/theodolite/benchmark/ConfigMapResourceSet.kt
@@ -5,14 +5,10 @@ import io.fabric8.kubernetes.api.model.KubernetesResource
 import io.fabric8.kubernetes.client.KubernetesClientException
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import io.quarkus.runtime.annotations.RegisterForReflection
-import mu.KotlinLogging
 import theodolite.k8s.resourceLoader.K8sResourceLoaderFromString
 import theodolite.util.DeploymentFailedException
 import theodolite.util.YamlParserFromString
 import java.lang.IllegalArgumentException
-import java.lang.IllegalStateException
-
-private val logger = KotlinLogging.logger {}
 
 @RegisterForReflection
 @JsonDeserialize
@@ -20,30 +16,26 @@ class ConfigMapResourceSet: ResourceSet, KubernetesResource {
     lateinit var name: String
     lateinit var files: List<String> // load all files, iff files is not set
 
-    @OptIn(ExperimentalStdlibApi::class)
     override fun getResourceSet(client: NamespacedKubernetesClient): Collection<Pair<String, KubernetesResource>> {
         val loader = K8sResourceLoaderFromString(client)
         var resources: Map<String, String>
 
         try {
-            resources = client
+            resources = (client
                 .configMaps()
                 .withName(name)
-                .get()
+                .get() ?: throw DeploymentFailedException("Cannot find ConfigMap with name '$name'."))
                 .data
-                .filter { it.key.endsWith(".yaml") } // consider only yaml files, e.g. ignore readme files
+                .filter { it.key.endsWith(".yaml") }
         } catch (e: KubernetesClientException) {
-            throw DeploymentFailedException("can not find or read configmap:  $name", e)
-        } catch (e: IllegalStateException) {
-            throw DeploymentFailedException("can not find configmap or data section is null $name", e)
+            throw DeploymentFailedException("Cannot find or read ConfigMap with name '$name'.", e)
         }
 
         if (::files.isInitialized){
-            resources = resources
-                .filter { files.contains(it.key) }
+            resources = resources.filter { files.contains(it.key) }
 
             if (resources.size != files.size) {
-                throw  DeploymentFailedException("Could not find all specified Kubernetes manifests files")
+                throw DeploymentFailedException("Could not find all specified Kubernetes manifests files")
             }
         }
 
@@ -57,7 +49,7 @@ class ConfigMapResourceSet: ResourceSet, KubernetesResource {
                         it.second.key,
                         loader.loadK8sResource(it.first, it.second.value)) }
         } catch (e: IllegalArgumentException) {
-            throw  DeploymentFailedException("Can not creat resource set from specified configmap", e)
+            throw DeploymentFailedException("Can not create resource set from specified configmap", e)
         }
 
     }
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/FileSystemResourceSet.kt b/theodolite/src/main/kotlin/theodolite/benchmark/FileSystemResourceSet.kt
index 92df1bec3cd6f21b1f830e73b466f70e37a9f4c8..e769f8b9883b98d9787f2de65571fc94056c3b9c 100644
--- a/theodolite/src/main/kotlin/theodolite/benchmark/FileSystemResourceSet.kt
+++ b/theodolite/src/main/kotlin/theodolite/benchmark/FileSystemResourceSet.kt
@@ -2,10 +2,8 @@ package theodolite.benchmark
 
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize
 import io.fabric8.kubernetes.api.model.KubernetesResource
-import io.fabric8.kubernetes.client.DefaultKubernetesClient
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import io.quarkus.runtime.annotations.RegisterForReflection
-import mu.KotlinLogging
 import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
 import theodolite.util.DeploymentFailedException
 import theodolite.util.YamlParserFromFile
@@ -13,8 +11,6 @@ import java.io.File
 import java.io.FileNotFoundException
 import java.lang.IllegalArgumentException
 
-private val logger = KotlinLogging.logger {}
-
 @RegisterForReflection
 @JsonDeserialize
 class FileSystemResourceSet: ResourceSet, KubernetesResource {
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt b/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt
index 2514c32158f07f822b34697cb7c4810848bfd27b..70d8b241c84d1c6875c8da3d74cd90b3f57956d6 100644
--- a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt
+++ b/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt
@@ -1,6 +1,5 @@
 package theodolite.benchmark
 
-import com.fasterxml.jackson.annotation.JsonInclude
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize
 import io.fabric8.kubernetes.api.model.KubernetesResource
 import io.fabric8.kubernetes.client.DefaultKubernetesClient
@@ -44,7 +43,7 @@ class KubernetesBenchmark : KubernetesResource, Benchmark {
     lateinit var infrastructure: Resources
     lateinit var sut: Resources
     lateinit var loadGenerator: Resources
-    var namespace = System.getenv("NAMESPACE") ?: DEFAULT_NAMESPACE
+    private var namespace = System.getenv("NAMESPACE") ?: DEFAULT_NAMESPACE
 
     @Transient
     private var client: NamespacedKubernetesClient = DefaultKubernetesClient().inNamespace(namespace)
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSets.kt b/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSets.kt
index a4fe443e7f304c411792ee06c32592ba3c9e692a..b6364949727d4ea134e348ce8b79e22334753c1c 100644
--- a/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSets.kt
+++ b/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSets.kt
@@ -6,7 +6,6 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize
 import io.fabric8.kubernetes.api.model.KubernetesResource
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import io.quarkus.runtime.annotations.RegisterForReflection
-import mu.KotlinLogging
 import theodolite.util.DeploymentFailedException
 
 @JsonDeserialize
@@ -14,7 +13,7 @@ import theodolite.util.DeploymentFailedException
 class ResourceSets: KubernetesResource {
     @JsonProperty("configMap")
     @JsonInclude(JsonInclude.Include.NON_NULL)
-    var  configMap: ConfigMapResourceSet? = null
+    var configMap: ConfigMapResourceSet? = null
 
     @JsonProperty("fileSystem")
     @JsonInclude(JsonInclude.Include.NON_NULL)
diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt b/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt
index 9a1315e7a88f0cdcae06dbb7ead757e1c0ce9931..be3e48be406b631e03ca2fd32909a442b592f259 100644
--- a/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt
+++ b/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt
@@ -1,6 +1,5 @@
 package theodolite.evaluation
 
-import mu.KotlinLogging
 import theodolite.benchmark.BenchmarkExecution
 import theodolite.util.EvaluationFailedException
 import theodolite.util.IOHandler
@@ -12,8 +11,6 @@ import java.time.Instant
 import java.util.*
 import java.util.regex.Pattern
 
-private val logger = KotlinLogging.logger {}
-
 /**
  * Contains the analysis. Fetches a metric from Prometheus, documents it, and evaluates it.
  * @param slo Slo that is used for the analysis.
@@ -81,6 +78,6 @@ class AnalysisExecutor(
         val noWhitespace: String = WHITESPACE.matcher(this).replaceAll("-")
         val normalized: String = Normalizer.normalize(noWhitespace, Normalizer.Form.NFD)
         val slug: String = NONLATIN.matcher(normalized).replaceAll("")
-        return slug.toLowerCase(Locale.ENGLISH)
+        return slug.lowercase(Locale.ENGLISH)
     }
 }
diff --git a/theodolite/src/main/kotlin/theodolite/execution/ExecutionModes.kt b/theodolite/src/main/kotlin/theodolite/execution/ExecutionModes.kt
index bf947be01b534fd000d3967f0b72ef25978d4110..370b87e062d942a512e059ee4041dca776376ddf 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/ExecutionModes.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/ExecutionModes.kt
@@ -2,6 +2,5 @@ package theodolite.execution
 
 enum class ExecutionModes(val value: String) {
     OPERATOR("operator"),
-    YAML_EXECUTOR("yaml-executor"),
     STANDALONE("standalone")
 }
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/execution/Main.kt b/theodolite/src/main/kotlin/theodolite/execution/Main.kt
index 11f696ddd739e987e92ecec724390948714d898b..17b3d4e7b86f9e430abfb6093e79aa7865cd5923 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/Main.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/Main.kt
@@ -17,8 +17,8 @@ object Main {
         val mode = Configuration.EXECUTION_MODE
         logger.info { "Start Theodolite with mode $mode" }
 
-        when (mode.toLowerCase()) {
-            ExecutionModes.STANDALONE.value, ExecutionModes.YAML_EXECUTOR.value -> TheodoliteStandalone().start()  // TODO remove standalone (#209)
+        when (mode.lowercase()) {
+            ExecutionModes.STANDALONE.value -> TheodoliteStandalone().start()
             ExecutionModes.OPERATOR.value -> TheodoliteOperator().start()
             else -> {
                 logger.error { "MODE $mode not found" }
diff --git a/theodolite/src/main/kotlin/theodolite/execution/Shutdown.kt b/theodolite/src/main/kotlin/theodolite/execution/Shutdown.kt
index 6dedc94af864269d7d15929c69ec54aa384fc8e3..29ac39c122f68636e08c6c5ecd5a6c01751edafb 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/Shutdown.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/Shutdown.kt
@@ -14,14 +14,13 @@ private val logger = KotlinLogging.logger {}
  * @property benchmarkExecution
  * @property benchmark
  */
-class Shutdown(private val benchmarkExecution: BenchmarkExecution, private val benchmark: KubernetesBenchmark) :
-    Thread() {
+class Shutdown(private val benchmarkExecution: BenchmarkExecution, private val benchmark: KubernetesBenchmark) {
 
     /**
      * Run
      * Delete all Kubernetes resources which are related to the execution and the benchmark.
      */
-    override fun run() {
+    fun run() {
         // Build Configuration to teardown
         try {
             logger.info { "Received shutdown signal -> Shutting down" }
@@ -34,9 +33,7 @@ class Shutdown(private val benchmarkExecution: BenchmarkExecution, private val b
                     afterTeardownDelay = 5L
                 )
             deployment.teardown()
-            logger.info {
-                "Finished teardown of all benchmark resources."
-            }
+            logger.info { "Finished teardown of all benchmark resources." }
         } catch (e: Exception) {
             logger.warn {
                 "Could not delete all specified resources from Kubernetes. " +
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt
index 0b5d6040bdea1316f8fb55bcc3f204c5443f6eee..8cd469394ac8f2b67d73a0b3d2565cd0f37d7318 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt
@@ -12,30 +12,30 @@ import mu.KotlinLogging
 import java.lang.Thread.sleep
 private val logger = KotlinLogging.logger {}
 
-abstract class AbstractStateHandler<T, L, D>(
+private const val MAX_RETRIES: Int = 5
+
+abstract class AbstractStateHandler<T : HasMetadata>(
     private val client: NamespacedKubernetesClient,
-    private val crd: Class<T>,
-    private val crdList: Class<L>
-) : StateHandler<T> where T : CustomResource<*, *>?, T : HasMetadata, T : Namespaced, L : KubernetesResourceList<T> {
+    private val crd: Class<T>
+) {
 
-    private val crdClient: MixedOperation<T, L, Resource<T>> =
-        this.client.customResources(this.crd, this.crdList)
+    private val crdClient: MixedOperation<T, KubernetesResourceList<T>, Resource<T>> = this.client.resources(this.crd)
 
     @Synchronized
-    override fun setState(resourceName: String, f: (T) -> T?) {
+    fun setState(resourceName: String, f: (T) -> T?) {
         try {
-            this.crdClient
-                .list().items
-                .filter { it.metadata.name == resourceName }
-                .map { customResource -> f(customResource) }
-                .forEach { this.crdClient.updateStatus(it) }
+            val resource = this.crdClient.withName(resourceName).get()
+            if (resource != null) {
+                val resourcePatched = f(resource)
+                this.crdClient.patchStatus(resourcePatched)
+            }
         } catch (e: KubernetesClientException) {
-            logger.warn { "Status cannot be set for resource $resourceName" }
+            logger.warn(e) { "Status cannot be set for resource $resourceName." }
         }
     }
 
     @Synchronized
-    override fun getState(resourceName: String, f: (T) -> String?): String? {
+    fun getState(resourceName: String, f: (T) -> String?): String? {
         return this.crdClient
             .list().items
             .filter { it.metadata.name == resourceName }
@@ -44,13 +44,13 @@ abstract class AbstractStateHandler<T, L, D>(
     }
 
     @Synchronized
-    override fun blockUntilStateIsSet(
+    fun blockUntilStateIsSet(
         resourceName: String,
         desiredStatusString: String,
         f: (T) -> String?,
-        maxTries: Int
+        maxRetries: Int = MAX_RETRIES
     ): Boolean {
-        for (i in 0.rangeTo(maxTries)) {
+        for (i in 0.rangeTo(maxRetries)) {
             val currentStatus = getState(resourceName, f)
             if (currentStatus == desiredStatusString) {
                 return true
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateHandler.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateHandler.kt
index adca2a8b7fdb9b3e610f15e57c011679869df14c..80cee0a3a30c0734ff2e12ef0d0291015d157f9c 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateHandler.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateHandler.kt
@@ -4,10 +4,9 @@ import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import theodolite.model.crd.*
 
 class BenchmarkStateHandler(val client: NamespacedKubernetesClient) :
-    AbstractStateHandler<BenchmarkCRD, KubernetesBenchmarkList, ExecutionStatus>(
+    AbstractStateHandler<BenchmarkCRD>(
         client = client,
-        crd = BenchmarkCRD::class.java,
-        crdList = KubernetesBenchmarkList::class.java
+        crd = BenchmarkCRD::class.java
     ) {
 
     private fun getBenchmarkResourceState() = { cr: BenchmarkCRD -> cr.status.resourceSetsState }
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt
index efca98f8bf72024daa0367c6c57574f0644872e4..6e0f9fa39a3d925c0e7d6f77b01f82ef1874deb1 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt
@@ -3,14 +3,11 @@ package theodolite.execution.operator
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import io.fabric8.kubernetes.client.dsl.MixedOperation
 import io.fabric8.kubernetes.client.dsl.Resource
-import mu.KotlinLogging
 import theodolite.execution.Shutdown
 import theodolite.k8s.K8sContextFactory
 import theodolite.k8s.ResourceByLabelHandler
 import theodolite.model.crd.*
 
-private val logger = KotlinLogging.logger {}
-
 class ClusterSetup(
     private val executionCRDClient: MixedOperation<ExecutionCRD, BenchmarkExecutionList, Resource<ExecutionCRD>>,
     private val benchmarkCRDClient: MixedOperation<BenchmarkCRD, KubernetesBenchmarkList, Resource<BenchmarkCRD>>,
@@ -52,7 +49,7 @@ class ClusterSetup(
                 if (benchmark != null) {
                     execution.spec.name = execution.metadata.name
                     benchmark.spec.name = benchmark.metadata.name
-                    Shutdown(execution.spec, benchmark.spec).start()
+                    Shutdown(execution.spec, benchmark.spec).run()
                 } else {
                     throw IllegalStateException("Execution with state ${ExecutionStates.RUNNING.value} was found, but no corresponding benchmark. " +
                             "Could not initialize cluster.")
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt
index 16c4ea98ba614bb3dcdd7d9f486f4e65ae70d380..86276af35dd13457cb6c971144153612705dc420 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt
@@ -17,20 +17,21 @@ private val logger = KotlinLogging.logger {}
  * @see TheodoliteController
  * @see BenchmarkExecution
  */
-class ExecutionHandler(
+class ExecutionEventHandler(
     private val controller: TheodoliteController,
     private val stateHandler: ExecutionStateHandler
 ) : ResourceEventHandler<ExecutionCRD> {
+
     private val gson: Gson = GsonBuilder().enableComplexMapKeySerialization().create()
 
     /**
-     * Add an execution to the end of the queue of the TheodoliteController.
+     * Adds an execution to the end of the queue of the TheodoliteController.
      *
-     * @param ExecutionCRD the execution to add
+     * @param execution the execution to add
      */
     @Synchronized
     override fun onAdd(execution: ExecutionCRD) {
-        logger.info { "Add execution ${execution.metadata.name}" }
+        logger.info { "Add execution ${execution.metadata.name}." }
         execution.spec.name = execution.metadata.name
         when (this.stateHandler.getExecutionState(execution.metadata.name)) {
             ExecutionStates.NO_STATE -> this.stateHandler.setExecutionState(execution.spec.name, ExecutionStates.PENDING)
@@ -44,19 +45,19 @@ class ExecutionHandler(
     }
 
     /**
-     * Updates an execution. If this execution is running at the time this function is called, it is stopped and
+     * To be called on update of an execution. If this execution is running at the time this function is called, it is stopped and
      * added to the beginning of the queue of the TheodoliteController.
      * Otherwise, it is just added to the beginning of the queue.
      *
-     * @param oldExecutionCRD the old execution
-     * @param newExecutionCRD the new execution
+     * @param oldExecution the old execution
+     * @param newExecution the new execution
      */
     @Synchronized
     override fun onUpdate(oldExecution: ExecutionCRD, newExecution: ExecutionCRD) {
         newExecution.spec.name = newExecution.metadata.name
         oldExecution.spec.name = oldExecution.metadata.name
         if (gson.toJson(oldExecution.spec) != gson.toJson(newExecution.spec)) {
-            logger.info { "Receive update event for execution ${oldExecution.metadata.name}" }
+            logger.info { "Receive update event for execution ${oldExecution.metadata.name}." }
             when (this.stateHandler.getExecutionState(newExecution.metadata.name)) {
                 ExecutionStates.RUNNING -> {
                     this.stateHandler.setExecutionState(newExecution.spec.name, ExecutionStates.RESTART)
@@ -74,11 +75,11 @@ class ExecutionHandler(
     /**
      * Delete an execution from the queue of the TheodoliteController.
      *
-     * @param ExecutionCRD the execution to delete
+     * @param execution the execution to delete
      */
     @Synchronized
-    override fun onDelete(execution: ExecutionCRD, b: Boolean) {
-        logger.info { "Delete execution ${execution.metadata.name}" }
+    override fun onDelete(execution: ExecutionCRD, deletedFinalStateUnknown: Boolean) {
+        logger.info { "Delete execution ${execution.metadata.name}." }
         if (execution.status.executionState == ExecutionStates.RUNNING.value
             && this.controller.isExecutionRunning(execution.metadata.name)
         ) {
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt
index 9f49cf3ee4f9f62e7006dbf6697340e1af152f27..a412805621fc7868d1efc215cdf4ff81b52d914e 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt
@@ -11,10 +11,9 @@ import java.time.Instant
 import java.util.concurrent.atomic.AtomicBoolean
 
 class ExecutionStateHandler(val client: NamespacedKubernetesClient) :
-    AbstractStateHandler<ExecutionCRD, BenchmarkExecutionList, ExecutionStatus>(
+    AbstractStateHandler<ExecutionCRD>(
         client = client,
-        crd = ExecutionCRD::class.java,
-        crdList = BenchmarkExecutionList::class.java
+        crd = ExecutionCRD::class.java
     ) {
 
     private var runExecutionDurationTimer: AtomicBoolean = AtomicBoolean(false)
@@ -24,7 +23,7 @@ class ExecutionStateHandler(val client: NamespacedKubernetesClient) :
     private fun getDurationLambda() = { cr: ExecutionCRD -> cr.status.executionDuration }
 
     fun setExecutionState(resourceName: String, status: ExecutionStates): Boolean {
-        setState(resourceName) { cr -> cr.status.executionState = status.value; cr }
+        super.setState(resourceName) { cr -> cr.status.executionState = status.value; cr }
         return blockUntilStateIsSet(resourceName, status.value, getExecutionLambda())
     }
 
@@ -44,11 +43,7 @@ class ExecutionStateHandler(val client: NamespacedKubernetesClient) :
 
     fun getDurationState(resourceName: String): String {
         val status = getState(resourceName, getDurationLambda())
-        return if (status.isNullOrBlank()) {
-            "-"
-        } else {
-            status
-        }
+        return if (status.isNullOrBlank()) "-" else status
     }
 
     private fun durationToK8sString(duration: Duration): String {
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/StateHandler.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/StateHandler.kt
index e2cfaa354443cdc940abf92ef2c7474d028daecf..28563ac5a640d0226224b812a8e0691cde83942a 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/StateHandler.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/StateHandler.kt
@@ -1,15 +1,19 @@
 package theodolite.execution.operator
 
-private const val MAX_TRIES: Int = 5
+private const val MAX_RETRIES: Int = 5
 
+@Deprecated("should not be needed")
 interface StateHandler<T> {
+
     fun setState(resourceName: String, f: (T) -> T?)
+
     fun getState(resourceName: String, f: (T) -> String?): String?
+
     fun blockUntilStateIsSet(
         resourceName: String,
         desiredStatusString: String,
         f: (T) -> String?,
-        maxTries: Int = MAX_TRIES
+        maxRetries: Int = MAX_RETRIES
     ): Boolean
 
 }
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
index f066c01024fef98fc3e6e2070b0ed98235a1f8bb..a23c1506b4d46aa9f87c3a4cd05bb0a8c7dcd570 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
@@ -22,7 +22,6 @@ const val CREATED_BY_LABEL_VALUE = "theodolite"
  *
  * @see BenchmarkExecution
  * @see KubernetesBenchmark
- * @see ConcurrentLinkedDeque
  */
 
 class TheodoliteController(
@@ -34,7 +33,6 @@ class TheodoliteController(
     lateinit var executor: TheodoliteExecutor
 
     /**
-     *
      * Runs the TheodoliteController forever.
      */
     fun run() {
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt
index 135ffeaef1a5165482d9d6f7f8f5f3dffd596574..071bd06071345499d01595df72e5de4c8535b3fc 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt
@@ -91,7 +91,7 @@ class TheodoliteOperator {
             ExecutionCRD::class.java,
             RESYNC_PERIOD
         ).addEventHandler(
-            ExecutionHandler(
+            ExecutionEventHandler(
                 controller = controller,
                 stateHandler = ExecutionStateHandler(client)
             )
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/ResourceByLabelHandler.kt b/theodolite/src/main/kotlin/theodolite/k8s/ResourceByLabelHandler.kt
index 28a72c8947bffe7b57203cacf2460d7080fa7b51..518b8eae211dd064e3c12b0713382bf3b12bb1ba 100644
--- a/theodolite/src/main/kotlin/theodolite/k8s/ResourceByLabelHandler.kt
+++ b/theodolite/src/main/kotlin/theodolite/k8s/ResourceByLabelHandler.kt
@@ -96,10 +96,9 @@ class ResourceByLabelHandler(private val client: NamespacedKubernetesClient) {
     /**
      * Block until all pods with are deleted
      *
-     * @param [labelName] the label name
-     * @param [labelValue] the value of this label
+     * @param matchLabels Map of label keys to label values to be deleted
      * */
-    fun blockUntilPodsDeleted(matchLabels: MutableMap<String, String>) {
+    fun blockUntilPodsDeleted(matchLabels: Map<String, String>) {
         while (
             !this.client
                 .pods()
@@ -108,7 +107,7 @@ class ResourceByLabelHandler(private val client: NamespacedKubernetesClient) {
                 .items
                 .isNullOrEmpty()
         ) {
-            logger.info { "Wait for pods with label ${matchLabels.toString()} to be deleted." }
+            logger.info { "Wait for pods with label $matchLabels to be deleted." }
             Thread.sleep(1000)
         }
     }
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/TopicManager.kt b/theodolite/src/main/kotlin/theodolite/k8s/TopicManager.kt
index f2afd71f6e4b4cf8e7106a8fc8a9bd113d9f36e6..ed1e06571d20c53fc82439833c8a31800a48b602 100644
--- a/theodolite/src/main/kotlin/theodolite/k8s/TopicManager.kt
+++ b/theodolite/src/main/kotlin/theodolite/k8s/TopicManager.kt
@@ -99,7 +99,7 @@ class TopicManager(private val kafkaConfig: Map<String, Any>) {
 
             val toDelete = topics.filter { kafkaAdmin.listTopics().names().get().contains(it) }
 
-            if (toDelete.isNullOrEmpty()) {
+            if (toDelete.isEmpty()) {
                 deleted = true
             } else {
                 logger.info { "Deletion of Kafka topics failed, will retry in ${RETRY_TIME / 1000} seconds." }
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/AbstractK8sLoader.kt b/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/AbstractK8sLoader.kt
index 862de14e2a7a4721e15215b0a1389e14f943fe24..871b8cf43907fcb8b0b5ea501c6b47f82e56ff69 100644
--- a/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/AbstractK8sLoader.kt
+++ b/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/AbstractK8sLoader.kt
@@ -9,7 +9,7 @@ private val logger = KotlinLogging.logger {}
 abstract class AbstractK8sLoader: K8sResourceLoader {
 
     fun loadK8sResource(kind: String, resourceString: String): KubernetesResource {
-        return when (kind.replaceFirst(kind[0],kind[0].toUpperCase())) {
+        return when (kind.replaceFirst(kind[0],kind[0].uppercaseChar())) {
             "Deployment" -> loadDeployment(resourceString)
             "Service" -> loadService(resourceString)
             "ServiceMonitor" -> loadServiceMonitor(resourceString)
@@ -18,13 +18,13 @@ abstract class AbstractK8sLoader: K8sResourceLoader {
             "Execution" -> loadExecution(resourceString)
             "Benchmark" -> loadBenchmark(resourceString)
             else -> {
-                logger.error { "Error during loading of unspecified resource Kind $kind" }
-                throw java.lang.IllegalArgumentException("error while loading resource with kind: $kind")
+                logger.error { "Error during loading of unspecified resource Kind '$kind'." }
+                throw IllegalArgumentException("error while loading resource with kind: $kind")
             }
         }
     }
 
-    fun <T> loadGenericResource(resourceString: String, f: (String) -> T): T {
+    fun <T : KubernetesResource> loadGenericResource(resourceString: String, f: (String) -> T): T {
         var resource: T? = null
 
         try {
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoaderFromString.kt b/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoaderFromString.kt
index e9611aaa82870dfb676820029cf42c5aab63d672..639e4c4584d47968cd718d601f1cd7064d85eda2 100644
--- a/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoaderFromString.kt
+++ b/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoaderFromString.kt
@@ -2,42 +2,37 @@ package theodolite.k8s.resourceLoader
 
 import io.fabric8.kubernetes.api.model.ConfigMap
 import io.fabric8.kubernetes.api.model.KubernetesResource
+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.NamespacedKubernetesClient
 import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
 import theodolite.k8s.CustomResourceWrapper
 import theodolite.util.YamlParserFromString
 import java.io.ByteArrayInputStream
+import java.io.InputStream
 
 class K8sResourceLoaderFromString(private val client: NamespacedKubernetesClient): AbstractK8sLoader(),
     K8sResourceLoader {
 
-    @OptIn(ExperimentalStdlibApi::class)
-    override fun loadService(resource: String): KubernetesResource {
-        return loadGenericResource(resource) { x: String ->
-            val stream = ByteArrayInputStream(x.encodeToByteArray())
-            client.services().load(stream).get() }
+    override fun loadService(resource: String): Service {
+        return loadAnyResource(resource) { stream -> client.services().load(stream).get() }
     }
 
-    @OptIn(ExperimentalStdlibApi::class)
     override fun loadDeployment(resource: String): Deployment {
-        return loadGenericResource(resource) { x: String ->
-            val stream = ByteArrayInputStream(x.encodeToByteArray())
-            client.apps().deployments().load(stream).get() }
+        return loadAnyResource(resource) { stream -> client.apps().deployments().load(stream).get() }
     }
 
-    @OptIn(ExperimentalStdlibApi::class)
     override fun loadConfigmap(resource: String): ConfigMap {
-        return loadGenericResource(resource) { x: String ->
-            val stream = ByteArrayInputStream(x.encodeToByteArray())
-            client.configMaps().load(stream).get() }
+        return loadAnyResource(resource) { stream -> client.configMaps().load(stream).get() }
     }
 
-    @OptIn(ExperimentalStdlibApi::class)
-    override fun loadStatefulSet(resource: String): KubernetesResource {
-        return loadGenericResource(resource) { x: String ->
-            val stream = ByteArrayInputStream(x.encodeToByteArray())
-            client.apps().statefulSets().load(stream).get() }
+    override fun loadStatefulSet(resource: String): StatefulSet {
+        return loadAnyResource(resource) { stream -> client.apps().statefulSets().load(stream).get() }
+    }
+
+    private fun <T : KubernetesResource> loadAnyResource(resource: String, f: (InputStream) -> T): T {
+        return loadGenericResource(resource) { f(ByteArrayInputStream(it.encodeToByteArray())) }
     }
 
     /**
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt b/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt
index b6468fff523e57b124e144d5b9fef6477973655a..2e9ffafb83734b3daceb3e9e523e900b887d785a 100644
--- a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt
+++ b/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt
@@ -7,13 +7,21 @@ import io.fabric8.kubernetes.client.CustomResource
 import io.fabric8.kubernetes.model.annotation.Group
 import io.fabric8.kubernetes.model.annotation.Kind
 import io.fabric8.kubernetes.model.annotation.Version
+import theodolite.benchmark.BenchmarkExecution
 import theodolite.benchmark.KubernetesBenchmark
 
 @JsonDeserialize
 @Version("v1")
 @Group("theodolite.com")
 @Kind("benchmark")
-class BenchmarkCRD(
-    var spec: KubernetesBenchmark = KubernetesBenchmark(),
-    var status: BenchmarkStatus = BenchmarkStatus()
-) : CustomResource<KubernetesBenchmark, BenchmarkStatus>(), Namespaced, HasMetadata
\ No newline at end of file
+class BenchmarkCRD : CustomResource<KubernetesBenchmark, BenchmarkStatus>(), Namespaced, HasMetadata {
+
+    override fun initSpec(): KubernetesBenchmark {
+        return KubernetesBenchmark()
+    }
+
+    override fun initStatus(): BenchmarkStatus {
+        return BenchmarkStatus()
+    }
+
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionCRD.kt b/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionCRD.kt
index 659621e8c3b1d5308a10d81240575dd3d432b53f..3be0aaf2a30cd4ef279edd34854eb936cc6e7e7c 100644
--- a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionCRD.kt
+++ b/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionCRD.kt
@@ -12,7 +12,14 @@ import theodolite.benchmark.BenchmarkExecution
 @Version("v1")
 @Group("theodolite.com")
 @Kind("execution")
-class ExecutionCRD(
-    var spec: BenchmarkExecution = BenchmarkExecution(),
-    var status: ExecutionStatus = ExecutionStatus()
-) : CustomResource<BenchmarkExecution, ExecutionStatus>(), Namespaced
+class ExecutionCRD: CustomResource<BenchmarkExecution, ExecutionStatus>(), Namespaced {
+
+    override fun initSpec(): BenchmarkExecution {
+        return BenchmarkExecution()
+    }
+
+    override fun initStatus(): ExecutionStatus {
+         return ExecutionStatus()
+    }
+
+}
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStates.kt b/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStates.kt
index ad68bf380b18af1a654c201817bb7fc982804c8b..368fc39a3cba1bc702f1f0831c96637a61548358 100644
--- a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStates.kt
+++ b/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStates.kt
@@ -1,7 +1,6 @@
 package theodolite.model.crd
 
 enum class ExecutionStates(val value: String) {
-    // Execution states
     RUNNING("Running"),
     PENDING("Pending"),
     FAILURE("Failure"),
diff --git a/theodolite/src/main/kotlin/theodolite/patcher/PatcherFactory.kt b/theodolite/src/main/kotlin/theodolite/patcher/PatcherFactory.kt
index ebad5de74a6b819dbf7887dfad91faac37ed5074..88b3e19e999a889cdcb8345ca7c90c37a6e6d275 100644
--- a/theodolite/src/main/kotlin/theodolite/patcher/PatcherFactory.kt
+++ b/theodolite/src/main/kotlin/theodolite/patcher/PatcherFactory.kt
@@ -1,7 +1,6 @@
 package theodolite.patcher
 
 import io.fabric8.kubernetes.api.model.KubernetesResource
-import theodolite.util.DeploymentFailedException
 import theodolite.util.InvalidPatcherConfigurationException
 import theodolite.util.PatcherDefinition
 
diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/CompositeStrategy.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/CompositeStrategy.kt
index 41cc5c325163ade54469398e815fdb8d95c6e6cd..d6ace6f564239e73a0d59f8eb7900f50018482c5 100644
--- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/CompositeStrategy.kt
+++ b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/CompositeStrategy.kt
@@ -23,7 +23,7 @@ class CompositeStrategy(
     override fun findSuitableResource(load: LoadDimension, resources: List<Resource>): Resource? {
         var restrictedResources = resources.toList()
         for (strategy in this.restrictionStrategies) {
-            restrictedResources = restrictedResources.intersect(strategy.apply(load, resources)).toList()
+            restrictedResources = restrictedResources.intersect(strategy.apply(load, resources).toSet()).toList()
         }
         return this.searchStrategy.findSuitableResource(load, restrictedResources)
     }
diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/FullSearch.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/FullSearch.kt
index cb0dd2d8ab528e42e8290f59f26c8b9b32f384c7..83c4abbdf44f1a1c2f3a27714d796580feedee49 100644
--- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/FullSearch.kt
+++ b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/FullSearch.kt
@@ -22,7 +22,7 @@ class FullSearch(benchmarkExecutor: BenchmarkExecutor) : SearchStrategy(benchmar
         for (res in resources) {
             logger.info { "Running experiment with load '${load.get()}' and resources '${res.get()}'" }
             val result = this.benchmarkExecutor.runExperiment(load, res)
-            if (result && minimalSuitableResources != null) {
+            if (result && minimalSuitableResources == null) {
                 minimalSuitableResources = res
             }
         }
diff --git a/theodolite/src/main/kotlin/theodolite/util/Configuration.kt b/theodolite/src/main/kotlin/theodolite/util/Configuration.kt
index 7b1232cd9ba72344cdb438f974cd6c4d17fd690d..0a63cfa84de9e60fba04707372ef884d77a1543b 100644
--- a/theodolite/src/main/kotlin/theodolite/util/Configuration.kt
+++ b/theodolite/src/main/kotlin/theodolite/util/Configuration.kt
@@ -7,8 +7,7 @@ private const val DEFAULT_NAMESPACE = "default"
 private const val DEFAULT_COMPONENT_NAME = "theodolite-operator"
 
 
-class Configuration(
-) {
+class Configuration {
     companion object {
         val NAMESPACE = System.getenv("NAMESPACE") ?: DEFAULT_NAMESPACE
         val COMPONENT_NAME = System.getenv("COMPONENT_NAME") ?: DEFAULT_COMPONENT_NAME
diff --git a/theodolite/src/main/kotlin/theodolite/util/EvaluationFailedException.kt b/theodolite/src/main/kotlin/theodolite/util/EvaluationFailedException.kt
index c67ed7ffd79afc733a97dae05c3203f8e78722ea..ebdf5a37b4e82c8d4b1870d065f5e77133154735 100644
--- a/theodolite/src/main/kotlin/theodolite/util/EvaluationFailedException.kt
+++ b/theodolite/src/main/kotlin/theodolite/util/EvaluationFailedException.kt
@@ -1,4 +1,3 @@
 package theodolite.util
 
-class EvaluationFailedException(message: String, e: Exception? = null) : ExecutionFailedException(message,e) {
-}
+class EvaluationFailedException(message: String, e: Exception? = null) : ExecutionFailedException(message,e)
diff --git a/theodolite/src/main/kotlin/theodolite/util/ExecutionFailedException.kt b/theodolite/src/main/kotlin/theodolite/util/ExecutionFailedException.kt
index 6566a451a3e273214f59962531b6bd17b33a850d..2e181dad35786d386226f8a57dfffbc2c3966754 100644
--- a/theodolite/src/main/kotlin/theodolite/util/ExecutionFailedException.kt
+++ b/theodolite/src/main/kotlin/theodolite/util/ExecutionFailedException.kt
@@ -1,4 +1,3 @@
 package theodolite.util
 
-open class ExecutionFailedException(message: String, e: Exception? = null) : TheodoliteException(message,e) {
-}
\ No newline at end of file
+open class ExecutionFailedException(message: String, e: Exception? = null) : TheodoliteException(message,e)
diff --git a/theodolite/src/main/kotlin/theodolite/util/ExecutionStateComparator.kt b/theodolite/src/main/kotlin/theodolite/util/ExecutionStateComparator.kt
index 8a6b0e9a49362afa401cf3c1279e7f7f6cddf85d..c8f0160c72ae85547e2988ea368c8d1a7a1b5651 100644
--- a/theodolite/src/main/kotlin/theodolite/util/ExecutionStateComparator.kt
+++ b/theodolite/src/main/kotlin/theodolite/util/ExecutionStateComparator.kt
@@ -6,12 +6,11 @@ import theodolite.model.crd.ExecutionStates
 class ExecutionStateComparator(private val preferredState: ExecutionStates): Comparator<ExecutionCRD> {
 
     /**
-     * Simple comparator which can be used to order a list of [ExecutionCRD] such that executions with
+     * Simple comparator which can be used to order a list of [ExecutionCRD]s such that executions with
      * status [ExecutionStates.RESTART] are before all other executions.
      */
     override fun compare(p0: ExecutionCRD, p1: ExecutionCRD): Int {
        return when {
-            (p0 == null && p1 == null) -> 0
             (p0.status.executionState == preferredState.value) -> -1
             else -> 1
         }
diff --git a/theodolite/src/main/kotlin/theodolite/util/IOHandler.kt b/theodolite/src/main/kotlin/theodolite/util/IOHandler.kt
index 57032189412d0937e4d77ddbf4354c78ffcc71a3..8b580c733ab7ae527d99c676223f4b09b392c6fd 100644
--- a/theodolite/src/main/kotlin/theodolite/util/IOHandler.kt
+++ b/theodolite/src/main/kotlin/theodolite/util/IOHandler.kt
@@ -85,7 +85,7 @@ class IOHandler {
      * @param data the data to write in the file as String
      */
     fun writeStringToTextFile(fileURL: String, data: String) {
-        val outputFile = File("$fileURL")
+        val outputFile = File(fileURL)
         outputFile.printWriter().use {
             it.println(data)
         }
diff --git a/theodolite/src/main/kotlin/theodolite/util/YamlParserFromString.kt b/theodolite/src/main/kotlin/theodolite/util/YamlParserFromString.kt
index 61db189ee99fa5fe36113b0fdecf589ad1114852..0e197908a501c0f6b89761a61989580b18e21f64 100644
--- a/theodolite/src/main/kotlin/theodolite/util/YamlParserFromString.kt
+++ b/theodolite/src/main/kotlin/theodolite/util/YamlParserFromString.kt
@@ -2,9 +2,6 @@ package theodolite.util
 
 import org.yaml.snakeyaml.Yaml
 import org.yaml.snakeyaml.constructor.Constructor
-import java.io.File
-import java.io.FileInputStream
-import java.io.InputStream
 
 /**
  * The YamlParser parses a YAML string
diff --git a/theodolite/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt b/theodolite/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt
index 46758583172c3fcd6417e17ff5bab85f8659734b..b7fc2d9f1b2d5110f974b3805584baa3903d5eb1 100644
--- a/theodolite/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt
@@ -3,7 +3,7 @@ package theodolite
 import io.fabric8.kubernetes.api.model.apps.Deployment
 import io.fabric8.kubernetes.client.DefaultKubernetesClient
 import io.quarkus.test.junit.QuarkusTest
-import io.smallrye.common.constraint.Assert.assertTrue
+import org.junit.jupiter.api.Assertions.assertTrue
 import org.junit.jupiter.api.Test
 import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
 import theodolite.patcher.PatcherFactory
diff --git a/theodolite/src/test/kotlin/theodolite/benchmark/ConfigMapResourceSetTest.kt b/theodolite/src/test/kotlin/theodolite/benchmark/ConfigMapResourceSetTest.kt
index 2cc8f931418e28ae8841b592f93df8d88440cf3c..bc3263aa5fd06a8a19609d9f677db51f173cf54f 100644
--- a/theodolite/src/test/kotlin/theodolite/benchmark/ConfigMapResourceSetTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/benchmark/ConfigMapResourceSetTest.kt
@@ -8,16 +8,17 @@ 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 io.smallrye.common.constraint.Assert.assertTrue
-import junit.framework.Assert.assertEquals
 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.Test
+import org.junit.jupiter.api.assertThrows
 import theodolite.k8s.CustomResourceWrapper
 import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
 import theodolite.util.DeploymentFailedException
 
-private val testResourcePath = "./src/test/resources/k8s-resource-files/"
+private const val testResourcePath = "./src/test/resources/k8s-resource-files/"
 
 @QuarkusTest
 class ConfigMapResourceSetTest {
@@ -206,21 +207,17 @@ class ConfigMapResourceSetTest {
 
         val createdResourcesSet = resourceSet.getResourceSet(server.client)
 
-        assertEquals(1,createdResourcesSet.size )
+        assertEquals(1, createdResourcesSet.size )
         assert(createdResourcesSet.toMutableSet().first().second is Deployment)
     }
 
 
-    @Test()
+    @Test
     fun testConfigMapNotExist() {
         val resourceSet = ConfigMapResourceSet()
         resourceSet.name = "test-configmap1"
-        lateinit var ex: Exception
-        try {
+        assertThrows<DeploymentFailedException> {
             resourceSet.getResourceSet(server.client)
-        } catch (e: Exception) {
-            ex = e
         }
-        assertTrue(ex is DeploymentFailedException)
     }
 }
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/benchmark/FileSystemResourceSetTest.kt b/theodolite/src/test/kotlin/theodolite/benchmark/FileSystemResourceSetTest.kt
index 59ad2be3248f67442ce352788f8b94b26f3b6b90..f15685c8e0ecd67b99caabb77f68cc35a78b47f2 100644
--- a/theodolite/src/test/kotlin/theodolite/benchmark/FileSystemResourceSetTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/benchmark/FileSystemResourceSetTest.kt
@@ -5,16 +5,16 @@ 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.smallrye.common.constraint.Assert.assertTrue
-import junit.framework.Assert.assertEquals
 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.Test
+import org.junit.jupiter.api.assertThrows
 import theodolite.k8s.CustomResourceWrapper
 import theodolite.util.DeploymentFailedException
-import java.lang.IllegalStateException
 
-private val testResourcePath = "./src/test/resources/k8s-resource-files/"
+private const val testResourcePath = "./src/test/resources/k8s-resource-files/"
 
 class FileSystemResourceSetTest {
 
@@ -104,12 +104,8 @@ class FileSystemResourceSetTest {
     fun testWrongPath() {
         val resourceSet = FileSystemResourceSet()
         resourceSet.path = "/abc/not-exist"
-        lateinit var ex: Exception
-        try {
+        assertThrows<DeploymentFailedException> {
             resourceSet.getResourceSet(server.client)
-        } catch (e: Exception) {
-            println(e)
-            ex = e
         }
-        assertTrue(ex is DeploymentFailedException)    }
+    }
 }
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkCRDummy.kt b/theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkCRDummy.kt
index b4d5950542c40aba0f39b1be772823a3de389793..cbddbfbfc5d6f838677c6d04b0a0c79f59d8bc66 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkCRDummy.kt
+++ b/theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkCRDummy.kt
@@ -8,7 +8,7 @@ import theodolite.util.KafkaConfig
 class BenchmarkCRDummy(name: String) {
 
     private val benchmark = KubernetesBenchmark()
-    private val benchmarkCR = BenchmarkCRD(benchmark)
+    private val benchmarkCR = BenchmarkCRD()
 
     fun getCR(): BenchmarkCRD {
         return benchmarkCR
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt
index 51347d41b396bf375c14d5580b0f2619ce5b518c..e8010f345140f41dc2edfbe387316f6d21511915 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt
+++ b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt
@@ -9,7 +9,7 @@ class ExecutionCRDummy(name: String, benchmark: String) {
 
     private val execution = BenchmarkExecution()
     private val executionState = ExecutionStatus()
-    private val executionCR = ExecutionCRD(execution, executionState)
+    private val executionCR = ExecutionCRD()
 
     fun getCR(): ExecutionCRD {
         return this.executionCR
@@ -25,6 +25,7 @@ class ExecutionCRDummy(name: String, benchmark: String) {
         executionCR.metadata.name = name
         executionCR.kind = "Execution"
         executionCR.apiVersion = "v1"
+        executionCR.status = executionState
 
         // configure execution
         val loadType = BenchmarkExecution.LoadDefinition()
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt
index c850e84f225bab7fc0b5eb145f9e655567de43d0..ec14d7d8fefb384efc53d79f3b9772c4ccc1e270 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt
@@ -1,227 +1,266 @@
 package theodolite.execution.operator
 
-import io.fabric8.kubernetes.api.model.KubernetesResource
-import io.fabric8.kubernetes.client.informers.SharedInformerFactory
+import io.fabric8.kubernetes.api.model.KubernetesResourceList
+import io.fabric8.kubernetes.client.dsl.MixedOperation
+import io.fabric8.kubernetes.client.dsl.Resource
 import io.fabric8.kubernetes.client.server.mock.KubernetesServer
 import io.quarkus.test.junit.QuarkusTest
+import io.quarkus.test.kubernetes.client.KubernetesTestServer
+import io.quarkus.test.kubernetes.client.WithKubernetesTestServer
 import org.junit.jupiter.api.AfterEach
-import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Assertions.*
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.DisplayName
 import org.junit.jupiter.api.Test
-import theodolite.k8s.K8sManager
-import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
+import org.junit.jupiter.params.ParameterizedTest
+import org.junit.jupiter.params.provider.Arguments
+import org.junit.jupiter.params.provider.MethodSource
+import org.mockito.kotlin.*
+import theodolite.model.crd.ExecutionCRD
 import theodolite.model.crd.ExecutionStates
+import theodolite.model.crd.ExecutionStatus
+import java.io.FileInputStream
 import java.lang.Thread.sleep
+import java.util.stream.Stream
 
+// TODO move somewhere else
+typealias ExecutionClient = MixedOperation<ExecutionCRD, KubernetesResourceList<ExecutionCRD>, Resource<ExecutionCRD>>
 
-private const val RESYNC_PERIOD = 1000 * 1000.toLong()
-
-
+@WithKubernetesTestServer
 @QuarkusTest
 class ExecutionEventHandlerTest {
-    private final val server = KubernetesServer(false, true)
-    private val testResourcePath = "./src/test/resources/k8s-resource-files/"
-    private final val executionName = "example-execution"
-    lateinit var factory: SharedInformerFactory
-    lateinit var executionVersion1: KubernetesResource
-    lateinit var executionVersion2: KubernetesResource
-    lateinit var stateHandler: ExecutionStateHandler
-    lateinit var manager: K8sManager
+
+    @KubernetesTestServer
+    private lateinit var server: KubernetesServer
+
+    lateinit var executionClient: ExecutionClient
+
     lateinit var controller: TheodoliteController
 
+    lateinit var stateHandler: ExecutionStateHandler
+
+    lateinit var eventHandler: ExecutionEventHandler
+
     @BeforeEach
     fun setUp() {
         server.before()
-        val operator = TheodoliteOperator()
-        this.controller = operator.getController(
-            client = server.client,
-            executionStateHandler = operator.getExecutionStateHandler(client = server.client),
-            benchmarkStateChecker = operator.getBenchmarkStateChecker(client = server.client)
-        )
-
-        this.factory = operator.getExecutionEventHandler(this.controller, server.client)
-        this.stateHandler = TheodoliteOperator().getExecutionStateHandler(client = server.client)
-
-        this.executionVersion1 = K8sResourceLoaderFromFile(server.client)
-            .loadK8sResource("Execution", testResourcePath + "test-execution.yaml")
 
-        this.executionVersion2 = K8sResourceLoaderFromFile(server.client)
-            .loadK8sResource("Execution", testResourcePath + "test-execution-update.yaml")
+        this.server.client
+            .apiextensions().v1()
+            .customResourceDefinitions()
+            .load(FileInputStream("crd/crd-execution.yaml"))
+            .create()
 
-        this.stateHandler = operator.getExecutionStateHandler(server.client)
+        this.executionClient = this.server.client.resources(ExecutionCRD::class.java)
 
-        this.manager = K8sManager((server.client))
+        this.controller = mock()
+        this.stateHandler = ExecutionStateHandler(server.client)
+        this.eventHandler = ExecutionEventHandler(this.controller, this.stateHandler)
     }
 
     @AfterEach
     fun tearDown() {
         server.after()
-        factory.stopAllRegisteredInformers()
     }
 
     @Test
-    @DisplayName("Check namespaced property of informers")
-    fun testNamespaced() {
-        manager.deploy(executionVersion1)
-        factory.startAllRegisteredInformers()
-        server.lastRequest
-        // the second request must be namespaced (this is the first `GET` request)
-        assert(
-            server
-                .lastRequest
-                .toString()
-                .contains("namespaces")
-        )
+    fun testCrdRegistered() {
+        val crds = this.server.client.apiextensions().v1().customResourceDefinitions().list();
+        assertEquals(1, crds.items.size)
+        assertEquals("execution", crds.items[0].spec.names.kind)
     }
 
     @Test
-    @DisplayName("Test onAdd method for executions without execution state")
-    fun testWithoutState() {
-        manager.deploy(executionVersion1)
-        factory.startAllRegisteredInformers()
-        sleep(500)
-        assertEquals(
-            ExecutionStates.PENDING,
-            stateHandler.getExecutionState(
-                resourceName = executionName
-            )
-        )
+    fun testExecutionDeploy() {
+        getExecutionFromSystemResource("k8s-resource-files/test-execution.yaml").create()
+
+        val executions = executionClient.list().items
+        assertEquals(1, executions.size)
     }
 
     @Test
-    @DisplayName("Test onAdd method for executions with execution state `RUNNING`")
-    fun testWithStateIsRunning() {
-        manager.deploy(executionVersion1)
-        stateHandler
-            .setExecutionState(
-                resourceName = executionName,
-                status = ExecutionStates.RUNNING
-            )
-        factory.startAllRegisteredInformers()
-        sleep(500)
-        assertEquals(
-            ExecutionStates.RESTART,
-            stateHandler.getExecutionState(
-                resourceName = executionName
-            )
-        )
+    fun testStatusSet() {
+        val execCreated = getExecutionFromSystemResource("k8s-resource-files/test-execution.yaml").create()
+        assertNotNull(execCreated.status)
+        val execResponse = this.executionClient.withName(execCreated.metadata.name)
+        val execResponseItem = execResponse.get()
+        assertNotNull(execResponseItem.status)
     }
 
     @Test
-    @DisplayName("Test onUpdate method for execution with execution state `PENDING`")
-    fun testOnUpdatePending() {
-        manager.deploy(executionVersion1)
-
-        factory.startAllRegisteredInformers()
-        sleep(500)
+    @DisplayName("Test onAdd method for executions without execution state")
+    fun testOnAddWithoutStatus() {
+        // Create first version of execution resource
+        val executionResource = getExecutionFromSystemResource("k8s-resource-files/test-execution.yaml")
+        val execution = executionResource.create()
+        val executionName = execution.metadata.name
 
-        assertEquals(
-            ExecutionStates.PENDING,
-            stateHandler.getExecutionState(
-                resourceName = executionName
-            )
-        )
+        // Get execution from server
+        val executionResponse = this.executionClient.withName(executionName).get()
+        this.eventHandler.onAdd(executionResponse)
 
-        manager.deploy(executionVersion2)
-        assertEquals(
-            ExecutionStates.PENDING,
-            stateHandler.getExecutionState(
-                resourceName = executionName
-            )
-        )
+        assertEquals(ExecutionStates.PENDING.value, this.executionClient.withName(executionName).get().status.executionState)
     }
 
     @Test
-    @DisplayName("Test onUpdate method for execution with execution state `FINISHED`")
-    fun testOnUpdateFinished() {
-        manager.deploy(executionVersion1)
-        factory.startAllRegisteredInformers()
-        sleep(500)
-
-        stateHandler.setExecutionState(
-            resourceName = executionName,
-            status = ExecutionStates.FINISHED
-        )
-
-        manager.deploy(executionVersion2)
-        sleep(500)
-
-        assertEquals(
-            ExecutionStates.PENDING,
-            stateHandler.getExecutionState(
-                resourceName = executionName
-            )
-        )
+    @DisplayName("Test onAdd method for executions with execution state `RUNNING`")
+    fun testOnAddWithStatusRunning() {
+        // Create first version of execution resource
+        val executionResource = getExecutionFromSystemResource("k8s-resource-files/test-execution.yaml")
+        val execution = executionResource.create()
+        val executionName = execution.metadata.name
+        stateHandler.setExecutionState(executionName, ExecutionStates.RUNNING)
+
+        // Update status of execution
+        execution.status.executionState = ExecutionStates.RUNNING.value
+        executionResource.patchStatus(execution)
+
+
+        // Get execution from server
+        val executionResponse = this.executionClient.withName(executionName).get()
+        // Assert that status at server matches set status
+        assertEquals(ExecutionStates.RUNNING.value, this.executionClient.withName(executionName).get().status.executionState)
+
+        whenever(this.controller.isExecutionRunning(executionName)).thenReturn(true)
+
+        this.eventHandler.onAdd(executionResponse)
+
+        verify(this.controller).stop(true)
+        assertEquals(ExecutionStates.RESTART.value, this.executionClient.withName(executionName).get().status.executionState)
     }
 
     @Test
-    @DisplayName("Test onUpdate method for execution with execution state `FAILURE`")
-    fun testOnUpdateFailure() {
-        manager.deploy(executionVersion1)
-        factory.startAllRegisteredInformers()
-        sleep(500)
-
-        stateHandler.setExecutionState(
-            resourceName = executionName,
-            status = ExecutionStates.FAILURE
-        )
-
-        manager.deploy(executionVersion2)
-        sleep(500)
-
-        assertEquals(
-            ExecutionStates.PENDING,
-            stateHandler.getExecutionState(
-                resourceName = executionName
-            )
-        )
+    @DisplayName("Test onUpdate method for execution with no status")
+    fun testOnUpdateWithoutStatus() {
+        // Create first version of execution resource
+        val firstExecutionResource = getExecutionFromSystemResource("k8s-resource-files/test-execution.yaml")
+        val firstExecution = firstExecutionResource.create()
+        val executionName = firstExecution.metadata.name
+
+        // Get execution from server
+        val firstExecutionResponse = this.executionClient.withName(executionName).get()
+        // Assert that execution at server has no status
+        assertEquals("", firstExecutionResponse.status.executionState)
+
+        // Create new version of execution and update at server
+        getExecutionFromSystemResource("k8s-resource-files/test-execution-update.yaml").createOrReplace()
+        // Get execution from server
+        val secondExecutionResponse = this.executionClient.withName(executionName).get()
+
+        this.eventHandler.onUpdate(firstExecutionResponse, secondExecutionResponse)
+
+        // Get execution from server and assert that new status matches expected one
+        assertEquals(ExecutionStates.PENDING.value, this.executionClient.withName(executionName).get().status.executionState)
     }
 
+    @ParameterizedTest
+    @MethodSource("provideOnUpdateTestArguments")
+    @DisplayName("Test onUpdate method for execution with different status")
+    fun testOnUpdateWithStatus(beforeState: ExecutionStates, expectedState: ExecutionStates) {
+        // Create first version of execution resource
+        val firstExecutionResource = getExecutionFromSystemResource("k8s-resource-files/test-execution.yaml")
+        val firstExecution = firstExecutionResource.create()
+        val executionName = firstExecution.metadata.name
+
+        // Update status of execution
+        firstExecution.status.executionState = beforeState.value
+        firstExecutionResource.patchStatus(firstExecution)
+
+        // Get execution from server
+        val firstExecutionResponse = this.executionClient.withName(executionName).get()
+        // Assert that status at server matches set status
+        assertEquals(beforeState.value, firstExecutionResponse.status.executionState)
+
+        // Create new version of execution and update at server
+        getExecutionFromSystemResource("k8s-resource-files/test-execution-update.yaml").createOrReplace()
+        // Get execution from server
+        val secondExecutionResponse = this.executionClient.withName(executionName).get()
+
+        this.eventHandler.onUpdate(firstExecutionResponse, secondExecutionResponse)
+
+        // Get execution from server and assert that new status matches expected one
+        assertEquals(expectedState.value, this.executionClient.withName(executionName).get().status.executionState)
+    }
 
     @Test
-    @DisplayName("Test onUpdate method for execution with execution state `RUNNING`")
-    fun testOnUpdateRunning() {
-        manager.deploy(executionVersion1)
-        factory.startAllRegisteredInformers()
-        sleep(500)
-
-        stateHandler.setExecutionState(
-            resourceName = executionName,
-            status = ExecutionStates.RUNNING
-        )
-
-        manager.deploy(executionVersion2)
-        sleep(500)
-
-        assertEquals(
-            ExecutionStates.RESTART,
-            stateHandler.getExecutionState(
-                resourceName = executionName
-            )
-        )
+    fun testOnDeleteWithExecutionRunning() {
+        // Create first version of execution resource
+        val firstExecutionResource = getExecutionFromSystemResource("k8s-resource-files/test-execution.yaml")
+        val firstExecution = firstExecutionResource.create()
+        val executionName = firstExecution.metadata.name
+
+        // Update status of execution to be running
+        firstExecution.status.executionState = ExecutionStates.RUNNING.value
+        firstExecutionResource.patchStatus(firstExecution)
+
+        // Get execution from server
+        val firstExecutionResponse = this.executionClient.withName(executionName).get()
+        // Assert that execution created at server
+        assertNotNull(firstExecutionResponse)
+
+        // Delete execution
+        this.executionClient.delete(firstExecutionResponse)
+
+        // Get execution from server
+        val secondExecutionResponse = this.executionClient.withName(executionName).get()
+        // Assert that execution created at server
+        assertNull(secondExecutionResponse)
+
+        // We consider execution to be running
+        whenever(this.controller.isExecutionRunning(executionName)).thenReturn(true)
+
+        this.eventHandler.onDelete(firstExecutionResponse, true)
+
+        verify(this.controller).stop(false)
     }
 
     @Test
-    @DisplayName("Test onUpdate method for execution with execution state `RESTART`")
-    fun testOnUpdateRestart() {
-        manager.deploy(executionVersion1)
-        factory.startAllRegisteredInformers()
-        sleep(500)
-
-        stateHandler.setExecutionState(
-            resourceName = executionName,
-            status = ExecutionStates.RESTART
-        )
-
-        manager.deploy(executionVersion2)
-        sleep(500)
-
-        assertEquals(
-            ExecutionStates.RESTART,
-            stateHandler.getExecutionState(
-                resourceName = executionName
+    fun testOnDeleteWithExecutionNotRunning() {
+        // Create first version of execution resource
+        val firstExecutionResource = getExecutionFromSystemResource("k8s-resource-files/test-execution.yaml")
+        val firstExecution = firstExecutionResource.create()
+        val executionName = firstExecution.metadata.name
+
+        // Update status of execution to be running
+        firstExecution.status.executionState = ExecutionStates.RUNNING.value
+        firstExecutionResource.patchStatus(firstExecution)
+
+        // Get execution from server
+        val firstExecutionResponse = this.executionClient.withName(executionName).get()
+        // Assert that execution created at server
+        assertNotNull(firstExecutionResponse)
+
+        // Delete execution
+        this.executionClient.delete(firstExecutionResponse)
+
+        // Get execution from server
+        val secondExecutionResponse = this.executionClient.withName(executionName).get()
+        // Assert that execution created at server
+        assertNull(secondExecutionResponse)
+
+        // We consider execution to be running
+        whenever(this.controller.isExecutionRunning(executionName)).thenReturn(false)
+        
+        this.eventHandler.onDelete(firstExecutionResponse, true)
+
+        verify(this.controller, never()).stop(false)
+    }
+
+    private fun getExecutionFromSystemResource(resourceName: String): Resource<ExecutionCRD> {
+        return executionClient.load(ClassLoader.getSystemResourceAsStream(resourceName))
+    }
+
+    companion object {
+        @JvmStatic
+        fun provideOnUpdateTestArguments(): Stream<Arguments> =
+            Stream.of(
+                // before state -> expected state
+                Arguments.of(ExecutionStates.PENDING, ExecutionStates.PENDING),
+                Arguments.of(ExecutionStates.FINISHED, ExecutionStates.PENDING),
+                Arguments.of(ExecutionStates.FAILURE, ExecutionStates.PENDING),
+                Arguments.of(ExecutionStates.RUNNING, ExecutionStates.RESTART),
+                Arguments.of(ExecutionStates.RESTART, ExecutionStates.RESTART)
             )
-        )
     }
+
 }
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTestWithInformer.kt b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTestWithInformer.kt
new file mode 100644
index 0000000000000000000000000000000000000000..77a3986f1e078c9b2557a9b4b0a19335a8267ab2
--- /dev/null
+++ b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTestWithInformer.kt
@@ -0,0 +1,283 @@
+package theodolite.execution.operator
+
+import io.fabric8.kubernetes.client.dsl.Resource
+import io.fabric8.kubernetes.client.server.mock.KubernetesServer
+import io.quarkus.test.junit.QuarkusTest
+import io.quarkus.test.kubernetes.client.KubernetesTestServer
+import io.quarkus.test.kubernetes.client.WithKubernetesTestServer
+import org.junit.jupiter.api.*
+import org.junit.jupiter.api.Assertions.*
+import org.junit.jupiter.params.ParameterizedTest
+import org.junit.jupiter.params.provider.Arguments
+import org.junit.jupiter.params.provider.MethodSource
+import org.mockito.kotlin.*
+import theodolite.model.crd.ExecutionCRD
+import theodolite.model.crd.ExecutionStates
+import java.io.FileInputStream
+import java.util.concurrent.CountDownLatch
+import java.util.stream.Stream
+
+@WithKubernetesTestServer
+@QuarkusTest
+class ExecutionEventHandlerTestWithInformer {
+
+    @KubernetesTestServer
+    private lateinit var server: KubernetesServer
+
+    lateinit var executionClient: ExecutionClient
+
+    lateinit var controller: TheodoliteController
+
+    lateinit var stateHandler: ExecutionStateHandler
+
+    lateinit var addCountDownLatch: CountDownLatch
+    lateinit var updateCountDownLatch: CountDownLatch
+    lateinit var deleteCountDownLatch: CountDownLatch
+
+    lateinit var eventHandler: ExecutionEventHandlerWrapper
+
+    @BeforeEach
+    fun setUp() {
+        server.before()
+
+        this.server.client
+            .apiextensions().v1()
+            .customResourceDefinitions()
+            .load(FileInputStream("crd/crd-execution.yaml"))
+            .create()
+
+        this.executionClient = this.server.client.resources(ExecutionCRD::class.java)
+
+        this.controller = mock()
+        this.stateHandler = ExecutionStateHandler(server.client)
+        this.addCountDownLatch = CountDownLatch(1)
+        this.updateCountDownLatch = CountDownLatch(2)
+        this.deleteCountDownLatch = CountDownLatch(1)
+        this.eventHandler = ExecutionEventHandlerWrapper(
+            ExecutionEventHandler(this.controller, this.stateHandler),
+            { addCountDownLatch.countDown() },
+            { updateCountDownLatch.countDown() },
+            { deleteCountDownLatch.countDown() }
+        )
+    }
+
+    @AfterEach
+    fun tearDown() {
+        server.after()
+        this.server.client.informers().stopAllRegisteredInformers()
+    }
+
+    @Test
+    fun testCrdRegistered() {
+        val crds = this.server.client.apiextensions().v1().customResourceDefinitions().list();
+        assertEquals(1, crds.items.size)
+        assertEquals("execution", crds.items[0].spec.names.kind)
+    }
+
+    @Test
+    fun testExecutionDeploy() {
+        getExecutionFromSystemResource("k8s-resource-files/test-execution.yaml").create()
+
+        val executions = executionClient.list().items
+        assertEquals(1, executions.size)
+    }
+
+    @Test
+    fun testStatusSet() {
+        val execCreated = getExecutionFromSystemResource("k8s-resource-files/test-execution.yaml").create()
+        assertNotNull(execCreated.status)
+        val execResponse = this.executionClient.withName(execCreated.metadata.name)
+        val execResponseItem = execResponse.get()
+        assertNotNull(execResponseItem.status)
+    }
+
+    @Test
+    @DisplayName("Test onAdd method for executions without execution state")
+    fun testOnAddWithoutStatus() {
+        // Create first version of execution resource
+        val executionResource = getExecutionFromSystemResource("k8s-resource-files/test-execution.yaml")
+        val execution = executionResource.create()
+        val executionName = execution.metadata.name
+
+        // Start informer
+        this.executionClient.inform(eventHandler)
+
+        // Await informer called
+        this.addCountDownLatch.await()
+        assertEquals(ExecutionStates.PENDING.value, this.executionClient.withName(executionName).get().status.executionState)
+    }
+
+    @Test
+    @DisplayName("Test onAdd method for executions with execution state `RUNNING`")
+    @Disabled("Flaky test due to multiple informer events.")
+    fun testOnAddWithStatusRunning() {
+        // Create first version of execution resource
+        val executionResource = getExecutionFromSystemResource("k8s-resource-files/test-execution.yaml")
+        val executionName = executionResource.get().metadata.name
+
+        whenever(this.controller.isExecutionRunning(executionName)).thenReturn(true)
+
+        // Start informer
+        this.executionClient.inform(eventHandler)
+
+        val execution = executionResource.create()
+
+        // Update status of execution
+        execution.status.executionState = ExecutionStates.RUNNING.value
+        executionResource.patchStatus(execution)
+
+        // Assert that status at server matches set status
+        // assertEquals(ExecutionStates.RUNNING.value, this.executionClient.withName(executionName).get().status.executionState)
+
+        // Await informer called
+        this.addCountDownLatch.await()
+        verify(this.controller).stop(true)
+        assertEquals(ExecutionStates.RESTART.value, this.executionClient.withName(executionName).get().status.executionState)
+    }
+
+    @Test
+    @DisplayName("Test onUpdate method for execution with no status")
+    fun testOnUpdateWithoutStatus() {
+        // Create first version of execution resource
+        val firstExecutionResource = getExecutionFromSystemResource("k8s-resource-files/test-execution.yaml")
+        val firstExecution = firstExecutionResource.create()
+        val executionName = firstExecution.metadata.name
+
+        // Start informer
+        this.executionClient.inform(eventHandler)
+
+        // Get execution from server
+        val firstExecutionResponse = this.executionClient.withName(executionName).get()
+        // Assert that execution at server has pending status
+        assertEquals(ExecutionStates.PENDING.value, firstExecutionResponse.status.executionState)
+
+        // Create new version of execution and update at server
+        getExecutionFromSystemResource("k8s-resource-files/test-execution-update.yaml").createOrReplace()
+
+        // Await informer called
+        this.updateCountDownLatch.await()
+        // Get execution from server and assert that new status matches expected one
+        assertEquals(ExecutionStates.PENDING.value, this.executionClient.withName(executionName).get().status.executionState)
+    }
+
+    @ParameterizedTest
+    @MethodSource("provideOnUpdateTestArguments")
+    @DisplayName("Test onUpdate method for execution with different status")
+    fun testOnUpdateWithStatus(beforeState: ExecutionStates, expectedState: ExecutionStates) {
+        // Create first version of execution resource
+        val firstExecutionResource = getExecutionFromSystemResource("k8s-resource-files/test-execution.yaml")
+        val firstExecution = firstExecutionResource.create()
+        val executionName = firstExecution.metadata.name
+
+        // Update status of execution
+        firstExecution.status.executionState = beforeState.value
+        firstExecutionResource.patchStatus(firstExecution)
+
+        // Start informer
+        this.executionClient.inform(eventHandler)
+
+        // Get execution from server
+        val firstExecutionResponse = this.executionClient.withName(executionName).get()
+        // Assert that status at server matches set status
+        assertEquals(beforeState.value, firstExecutionResponse.status.executionState)
+
+        // Create new version of execution and update at server
+        getExecutionFromSystemResource("k8s-resource-files/test-execution-update.yaml").createOrReplace()
+
+        // Await informer called
+        this.updateCountDownLatch.await()
+        // Get execution from server and assert that new status matches expected one
+        assertEquals(expectedState.value, this.executionClient.withName(executionName).get().status.executionState)
+    }
+
+    @Test
+    @Disabled("Informer also called onAdd and changes status")
+    fun testOnDeleteWithExecutionRunning() {
+        // Create first version of execution resource
+        val firstExecutionResource = getExecutionFromSystemResource("k8s-resource-files/test-execution.yaml")
+        val firstExecution = firstExecutionResource.create()
+        val executionName = firstExecution.metadata.name
+
+        // Update status of execution to be running
+        firstExecution.status.executionState = ExecutionStates.RUNNING.value
+        firstExecutionResource.patchStatus(firstExecution)
+
+        // Get execution from server
+        val firstExecutionResponse = this.executionClient.withName(executionName).get()
+        // Assert that execution created at server
+        assertNotNull(firstExecutionResponse)
+
+        // Start informer
+        this.executionClient.inform(eventHandler)
+
+        // We consider execution to be running
+        whenever(this.controller.isExecutionRunning(executionName)).thenReturn(true)
+
+        // Delete execution
+        this.executionClient.delete(firstExecutionResponse)
+
+        // Get execution from server
+        val secondExecutionResponse = this.executionClient.withName(executionName).get()
+        // Assert that execution deleted at server
+        assertNull(secondExecutionResponse)
+
+        // Await informer called
+        this.deleteCountDownLatch.await()
+
+        verify(this.controller).stop(false)
+    }
+
+    @Test
+    fun testOnDeleteWithExecutionNotRunning() {
+        // Create first version of execution resource
+        val firstExecutionResource = getExecutionFromSystemResource("k8s-resource-files/test-execution.yaml")
+        val firstExecution = firstExecutionResource.create()
+        val executionName = firstExecution.metadata.name
+
+        // Update status of execution to be running
+        firstExecution.status.executionState = ExecutionStates.RUNNING.value
+        firstExecutionResource.patchStatus(firstExecution)
+
+        // Get execution from server
+        val firstExecutionResponse = this.executionClient.withName(executionName).get()
+        // Assert that execution created at server
+        assertNotNull(firstExecutionResponse)
+
+        // Start informer
+        this.executionClient.inform(eventHandler)
+
+        // We consider execution to be running
+        whenever(this.controller.isExecutionRunning(executionName)).thenReturn(false)
+
+        // Delete execution
+        this.executionClient.delete(firstExecutionResponse)
+
+        // Get execution from server
+        val secondExecutionResponse = this.executionClient.withName(executionName).get()
+        // Assert that execution created at server
+        assertNull(secondExecutionResponse)
+
+        // Await informer called
+        this.deleteCountDownLatch.await()
+
+        verify(this.controller, never()).stop(false)
+    }
+
+    private fun getExecutionFromSystemResource(resourceName: String): Resource<ExecutionCRD> {
+        return executionClient.load(ClassLoader.getSystemResourceAsStream(resourceName))
+    }
+
+    companion object {
+        @JvmStatic
+        fun provideOnUpdateTestArguments(): Stream<Arguments> =
+            Stream.of(
+                // before state -> expected state
+                Arguments.of(ExecutionStates.PENDING, ExecutionStates.PENDING),
+                Arguments.of(ExecutionStates.FINISHED, ExecutionStates.PENDING),
+                Arguments.of(ExecutionStates.FAILURE, ExecutionStates.PENDING),
+                // Arguments.of(ExecutionStates.RUNNING, ExecutionStates.RESTART), // see testOnDeleteWithExecutionRunning
+                Arguments.of(ExecutionStates.RESTART, ExecutionStates.RESTART)
+            )
+    }
+
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerWrapper.kt b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerWrapper.kt
new file mode 100644
index 0000000000000000000000000000000000000000..5dbc515a7799dd51e6395153f13d80650587d7fa
--- /dev/null
+++ b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerWrapper.kt
@@ -0,0 +1,27 @@
+package theodolite.execution.operator
+
+import io.fabric8.kubernetes.client.informers.ResourceEventHandler
+import theodolite.model.crd.ExecutionCRD
+
+class ExecutionEventHandlerWrapper(
+    private val executionEventHandler: ExecutionEventHandler,
+    private val afterOnAddCallback: () -> Unit,
+    private val afterOnUpdateCallback: () -> Unit,
+    private val afterOnDeleteCallback: () -> Unit
+) : ResourceEventHandler<ExecutionCRD> {
+
+    override fun onAdd(execution: ExecutionCRD) {
+        this.executionEventHandler.onAdd(execution)
+        this.afterOnAddCallback()
+    }
+
+    override fun onUpdate(oldExecution: ExecutionCRD, newExecution: ExecutionCRD) {
+        this.executionEventHandler.onUpdate(oldExecution, newExecution)
+        this.afterOnUpdateCallback()
+    }
+
+    override fun onDelete(execution: ExecutionCRD, deletedFinalStateUnknown: Boolean) {
+        this.executionEventHandler.onDelete(execution, deletedFinalStateUnknown)
+        this.afterOnDeleteCallback()
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt b/theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt
index a54f4ed6db559f8f7f15ae82deecf3fedf8b4abe..44b6fce2796222d33c7f49091e4b61c79da770b8 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt
@@ -1,6 +1,9 @@
 package theodolite.execution.operator
 
 import io.fabric8.kubernetes.client.server.mock.KubernetesServer
+import io.quarkus.test.junit.QuarkusTest
+import io.quarkus.test.kubernetes.client.KubernetesTestServer
+import io.quarkus.test.kubernetes.client.WithKubernetesTestServer
 import org.junit.jupiter.api.AfterEach
 import org.junit.jupiter.api.Assertions.assertEquals
 import org.junit.jupiter.api.Assertions.assertTrue
@@ -12,9 +15,13 @@ import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
 import theodolite.model.crd.ExecutionStates
 import java.time.Duration
 
+@WithKubernetesTestServer
+@QuarkusTest
 class StateHandlerTest {
     private val testResourcePath = "./src/test/resources/k8s-resource-files/"
-    private val server = KubernetesServer(false, true)
+
+    @KubernetesTestServer
+    private lateinit var server: KubernetesServer
 
     @BeforeEach
     fun setUp() {
diff --git a/theodolite/src/test/kotlin/theodolite/k8s/K8sManagerTest.kt b/theodolite/src/test/kotlin/theodolite/k8s/K8sManagerTest.kt
index 7c69618de03f730f5b6f1cb83c5df544e2cd120c..ffc3f2f2b8083ab8b8170fa77c19de3a6ef387e7 100644
--- a/theodolite/src/test/kotlin/theodolite/k8s/K8sManagerTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/k8s/K8sManagerTest.kt
@@ -8,7 +8,6 @@ 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
@@ -17,9 +16,6 @@ import org.junit.jupiter.api.DisplayName
 import org.junit.jupiter.api.Test
 import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
 
-
-private val logger = KotlinLogging.logger {}
-
 @QuarkusTest
 @JsonIgnoreProperties(ignoreUnknown = true)
 class K8sManagerTest {
diff --git a/theodolite/src/test/kotlin/theodolite/util/ExecutionStateComparatorTest.kt b/theodolite/src/test/kotlin/theodolite/util/ExecutionStateComparatorTest.kt
index 7332e53f9e1814f28b8ff37a595b31b0eb931ea7..5d50514857a7a206a64a0612c2270936fe01aa3b 100644
--- a/theodolite/src/test/kotlin/theodolite/util/ExecutionStateComparatorTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/util/ExecutionStateComparatorTest.kt
@@ -19,7 +19,6 @@ class ExecutionStateComparatorTest {
         execution2.getStatus().executionState = ExecutionStates.PENDING.value
         val list = listOf(execution2.getCR(), execution1.getCR())
 
-
         assertEquals(
             list.reversed(),
             list.sortedWith(comparator)
diff --git a/theodolite/src/test/kotlin/theodolite/util/IOHandlerTest.kt b/theodolite/src/test/kotlin/theodolite/util/IOHandlerTest.kt
index 6b8aa1d567fd2c93c1301fe3f953273e0f5d5420..f84536bfc029a829c1798293938386965eedcf47 100644
--- a/theodolite/src/test/kotlin/theodolite/util/IOHandlerTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/util/IOHandlerTest.kt
@@ -96,7 +96,7 @@ internal class IOHandlerTest {
     }
 
 
-    @Test()
+    @Test
     @SetEnvironmentVariable.SetEnvironmentVariables(
         SetEnvironmentVariable(key = "RESULTS_FOLDER", value = "./src/test/resources"),
         SetEnvironmentVariable(key = "CREATE_RESULTS_FOLDER", value = "false")
@@ -105,7 +105,7 @@ internal class IOHandlerTest {
         assertEquals("./src/test/resources/", IOHandler().getResultFolderURL())
     }
 
-    @Test()
+    @Test
     @SetEnvironmentVariable.SetEnvironmentVariables(
         SetEnvironmentVariable(key = "RESULTS_FOLDER", value = "$FOLDER_URL-0"),
         SetEnvironmentVariable(key = "CREATE_RESULTS_FOLDER", value = "false")
@@ -121,7 +121,7 @@ internal class IOHandlerTest {
         assertTrue(exceptionWasThrown)
     }
 
-    @Test()
+    @Test
     @SetEnvironmentVariable.SetEnvironmentVariables(
         SetEnvironmentVariable(key = "RESULTS_FOLDER", value = FOLDER_URL),
         SetEnvironmentVariable(key = "CREATE_RESULTS_FOLDER", value = "true")
@@ -130,7 +130,7 @@ internal class IOHandlerTest {
         assertEquals("$FOLDER_URL/", IOHandler().getResultFolderURL())
     }
 
-    @Test()
+    @Test
     @ClearEnvironmentVariable(key = "RESULTS_FOLDER")
     @SetEnvironmentVariable(key = "CREATE_RESULTS_FOLDER", value = "true")
     fun testGetResultFolderURL_CreateFolderButNoFolderGiven() {
diff --git a/theodolite/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/theodolite/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000000000000000000000000000000000000..1f0955d450f0dc49ca715b1a0a88a5aa746ee11e
--- /dev/null
+++ b/theodolite/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1 @@
+mock-maker-inline