diff --git a/docs/CNAME b/docs/CNAME
new file mode 100644
index 0000000000000000000000000000000000000000..b1c7ffdbcd7523245c451869092ff0498bd7b8db
--- /dev/null
+++ b/docs/CNAME
@@ -0,0 +1 @@
+www.theodolite.rocks
\ No newline at end of file
diff --git a/docs/crd-benchmark-doc.md b/docs/crd-benchmark-doc.md
deleted file mode 100644
index 1e12d6ebd776b11d76241cfb530daeba9e0b5c24..0000000000000000000000000000000000000000
--- a/docs/crd-benchmark-doc.md
+++ /dev/null
@@ -1,374 +0,0 @@
-# API Reference
-
-Packages:
-
-- [theodolite.com/v1](#theodolitecomv1)
-
-# theodolite.com/v1
-
-Resource Types:
-
-- [benchmark](#benchmark)
-
-
-
-
-## benchmark
-<sup><sup>[↩ Parent](#theodolitecomv1 )</sup></sup>
-
-
-
-
-
-
-
-
-<table>
-    <thead>
-        <tr>
-            <th>Name</th>
-            <th>Type</th>
-            <th>Description</th>
-            <th>Required</th>
-        </tr>
-    </thead>
-    <tbody><tr>
-      <td><b>apiVersion</b></td>
-      <td>string</td>
-      <td>theodolite.com/v1</td>
-      <td>true</td>
-      </tr>
-      <tr>
-      <td><b>kind</b></td>
-      <td>string</td>
-      <td>benchmark</td>
-      <td>true</td>
-      </tr>
-      <tr>
-      <td><b><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#objectmeta-v1-meta">metadata</a></b></td>
-      <td>object</td>
-      <td>Refer to the Kubernetes API documentation for the fields of the `metadata` field.</td>
-      <td>true</td>
-      </tr><tr>
-        <td><b><a href="#benchmarkspec">spec</a></b></td>
-        <td>object</td>
-        <td>
-          <br/>
-        </td>
-        <td>true</td>
-      </tr></tbody>
-</table>
-
-
-### benchmark.spec
-<sup><sup>[↩ Parent](#benchmark)</sup></sup>
-
-
-
-
-
-<table>
-    <thead>
-        <tr>
-            <th>Name</th>
-            <th>Type</th>
-            <th>Description</th>
-            <th>Required</th>
-        </tr>
-    </thead>
-    <tbody><tr>
-        <td><b>name</b></td>
-        <td>string</td>
-        <td>
-          This field exists only for technical reasons and should not be set by the user. The value of the field will be overwritten.<br/>
-        </td>
-        <td>false</td>
-      </tr><tr>
-        <td><b>appResource</b></td>
-        <td>[]string</td>
-        <td>
-          A list of file names that reference Kubernetes resources that are deployed on the cluster for the system under test (SUT).<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b><a href="#benchmarkspeckafkaconfig">kafkaConfig</a></b></td>
-        <td>object</td>
-        <td>
-          Contains the Kafka configuration.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>loadGenResource</b></td>
-        <td>[]string</td>
-        <td>
-          A list of file names that reference Kubernetes resources that are deployed on the cluster for the load generator.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b><a href="#benchmarkspecloadtypesindex">loadTypes</a></b></td>
-        <td>[]object</td>
-        <td>
-          A list of load types that can be scaled for this benchmark. For each load type the concrete values are defined in the execution object.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b><a href="#benchmarkspecresourcetypesindex">resourceTypes</a></b></td>
-        <td>[]object</td>
-        <td>
-          A list of resource types that can be scaled for this `benchmark` resource. For each resource type the concrete values are defined in the `execution` object.<br/>
-        </td>
-        <td>true</td>
-      </tr></tbody>
-</table>
-
-
-### benchmark.spec.kafkaConfig
-<sup><sup>[↩ Parent](#benchmarkspec)</sup></sup>
-
-
-
-Contains the Kafka configuration.
-
-<table>
-    <thead>
-        <tr>
-            <th>Name</th>
-            <th>Type</th>
-            <th>Description</th>
-            <th>Required</th>
-        </tr>
-    </thead>
-    <tbody><tr>
-        <td><b>bootstrapServer</b></td>
-        <td>string</td>
-        <td>
-          The bootstrap servers connection string.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b><a href="#benchmarkspeckafkaconfigtopicsindex">topics</a></b></td>
-        <td>[]object</td>
-        <td>
-          List of topics to be created for each experiment. Alternative theodolite offers the possibility to remove certain topics after each experiment.<br/>
-        </td>
-        <td>true</td>
-      </tr></tbody>
-</table>
-
-
-### benchmark.spec.kafkaConfig.topics[index]
-<sup><sup>[↩ Parent](#benchmarkspeckafkaconfig)</sup></sup>
-
-
-
-
-
-<table>
-    <thead>
-        <tr>
-            <th>Name</th>
-            <th>Type</th>
-            <th>Description</th>
-            <th>Required</th>
-        </tr>
-    </thead>
-    <tbody><tr>
-        <td><b>removeOnly</b></td>
-        <td>boolean</td>
-        <td>
-          Determines if this topic should only be deleted after each experiement. For removeOnly topics the name can be a RegEx describing the topic.<br/>
-          <br/>
-            <i>Default</i>: false<br/>
-        </td>
-        <td>false</td>
-      </tr><tr>
-        <td><b>name</b></td>
-        <td>string</td>
-        <td>
-          The name of the topic.<br/>
-          <br/>
-            <i>Default</i>: <br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>numPartitions</b></td>
-        <td>integer</td>
-        <td>
-          The number of partitions of the topic.<br/>
-          <br/>
-            <i>Default</i>: 0<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>replicationFactor</b></td>
-        <td>integer</td>
-        <td>
-          The replication factor of the topic.<br/>
-          <br/>
-            <i>Default</i>: 0<br/>
-        </td>
-        <td>true</td>
-      </tr></tbody>
-</table>
-
-
-### benchmark.spec.loadTypes[index]
-<sup><sup>[↩ Parent](#benchmarkspec)</sup></sup>
-
-
-
-
-
-<table>
-    <thead>
-        <tr>
-            <th>Name</th>
-            <th>Type</th>
-            <th>Description</th>
-            <th>Required</th>
-        </tr>
-    </thead>
-    <tbody><tr>
-        <td><b><a href="#benchmarkspecloadtypesindexpatchersindex">patchers</a></b></td>
-        <td>[]object</td>
-        <td>
-          List of patchers used to scale this resource type.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>typeName</b></td>
-        <td>string</td>
-        <td>
-          Name of the load type.<br/>
-        </td>
-        <td>true</td>
-      </tr></tbody>
-</table>
-
-
-### benchmark.spec.loadTypes[index].patchers[index]
-<sup><sup>[↩ Parent](#benchmarkspecloadtypesindex)</sup></sup>
-
-
-
-
-
-<table>
-    <thead>
-        <tr>
-            <th>Name</th>
-            <th>Type</th>
-            <th>Description</th>
-            <th>Required</th>
-        </tr>
-    </thead>
-    <tbody><tr>
-        <td><b>properties</b></td>
-        <td>object</td>
-        <td>
-          (Optional) Patcher specific additional arguments.<br/>
-          <br/>
-            <i>Default</i>: map[]<br/>
-        </td>
-        <td>false</td>
-      </tr><tr>
-        <td><b>resource</b></td>
-        <td>string</td>
-        <td>
-          Specifies the Kubernetes resource to be patched.<br/>
-          <br/>
-            <i>Default</i>: <br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>type</b></td>
-        <td>string</td>
-        <td>
-          Type of the Patcher.<br/>
-          <br/>
-            <i>Default</i>: <br/>
-        </td>
-        <td>true</td>
-      </tr></tbody>
-</table>
-
-
-### benchmark.spec.resourceTypes[index]
-<sup><sup>[↩ Parent](#benchmarkspec)</sup></sup>
-
-
-
-
-
-<table>
-    <thead>
-        <tr>
-            <th>Name</th>
-            <th>Type</th>
-            <th>Description</th>
-            <th>Required</th>
-        </tr>
-    </thead>
-    <tbody><tr>
-        <td><b><a href="#benchmarkspecresourcetypesindexpatchersindex">patchers</a></b></td>
-        <td>[]object</td>
-        <td>
-          List of patchers used to scale this resource type.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>typeName</b></td>
-        <td>string</td>
-        <td>
-          Name of the resource type.<br/>
-        </td>
-        <td>true</td>
-      </tr></tbody>
-</table>
-
-
-### benchmark.spec.resourceTypes[index].patchers[index]
-<sup><sup>[↩ Parent](#benchmarkspecresourcetypesindex)</sup></sup>
-
-
-
-
-
-<table>
-    <thead>
-        <tr>
-            <th>Name</th>
-            <th>Type</th>
-            <th>Description</th>
-            <th>Required</th>
-        </tr>
-    </thead>
-    <tbody><tr>
-        <td><b>properties</b></td>
-        <td>object</td>
-        <td>
-          (Optional) Patcher specific additional arguments.<br/>
-          <br/>
-            <i>Default</i>: map[]<br/>
-        </td>
-        <td>false</td>
-      </tr><tr>
-        <td><b>resource</b></td>
-        <td>string</td>
-        <td>
-          Specifies the Kubernetes resource to be patched.<br/>
-          <br/>
-            <i>Default</i>: <br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>type</b></td>
-        <td>string</td>
-        <td>
-          Type of the patcher.<br/>
-          <br/>
-            <i>Default</i>: <br/>
-        </td>
-        <td>true</td>
-      </tr></tbody>
-</table>
\ No newline at end of file
diff --git a/docs/crd-docu.md b/docs/crd-docu.md
new file mode 100644
index 0000000000000000000000000000000000000000..73d85c951fc2958aee25cde2cdff652034643c1a
--- /dev/null
+++ b/docs/crd-docu.md
@@ -0,0 +1,1226 @@
+# API Reference
+
+Packages:
+
+- [theodolite.com/v1](#theodolitecomv1)
+
+# theodolite.com/v1
+
+Resource Types:
+
+- [benchmark](#benchmark)
+
+- [execution](#execution)
+
+
+
+
+## benchmark
+<sup><sup>[↩ Parent](#theodolitecomv1 )</sup></sup>
+
+
+
+
+
+
+
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+      <td><b>apiVersion</b></td>
+      <td>string</td>
+      <td>theodolite.com/v1</td>
+      <td>true</td>
+      </tr>
+      <tr>
+      <td><b>kind</b></td>
+      <td>string</td>
+      <td>benchmark</td>
+      <td>true</td>
+      </tr>
+      <tr>
+      <td><b><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#objectmeta-v1-meta">metadata</a></b></td>
+      <td>object</td>
+      <td>Refer to the Kubernetes API documentation for the fields of the `metadata` field.</td>
+      <td>true</td>
+      </tr><tr>
+        <td><b><a href="#benchmarkstatus">status</a></b></td>
+        <td>object</td>
+        <td>
+          <br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b><a href="#benchmarkspec">spec</a></b></td>
+        <td>object</td>
+        <td>
+          <br/>
+        </td>
+        <td>true</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.status
+<sup><sup>[↩ Parent](#benchmark)</sup></sup>
+
+
+
+
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>resourceSetsState</b></td>
+        <td>string</td>
+        <td>
+          The status of a Benchmark indicates whether all resources are available to start the benchmark or not.<br/>
+        </td>
+        <td>false</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.spec
+<sup><sup>[↩ Parent](#benchmark)</sup></sup>
+
+
+
+
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b><a href="#benchmarkspecinfrastructure">infrastructure</a></b></td>
+        <td>object</td>
+        <td>
+          (Optional) A list of file names that reference Kubernetes resources that are deployed on the cluster to create the required infrastructure.<br/>
+          <br/>
+            <i>Default</i>: map[]<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>name</b></td>
+        <td>string</td>
+        <td>
+          This field exists only for technical reasons and should not be set by the user. The value of the field will be overwritten.<br/>
+          <br/>
+            <i>Default</i>: <br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b><a href="#benchmarkspeckafkaconfig">kafkaConfig</a></b></td>
+        <td>object</td>
+        <td>
+          Contains the Kafka configuration.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b><a href="#benchmarkspecloadgenerator">loadGenerator</a></b></td>
+        <td>object</td>
+        <td>
+          The loadGenResourceSets specifies all Kubernetes resources required to start the load generator. A resourceSet can be either a configMap resourceSet or a fileSystem resourceSet.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b><a href="#benchmarkspecloadtypesindex">loadTypes</a></b></td>
+        <td>[]object</td>
+        <td>
+          A list of load types that can be scaled for this benchmark. For each load type the concrete values are defined in the execution object.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b><a href="#benchmarkspecresourcetypesindex">resourceTypes</a></b></td>
+        <td>[]object</td>
+        <td>
+          A list of resource types that can be scaled for this `benchmark` resource. For each resource type the concrete values are defined in the `execution` object.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b><a href="#benchmarkspecsut">sut</a></b></td>
+        <td>object</td>
+        <td>
+          The appResourceSets specifies all Kubernetes resources required to start the sut. A resourceSet can be either a configMap resourceSet or a fileSystem resourceSet.<br/>
+        </td>
+        <td>true</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.spec.infrastructure
+<sup><sup>[↩ Parent](#benchmarkspec)</sup></sup>
+
+
+
+(Optional) A list of file names that reference Kubernetes resources that are deployed on the cluster to create the required infrastructure.
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b><a href="#benchmarkspecinfrastructureresourcesindex">resources</a></b></td>
+        <td>[]object</td>
+        <td>
+          <br/>
+          <br/>
+            <i>Default</i>: []<br/>
+        </td>
+        <td>false</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.spec.infrastructure.resources[index]
+<sup><sup>[↩ Parent](#benchmarkspecinfrastructure)</sup></sup>
+
+
+
+
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b><a href="#benchmarkspecinfrastructureresourcesindexconfigmap">configMap</a></b></td>
+        <td>object</td>
+        <td>
+          The configMap resourceSet loads the Kubernetes manifests from an Kubernetes configMap.<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b><a href="#benchmarkspecinfrastructureresourcesindexfilesystem">fileSystem</a></b></td>
+        <td>object</td>
+        <td>
+          The fileSystem resourceSet loads the Kubernetes manifests from the filesystem.<br/>
+        </td>
+        <td>false</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.spec.infrastructure.resources[index].configMap
+<sup><sup>[↩ Parent](#benchmarkspecinfrastructureresourcesindex)</sup></sup>
+
+
+
+The configMap resourceSet loads the Kubernetes manifests from an Kubernetes configMap.
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>files</b></td>
+        <td>[]string</td>
+        <td>
+          (Optional) Specifies which files from the configMap should be loaded. If this field is not set, all files are loaded.<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>name</b></td>
+        <td>string</td>
+        <td>
+          The name of the configMap<br/>
+        </td>
+        <td>false</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.spec.infrastructure.resources[index].fileSystem
+<sup><sup>[↩ Parent](#benchmarkspecinfrastructureresourcesindex)</sup></sup>
+
+
+
+The fileSystem resourceSet loads the Kubernetes manifests from the filesystem.
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>files</b></td>
+        <td>[]string</td>
+        <td>
+          (Optional) Specifies which files from the configMap should be loaded. If this field is not set, all files are loaded.<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>path</b></td>
+        <td>string</td>
+        <td>
+          The path to the folder which contains the Kubernetes manifests files.<br/>
+        </td>
+        <td>false</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.spec.kafkaConfig
+<sup><sup>[↩ Parent](#benchmarkspec)</sup></sup>
+
+
+
+Contains the Kafka configuration.
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>bootstrapServer</b></td>
+        <td>string</td>
+        <td>
+          The bootstrap servers connection string.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b><a href="#benchmarkspeckafkaconfigtopicsindex">topics</a></b></td>
+        <td>[]object</td>
+        <td>
+          List of topics to be created for each experiment. Alternative theodolite offers the possibility to remove certain topics after each experiment.<br/>
+        </td>
+        <td>true</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.spec.kafkaConfig.topics[index]
+<sup><sup>[↩ Parent](#benchmarkspeckafkaconfig)</sup></sup>
+
+
+
+
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>numPartitions</b></td>
+        <td>integer</td>
+        <td>
+          The number of partitions of the topic.<br/>
+          <br/>
+            <i>Default</i>: 0<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>removeOnly</b></td>
+        <td>boolean</td>
+        <td>
+          Determines if this topic should only be deleted after each experiement. For removeOnly topics the name can be a RegEx describing the topic.<br/>
+          <br/>
+            <i>Default</i>: false<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>replicationFactor</b></td>
+        <td>integer</td>
+        <td>
+          The replication factor of the topic.<br/>
+          <br/>
+            <i>Default</i>: 0<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>name</b></td>
+        <td>string</td>
+        <td>
+          The name of the topic.<br/>
+          <br/>
+            <i>Default</i>: <br/>
+        </td>
+        <td>true</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.spec.loadGenerator
+<sup><sup>[↩ Parent](#benchmarkspec)</sup></sup>
+
+
+
+The loadGenResourceSets specifies all Kubernetes resources required to start the load generator. A resourceSet can be either a configMap resourceSet or a fileSystem resourceSet.
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b><a href="#benchmarkspecloadgeneratorresourcesindex">resources</a></b></td>
+        <td>[]object</td>
+        <td>
+          <br/>
+          <br/>
+            <i>Default</i>: []<br/>
+        </td>
+        <td>false</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.spec.loadGenerator.resources[index]
+<sup><sup>[↩ Parent](#benchmarkspecloadgenerator)</sup></sup>
+
+
+
+
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b><a href="#benchmarkspecloadgeneratorresourcesindexconfigmap">configMap</a></b></td>
+        <td>object</td>
+        <td>
+          The configMap resourceSet loads the Kubernetes manifests from an Kubernetes configMap.<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b><a href="#benchmarkspecloadgeneratorresourcesindexfilesystem">fileSystem</a></b></td>
+        <td>object</td>
+        <td>
+          The fileSystem resourceSet loads the Kubernetes manifests from the filesystem.<br/>
+        </td>
+        <td>false</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.spec.loadGenerator.resources[index].configMap
+<sup><sup>[↩ Parent](#benchmarkspecloadgeneratorresourcesindex)</sup></sup>
+
+
+
+The configMap resourceSet loads the Kubernetes manifests from an Kubernetes configMap.
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>files</b></td>
+        <td>[]string</td>
+        <td>
+          (Optional) Specifies which files from the configMap should be loaded. If this field is not set, all files are loaded.<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>name</b></td>
+        <td>string</td>
+        <td>
+          The name of the configMap<br/>
+        </td>
+        <td>false</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.spec.loadGenerator.resources[index].fileSystem
+<sup><sup>[↩ Parent](#benchmarkspecloadgeneratorresourcesindex)</sup></sup>
+
+
+
+The fileSystem resourceSet loads the Kubernetes manifests from the filesystem.
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>files</b></td>
+        <td>[]string</td>
+        <td>
+          (Optional) Specifies which files from the configMap should be loaded. If this field is not set, all files are loaded.<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>path</b></td>
+        <td>string</td>
+        <td>
+          The path to the folder which contains the Kubernetes manifests files.<br/>
+        </td>
+        <td>false</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.spec.loadTypes[index]
+<sup><sup>[↩ Parent](#benchmarkspec)</sup></sup>
+
+
+
+
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b><a href="#benchmarkspecloadtypesindexpatchersindex">patchers</a></b></td>
+        <td>[]object</td>
+        <td>
+          List of patchers used to scale this resource type.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b>typeName</b></td>
+        <td>string</td>
+        <td>
+          Name of the load type.<br/>
+        </td>
+        <td>true</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.spec.loadTypes[index].patchers[index]
+<sup><sup>[↩ Parent](#benchmarkspecloadtypesindex)</sup></sup>
+
+
+
+
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>properties</b></td>
+        <td>map[string]string</td>
+        <td>
+          (Optional) Patcher specific additional arguments.<br/>
+          <br/>
+            <i>Default</i>: map[]<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>resource</b></td>
+        <td>string</td>
+        <td>
+          Specifies the Kubernetes resource to be patched.<br/>
+          <br/>
+            <i>Default</i>: <br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b>type</b></td>
+        <td>string</td>
+        <td>
+          Type of the Patcher.<br/>
+          <br/>
+            <i>Default</i>: <br/>
+        </td>
+        <td>true</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.spec.resourceTypes[index]
+<sup><sup>[↩ Parent](#benchmarkspec)</sup></sup>
+
+
+
+
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b><a href="#benchmarkspecresourcetypesindexpatchersindex">patchers</a></b></td>
+        <td>[]object</td>
+        <td>
+          List of patchers used to scale this resource type.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b>typeName</b></td>
+        <td>string</td>
+        <td>
+          Name of the resource type.<br/>
+        </td>
+        <td>true</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.spec.resourceTypes[index].patchers[index]
+<sup><sup>[↩ Parent](#benchmarkspecresourcetypesindex)</sup></sup>
+
+
+
+
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>properties</b></td>
+        <td>map[string]string</td>
+        <td>
+          (Optional) Patcher specific additional arguments.<br/>
+          <br/>
+            <i>Default</i>: map[]<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>resource</b></td>
+        <td>string</td>
+        <td>
+          Specifies the Kubernetes resource to be patched.<br/>
+          <br/>
+            <i>Default</i>: <br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b>type</b></td>
+        <td>string</td>
+        <td>
+          Type of the patcher.<br/>
+          <br/>
+            <i>Default</i>: <br/>
+        </td>
+        <td>true</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.spec.sut
+<sup><sup>[↩ Parent](#benchmarkspec)</sup></sup>
+
+
+
+The appResourceSets specifies all Kubernetes resources required to start the sut. A resourceSet can be either a configMap resourceSet or a fileSystem resourceSet.
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b><a href="#benchmarkspecsutresourcesindex">resources</a></b></td>
+        <td>[]object</td>
+        <td>
+          <br/>
+          <br/>
+            <i>Default</i>: []<br/>
+        </td>
+        <td>false</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.spec.sut.resources[index]
+<sup><sup>[↩ Parent](#benchmarkspecsut)</sup></sup>
+
+
+
+
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b><a href="#benchmarkspecsutresourcesindexconfigmap">configMap</a></b></td>
+        <td>object</td>
+        <td>
+          The configMap resourceSet loads the Kubernetes manifests from an Kubernetes configMap.<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b><a href="#benchmarkspecsutresourcesindexfilesystem">fileSystem</a></b></td>
+        <td>object</td>
+        <td>
+          The fileSystem resourceSet loads the Kubernetes manifests from the filesystem.<br/>
+        </td>
+        <td>false</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.spec.sut.resources[index].configMap
+<sup><sup>[↩ Parent](#benchmarkspecsutresourcesindex)</sup></sup>
+
+
+
+The configMap resourceSet loads the Kubernetes manifests from an Kubernetes configMap.
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>files</b></td>
+        <td>[]string</td>
+        <td>
+          (Optional) Specifies which files from the configMap should be loaded. If this field is not set, all files are loaded.<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>name</b></td>
+        <td>string</td>
+        <td>
+          The name of the configMap<br/>
+        </td>
+        <td>false</td>
+      </tr></tbody>
+</table>
+
+
+### benchmark.spec.sut.resources[index].fileSystem
+<sup><sup>[↩ Parent](#benchmarkspecsutresourcesindex)</sup></sup>
+
+
+
+The fileSystem resourceSet loads the Kubernetes manifests from the filesystem.
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>files</b></td>
+        <td>[]string</td>
+        <td>
+          (Optional) Specifies which files from the configMap should be loaded. If this field is not set, all files are loaded.<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>path</b></td>
+        <td>string</td>
+        <td>
+          The path to the folder which contains the Kubernetes manifests files.<br/>
+        </td>
+        <td>false</td>
+      </tr></tbody>
+</table>
+
+## execution
+<sup><sup>[↩ Parent](#theodolitecomv1 )</sup></sup>
+
+
+
+
+
+
+
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+      <td><b>apiVersion</b></td>
+      <td>string</td>
+      <td>theodolite.com/v1</td>
+      <td>true</td>
+      </tr>
+      <tr>
+      <td><b>kind</b></td>
+      <td>string</td>
+      <td>execution</td>
+      <td>true</td>
+      </tr>
+      <tr>
+      <td><b><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#objectmeta-v1-meta">metadata</a></b></td>
+      <td>object</td>
+      <td>Refer to the Kubernetes API documentation for the fields of the `metadata` field.</td>
+      <td>true</td>
+      </tr><tr>
+        <td><b><a href="#executionstatus">status</a></b></td>
+        <td>object</td>
+        <td>
+          <br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b><a href="#executionspec">spec</a></b></td>
+        <td>object</td>
+        <td>
+          <br/>
+        </td>
+        <td>true</td>
+      </tr></tbody>
+</table>
+
+
+### execution.status
+<sup><sup>[↩ Parent](#execution)</sup></sup>
+
+
+
+
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>executionDuration</b></td>
+        <td>string</td>
+        <td>
+          Duration of the execution in seconds<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>executionState</b></td>
+        <td>string</td>
+        <td>
+          <br/>
+        </td>
+        <td>false</td>
+      </tr></tbody>
+</table>
+
+
+### execution.spec
+<sup><sup>[↩ Parent](#execution)</sup></sup>
+
+
+
+
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>name</b></td>
+        <td>string</td>
+        <td>
+          This field exists only for technical reasons and should not be set by the user. The value of the field will be overwritten.<br/>
+          <br/>
+            <i>Default</i>: <br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>benchmark</b></td>
+        <td>string</td>
+        <td>
+          The name of the benchmark this execution is referring to.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b><a href="#executionspecconfigoverridesindex">configOverrides</a></b></td>
+        <td>[]object</td>
+        <td>
+          List of patchers that are used to override existing configurations.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b><a href="#executionspecexecution">execution</a></b></td>
+        <td>object</td>
+        <td>
+          Defines the overall parameter for the execution.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b><a href="#executionspecload">load</a></b></td>
+        <td>object</td>
+        <td>
+          Specifies the load values that are benchmarked.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b><a href="#executionspecresources">resources</a></b></td>
+        <td>object</td>
+        <td>
+          Specifies the scaling resource that is benchmarked.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b><a href="#executionspecslosindex">slos</a></b></td>
+        <td>[]object</td>
+        <td>
+          List of resource values for the specified resource type.<br/>
+        </td>
+        <td>true</td>
+      </tr></tbody>
+</table>
+
+
+### execution.spec.configOverrides[index]
+<sup><sup>[↩ Parent](#executionspec)</sup></sup>
+
+
+
+
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b><a href="#executionspecconfigoverridesindexpatcher">patcher</a></b></td>
+        <td>object</td>
+        <td>
+          Patcher used to patch a resource<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>value</b></td>
+        <td>string</td>
+        <td>
+          <br/>
+        </td>
+        <td>false</td>
+      </tr></tbody>
+</table>
+
+
+### execution.spec.configOverrides[index].patcher
+<sup><sup>[↩ Parent](#executionspecconfigoverridesindex)</sup></sup>
+
+
+
+Patcher used to patch a resource
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>properties</b></td>
+        <td>map[string]string</td>
+        <td>
+          (Optional) Patcher specific additional arguments.<br/>
+          <br/>
+            <i>Default</i>: map[]<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>resource</b></td>
+        <td>string</td>
+        <td>
+          Specifies the Kubernetes resource to be patched.<br/>
+          <br/>
+            <i>Default</i>: <br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b>type</b></td>
+        <td>string</td>
+        <td>
+          Type of the Patcher.<br/>
+          <br/>
+            <i>Default</i>: <br/>
+        </td>
+        <td>true</td>
+      </tr></tbody>
+</table>
+
+
+### execution.spec.execution
+<sup><sup>[↩ Parent](#executionspec)</sup></sup>
+
+
+
+Defines the overall parameter for the execution.
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>loadGenerationDelay</b></td>
+        <td>integer</td>
+        <td>
+          Seconds to wait between the start of the SUT and the load generator.<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>duration</b></td>
+        <td>integer</td>
+        <td>
+          Defines the duration of each experiment in seconds.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b>repetitions</b></td>
+        <td>integer</td>
+        <td>
+          Numper of repititions for each experiments.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b>restrictions</b></td>
+        <td>[]string</td>
+        <td>
+          List of restriction strategys used to delimit the search space.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b>strategy</b></td>
+        <td>string</td>
+        <td>
+          Defines the used strategy for the execution, either 'LinearSearch' or 'BinarySearch'<br/>
+        </td>
+        <td>true</td>
+      </tr></tbody>
+</table>
+
+
+### execution.spec.load
+<sup><sup>[↩ Parent](#executionspec)</sup></sup>
+
+
+
+Specifies the load values that are benchmarked.
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>loadType</b></td>
+        <td>string</td>
+        <td>
+          The type of the load. It must match one of the load types specified in the referenced benchmark.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b>loadValues</b></td>
+        <td>[]integer</td>
+        <td>
+          List of load values for the specified load type.<br/>
+        </td>
+        <td>true</td>
+      </tr></tbody>
+</table>
+
+
+### execution.spec.resources
+<sup><sup>[↩ Parent](#executionspec)</sup></sup>
+
+
+
+Specifies the scaling resource that is benchmarked.
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>resourceType</b></td>
+        <td>string</td>
+        <td>
+          The type of the resource. It must match one of the resource types specified in the referenced benchmark.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b>resourceValues</b></td>
+        <td>[]integer</td>
+        <td>
+          List of resource values for the specified resource type.<br/>
+        </td>
+        <td>true</td>
+      </tr></tbody>
+</table>
+
+
+### execution.spec.slos[index]
+<sup><sup>[↩ Parent](#executionspec)</sup></sup>
+
+
+
+
+
+<table>
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Type</th>
+            <th>Description</th>
+            <th>Required</th>
+        </tr>
+    </thead>
+    <tbody><tr>
+        <td><b>properties</b></td>
+        <td>map[string]string</td>
+        <td>
+          (Optional) SLO specific additional arguments.<br/>
+          <br/>
+            <i>Default</i>: map[]<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
+        <td><b>offset</b></td>
+        <td>integer</td>
+        <td>
+          Hours by which the start and end timestamp will be shifted (for different timezones).<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b>prometheusUrl</b></td>
+        <td>string</td>
+        <td>
+          Connection string for Promehteus.<br/>
+        </td>
+        <td>true</td>
+      </tr><tr>
+        <td><b>sloType</b></td>
+        <td>string</td>
+        <td>
+          The type of the SLO. It must match 'lag trend'.<br/>
+        </td>
+        <td>true</td>
+      </tr></tbody>
+</table>
\ No newline at end of file
diff --git a/docs/crd-execution-doc.md b/docs/crd-execution-doc.md
deleted file mode 100644
index 21b5cdecabd4a247df9f2c0c8d376ad578f4032f..0000000000000000000000000000000000000000
--- a/docs/crd-execution-doc.md
+++ /dev/null
@@ -1,438 +0,0 @@
-# API Reference
-
-Packages:
-
-- [theodolite.com/v1](#theodolitecomv1)
-
-# theodolite.com/v1
-
-Resource Types:
-
-- [execution](#execution)
-
-
-
-
-## execution
-<sup><sup>[↩ Parent](#theodolitecomv1 )</sup></sup>
-
-
-
-
-
-
-
-
-<table>
-    <thead>
-        <tr>
-            <th>Name</th>
-            <th>Type</th>
-            <th>Description</th>
-            <th>Required</th>
-        </tr>
-    </thead>
-    <tbody><tr>
-      <td><b>apiVersion</b></td>
-      <td>string</td>
-      <td>theodolite.com/v1</td>
-      <td>true</td>
-      </tr>
-      <tr>
-      <td><b>kind</b></td>
-      <td>string</td>
-      <td>execution</td>
-      <td>true</td>
-      </tr>
-      <tr>
-      <td><b><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#objectmeta-v1-meta">metadata</a></b></td>
-      <td>object</td>
-      <td>Refer to the Kubernetes API documentation for the fields of the `metadata` field.</td>
-      <td>true</td>
-      </tr><tr>
-        <td><b><a href="#executionstatus">status</a></b></td>
-        <td>object</td>
-        <td>
-          <br/>
-        </td>
-        <td>false</td>
-      </tr><tr>
-        <td><b><a href="#executionspec">spec</a></b></td>
-        <td>object</td>
-        <td>
-          <br/>
-        </td>
-        <td>true</td>
-      </tr></tbody>
-</table>
-
-
-### execution.status
-<sup><sup>[↩ Parent](#execution)</sup></sup>
-
-
-
-
-
-<table>
-    <thead>
-        <tr>
-            <th>Name</th>
-            <th>Type</th>
-            <th>Description</th>
-            <th>Required</th>
-        </tr>
-    </thead>
-    <tbody><tr>
-        <td><b>executionDuration</b></td>
-        <td>string</td>
-        <td>
-          Duration of the execution in seconds<br/>
-        </td>
-        <td>false</td>
-      </tr><tr>
-        <td><b>executionState</b></td>
-        <td>string</td>
-        <td>
-          <br/>
-        </td>
-        <td>false</td>
-      </tr></tbody>
-</table>
-
-
-### execution.spec
-<sup><sup>[↩ Parent](#execution)</sup></sup>
-
-
-
-
-
-<table>
-    <thead>
-        <tr>
-            <th>Name</th>
-            <th>Type</th>
-            <th>Description</th>
-            <th>Required</th>
-        </tr>
-    </thead>
-    <tbody><tr>
-        <td><b>name</b></td>
-        <td>string</td>
-        <td>
-          This field exists only for technical reasons and should not be set by the user. The value of the field will be overwritten.<br/>
-          <br/>
-            <i>Default</i>: <br/>
-        </td>
-        <td>false</td>
-      </tr><tr>
-        <td><b>benchmark</b></td>
-        <td>string</td>
-        <td>
-          The name of the benchmark this execution is referring to.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b><a href="#executionspecconfigoverridesindex">configOverrides</a></b></td>
-        <td>[]object</td>
-        <td>
-          List of patchers that are used to override existing configurations.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b><a href="#executionspecexecution">execution</a></b></td>
-        <td>object</td>
-        <td>
-          Defines the overall parameter for the execution.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b><a href="#executionspecload">load</a></b></td>
-        <td>object</td>
-        <td>
-          Specifies the load values that are benchmarked.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b><a href="#executionspecresources">resources</a></b></td>
-        <td>object</td>
-        <td>
-          Specifies the scaling resource that is benchmarked.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b><a href="#executionspecslosindex">slos</a></b></td>
-        <td>[]object</td>
-        <td>
-          List of resource values for the specified resource type.<br/>
-        </td>
-        <td>true</td>
-      </tr></tbody>
-</table>
-
-
-### execution.spec.configOverrides[index]
-<sup><sup>[↩ Parent](#executionspec)</sup></sup>
-
-
-
-
-
-<table>
-    <thead>
-        <tr>
-            <th>Name</th>
-            <th>Type</th>
-            <th>Description</th>
-            <th>Required</th>
-        </tr>
-    </thead>
-    <tbody><tr>
-        <td><b><a href="#executionspecconfigoverridesindexpatcher">patcher</a></b></td>
-        <td>object</td>
-        <td>
-          Patcher used to patch a resource<br/>
-        </td>
-        <td>false</td>
-      </tr><tr>
-        <td><b>value</b></td>
-        <td>string</td>
-        <td>
-          <br/>
-        </td>
-        <td>false</td>
-      </tr></tbody>
-</table>
-
-
-### execution.spec.configOverrides[index].patcher
-<sup><sup>[↩ Parent](#executionspecconfigoverridesindex)</sup></sup>
-
-
-
-Patcher used to patch a resource
-
-<table>
-    <thead>
-        <tr>
-            <th>Name</th>
-            <th>Type</th>
-            <th>Description</th>
-            <th>Required</th>
-        </tr>
-    </thead>
-    <tbody><tr>
-        <td><b>properties</b></td>
-        <td>object</td>
-        <td>
-          (Optional) Patcher specific additional arguments.<br/>
-          <br/>
-            <i>Default</i>: map[]<br/>
-        </td>
-        <td>false</td>
-      </tr><tr>
-        <td><b>resource</b></td>
-        <td>string</td>
-        <td>
-          Specifies the Kubernetes resource to be patched.<br/>
-          <br/>
-            <i>Default</i>: <br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>type</b></td>
-        <td>string</td>
-        <td>
-          Type of the Patcher.<br/>
-          <br/>
-            <i>Default</i>: <br/>
-        </td>
-        <td>true</td>
-      </tr></tbody>
-</table>
-
-
-### execution.spec.execution
-<sup><sup>[↩ Parent](#executionspec)</sup></sup>
-
-
-
-Defines the overall parameter for the execution.
-
-<table>
-    <thead>
-        <tr>
-            <th>Name</th>
-            <th>Type</th>
-            <th>Description</th>
-            <th>Required</th>
-        </tr>
-    </thead>
-    <tbody><tr>
-        <td><b>loadGenerationDelay</b></td>
-        <td>integer</td>
-        <td>
-          Seconds to wait between the start of the SUT and the load generator.<br/>
-        </td>
-        <td>false</td>
-      </tr><tr>
-        <td><b>duration</b></td>
-        <td>integer</td>
-        <td>
-          Defines the duration of each experiment in seconds.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>repetitions</b></td>
-        <td>integer</td>
-        <td>
-          Numper of repititions for each experiments.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>restrictions</b></td>
-        <td>[]string</td>
-        <td>
-          List of restriction strategys used to delimit the search space.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>strategy</b></td>
-        <td>string</td>
-        <td>
-          Defines the used strategy for the execution, either 'LinearSearch' or 'BinarySearch'<br/>
-        </td>
-        <td>true</td>
-      </tr></tbody>
-</table>
-
-
-### execution.spec.load
-<sup><sup>[↩ Parent](#executionspec)</sup></sup>
-
-
-
-Specifies the load values that are benchmarked.
-
-<table>
-    <thead>
-        <tr>
-            <th>Name</th>
-            <th>Type</th>
-            <th>Description</th>
-            <th>Required</th>
-        </tr>
-    </thead>
-    <tbody><tr>
-        <td><b>loadType</b></td>
-        <td>string</td>
-        <td>
-          The type of the load. It must match one of the load types specified in the referenced benchmark.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>loadValues</b></td>
-        <td>[]integer</td>
-        <td>
-          List of load values for the specified load type.<br/>
-        </td>
-        <td>true</td>
-      </tr></tbody>
-</table>
-
-
-### execution.spec.resources
-<sup><sup>[↩ Parent](#executionspec)</sup></sup>
-
-
-
-Specifies the scaling resource that is benchmarked.
-
-<table>
-    <thead>
-        <tr>
-            <th>Name</th>
-            <th>Type</th>
-            <th>Description</th>
-            <th>Required</th>
-        </tr>
-    </thead>
-    <tbody><tr>
-        <td><b>resourceType</b></td>
-        <td>string</td>
-        <td>
-          The type of the resource. It must match one of the resource types specified in the referenced benchmark.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>resourceValues</b></td>
-        <td>[]integer</td>
-        <td>
-          <br/>
-        </td>
-        <td>true</td>
-      </tr></tbody>
-</table>
-
-
-### execution.spec.slos[index]
-<sup><sup>[↩ Parent](#executionspec)</sup></sup>
-
-
-
-
-
-<table>
-    <thead>
-        <tr>
-            <th>Name</th>
-            <th>Type</th>
-            <th>Description</th>
-            <th>Required</th>
-        </tr>
-    </thead>
-    <tbody><tr>
-        <td><b>externalSloUrl</b></td>
-        <td>string</td>
-        <td>
-          Connection string for a external slo analysis.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>offset</b></td>
-        <td>integer</td>
-        <td>
-          Hours by which the start and end timestamp will be shifted (for different timezones).<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>prometheusUrl</b></td>
-        <td>string</td>
-        <td>
-          Connection string for Promehteus.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>sloType</b></td>
-        <td>string</td>
-        <td>
-          The type of the SLO. It must match 'lag trend'.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>threshold</b></td>
-        <td>integer</td>
-        <td>
-          The threshold the SUT should meet for a sucessful experiment.<br/>
-        </td>
-        <td>true</td>
-      </tr><tr>
-        <td><b>warmup</b></td>
-        <td>integer</td>
-        <td>
-          Seconds of time that are ignored in the analysis.<br/>
-        </td>
-        <td>true</td>
-      </tr></tbody>
-</table>
\ No newline at end of file
diff --git a/execution/README.md b/execution/README.md
index eb6ade9f2aab28b6d237e9622f22da0ea5998a50..c12eff782ffc129bb4b1820ce4a1e3076ab4f8ad 100644
--- a/execution/README.md
+++ b/execution/README.md
@@ -1,13 +1,13 @@
 # Theodolite Execution Framework
 
+**Please note: Most of the content in this directory is deprecated. Please refer to the `helm` directory for installing the latest version of Theodolite.**
+
 This directory contains the Theodolite framework for executing scalability
 benchmarks in a Kubernetes cluster. As Theodolite aims for executing benchmarks
 in realistic execution environments, some third-party components are [required](#installation).
 After everything is installed and configured, you can move on the [execution of
 benchmarks](#execution).
 
-*Note: The currently released version of Theodolite only allows running Kafka Streams benchmarks. With the upcoming release `0.5`, we plan to support arbitrary stream processing engines, in particular, our already available implementations for Apache Flink. To already run them now, please contact us.*
-
 ## Installation
 
 For executing benchmarks, access to a Kubernetes cluster is required. If you already run other applications inside your
diff --git a/helm/README.md b/helm/README.md
index 1a3428b5e601de0c6c33f9dab236321e95592c6c..af253482bcbacf628fd718eb70b3b157cc06e3f8 100644
--- a/helm/README.md
+++ b/helm/README.md
@@ -9,6 +9,8 @@ helm dependencies update .
 helm install theodolite .
 ```
 
+**Hint for Windows users:** The Theodolite Helm chart makes use of some symbolic links. These are not properly created when this repository is checked out with Windows. There are a couple of solutions presented in this [Stack Overflow post](https://stackoverflow.com/q/5917249/4121056). A simpler workaround is to manually delete the symbolic links and replace them by the files and folders, they are pointing to. The relevant symbolic links are `benchmark-definitions` and the files inside `crd`.
+
 ## Customize Installation
 
 As usual, the installation with Helm can be configured by passing a values YAML file:
diff --git a/helm/preconfigs/oci.yaml b/helm/preconfigs/oci.yaml
index dd070a1d7983404add85cf75ded0a057a76e854f..35fe5dcf423eed77cb2d3d4298088738125fa9fe 100644
--- a/helm/preconfigs/oci.yaml
+++ b/helm/preconfigs/oci.yaml
@@ -1,4 +1,6 @@
 operator:
   resultsVolume:
-    storageClassName: "oci-bv"
-    size: 50Gi # minimal size in OCI
\ No newline at end of file
+    persistent:
+      enabled: true
+      storageClassName: "oci-bv"
+      size: 50Gi # minimal size in OCI
diff --git a/helm/templates/_helpers.tpl b/helm/templates/_helpers.tpl
index b530b553ea90671aba8154cc250a20924bae0183..569cf454a950f3f621c23472f0346c8bbd52229d 100644
--- a/helm/templates/_helpers.tpl
+++ b/helm/templates/_helpers.tpl
@@ -65,5 +65,5 @@ Create the name of the service account to use
 Create the name of the results volume to use
 */}}
 {{- define "theodolite.resultsClaimName" -}}
-{{- default (printf "%s-results" (include "theodolite.fullname" .)) .Values.operator.resultsVolume.existingClaim }}
+{{- default (printf "%s-results" (include "theodolite.fullname" .)) .Values.operator.resultsVolume.persistent.existingClaim }}
 {{- end }}
diff --git a/helm/templates/theodolite/benchmark-resources-config-map.yaml b/helm/templates/theodolite/benchmark-resources-config-map.yaml
deleted file mode 100644
index 4ec1c1bd9c3b9c05cb77920c20b9b573d413c94a..0000000000000000000000000000000000000000
--- a/helm/templates/theodolite/benchmark-resources-config-map.yaml
+++ /dev/null
@@ -1,19 +0,0 @@
-{{- $processedDict := dict -}}
-{{- range $path, $bytes := .Files.Glob "benchmark-definitions/**/resources/**" }}
-{{- $name := base (dir (dir $path)) }}
-{{- if not (hasKey $processedDict $name) -}}
-{{ $_ := set $processedDict $name "true" }}
-apiVersion: v1
-kind: ConfigMap
-metadata:
-    name: benchmark-resources-{{ $name }}
-data:
-{{ ($.Files.Glob (printf "benchmark-definitions/%s/resources/*" $name)).AsConfig | indent 2 }}
----
-{{- end }}
-{{- end }}
-apiVersion: v1
-kind: ConfigMap
-metadata:
-    name: benchmark-resources-custom
-data: {}
diff --git a/helm/templates/theodolite/benchmarks/benchmark-resources-config-map.yaml b/helm/templates/theodolite/benchmarks/benchmark-resources-config-map.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..2dd355141350921d772edb73a1e8e7795600b0d1
--- /dev/null
+++ b/helm/templates/theodolite/benchmarks/benchmark-resources-config-map.yaml
@@ -0,0 +1,12 @@
+{{- range $configmap, $enabled := .Values.operator.theodoliteBenchmarks.resourceConfigMaps }}
+{{- if $enabled -}}
+{{- $name := kebabcase $configmap }}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: benchmark-resources-{{ $name }}
+data:
+{{ ($.Files.Glob (printf "benchmark-definitions/%s/resources/*" $name)).AsConfig | indent 2 }}
+---
+{{- end }}
+{{- end }}
diff --git a/helm/templates/theodolite/benchmarks/benchmark.yaml b/helm/templates/theodolite/benchmarks/benchmark.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..1c4cb02ea69dbed711b781535127e00e2a24f1d7
--- /dev/null
+++ b/helm/templates/theodolite/benchmarks/benchmark.yaml
@@ -0,0 +1,7 @@
+{{- range $benchmark, $enabled := .Values.operator.theodoliteBenchmarks.benchmarks }}
+{{- if $enabled -}}
+{{- $name := kebabcase $benchmark }}
+{{ $.Files.Get (printf "benchmark-definitions/%s/%s-benchmark-operator.yaml" $name $name) }}
+---
+{{- end }}
+{{- end }}
diff --git a/helm/templates/theodolite/random-scheduler/deployment.yaml b/helm/templates/theodolite/random-scheduler/deployment.yaml
index 55b6e4ad5f8fafccc9623e69ef1df1fccf81ed39..132c5dcf86b9bf6213ac0db6cc03fb1dbadbc2cd 100644
--- a/helm/templates/theodolite/random-scheduler/deployment.yaml
+++ b/helm/templates/theodolite/random-scheduler/deployment.yaml
@@ -27,4 +27,8 @@ spec:
           env:
             - name: TARGET_NAMESPACE
               value: {{ .Release.Namespace }}
+      {{- with .Values.randomScheduler.nodeSelector }}
+      nodeSelector:
+      {{ toYaml . | indent 2 }}
+      {{- end }}
 {{- end }}
diff --git a/helm/templates/theodolite/results-volume/pvc.yaml b/helm/templates/theodolite/results-volume/pvc.yaml
index 6dda16bc85d308c8bf0c9c41dd55cca3582f0793..26ac56e42889ccaebbc669791ad4d318b8318fec 100644
--- a/helm/templates/theodolite/results-volume/pvc.yaml
+++ b/helm/templates/theodolite/results-volume/pvc.yaml
@@ -1,18 +1,18 @@
-{{- if and .Values.operator.resultsVolume.enabled (not .Values.operator.resultsVolume.existingClaim) -}}
+{{- if and .Values.operator.resultsVolume.persistent.enabled (not .Values.operator.resultsVolume.persistent.existingClaim) -}}
 apiVersion: v1
 kind: PersistentVolumeClaim
 metadata:
   name: {{ include "theodolite.resultsClaimName" . }}
 spec:
-  {{- if .Values.operator.resultsVolume.storageClassName }}
-  storageClassName: {{ .Values.operator.resultsVolume.storageClassName }}
+  {{- if .Values.operator.resultsVolume.persistent.storageClassName }}
+  storageClassName: {{ .Values.operator.resultsVolume.persistent.storageClassName }}
   {{- end }}
   accessModes:
     - ReadWriteOnce
-    {{- range .Values.operator.resultsVolume.accessModes }}
+    {{- range .Values.operator.resultsVolume.persistent.accessModes }}
     - {{ . | quote }}
     {{- end }}
   resources:
     requests:
-      storage: {{ .Values.operator.resultsVolume.size | quote }}
+      storage: {{ .Values.operator.resultsVolume.persistent.size | quote }}
 {{- end }}
\ No newline at end of file
diff --git a/helm/templates/theodolite/role.yaml b/helm/templates/theodolite/role.yaml
index b9924ea4908718c361851ff6137b44a19589a0be..43ee0e43d6974cd95548df32d6c4b1df8f3e497e 100644
--- a/helm/templates/theodolite/role.yaml
+++ b/helm/templates/theodolite/role.yaml
@@ -49,6 +49,7 @@ rules:
     - theodolite.com
     resources:
     - benchmarks
+    - benchmarks/status
     - executions
     - executions/status
     verbs:
@@ -68,5 +69,11 @@ rules:
     - get
     - create
     - update
+  - apiGroups:
+    - ""
+    resources:
+    - events
+    verbs:
+    - create
   {{- end }}
 {{- end }}
\ No newline at end of file
diff --git a/helm/templates/theodolite/theodolite-operator.yaml b/helm/templates/theodolite/theodolite-operator.yaml
index 52ddcd500ab8d050187028026def84e9d057c252..c7ced880cbbfbb9795ef59156ea1df7d5b860ec6 100644
--- a/helm/templates/theodolite/theodolite-operator.yaml
+++ b/helm/templates/theodolite/theodolite-operator.yaml
@@ -26,33 +26,11 @@ spec:
               value: {{ .Release.Namespace }}
             - name: MODE
               value: operator
-            - name: THEODOLITE_APP_RESOURCES
-              value: "./benchmark-resources"
             - name: RESULTS_FOLDER
               value: "./results"
           volumeMounts:
-            {{- if .Values.operator.resultsVolume.enabled }}
-            - name: theodolite-pv-storage
+            - name: theodolite-results-volume
               mountPath: "/deployments/results"
-            {{- end }}
-            - name: benchmark-resources-uc1-kstreams
-              mountPath: /deployments/benchmark-resources/uc1-kstreams
-            - name: benchmark-resources-uc2-kstreams
-              mountPath: /deployments/benchmark-resources/uc2-kstreams
-            - name: benchmark-resources-uc3-kstreams
-              mountPath: /deployments/benchmark-resources/uc3-kstreams
-            - name: benchmark-resources-uc4-kstreams
-              mountPath: /deployments/benchmark-resources/uc4-kstreams
-            - name: benchmark-resources-uc1-flink
-              mountPath: /deployments/benchmark-resources/uc1-flink
-            - name: benchmark-resources-uc2-flink
-              mountPath: /deployments/benchmark-resources/uc2-flink
-            - name: benchmark-resources-uc3-flink
-              mountPath: /deployments/benchmark-resources/uc3-flink
-            - name: benchmark-resources-uc4-flink
-              mountPath: /deployments/benchmark-resources/uc4-flink
-            - name: benchmark-resources-custom
-              mountPath: /deployments/benchmark-resources/custom
         {{- if .Values.operator.sloChecker.lagTrend.enabled }}
         - name: lag-trend-slo-checker
           image: "{{ .Values.operator.sloChecker.lagTrend.image }}:{{ .Values.operator.sloChecker.lagTrend.imageTag }}"
@@ -77,7 +55,7 @@ spec:
           - name: LOG_LEVEL
             value: INFO
         {{- end }}
-        {{- if and .Values.operator.resultsVolume.enabled .Values.operator.resultsVolume.accessSidecar.enabled }}
+        {{- if .Values.operator.resultsVolume.accessSidecar.enabled }}
         - name: results-access
           image: busybox:stable
           image: "{{ .Values.operator.resultsVolume.accessSidecar.image }}:{{ .Values.operator.resultsVolume.accessSidecar.imageTag }}"
@@ -88,48 +66,18 @@ spec:
           - exec tail -f /dev/null
           volumeMounts:
           - mountPath: /results
-            name: theodolite-pv-storage
+            name: theodolite-results-volume
         {{- end }}
       volumes:
-      {{- if .Values.operator.resultsVolume.enabled }}
-      - name: theodolite-pv-storage
+      - name: theodolite-results-volume
+        {{- if .Values.operator.resultsVolume.persistent.enabled }}
         persistentVolumeClaim:
           claimName: {{ include "theodolite.resultsClaimName" . | quote }}
+        {{- else }}
+        emptyDir: {}
+        {{- end }}
+      {{- with .Values.operator.nodeSelector }}
+      nodeSelector:
+      {{ toYaml . | indent 2 }}
       {{- end }}
-      - name: benchmark-resources-uc1-kstreams
-        configMap:
-          name: benchmark-resources-uc1-kstreams
-          optional: true
-      - name: benchmark-resources-uc2-kstreams
-        configMap:
-          name: benchmark-resources-uc2-kstreams
-          optional: true
-      - name: benchmark-resources-uc3-kstreams
-        configMap:
-          name: benchmark-resources-uc3-kstreams
-          optional: true
-      - name: benchmark-resources-uc4-kstreams
-        configMap:
-          name: benchmark-resources-uc4-kstreams
-          optional: true
-      - name: benchmark-resources-uc1-flink
-        configMap:
-          name: benchmark-resources-uc1-flink
-          optional: true
-      - name: benchmark-resources-uc2-flink
-        configMap:
-          name: benchmark-resources-uc2-flink
-          optional: true
-      - name: benchmark-resources-uc3-flink
-        configMap:
-          name: benchmark-resources-uc3-flink
-          optional: true
-      - name: benchmark-resources-uc4-flink
-        configMap:
-          name: benchmark-resources-uc4-flink
-          optional: true
-      - name: benchmark-resources-custom
-        configMap:
-          name: benchmark-resources-custom
-          optional: true
 {{- end }}
diff --git a/helm/values.yaml b/helm/values.yaml
index b0ce0faeaa7989872fdedc308d3d4c507894e0e7..9de0155cf26d26bc20975d8ec6524607ac9a1d43 100644
--- a/helm/values.yaml
+++ b/helm/values.yaml
@@ -3,7 +3,7 @@
 ###
 
 kafkaClient:
-  enabled: true
+  enabled: false
   nodeSelector: {}
   
 
@@ -155,7 +155,10 @@ cp-helm-charts:
 ###
 kafka-lag-exporter:
   enabled: true
+  image:
+    pullPolicy: IfNotPresent
   nodeSelector: {}
+  
   clusters:
     - name: "theodolite-cp-kafka"
       bootstrapBrokers: "theodolite-cp-kafka:9092"
@@ -250,6 +253,8 @@ operator:
   imageTag: latest
   imagePullPolicy: Always
 
+  nodeSelector: {}
+
   sloChecker:
     lagTrend:
       enabled: true
@@ -263,18 +268,42 @@ operator:
       imagePullPolicy: Always
 
   resultsVolume:
-    enabled: true
-    # existingClaim:
-    # storageClassName:
-    accessModes:
-      - ReadWriteOnce
-    size: 1Gi
+    persistent:
+      enabled: false
+      # existingClaim:
+      # storageClassName:
+      accessModes:
+        - ReadWriteOnce
+      size: 1Gi
     accessSidecar:
       enabled: true
       image: busybox
       imageTag: stable
       imagePullPolicy: IfNotPresent
 
+  theodoliteBenchmarks:
+    resourceConfigMaps:
+      uc1LoadGenerator: true
+      uc1Kstreams: true
+      uc1Flink: true
+      uc2LoadGenerator: true
+      uc2Kstreams: true
+      uc2Flink: true
+      uc3LoadGenerator: true
+      uc3Kstreams: true
+      uc3Flink: true
+      uc4LoadGenerator: true
+      uc4Kstreams: true
+      uc4Flink: true
+    benchmarks:
+      uc1Kstreams: true
+      uc1Flink: true
+      uc2Kstreams: true
+      uc2Flink: true
+      uc3Kstreams: true
+      uc3Flink: true
+      uc4Kstreams: true
+      uc4Flink: true
 
 serviceAccount:
   create: true
@@ -291,3 +320,4 @@ randomScheduler:
     create: true
   serviceAccount:
     create: true
+  nodeSelector: {}
diff --git a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.flink.gradle b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.flink.gradle
index d6d5217667a73a1529d73ac59260bcf47d8cf2e1..333a87bf55bcd0051be05ca91dfe8dc9a2e9e8fa 100644
--- a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.flink.gradle
+++ b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.flink.gradle
@@ -48,19 +48,19 @@ dependencies {
     implementation 'com.google.guava:guava:24.1-jre'
     implementation 'com.google.code.gson:gson:2.8.2'
     implementation 'org.slf4j:slf4j-simple:1.6.1'
-    compile project(':flink-commons')
+    implementation project(':flink-commons')
 
     //compile group: 'org.apache.kafka', name: 'kafka-clients', version: "2.2.0"
-    compile group: 'org.apache.flink', name: 'flink-java', version: "${flinkVersion}"
-    compile group: 'org.apache.flink', name: "flink-streaming-java_${scalaBinaryVersion}", version:"${flinkVersion}"
-    compile group: 'org.apache.flink', name: "flink-table-api-java-bridge_${scalaBinaryVersion}", version: "${flinkVersion}"
-    compile group: 'org.apache.flink', name: "flink-table-planner-blink_${scalaBinaryVersion}", version: "${flinkVersion}"
-    compile group: 'org.apache.flink', name: "flink-connector-kafka_${scalaBinaryVersion}", version: "${flinkVersion}"
+    implementation "org.apache.flink:flink-java:${flinkVersion}"
+    implementation "org.apache.flink:flink-streaming-java_${scalaBinaryVersion}:${flinkVersion}"
+    implementation "org.apache.flink:flink-table-api-java-bridge_${scalaBinaryVersion}:${flinkVersion}"
+    implementation "org.apache.flink:flink-table-planner-blink_${scalaBinaryVersion}:${flinkVersion}"
+    implementation "org.apache.flink:flink-connector-kafka_${scalaBinaryVersion}:${flinkVersion}"
     implementation "org.apache.flink:flink-avro:${flinkVersion}"
     implementation "org.apache.flink:flink-avro-confluent-registry:${flinkVersion}"
-    compile group: 'org.apache.flink', name: "flink-runtime-web_${scalaBinaryVersion}", version: "${flinkVersion}" // TODO: remove after development
-    compile group: 'org.apache.flink', name: "flink-statebackend-rocksdb_${scalaBinaryVersion}", version: "${flinkVersion}"
-    compile group: 'org.apache.flink', name: "flink-metrics-prometheus_${scalaBinaryVersion}", version: "${flinkVersion}"
+    implementation "org.apache.flink:flink-runtime-web_${scalaBinaryVersion}:${flinkVersion}" // For debugging
+    implementation "org.apache.flink:flink-statebackend-rocksdb_${scalaBinaryVersion}:${flinkVersion}"
+    implementation "org.apache.flink:flink-metrics-prometheus_${scalaBinaryVersion}:${flinkVersion}"
 
     // Use JUnit test framework
     testImplementation 'junit:junit:4.12'
diff --git a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.java-conventions.gradle b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.java-conventions.gradle
index c546156736017d742ddbdbf8b9f1f13726dc5ed8..5b0e2a8a1211653428b296b11b14c1531e40e46b 100644
--- a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.java-conventions.gradle
+++ b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.java-conventions.gradle
@@ -50,7 +50,7 @@ pmd {
   ruleSets = [] // Gradle requires to clean the rule sets first
   ruleSetFiles = files("$rootProject.projectDir/config/pmd.xml")
   ignoreFailures = false
-  toolVersion = "6.8.0"
+  toolVersion = "6.13.0"
 }
 
 checkstyle {
@@ -58,7 +58,7 @@ checkstyle {
   configFile = file("$rootProject.projectDir/config/checkstyle.xml")
   maxWarnings = 0
   ignoreFailures = false
-  toolVersion = "8.12"
+  toolVersion = "8.19"
 }
 
 spotbugs {
diff --git a/theodolite-benchmarks/definitions/install-configmaps.sh b/theodolite-benchmarks/definitions/install-configmaps.sh
index 7ddd606a162185993ce402ef4d3b84d8d00eb82c..841a293bbb77c4960a2532a13a009a42227223d3 100755
--- a/theodolite-benchmarks/definitions/install-configmaps.sh
+++ b/theodolite-benchmarks/definitions/install-configmaps.sh
@@ -1,8 +1,17 @@
+# Flink 
 kubectl create configmap benchmark-resources-uc1-flink --from-file uc1-flink/resources
 kubectl create configmap benchmark-resources-uc2-flink --from-file uc2-flink/resources
 kubectl create configmap benchmark-resources-uc3-flink --from-file uc3-flink/resources
 kubectl create configmap benchmark-resources-uc4-flink --from-file uc4-flink/resources
+
+# Kafka Streams
 kubectl create configmap benchmark-resources-uc1-kstreams --from-file uc1-kstreams/resources
 kubectl create configmap benchmark-resources-uc2-kstreams --from-file uc2-kstreams/resources
 kubectl create configmap benchmark-resources-uc3-kstreams --from-file uc3-kstreams/resources
-kubectl create configmap benchmark-resources-uc4-kstreams --from-file uc4-kstreams/resources
\ No newline at end of file
+kubectl create configmap benchmark-resources-uc4-kstreams --from-file uc4-kstreams/resources
+
+# Load Generator
+kubectl create configmap benchmark-resources-uc1-load-generator --from-file uc1-load-generator/resources
+kubectl create configmap benchmark-resources-uc2-load-generator --from-file uc2-load-generator/resources
+kubectl create configmap benchmark-resources-uc3-load-generator --from-file uc3-load-generator/resources
+kubectl create configmap benchmark-resources-uc4-load-generator --from-file uc4-load-generator/resources
diff --git a/theodolite-benchmarks/definitions/uc1-flink/uc1-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc1-flink/uc1-flink-benchmark-operator.yaml
index 3e16e486446d568d2cac0fe5196ab7446be25978..89bac41ee5c8dcefa628b3cb01052df5a1df9292 100644
--- a/theodolite-benchmarks/definitions/uc1-flink/uc1-flink-benchmark-operator.yaml
+++ b/theodolite-benchmarks/definitions/uc1-flink/uc1-flink-benchmark-operator.yaml
@@ -3,29 +3,37 @@ kind: benchmark
 metadata:
   name: uc1-flink
 spec:
-  appResource:
-    - "uc1-flink/flink-configuration-configmap.yaml"
-    - "uc1-flink/taskmanager-deployment.yaml"
-    - "uc1-flink/taskmanager-service.yaml"
-    - "uc1-flink/service-monitor.yaml"
-    - "uc1-flink/jobmanager-service.yaml"
-    - "uc1-flink/jobmanager-deployment.yaml"
-    #- "uc1-flink/jobmanager-rest-service.yaml"
-  loadGenResource:
-    - "uc1-kstreams/uc1-load-generator-deployment.yaml"
-    - "uc1-kstreams/uc1-load-generator-service.yaml"
+  sut:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc1-flink"
+          files:
+          - "flink-configuration-configmap.yaml"
+          - "taskmanager-deployment.yaml"
+          - "taskmanager-service.yaml"
+          - "service-monitor.yaml"
+          - "jobmanager-service.yaml"
+          - "jobmanager-deployment.yaml"
+          #- "jobmanager-rest-service.yaml"
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc1-load-generator"
+          files:
+          - "uc1-load-generator-deployment.yaml"
+          - "uc1-load-generator-service.yaml"
   resourceTypes:
     - typeName: "Instances"
       patchers:
         - type: "ReplicaPatcher"
-          resource: "uc1-flink/taskmanager-deployment.yaml"
+          resource: "taskmanager-deployment.yaml"
         - type: "EnvVarPatcher"
-          resource: "uc1-flink/jobmanager-deployment.yaml"
+          resource: "jobmanager-deployment.yaml"
           properties:
             container: "jobmanager"
             variableName: "PARALLELISM"
         - type: "EnvVarPatcher" # required?
-          resource: "uc1-flink/taskmanager-deployment.yaml"
+          resource: "taskmanager-deployment.yaml"
           properties:
             container: "taskmanager"
             variableName: "PARALLELISM"
@@ -33,12 +41,12 @@ spec:
     - typeName: "NumSensors"
       patchers:
         - type: "EnvVarPatcher"
-          resource: "uc1-kstreams/uc1-load-generator-deployment.yaml"
+          resource: "uc1-load-generator-deployment.yaml"
           properties:
             container: "workload-generator"
             variableName: "NUM_SENSORS"
         - type: NumSensorsLoadGeneratorReplicaPatcher
-          resource: "uc1-kstreams/uc1-load-generator-deployment.yaml"
+          resource: "uc1-load-generator-deployment.yaml"
           properties:
             loadGenMaxRecords: "150000"
   kafkaConfig:
diff --git a/theodolite-benchmarks/definitions/uc1-kstreams/uc1-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc1-kstreams/uc1-benchmark-operator.yaml
deleted file mode 100644
index 8bcc7d5a1d750eed140527e7c6176a881bc9e6e1..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/definitions/uc1-kstreams/uc1-benchmark-operator.yaml
+++ /dev/null
@@ -1,36 +0,0 @@
-apiVersion: theodolite.com/v1
-kind: benchmark
-metadata:
-  name: uc1-kstreams
-spec:
-  appResource:
-    - "uc1-kstreams/uc1-kstreams-deployment.yaml"
-    - "uc1-kstreams/uc1-kstreams-service.yaml"
-    - "uc1-kstreams/uc1-jmx-configmap.yaml"
-    - "uc1-kstreams/uc1-service-monitor.yaml"
-  loadGenResource:
-    - "uc1-kstreams/uc1-load-generator-deployment.yaml"
-    - "uc1-kstreams/uc1-load-generator-service.yaml"
-  resourceTypes:
-    - typeName: "Instances"
-      patchers:
-        - type: "ReplicaPatcher"
-          resource: "uc1-kstreams/uc1-kstreams-deployment.yaml"
-  loadTypes:
-    - typeName: "NumSensors"
-      patchers:
-        - type: "EnvVarPatcher"
-          resource: "uc1-kstreams/uc1-load-generator-deployment.yaml"
-          properties:
-            container: "workload-generator"
-            variableName: "NUM_SENSORS"
-        - type: NumSensorsLoadGeneratorReplicaPatcher
-          resource: "uc1-kstreams/uc1-load-generator-deployment.yaml"
-          properties:
-            loadGenMaxRecords: "150000"
-  kafkaConfig:
-    bootstrapServer: "theodolite-cp-kafka:9092"
-    topics:
-      - name: "input"
-        numPartitions: 40
-        replicationFactor: 1
diff --git a/theodolite-benchmarks/definitions/uc1-kstreams/uc1-kstreams-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc1-kstreams/uc1-kstreams-benchmark-operator.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..fb5557c2df8b483164d3c1000717db4c7cface81
--- /dev/null
+++ b/theodolite-benchmarks/definitions/uc1-kstreams/uc1-kstreams-benchmark-operator.yaml
@@ -0,0 +1,44 @@
+apiVersion: theodolite.com/v1
+kind: benchmark
+metadata:
+  name: uc1-kstreams
+spec:
+  sut:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc1-kstreams"
+          files:
+          - "uc1-kstreams-deployment.yaml"
+          - "uc1-kstreams-service.yaml"
+          - "uc1-jmx-configmap.yaml"
+          - "uc1-service-monitor.yaml"
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc1-load-generator"
+          files:
+          - "uc1-load-generator-deployment.yaml"
+          - "uc1-load-generator-service.yaml"
+  resourceTypes:
+    - typeName: "Instances"
+      patchers:
+        - type: "ReplicaPatcher"
+          resource: "uc1-kstreams-deployment.yaml"
+  loadTypes:
+    - typeName: "NumSensors"
+      patchers:
+        - type: "EnvVarPatcher"
+          resource: "uc1-load-generator-deployment.yaml"
+          properties:
+            container: "workload-generator"
+            variableName: "NUM_SENSORS"
+        - type: NumSensorsLoadGeneratorReplicaPatcher
+          resource: "uc1-load-generator-deployment.yaml"
+          properties:
+            loadGenMaxRecords: "150000"
+  kafkaConfig:
+    bootstrapServer: "theodolite-cp-kafka:9092"
+    topics:
+      - name: "input"
+        numPartitions: 40
+        replicationFactor: 1
diff --git a/theodolite-benchmarks/definitions/uc1-kstreams/uc1-benchmark-standalone.yaml b/theodolite-benchmarks/definitions/uc1-kstreams/uc1-kstreams-benchmark-standalone.yaml
similarity index 59%
rename from theodolite-benchmarks/definitions/uc1-kstreams/uc1-benchmark-standalone.yaml
rename to theodolite-benchmarks/definitions/uc1-kstreams/uc1-kstreams-benchmark-standalone.yaml
index 871210c213b70070e2aae8f4986058763be74b7e..5aaf87e724a4e8c728c3c15b998cb927ff57f3d5 100644
--- a/theodolite-benchmarks/definitions/uc1-kstreams/uc1-benchmark-standalone.yaml
+++ b/theodolite-benchmarks/definitions/uc1-kstreams/uc1-kstreams-benchmark-standalone.yaml
@@ -1,12 +1,20 @@
 name: "uc1-kstreams"
-appResource:
-  - "uc1-kstreams-deployment.yaml"
-  - "uc1-kstreams-service.yaml"
-  - "uc1-jmx-configmap.yaml"
-  - "uc1-service-monitor.yaml"
-loadGenResource:
-  - "uc1-load-generator-deployment.yaml"
-  - "uc1-load-generator-service.yaml"
+sut:
+  resources:
+    - configMap:
+        name: "benchmark-resources-uc1-kstreams"
+        files:
+        - "uc1-kstreams-deployment.yaml"
+        - "uc1-kstreams-service.yaml"
+        - "uc1-jmx-configmap.yaml"
+        - "uc1-service-monitor.yaml"
+loadGenerator:
+  resources:
+    - configMap:
+        name: "benchmark-resources-uc1-load-generator"
+        files:
+        - "uc1-load-generator-deployment.yaml"
+        - "uc1-load-generator-service.yaml"
 resourceTypes:
   - typeName: "Instances"
     patchers:
diff --git a/theodolite-benchmarks/definitions/uc1-kstreams/resources/uc1-load-generator-deployment.yaml b/theodolite-benchmarks/definitions/uc1-load-generator/resources/uc1-load-generator-deployment.yaml
similarity index 100%
rename from theodolite-benchmarks/definitions/uc1-kstreams/resources/uc1-load-generator-deployment.yaml
rename to theodolite-benchmarks/definitions/uc1-load-generator/resources/uc1-load-generator-deployment.yaml
diff --git a/theodolite-benchmarks/definitions/uc1-kstreams/resources/uc1-load-generator-service.yaml b/theodolite-benchmarks/definitions/uc1-load-generator/resources/uc1-load-generator-service.yaml
similarity index 100%
rename from theodolite-benchmarks/definitions/uc1-kstreams/resources/uc1-load-generator-service.yaml
rename to theodolite-benchmarks/definitions/uc1-load-generator/resources/uc1-load-generator-service.yaml
diff --git a/theodolite-benchmarks/definitions/uc2-flink/uc2-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc2-flink/uc2-flink-benchmark-operator.yaml
index ab335cc4f9f8413dd7871fc2184491235aad67e4..206fbf9683659fcc074341d7077da04c36909b75 100644
--- a/theodolite-benchmarks/definitions/uc2-flink/uc2-flink-benchmark-operator.yaml
+++ b/theodolite-benchmarks/definitions/uc2-flink/uc2-flink-benchmark-operator.yaml
@@ -3,29 +3,37 @@ kind: benchmark
 metadata:
   name: uc2-flink
 spec:
-  appResource:
-    - "uc2-flink/flink-configuration-configmap.yaml"
-    - "uc2-flink/taskmanager-deployment.yaml"
-    - "uc2-flink/taskmanager-service.yaml"
-    - "uc2-flink/service-monitor.yaml"
-    - "uc2-flink/jobmanager-service.yaml"
-    - "uc2-flink/jobmanager-deployment.yaml"
-    #- "uc2-flink/jobmanager-rest-service.yaml"
-  loadGenResource:
-    - "uc2-kstreams/uc2-load-generator-deployment.yaml"
-    - "uc2-kstreams/uc2-load-generator-service.yaml"
+  sut:
+    resources:
+        - configMap:
+            name: "benchmark-resources-uc2-flink"
+            files:
+            - "flink-configuration-configmap.yaml"
+            - "taskmanager-deployment.yaml"
+            - "taskmanager-service.yaml"
+            - "service-monitor.yaml"
+            - "jobmanager-service.yaml"
+            - "jobmanager-deployment.yaml"
+            #- "jobmanager-rest-service.yaml"
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc2-load-generator"
+          files:
+            - "uc2-load-generator-deployment.yaml"
+            - "uc2-load-generator-service.yaml"
   resourceTypes:
     - typeName: "Instances"
       patchers:
         - type: "ReplicaPatcher"
-          resource: "uc2-flink/taskmanager-deployment.yaml"
+          resource: "taskmanager-deployment.yaml"
         - type: "EnvVarPatcher"
-          resource: "uc2-flink/jobmanager-deployment.yaml"
+          resource: "jobmanager-deployment.yaml"
           properties:
             container: "jobmanager"
             variableName: "PARALLELISM"
         - type: "EnvVarPatcher" # required?
-          resource: "uc2-flink/taskmanager-deployment.yaml"
+          resource: "taskmanager-deployment.yaml"
           properties:
             container: "taskmanager"
             variableName: "PARALLELISM"
@@ -33,12 +41,12 @@ spec:
     - typeName: "NumSensors"
       patchers:
         - type: "EnvVarPatcher"
-          resource: "uc2-kstreams/uc2-load-generator-deployment.yaml"
+          resource: "uc2-load-generator-deployment.yaml"
           properties:
             container: "workload-generator"
             variableName: "NUM_SENSORS"
         - type: NumSensorsLoadGeneratorReplicaPatcher
-          resource: "uc2-kstreams/uc2-load-generator-deployment.yaml"
+          resource: "uc2-load-generator-deployment.yaml"
           properties:
             loadGenMaxRecords: "150000"
   kafkaConfig:
diff --git a/theodolite-benchmarks/definitions/uc2-kstreams/uc2-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc2-kstreams/uc2-kstreams-benchmark-operator.yaml
similarity index 53%
rename from theodolite-benchmarks/definitions/uc2-kstreams/uc2-benchmark-operator.yaml
rename to theodolite-benchmarks/definitions/uc2-kstreams/uc2-kstreams-benchmark-operator.yaml
index c71318c95ceb9d462f64e19b135ce59b43b03099..0db22fa95f46d1cb484fa1a7730b8b6801dac67c 100644
--- a/theodolite-benchmarks/definitions/uc2-kstreams/uc2-benchmark-operator.yaml
+++ b/theodolite-benchmarks/definitions/uc2-kstreams/uc2-kstreams-benchmark-operator.yaml
@@ -3,29 +3,37 @@ kind: benchmark
 metadata:
   name: uc2-kstreams
 spec:
-  appResource:
-    - "uc2-kstreams/uc2-kstreams-deployment.yaml"
-    - "uc2-kstreams/uc2-kstreams-service.yaml"
-    - "uc2-kstreams/uc2-jmx-configmap.yaml"
-    - "uc2-kstreams/uc2-service-monitor.yaml"
-  loadGenResource:
-    - "uc2-kstreams/uc2-load-generator-deployment.yaml"
-    - "uc2-kstreams/uc2-load-generator-service.yaml"
+  sut:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc2-kstreams"
+          files:
+            - "uc2-kstreams-deployment.yaml"
+            - "uc2-kstreams-service.yaml"
+            - "uc2-jmx-configmap.yaml"
+            - "uc2-service-monitor.yaml"
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc2-load-generator"
+          files:
+            - "uc2-load-generator-deployment.yaml"
+            - "uc2-load-generator-service.yaml"
   resourceTypes:
     - typeName: "Instances"
       patchers:
         - type: "ReplicaPatcher"
-          resource: "uc2-kstreams/uc2-kstreams-deployment.yaml"
+          resource: "uc2-kstreams-deployment.yaml"
   loadTypes:
     - typeName: "NumSensors"
       patchers:
         - type: "EnvVarPatcher"
-          resource: "uc2-kstreams/uc2-load-generator-deployment.yaml"
+          resource: "uc2-load-generator-deployment.yaml"
           properties:
             container: "workload-generator"
             variableName: "NUM_SENSORS"
         - type: NumSensorsLoadGeneratorReplicaPatcher
-          resource: "uc2-kstreams/uc2-load-generator-deployment.yaml"
+          resource: "uc2-load-generator-deployment.yaml"
           properties:
             loadGenMaxRecords: "150000"
   kafkaConfig:
diff --git a/theodolite-benchmarks/definitions/uc2-kstreams/uc2-benchmark-standalone.yaml b/theodolite-benchmarks/definitions/uc2-kstreams/uc2-kstreams-benchmark-standalone.yaml
similarity index 63%
rename from theodolite-benchmarks/definitions/uc2-kstreams/uc2-benchmark-standalone.yaml
rename to theodolite-benchmarks/definitions/uc2-kstreams/uc2-kstreams-benchmark-standalone.yaml
index 48269b38a086f074ead80964df3bd4633742743e..67376d76bf0a7cc4cd47563a1d8da8dc0aa3b944 100644
--- a/theodolite-benchmarks/definitions/uc2-kstreams/uc2-benchmark-standalone.yaml
+++ b/theodolite-benchmarks/definitions/uc2-kstreams/uc2-kstreams-benchmark-standalone.yaml
@@ -1,12 +1,20 @@
 name: "uc2-kstreams"
-appResource:
-  - "uc2-kstreams-deployment.yaml"
-  - "uc2-kstreams-service.yaml"
-  - "uc2-jmx-configmap.yaml"
-  - "uc2-service-monitor.yaml"
-loadGenResource:
-  - "uc2-load-generator-deployment.yaml"
-  - "uc2-load-generator-service.yaml"
+sut:
+  resources:
+    - configMap:
+        name: "benchmark-resources-uc2-kstreams"
+        files:
+          - "uc2-kstreams-deployment.yaml"
+          - "uc2-kstreams-service.yaml"
+          - "uc2-jmx-configmap.yaml"
+          - "uc2-service-monitor.yaml"
+loadGenerator:
+  resources:
+    - configMap:
+        name: "benchmark-resources-uc2-load-generator"
+        files:
+          - "uc2-load-generator-deployment.yaml"
+          - "uc2-load-generator-service.yaml"
 resourceTypes:
   - typeName: "Instances"
     patchers:
diff --git a/theodolite-benchmarks/definitions/uc2-kstreams/resources/uc2-load-generator-deployment.yaml b/theodolite-benchmarks/definitions/uc2-load-generator/resources/uc2-load-generator-deployment.yaml
similarity index 100%
rename from theodolite-benchmarks/definitions/uc2-kstreams/resources/uc2-load-generator-deployment.yaml
rename to theodolite-benchmarks/definitions/uc2-load-generator/resources/uc2-load-generator-deployment.yaml
diff --git a/theodolite-benchmarks/definitions/uc2-kstreams/resources/uc2-load-generator-service.yaml b/theodolite-benchmarks/definitions/uc2-load-generator/resources/uc2-load-generator-service.yaml
similarity index 100%
rename from theodolite-benchmarks/definitions/uc2-kstreams/resources/uc2-load-generator-service.yaml
rename to theodolite-benchmarks/definitions/uc2-load-generator/resources/uc2-load-generator-service.yaml
diff --git a/theodolite-benchmarks/definitions/uc3-flink/uc3-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc3-flink/uc3-flink-benchmark-operator.yaml
index bc881d83d622f49409c4b2023b7fd9445038c2e8..47b64d9890fc0f300ee1bd8e67acbdf7c8c4e4f9 100644
--- a/theodolite-benchmarks/definitions/uc3-flink/uc3-flink-benchmark-operator.yaml
+++ b/theodolite-benchmarks/definitions/uc3-flink/uc3-flink-benchmark-operator.yaml
@@ -3,29 +3,37 @@ kind: benchmark
 metadata:
   name: uc3-flink
 spec:
-  appResource:
-    - "uc3-flink/flink-configuration-configmap.yaml"
-    - "uc3-flink/taskmanager-deployment.yaml"
-    - "uc3-flink/taskmanager-service.yaml"
-    - "uc3-flink/service-monitor.yaml"
-    - "uc3-flink/jobmanager-service.yaml"
-    - "uc3-flink/jobmanager-deployment.yaml"
-    #- "uc3-flink/jobmanager-rest-service.yaml"
-  loadGenResource:
-    - "uc3-kstreams/uc3-load-generator-deployment.yaml"
-    - "uc3-kstreams/uc3-load-generator-service.yaml"
+  sut:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc3-flink"
+          files:
+            - "flink-configuration-configmap.yaml"
+            - "taskmanager-deployment.yaml"
+            - "taskmanager-service.yaml"
+            - "service-monitor.yaml"
+            - "jobmanager-service.yaml"
+            - "jobmanager-deployment.yaml"
+            #- "jobmanager-rest-service.yaml"
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc3-load-generator"
+          files:
+            - "uc3-load-generator-deployment.yaml"
+            - "uc3-load-generator-service.yaml"
   resourceTypes:
     - typeName: "Instances"
       patchers:
         - type: "ReplicaPatcher"
-          resource: "uc3-flink/taskmanager-deployment.yaml"
+          resource: "taskmanager-deployment.yaml"
         - type: "EnvVarPatcher"
-          resource: "uc3-flink/jobmanager-deployment.yaml"
+          resource: "jobmanager-deployment.yaml"
           properties:
             container: "jobmanager"
             variableName: "PARALLELISM"
         - type: "EnvVarPatcher" # required?
-          resource: "uc3-flink/taskmanager-deployment.yaml"
+          resource: "taskmanager-deployment.yaml"
           properties:
             container: "taskmanager"
             variableName: "PARALLELISM"
@@ -33,12 +41,12 @@ spec:
     - typeName: "NumSensors"
       patchers:
         - type: "EnvVarPatcher"
-          resource: "uc3-kstreams/uc3-load-generator-deployment.yaml"
+          resource: "uc3-load-generator-deployment.yaml"
           properties:
             container: "workload-generator"
             variableName: "NUM_SENSORS"
         - type: NumSensorsLoadGeneratorReplicaPatcher
-          resource: "uc3-kstreams/uc3-load-generator-deployment.yaml"
+          resource: "uc3-load-generator-deployment.yaml"
           properties:
             loadGenMaxRecords: "150000"
   kafkaConfig:
diff --git a/theodolite-benchmarks/definitions/uc3-kstreams/uc3-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc3-kstreams/uc3-kstreams-benchmark-operator.yaml
similarity index 54%
rename from theodolite-benchmarks/definitions/uc3-kstreams/uc3-benchmark-operator.yaml
rename to theodolite-benchmarks/definitions/uc3-kstreams/uc3-kstreams-benchmark-operator.yaml
index cc10020b17c7a31b61f5fdaf6963be9fda75865f..25374ad92a32782857cea5924ea6482060832eac 100644
--- a/theodolite-benchmarks/definitions/uc3-kstreams/uc3-benchmark-operator.yaml
+++ b/theodolite-benchmarks/definitions/uc3-kstreams/uc3-kstreams-benchmark-operator.yaml
@@ -3,29 +3,37 @@ kind: benchmark
 metadata:
   name: uc3-kstreams
 spec:
-  appResource:
-    - "uc3-kstreams/uc3-kstreams-deployment.yaml"
-    - "uc3-kstreams/uc3-kstreams-service.yaml"
-    - "uc3-kstreams/uc3-jmx-configmap.yaml"
-    - "uc3-kstreams/uc3-service-monitor.yaml"
-  loadGenResource:
-    - "uc3-kstreams/uc3-load-generator-deployment.yaml"
-    - "uc3-kstreams/uc3-load-generator-service.yaml"
+  sut:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc3-kstreams"
+          files:
+          - "uc3-kstreams-deployment.yaml"
+          - "uc3-kstreams-service.yaml"
+          - "uc3-jmx-configmap.yaml"
+          - "uc3-service-monitor.yaml"
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc3-load-generator"
+          files:
+            - "uc3-load-generator-deployment.yaml"
+            - "uc3-load-generator-service.yaml"
   resourceTypes:
     - typeName: "Instances"
       patchers:
         - type: "ReplicaPatcher"
-          resource: "uc3-kstreams/uc3-kstreams-deployment.yaml"
+          resource: "uc3-kstreams-deployment.yaml"
   loadTypes:
     - typeName: "NumSensors"
       patchers:
         - type: "EnvVarPatcher"
-          resource: "uc3-kstreams/uc3-load-generator-deployment.yaml"
+          resource: "uc3-load-generator-deployment.yaml"
           properties:
             container: "workload-generator"
             variableName: "NUM_SENSORS"
         - type: NumSensorsLoadGeneratorReplicaPatcher
-          resource: "uc3-kstreams/uc3-load-generator-deployment.yaml"
+          resource: "uc3-load-generator-deployment.yaml"
           properties:
             loadGenMaxRecords: "150000"
   kafkaConfig:
diff --git a/theodolite-benchmarks/definitions/uc3-kstreams/uc3-benchmark-standalone.yaml b/theodolite-benchmarks/definitions/uc3-kstreams/uc3-kstreams-benchmark-standalone.yaml
similarity index 64%
rename from theodolite-benchmarks/definitions/uc3-kstreams/uc3-benchmark-standalone.yaml
rename to theodolite-benchmarks/definitions/uc3-kstreams/uc3-kstreams-benchmark-standalone.yaml
index 0c2311388f1dfa87e8a182eb8399020bc83ae4ce..aa92913d2c992835078174747ea849ce296c3eb1 100644
--- a/theodolite-benchmarks/definitions/uc3-kstreams/uc3-benchmark-standalone.yaml
+++ b/theodolite-benchmarks/definitions/uc3-kstreams/uc3-kstreams-benchmark-standalone.yaml
@@ -1,12 +1,20 @@
 name: "uc3-kstreams"
-appResource:
-  - "uc3-kstreams-deployment.yaml"
-  - "uc3-kstreams-service.yaml"
-  - "uc3-jmx-configmap.yaml"
-  - "uc3-service-monitor.yaml"
-loadGenResource:
-  - "uc3-load-generator-deployment.yaml"
-  - "uc3-load-generator-service.yaml"
+sut:
+  resources:
+    - configMap:
+        name: "benchmark-resources-uc3-kstreams"
+        files:
+        - "uc3-kstreams-deployment.yaml"
+        - "uc3-kstreams-service.yaml"
+        - "uc3-jmx-configmap.yaml"
+        - "uc3-service-monitor.yaml"
+loadGenerator:
+  resources:
+    - configMap:
+        name: "benchmark-resources-uc3-load-generator"
+        files:
+          - "uc3-load-generator-deployment.yaml"
+          - "uc3-load-generator-service.yaml"
 resourceTypes:
   - typeName: "Instances"
     patchers:
diff --git a/theodolite-benchmarks/definitions/uc3-kstreams/resources/uc3-load-generator-deployment.yaml b/theodolite-benchmarks/definitions/uc3-load-generator/resources/uc3-load-generator-deployment.yaml
similarity index 100%
rename from theodolite-benchmarks/definitions/uc3-kstreams/resources/uc3-load-generator-deployment.yaml
rename to theodolite-benchmarks/definitions/uc3-load-generator/resources/uc3-load-generator-deployment.yaml
diff --git a/theodolite-benchmarks/definitions/uc3-kstreams/resources/uc3-load-generator-service.yaml b/theodolite-benchmarks/definitions/uc3-load-generator/resources/uc3-load-generator-service.yaml
similarity index 100%
rename from theodolite-benchmarks/definitions/uc3-kstreams/resources/uc3-load-generator-service.yaml
rename to theodolite-benchmarks/definitions/uc3-load-generator/resources/uc3-load-generator-service.yaml
diff --git a/theodolite-benchmarks/definitions/uc4-flink/uc4-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc4-flink/uc4-flink-benchmark-operator.yaml
index 9979f540ae343a065d8ca483fa9c5934fc550a46..8a73f5b0f87198def7b152ea52008e3d4a1aa4ee 100644
--- a/theodolite-benchmarks/definitions/uc4-flink/uc4-flink-benchmark-operator.yaml
+++ b/theodolite-benchmarks/definitions/uc4-flink/uc4-flink-benchmark-operator.yaml
@@ -3,29 +3,37 @@ kind: benchmark
 metadata:
   name: uc4-flink
 spec:
-  appResource:
-    - "uc4-flink/flink-configuration-configmap.yaml"
-    - "uc4-flink/taskmanager-deployment.yaml"
-    - "uc4-flink/taskmanager-service.yaml"
-    - "uc4-flink/service-monitor.yaml"
-    - "uc4-flink/jobmanager-service.yaml"
-    - "uc4-flink/jobmanager-deployment.yaml"
-    #- "uc4-flink/jobmanager-rest-service.yaml"
-  loadGenResource:
-    - "uc4-kstreams/uc4-load-generator-deployment.yaml"
-    - "uc4-kstreams/uc4-load-generator-service.yaml"
+  sut:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc4-flink"
+          files:
+            - "flink-configuration-configmap.yaml"
+            - "taskmanager-deployment.yaml"
+            - "taskmanager-service.yaml"
+            - "service-monitor.yaml"
+            - "jobmanager-service.yaml"
+            - "jobmanager-deployment.yaml"
+            #- "jobmanager-rest-service.yaml"
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc4-load-generator"
+          files:
+            - "uc4-load-generator-deployment.yaml"
+            - "uc4-load-generator-service.yaml"
   resourceTypes:
     - typeName: "Instances"
       patchers:
         - type: "ReplicaPatcher"
-          resource: "uc4-flink/taskmanager-deployment.yaml"
+          resource: "taskmanager-deployment.yaml"
         - type: "EnvVarPatcher"
-          resource: "uc4-flink/jobmanager-deployment.yaml"
+          resource: "jobmanager-deployment.yaml"
           properties:
             container: "jobmanager"
             variableName: "PARALLELISM"
         - type: "EnvVarPatcher" # required?
-          resource: "uc4-flink/taskmanager-deployment.yaml"
+          resource: "taskmanager-deployment.yaml"
           properties:
             container: "taskmanager"
             variableName: "PARALLELISM"
@@ -33,12 +41,12 @@ spec:
     - typeName: "NumNestedGroups"
       patchers:
         - type: "EnvVarPatcher"
-          resource: "uc4-kstreams/uc4-load-generator-deployment.yaml"
+          resource: "uc4-load-generator-deployment.yaml"
           properties:
             container: "workload-generator"
             variableName: "NUM_NESTED_GROUPS"
         - type: NumNestedGroupsLoadGeneratorReplicaPatcher
-          resource: "uc4-kstreams/uc4-load-generator-deployment.yaml"
+          resource: "uc4-load-generator-deployment.yaml"
           properties:
             loadGenMaxRecords: "150000"
             numSensors: "4.0"
diff --git a/theodolite-benchmarks/definitions/uc4-kstreams/uc4-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc4-kstreams/uc4-kstreams-benchmark-operator.yaml
similarity index 59%
rename from theodolite-benchmarks/definitions/uc4-kstreams/uc4-benchmark-operator.yaml
rename to theodolite-benchmarks/definitions/uc4-kstreams/uc4-kstreams-benchmark-operator.yaml
index 61cdfeeea5298d05cca5f5a44cdb4bdf9f108b7c..655db2fd4122c9e0e844eed3bfe7c0a878c6d7ec 100644
--- a/theodolite-benchmarks/definitions/uc4-kstreams/uc4-benchmark-operator.yaml
+++ b/theodolite-benchmarks/definitions/uc4-kstreams/uc4-kstreams-benchmark-operator.yaml
@@ -3,29 +3,37 @@ kind: benchmark
 metadata:
   name: uc4-kstreams
 spec:
-  appResource:
-    - "uc4-kstreams/uc4-kstreams-deployment.yaml"
-    - "uc4-kstreams/uc4-kstreams-service.yaml"
-    - "uc4-kstreams/uc4-jmx-configmap.yaml"
-    - "uc4-kstreams/uc4-service-monitor.yaml"
-  loadGenResource:
-    - "uc4-kstreams/uc4-load-generator-deployment.yaml"
-    - "uc4-kstreams/uc4-load-generator-service.yaml"
+  sut:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc4-kstreams"
+          files:
+            - "uc4-kstreams-deployment.yaml"
+            - "uc4-kstreams-service.yaml"
+            - "uc4-jmx-configmap.yaml"
+            - "uc4-service-monitor.yaml"
+  loadGenerator:
+    resources:
+      - configMap:
+          name: "benchmark-resources-uc4-load-generator"
+          files:
+            - "uc4-load-generator-deployment.yaml"
+            - "uc4-load-generator-service.yaml"
   resourceTypes:
     - typeName: "Instances"
       patchers:
         - type: "ReplicaPatcher"
-          resource: "uc4-kstreams/uc4-kstreams-deployment.yaml"
+          resource: "uc4-kstreams-deployment.yaml"
   loadTypes:
     - typeName: "NumNestedGroups"
       patchers:
         - type: "EnvVarPatcher"
-          resource: "uc4-kstreams/uc4-load-generator-deployment.yaml"
+          resource: "uc4-load-generator-deployment.yaml"
           properties:
             container: "workload-generator"
             variableName: "NUM_SENSORS"
         - type: NumNestedGroupsLoadGeneratorReplicaPatcher
-          resource: "uc4-kstreams/uc4-load-generator-deployment.yaml"
+          resource: "uc4-load-generator-deployment.yaml"
           properties:
             loadGenMaxRecords: "150000"
             numSensors: "4.0"
diff --git a/theodolite-benchmarks/definitions/uc4-kstreams/uc4-benchmark-standalone.yaml b/theodolite-benchmarks/definitions/uc4-kstreams/uc4-kstreams-benchmark-standalone.yaml
similarity index 68%
rename from theodolite-benchmarks/definitions/uc4-kstreams/uc4-benchmark-standalone.yaml
rename to theodolite-benchmarks/definitions/uc4-kstreams/uc4-kstreams-benchmark-standalone.yaml
index ec7a67db4ea24547bc23d5c57e7b907ba489859c..5c50b6f95d796941c0b2830549ef825f4a4ff6fb 100644
--- a/theodolite-benchmarks/definitions/uc4-kstreams/uc4-benchmark-standalone.yaml
+++ b/theodolite-benchmarks/definitions/uc4-kstreams/uc4-kstreams-benchmark-standalone.yaml
@@ -1,12 +1,20 @@
 name: "uc4-kstreams"
-appResource:
-  - "uc4-kstreams-deployment.yaml"
-  - "uc4-kstreams-service.yaml"
-  - "uc4-jmx-configmap.yaml"
-  - "uc4-service-monitor.yaml"
-loadGenResource:
-  - "uc4-load-generator-deployment.yaml"
-  - "uc4-load-generator-service.yaml"
+sut:
+  resources:
+    - configMap:
+        name: "benchmark-resources-uc4-kstreams"
+        files:
+          - "uc4-kstreams-deployment.yaml"
+          - "uc4-kstreams-service.yaml"
+          - "uc4-jmx-configmap.yaml"
+          - "uc4-service-monitor.yaml"
+loadGenerator:
+  resources:
+    - configMap:
+        name: "benchmark-resources-uc4-load-generator"
+        files:
+          - "uc4-load-generator-deployment.yaml"
+          - "uc4-load-generator-service.yaml"
 resourceTypes:
   - typeName: "Instances"
     patchers:
diff --git a/theodolite-benchmarks/definitions/uc4-kstreams/resources/uc4-load-generator-deployment.yaml b/theodolite-benchmarks/definitions/uc4-load-generator/resources/uc4-load-generator-deployment.yaml
similarity index 100%
rename from theodolite-benchmarks/definitions/uc4-kstreams/resources/uc4-load-generator-deployment.yaml
rename to theodolite-benchmarks/definitions/uc4-load-generator/resources/uc4-load-generator-deployment.yaml
diff --git a/theodolite-benchmarks/definitions/uc4-kstreams/resources/uc4-load-generator-service.yaml b/theodolite-benchmarks/definitions/uc4-load-generator/resources/uc4-load-generator-service.yaml
similarity index 100%
rename from theodolite-benchmarks/definitions/uc4-kstreams/resources/uc4-load-generator-service.yaml
rename to theodolite-benchmarks/definitions/uc4-load-generator/resources/uc4-load-generator-service.yaml
diff --git a/theodolite-benchmarks/docker-test/README.md b/theodolite-benchmarks/docker-test/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..fd1e9bf4730f897273be45a022ad2adeae1b7e6e
--- /dev/null
+++ b/theodolite-benchmarks/docker-test/README.md
@@ -0,0 +1,38 @@
+# Docker Compose Files for Testing
+
+This directory contains Docker Compose files, which help testing Benchmark implementations.
+For each stream processing engine (Kafka Streams and Flink) and Benchmark (UC1-4), a Docker Compose file is provided
+in the corresponding subdirectory.
+
+## Full Dockerized Testing
+
+Running the load generator, the benchmark and all required infrastructure (Kafka etc.) is easy. Simply, `cd` into the
+directory of the benchmark implementation Compose file and *up* it.
+For example:
+
+```sh
+cd uc1-kstreams-docker-compose/
+docker-compose up -d
+```
+
+On less powerful hardware, starting all containers together might fail. In such cases, it usually helps to first *up*
+Kafka and ZooKeeper (`docker-compose up -d kafka zookeeper`), then after some delay the Schema Registry
+(`docker-compose up -d schema-registry`) and finally, after some more further delay, the rest (`docker-compose up -d`).
+
+To tear down the entire Docker Compose configuration:
+
+```sh
+docker-compose down
+```
+
+## Benchmark (+ Load Generator) on Host, Infrastructure in Docker
+
+For development and debugging purposes, it is often required to run the benchmark and/or the load generator directly on
+the host, for example, from the IDE or Gradle. In such cases, the following adjustments have to be made to the
+`docker-compose.yaml` file:
+
+1. Comment out the services that you intend to run locally.
+2. Uncomment the `ports` block in the Kafka and the Schema Registry services.
+
+You can now connect to Kafka from your host system with bootstrap server `localhost:19092` and contact the Schema
+Registry via `localhost:8081`. **Pay attention to the Kafka port, which is *19092* instead of the default one *9092*.**
diff --git a/theodolite-benchmarks/docker-test/uc1-flink-docker-compose/docker-compose.yml b/theodolite-benchmarks/docker-test/uc1-flink-docker-compose/docker-compose.yml
index aa35ac2d1dee01cdf25d2eb2ac77bd056865479a..419c9cfb741578cccd91845c8164d4e5554d2ab6 100755
--- a/theodolite-benchmarks/docker-test/uc1-flink-docker-compose/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc1-flink-docker-compose/docker-compose.yml
@@ -3,7 +3,7 @@ services:
   zookeeper:
     image: confluentinc/cp-zookeeper
     expose:
-      - "9092"
+      - "2181"
     environment:
       ZOOKEEPER_CLIENT_PORT: 2181
   kafka:
@@ -37,7 +37,7 @@ services:
       - schema-registry
       - kafka
     environment:
-      BOOTSTRAP_SERVER: uc-wg:5701
+      BOOTSTRAP_SERVER: load-generator:5701
       PORT: 5701
       KAFKA_BOOTSTRAP_SERVERS: kafka:9092
       SCHEMA_REGISTRY_URL: http://schema-registry:8081
diff --git a/theodolite-benchmarks/docker-test/uc1-kstreams-docker-compose/docker-compose.yml b/theodolite-benchmarks/docker-test/uc1-kstreams-docker-compose/docker-compose.yml
index 403becacff5a386eddfaa8e59fe7873d2adb006c..cebf3676e92f8ececa5b6707df156f9f22f3be38 100755
--- a/theodolite-benchmarks/docker-test/uc1-kstreams-docker-compose/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc1-kstreams-docker-compose/docker-compose.yml
@@ -3,7 +3,7 @@ services:
   zookeeper:
     image: confluentinc/cp-zookeeper
     expose:
-      - "9092"
+      - "2181"
     environment:
       ZOOKEEPER_CLIENT_PORT: 2181
   kafka:
@@ -45,7 +45,7 @@ services:
       - schema-registry
       - kafka
     environment:
-      BOOTSTRAP_SERVER: uc-wg:5701
+      BOOTSTRAP_SERVER: load-generator:5701
       PORT: 5701
       KAFKA_BOOTSTRAP_SERVERS: kafka:9092
       SCHEMA_REGISTRY_URL: http://schema-registry:8081
diff --git a/theodolite-benchmarks/docker-test/uc2-flink-docker-compose/docker-compose.yml b/theodolite-benchmarks/docker-test/uc2-flink-docker-compose/docker-compose.yml
index a8bf56d52c1be7fea3f172d86f6deac27fcc24f7..c4265702b6f2b833e7b3792a787e3d8a67486ac7 100755
--- a/theodolite-benchmarks/docker-test/uc2-flink-docker-compose/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc2-flink-docker-compose/docker-compose.yml
@@ -1,10 +1,9 @@
 version: '2'
 services:
   zookeeper:
-    #image: wurstmeister/zookeeper
     image: confluentinc/cp-zookeeper
-    ports:
-      - "2181:2181"
+    expose:
+      - "2181"
     environment:
       ZOOKEEPER_CLIENT_PORT: 2181
   kafka:
@@ -38,7 +37,7 @@ services:
       - schema-registry
       - kafka
     environment:
-      BOOTSTRAP_SERVER: uc-wg:5701
+      BOOTSTRAP_SERVER: load-generator:5701
       PORT: 5701
       KAFKA_BOOTSTRAP_SERVERS: kafka:9092
       SCHEMA_REGISTRY_URL: http://schema-registry:8081
diff --git a/theodolite-benchmarks/docker-test/uc2-kstreams-docker-compose/docker-compose.yml b/theodolite-benchmarks/docker-test/uc2-kstreams-docker-compose/docker-compose.yml
index 20d2c62dac13af29ec50439670308f2911f0d57a..b520611e4855f6e942fab62b02d27d5f360860d1 100755
--- a/theodolite-benchmarks/docker-test/uc2-kstreams-docker-compose/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc2-kstreams-docker-compose/docker-compose.yml
@@ -1,10 +1,9 @@
 version: '2'
 services:
   zookeeper:
-    #image: wurstmeister/zookeeper
     image: confluentinc/cp-zookeeper
-    ports:
-      - "2181:2181"
+    expose:
+      - "2181"
     environment:
       ZOOKEEPER_CLIENT_PORT: 2181
   kafka:
@@ -47,7 +46,7 @@ services:
       - schema-registry
       - kafka
     environment:
-      BOOTSTRAP_SERVER: uc-wg:5701
+      BOOTSTRAP_SERVER: load-generator:5701
       PORT: 5701
       KAFKA_BOOTSTRAP_SERVERS: kafka:9092
       SCHEMA_REGISTRY_URL: http://schema-registry:8081
diff --git a/theodolite-benchmarks/docker-test/uc3-flink-docker-compose/docker-compose.yml b/theodolite-benchmarks/docker-test/uc3-flink-docker-compose/docker-compose.yml
index 9999caf046e844d066200ecfbf15d3351c167d31..2c69a659c6ed1e83c149e699484ec148196806c5 100755
--- a/theodolite-benchmarks/docker-test/uc3-flink-docker-compose/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc3-flink-docker-compose/docker-compose.yml
@@ -1,10 +1,9 @@
 version: '2'
 services:
   zookeeper:
-    #image: wurstmeister/zookeeper
     image: confluentinc/cp-zookeeper
-    ports:
-      - "2181:2181"
+    expose:
+      - "2181"
     environment:
       ZOOKEEPER_CLIENT_PORT: 2181
   kafka:
@@ -38,7 +37,7 @@ services:
       - schema-registry
       - kafka
     environment:
-      BOOTSTRAP_SERVER: uc-wg:5701
+      BOOTSTRAP_SERVER: load-generator:5701
       PORT: 5701
       KAFKA_BOOTSTRAP_SERVERS: kafka:9092
       SCHEMA_REGISTRY_URL: http://schema-registry:8081
diff --git a/theodolite-benchmarks/docker-test/uc3-kstreams-docker-compose/docker-compose.yml b/theodolite-benchmarks/docker-test/uc3-kstreams-docker-compose/docker-compose.yml
index ef16b858536b0d133dc49d002d16cf6c04193297..5ed8e7a673afd825b2e1426fa018db3e00848296 100755
--- a/theodolite-benchmarks/docker-test/uc3-kstreams-docker-compose/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc3-kstreams-docker-compose/docker-compose.yml
@@ -1,10 +1,9 @@
 version: '2'
 services:
   zookeeper:
-    #image: wurstmeister/zookeeper
     image: confluentinc/cp-zookeeper
-    ports:
-      - "2181:2181"
+    expose:
+      - "2181"
     environment:
       ZOOKEEPER_CLIENT_PORT: 2181
   kafka:
@@ -32,7 +31,7 @@ services:
     environment:
       SCHEMA_REGISTRY_HOST_NAME: schema-registry
       SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181'
-      benchmark:
+  benchmark:
     image: ghcr.io/cau-se/theodolite-uc3-kstreams-app:latest
     depends_on:
       - schema-registry
@@ -46,7 +45,7 @@ services:
       - schema-registry
       - kafka
     environment:
-      BOOTSTRAP_SERVER: uc-wg:5701
+      BOOTSTRAP_SERVER: load-generator:5701
       PORT: 5701
       KAFKA_BOOTSTRAP_SERVERS: kafka:9092
       SCHEMA_REGISTRY_URL: http://schema-registry:8081
diff --git a/theodolite-benchmarks/docker-test/uc4-flink-docker-compose/docker-compose.yml b/theodolite-benchmarks/docker-test/uc4-flink-docker-compose/docker-compose.yml
index 80720063991100bae2c8c148f14cd6f1a32bb0ff..b6bb905e2a950e23970392f256f16935a7777fed 100755
--- a/theodolite-benchmarks/docker-test/uc4-flink-docker-compose/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc4-flink-docker-compose/docker-compose.yml
@@ -37,7 +37,7 @@ services:
       - schema-registry
       - kafka
     environment:
-      BOOTSTRAP_SERVER: uc-wg:5701
+      BOOTSTRAP_SERVER: load-generator:5701
       PORT: 5701
       KAFKA_BOOTSTRAP_SERVERS: kafka:9092
       SCHEMA_REGISTRY_URL: http://schema-registry:8081
diff --git a/theodolite-benchmarks/docker-test/uc4-kstreams-docker-compose/docker-compose.yml b/theodolite-benchmarks/docker-test/uc4-kstreams-docker-compose/docker-compose.yml
index 5e4cb94469f2f6cc8c48694a7ea6c885f066622d..68264b244c16f1a1be7b370bb4e78052d3a8518f 100755
--- a/theodolite-benchmarks/docker-test/uc4-kstreams-docker-compose/docker-compose.yml
+++ b/theodolite-benchmarks/docker-test/uc4-kstreams-docker-compose/docker-compose.yml
@@ -45,7 +45,7 @@ services:
       - schema-registry
       - kafka
     environment:
-      BOOTSTRAP_SERVER: uc-wg:5701
+      BOOTSTRAP_SERVER: load-generator:5701
       PORT: 5701
       KAFKA_BOOTSTRAP_SERVERS: kafka:9092
       SCHEMA_REGISTRY_URL: http://schema-registry:8081
diff --git a/theodolite-benchmarks/flink-commons/build.gradle b/theodolite-benchmarks/flink-commons/build.gradle
index 1b0b9359a406bf2ab16fbbe52631877cf360df2a..0da7c6f93f4e77e1376f5f2d006ec0bf0f398ec8 100644
--- a/theodolite-benchmarks/flink-commons/build.gradle
+++ b/theodolite-benchmarks/flink-commons/build.gradle
@@ -22,13 +22,14 @@ dependencies {
     implementation('org.industrial-devops:titan-ccp-common:0.1.0-flink-ready-SNAPSHOT') { changing = true }
     implementation('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true }
     implementation 'com.google.guava:guava:30.1-jre'
-    compile group: 'org.apache.flink', name: "flink-connector-kafka_${scalaBinaryVersion}", version: "${flinkVersion}"
-    compile group: 'org.apache.flink', name: "flink-statebackend-rocksdb_${scalaBinaryVersion}", version: "${flinkVersion}"
-    compile group: 'org.apache.flink', name: "flink-runtime_${scalaBinaryVersion}", version: "${flinkVersion}"
-    compile group: 'org.apache.flink', name: 'flink-java', version: "${flinkVersion}"
-    compile group: 'org.apache.flink', name: "flink-streaming-java_${scalaBinaryVersion}", version:"${flinkVersion}"
+
+    implementation "org.apache.flink:flink-java:${flinkVersion}"    
+    implementation "org.apache.flink:flink-connector-kafka_${scalaBinaryVersion}:${flinkVersion}"
     implementation "org.apache.flink:flink-avro:${flinkVersion}"
     implementation "org.apache.flink:flink-avro-confluent-registry:${flinkVersion}"
+    implementation "org.apache.flink:flink-runtime-web_${scalaBinaryVersion}:${flinkVersion}" // For debugging
+    implementation "org.apache.flink:flink-statebackend-rocksdb_${scalaBinaryVersion}:${flinkVersion}"
+    implementation "org.apache.flink:flink-metrics-prometheus_${scalaBinaryVersion}:${flinkVersion}"
     
     // Use JUnit test framework
     testImplementation 'junit:junit:4.12'
diff --git a/theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/serialization/StatsSerializer.java b/theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/serialization/StatsSerializer.java
index f1f9870fda73ccec0fc25c5c70665759ab07d893..fe74fbe4b9dcb6ce89d10131de1336bfff40a919 100644
--- a/theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/serialization/StatsSerializer.java
+++ b/theodolite-benchmarks/flink-commons/src/main/java/theodolite/commons/flink/serialization/StatsSerializer.java
@@ -5,7 +5,6 @@ import com.esotericsoftware.kryo.Serializer;
 import com.esotericsoftware.kryo.io.Input;
 import com.esotericsoftware.kryo.io.Output;
 import com.google.common.math.Stats;
-
 import java.io.Serializable;
 
 /**
@@ -13,7 +12,7 @@ import java.io.Serializable;
  */
 public class StatsSerializer extends Serializer<Stats> implements Serializable {
 
-  private static final long serialVersionUID = -1276866176534267373L; //NOPMD
+  private static final long serialVersionUID = -1276866176534267373L; // NOPMD
 
   @Override
   public void write(final Kryo kryo, final Output output, final Stats object) {
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/GeneratorAction.java b/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/GeneratorAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..11a9cbf2d96bc3a02f3972ba23f2167af06a2ec3
--- /dev/null
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/GeneratorAction.java
@@ -0,0 +1,18 @@
+package theodolite.commons.workloadgeneration;
+
+/**
+ * Interface representing a record generator action consisting of generating a record and sending
+ * it.
+ */
+@FunctionalInterface
+interface GeneratorAction {
+
+  void generate(final String key);
+
+  public static <T> GeneratorAction from(
+      final RecordGenerator<? extends T> generator,
+      final RecordSender<? super T> sender) {
+    return key -> sender.send(generator.generate(key));
+  }
+
+}
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/KafkaRecordSender.java b/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/KafkaRecordSender.java
index 6e4a43271fbf1e0193c2d39569a0814d1f7935cd..ded7c347c8d6b057581dc63b691df5bb60997791 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/KafkaRecordSender.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/KafkaRecordSender.java
@@ -53,6 +53,33 @@ public class KafkaRecordSender<T extends SpecificRecord> implements RecordSender
         avroSerdeFactory.<T>forKeys().serializer());
   }
 
+  /**
+   * Write the passed monitoring record to Kafka.
+   */
+  public void write(final T monitoringRecord) {
+    final ProducerRecord<String, T> record =
+        new ProducerRecord<>(this.topic, null, this.timestampAccessor.apply(monitoringRecord),
+            this.keyAccessor.apply(monitoringRecord), monitoringRecord);
+
+    LOGGER.debug("Send record to Kafka topic {}: {}", this.topic, record);
+    try {
+      this.producer.send(record);
+    } catch (final SerializationException e) {
+      LOGGER.warn(
+          "Record could not be serialized and thus not sent to Kafka due to exception. Skipping this record.", // NOCS
+          e);
+    }
+  }
+
+  public void terminate() {
+    this.producer.close();
+  }
+
+  @Override
+  public void send(final T message) {
+    this.write(message);
+  }
+
   public static <T extends SpecificRecord> Builder<T> builder(
       final String bootstrapServers,
       final String topic,
@@ -108,31 +135,4 @@ public class KafkaRecordSender<T extends SpecificRecord> implements RecordSender
     }
   }
 
-  /**
-   * Write the passed monitoring record to Kafka.
-   */
-  public void write(final T monitoringRecord) {
-    final ProducerRecord<String, T> record =
-        new ProducerRecord<>(this.topic, null, this.timestampAccessor.apply(monitoringRecord),
-            this.keyAccessor.apply(monitoringRecord), monitoringRecord);
-
-    LOGGER.debug("Send record to Kafka topic {}: {}", this.topic, record);
-    try {
-      this.producer.send(record);
-    } catch (final SerializationException e) {
-      LOGGER.warn(
-          "Record could not be serialized and thus not sent to Kafka due to exception. Skipping this record.", // NOCS
-          e);
-    }
-  }
-
-  public void terminate() {
-    this.producer.close();
-  }
-
-  @Override
-  public void send(final T message) {
-    this.write(message);
-  }
-
 }
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGenerator.java b/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGenerator.java
index a9a1ce65ac32e3508299c99a38ecd21e4c9461cf..73f064d1ce44ff8a613f9ce0a7b9a64d4bac6c38 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGenerator.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGenerator.java
@@ -91,12 +91,11 @@ public final class LoadGenerator {
             new KeySpace(SENSOR_PREFIX_DEFAULT, NUMBER_OF_KEYS_DEFAULT),
             Duration.ofMillis(PERIOD_MS_DEFAULT)))
         .setGeneratorConfig(new LoadGeneratorConfig(
-            TitanMessageGeneratorFactory
-                .withKafkaConfig(
-                    KAFKA_BOOTSTRAP_SERVERS_DEFAULT,
-                    KAFKA_TOPIC_DEFAULT,
-                    SCHEMA_REGISTRY_URL_DEFAULT)
-                .forConstantValue(VALUE_DEFAULT)));
+            TitanRecordGeneratorFactory.forConstantValue(VALUE_DEFAULT),
+            TitanKafkaSenderFactory.forKafkaConfig(
+                KAFKA_BOOTSTRAP_SERVERS_DEFAULT,
+                KAFKA_TOPIC_DEFAULT,
+                SCHEMA_REGISTRY_URL_DEFAULT)));
   }
 
   /**
@@ -170,13 +169,11 @@ public final class LoadGenerator {
             new KeySpace(SENSOR_PREFIX_DEFAULT, numSensors),
             Duration.ofMillis(periodMs)))
         .setGeneratorConfig(new LoadGeneratorConfig(
-            TitanMessageGeneratorFactory
-                .withKafkaConfig(
-                    kafkaBootstrapServers,
-                    kafkaInputTopic,
-                    schemaRegistryUrl,
-                    kafkaProperties)
-                .forConstantValue(value)))
+            TitanRecordGeneratorFactory.forConstantValue(value),
+            TitanKafkaSenderFactory.forKafkaConfig(
+                kafkaBootstrapServers,
+                kafkaInputTopic,
+                schemaRegistryUrl)))
         .withThreads(threads);
   }
 
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGeneratorConfig.java b/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGeneratorConfig.java
index 2e907d8e90172288099bc6a1776777c37ae90fff..4b5fea3e4670315ef47d94669b42a3cca4b5d0ae 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGeneratorConfig.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGeneratorConfig.java
@@ -5,30 +5,24 @@ package theodolite.commons.workloadgeneration;
  */
 public class LoadGeneratorConfig {
 
-  private final MessageGenerator messageGenerator;
+  private final GeneratorAction messageGenerator;
   private BeforeAction beforeAction = BeforeAction.doNothing();
   private int threads = 1;
 
-  public LoadGeneratorConfig(final MessageGenerator messageGenerator) {
-    this.messageGenerator = messageGenerator;
+  public <T> LoadGeneratorConfig(
+      final RecordGenerator<? extends T> generator,
+      final RecordSender<? super T> sender) {
+    this.messageGenerator = GeneratorAction.from(generator, sender);
   }
 
-  public LoadGeneratorConfig(
-      final MessageGenerator messageGenerator,
+  public <T> LoadGeneratorConfig(
+      final RecordGenerator<? extends T> generator,
+      final RecordSender<? super T> sender,
       final int threads) {
-    this.messageGenerator = messageGenerator;
+    this(generator, sender);
     this.threads = threads;
   }
 
-  public LoadGeneratorExecution buildLoadGeneratorExecution(
-      final WorkloadDefinition workloadDefinition) {
-    return new LoadGeneratorExecution(workloadDefinition, this.messageGenerator, this.threads);
-  }
-
-  public BeforeAction getBeforeAction() {
-    return this.beforeAction;
-  }
-
   public void setThreads(final int threads) {
     this.threads = threads;
   }
@@ -37,6 +31,13 @@ public class LoadGeneratorConfig {
     this.beforeAction = beforeAction;
   }
 
+  public BeforeAction getBeforeAction() {
+    return this.beforeAction;
+  }
 
+  public LoadGeneratorExecution buildLoadGeneratorExecution(
+      final WorkloadDefinition workloadDefinition) {
+    return new LoadGeneratorExecution(workloadDefinition, this.messageGenerator, this.threads);
+  }
 
 }
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGeneratorExecution.java b/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGeneratorExecution.java
index 3934c3d3499215b37ce96391ff5ae1d5cc135f84..e1a2a7e1bea964b5c69a6cd34374d7b0932bac03 100644
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGeneratorExecution.java
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/LoadGeneratorExecution.java
@@ -8,25 +8,25 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * A {@link LoadGeneratorExecution} represents the execution of load generator, i.e., it can be
+ * A {@link LoadGeneratorExecution} represents the execution of a load generator, i.e., it can be
  * started and stopped.
  */
-public class LoadGeneratorExecution {
+class LoadGeneratorExecution {
 
   private static final Logger LOGGER = LoggerFactory.getLogger(LoadGeneratorExecution.class);
 
   private final Random random = new Random();
   private final WorkloadDefinition workloadDefinition;
-  private final MessageGenerator messageGenerator;
+  private final GeneratorAction messageGenerator;
   private final ScheduledExecutorService executor;
 
   /**
    * Create a new {@link LoadGeneratorExecution} for a given {@link WorkloadDefinition} and a
-   * {@link MessageGenerator}. Load is generated by the given number of threads.
+   * {@link GeneratorAction}. Load is generated by the given number of threads.
    */
   public LoadGeneratorExecution(
       final WorkloadDefinition workloadDefinition,
-      final MessageGenerator messageGenerator,
+      final GeneratorAction messageGenerator,
       final int threads) {
     this.workloadDefinition = workloadDefinition;
     this.messageGenerator = messageGenerator;
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/MessageGenerator.java b/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/MessageGenerator.java
deleted file mode 100644
index c369f16557d60dae50e22ec7ad820c6a0ab4d137..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/MessageGenerator.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package theodolite.commons.workloadgeneration;
-
-/**
- * Interface representing a message generator, which sends messages for given keys to some
- * destination.
- */
-@FunctionalInterface
-public interface MessageGenerator {
-
-  void generate(final String key);
-
-  public static <T> MessageGenerator from(
-      final RecordGenerator<T> generator,
-      final RecordSender<T> sender) {
-    return key -> sender.send(generator.generate(key));
-  }
-
-}
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/TitanKafkaSenderFactory.java b/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/TitanKafkaSenderFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..0cdf8d91ea01cc16df5dcd55d77b08c3f4986442
--- /dev/null
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/TitanKafkaSenderFactory.java
@@ -0,0 +1,42 @@
+package theodolite.commons.workloadgeneration;
+
+import java.util.Properties;
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * A factory for creating {@link KafkaRecordSender}s that sends Titan {@link ActivePowerRecord}s.
+ */
+public final class TitanKafkaSenderFactory {
+
+  private TitanKafkaSenderFactory() {}
+
+  /**
+   * Create a new KafkaRecordSender for {@link ActivePowerRecord}s for the given Kafka
+   * configuration.
+   */
+  public static KafkaRecordSender<ActivePowerRecord> forKafkaConfig(
+      final String bootstrapServers,
+      final String topic,
+      final String schemaRegistryUrl) {
+    return forKafkaConfig(bootstrapServers, topic, schemaRegistryUrl, new Properties());
+  }
+
+  /**
+   * Create a new KafkaRecordSender for {@link ActivePowerRecord}s for the given Kafka
+   * configuration.
+   */
+  public static KafkaRecordSender<ActivePowerRecord> forKafkaConfig(
+      final String bootstrapServers,
+      final String topic,
+      final String schemaRegistryUrl,
+      final Properties properties) {
+    return KafkaRecordSender
+        .<ActivePowerRecord>builder(
+            bootstrapServers,
+            topic,
+            schemaRegistryUrl)
+        .keyAccessor(r -> r.getIdentifier())
+        .timestampAccessor(r -> r.getTimestamp())
+        .build();
+  }
+}
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/TitanMessageGeneratorFactory.java b/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/TitanMessageGeneratorFactory.java
deleted file mode 100644
index bd0b41d4e6e004d024ed2fd179eddcf6af50438f..0000000000000000000000000000000000000000
--- a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/TitanMessageGeneratorFactory.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package theodolite.commons.workloadgeneration;
-
-import java.util.Properties;
-import titan.ccp.model.records.ActivePowerRecord;
-
-/**
- * A factory for creating {@link MessageGenerator}s that creates Titan {@link ActivePowerRecord}s
- * and sends them via Kafka.
- */
-public final class TitanMessageGeneratorFactory {
-
-  private final RecordSender<ActivePowerRecord> recordSender;
-
-  private TitanMessageGeneratorFactory(final RecordSender<ActivePowerRecord> recordSender) {
-    this.recordSender = recordSender;
-  }
-
-  /**
-   * Create a {@link MessageGenerator} that generates Titan {@link ActivePowerRecord}s with a
-   * constant value.
-   */
-  public MessageGenerator forConstantValue(final double value) {
-    return MessageGenerator.from(
-        sensor -> new ActivePowerRecord(sensor, System.currentTimeMillis(), value),
-        this.recordSender);
-  }
-
-  /**
-   * Create a new TitanMessageGeneratorFactory for the given Kafka configuration.
-   */
-  public static TitanMessageGeneratorFactory withKafkaConfig(
-      final String bootstrapServers,
-      final String topic,
-      final String schemaRegistryUrl) {
-    return withKafkaConfig(bootstrapServers, topic, schemaRegistryUrl, new Properties());
-  }
-
-  /**
-   * Create a new TitanMessageGeneratorFactory for the given Kafka configuration.
-   */
-  public static TitanMessageGeneratorFactory withKafkaConfig(
-      final String bootstrapServers,
-      final String topic,
-      final String schemaRegistryUrl,
-      final Properties properties) {
-    final KafkaRecordSender<ActivePowerRecord> kafkaRecordSender = KafkaRecordSender
-        .<ActivePowerRecord>builder(
-            bootstrapServers,
-            topic,
-            schemaRegistryUrl)
-        .keyAccessor(r -> r.getIdentifier())
-        .timestampAccessor(r -> r.getTimestamp())
-        .build();
-    return new TitanMessageGeneratorFactory(kafkaRecordSender);
-  }
-
-}
diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/TitanRecordGeneratorFactory.java b/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/TitanRecordGeneratorFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..4e1c10071eff28d77514dbc121e30bead3f6fa74
--- /dev/null
+++ b/theodolite-benchmarks/load-generator-commons/src/main/java/theodolite/commons/workloadgeneration/TitanRecordGeneratorFactory.java
@@ -0,0 +1,21 @@
+package theodolite.commons.workloadgeneration;
+
+import titan.ccp.model.records.ActivePowerRecord;
+
+/**
+ * A factory for creating {@link RecordGenerator}s that creates Titan {@link ActivePowerRecord}s.
+ */
+public final class TitanRecordGeneratorFactory {
+
+
+  private TitanRecordGeneratorFactory() {}
+
+  /**
+   * Create a {@link RecordGenerator} that generates Titan {@link ActivePowerRecord}s with a
+   * constant value.
+   */
+  public static RecordGenerator<ActivePowerRecord> forConstantValue(final double value) {
+    return sensor -> new ActivePowerRecord(sensor, System.currentTimeMillis(), value);
+  }
+
+}
diff --git a/theodolite/README.md b/theodolite/README.md
index 26efe96b4756316971378be810f69f6138613958..60bd56d933d8955217120465c47e70b4b34585e1 100644
--- a/theodolite/README.md
+++ b/theodolite/README.md
@@ -2,21 +2,30 @@
 
 This project uses Quarkus, the Supersonic Subatomic Java Framework.
 
-If you want to learn more about Quarkus, please visit its website: https://quarkus.io/ .
+If you want to learn more about Quarkus, please visit its website: <https://quarkus.io/> .
 
 ## Running the application in dev mode
 
 You can run your application in dev mode using:
 
-```shell script
+```sh
 ./gradlew quarkusDev
 ```
 
+### Hint for running with k3s (or k3d)
+
+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
 
 The application can be packaged using:
 
-```shell script
+```sh
 ./gradlew build
 ```
 
@@ -25,7 +34,7 @@ an _über-jar_ as the dependencies are copied into the `build/lib` directory.
 
 If you want to build an _über-jar_, execute the following command:
 
-```shell script
+```sh
 ./gradlew build -Dquarkus.package.type=uber-jar
 ```
 
@@ -33,92 +42,108 @@ The application is now runnable using `java -jar build/theodolite-1.0.0-SNAPSHOT
 
 ## Creating a native executable
 
+It is recommended to use the native GraalVM images to create executable jars from Theodolite. For more information please visit the [Native Image guide](https://www.graalvm.org/reference-manual/native-image/).
+
 You can create a native executable using:
 
-```shell script
+```sh
 ./gradlew build -Dquarkus.package.type=native
 ```
 
 Or, if you don't have GraalVM installed, you can run the native executable build in a container using:
 
-```shell script
+```sh
 ./gradlew build -Dquarkus.package.type=native -Dquarkus.native.container-build=true
 ```
 
 You can then execute your native executable with:
 ```./build/theodolite-1.0.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
 
 For the jvm version use:
 
-```shell script
+```sh
 ./gradlew build
 docker build -f src/main/docker/Dockerfile.jvm -t theodolite-jvm .
 ```
 
 For the native image version use:
 
-```shell script
+```sh
 ./gradlew build -Dquarkus.package.type=native
 docker build -f src/main/docker/Dockerfile.native -t theodolite-native .
 ```
 
-## Execute docker images:
+## Execute docker images
 
 Remember to set the environment variables first.
 
 Jvm version:
 
-```shell script
+```sh
 docker run -i --rm theodolite-jvm
 ```
 
 Native image version:
 
-```shell script
+```sh
 docker run -i --rm theodolite-native
 ```
 
 ## Environment variables
 
-**Production:** (Docker-Container)
+**Execution in Docker**:
 
 | Variables name               | Default value                      |Usage         |
 | -----------------------------|:----------------------------------:| ------------:|
 | `NAMESPACE`                  | `default`                          |Determines the namespace of the Theodolite will be executed in. Used in the KubernetesBenchmark|
-| `THEODOLITE_EXECUTION`       |  `./config/BenchmarkExecution.yaml`|The complete path to the benchmarkExecution file. Used in the TheodoliteYamlExecutor. |
-| `THEODOLITE_BENCHMARK_TYPE`  |  `./config/BenchmarkType.yaml`     |The complete path to the benchmarkType file. Used in the TheodoliteYamlExecutor.|
-| `THEODOLITE_APP_RESOURCES`   |  `./config`                        |The path under which the yamls for the resources for the subexperiments are found. Used in the KubernetesBenchmark|
-| `MODE`                       | `yaml-executor`                    |  Defines the mode of operation: either `yaml-executor` or `operator`|
+| `THEODOLITE_EXECUTION`       |  `execution/execution.yaml`        |The complete path to the benchmarkExecution file. Used in the TheodoliteYamlExecutor. |
+| `THEODOLITE_BENCHMARK_TYPE`  |  `benchmark/benchmark.yaml`        |The complete path to the benchmarkType file. Used in the TheodoliteYamlExecutor.|
+| `THEODOLITE_APP_RESOURCES`   |  `./benchmark-resources`           |The path under which the yamls for the resources for the subexperiments are found. Used in the KubernetesBenchmark|
+| `MODE`                       | `standalone`                       |Defines the mode of operation: either `standalone` or `operator`
 
-**Development:** (local via Intellij)
+**Execution in IntelliJ**:
 
 When running Theodolite from within IntelliJ via
-[Run Configurations](https://www.jetbrains.com/help/idea/work-with-gradle-tasks.html#gradle_run_config), set the *
-Environment variables* field to:
+[Run Configurations](https://www.jetbrains.com/help/idea/work-with-gradle-tasks.html#gradle_run_config), set the *Environment variables* field to:
+
+Set the following environment variables to run the example in the `standalone` mode within the IDE:
 
+```sh
+THEODOLITE_BENCHMARK=./../../../../examples/standalone/example-benchmark.yaml;THEODOLITE_EXECUTION=./../../../../examples/standalone/example-execution.yaml;THEODOLITE_APP_RESOURCES=./../../../../examples/resources;
 ```
-NAMESPACE=default;THEODOLITE_BENCHMARK=./../../../../config/BenchmarkType.yaml;THEODOLITE_APP_RESOURCES=./../../../../config;THEODOLITE_EXECUTION=./../../../../config/BenchmarkExecution.yaml;MODE=operator
+
+Alternative:
+
+``` sh
+export THEODOLITE_BENCHMARK=./../../../../examples/standalone/example-benchmark.yaml
+export THEODOLITE_APP_RESOURCES=./../../../../examples/resources;
+export THEODOLITE_EXECUTION=./../../../../examples/standalone/example-execution.yaml
+./gradlew quarkusDev
+```
+
+Set the following environment variables to run the example in the `operator` mode within the IDE:
+
+```sh
+THEODOLITE_APP_RESOURCES=./../../../../examples/resources;MODE=operator
 ```
 
 Alternative:
 
 ``` sh
-export NAMESPACE=default
-export THEODOLITE_BENCHMARK=./../../../../config/BenchmarkType.yaml
-export THEODOLITE_APP_RESOURCES=./../../../../config
-export THEODOLITE_EXECUTION=./../../../../config/BenchmarkExecution.yaml
+export THEODOLITE_APP_RESOURCES=./../../../../examples/resources;
 export MODE=operator
 ./gradlew quarkusDev
-
 ```
 
-#### Install Detekt Code analysis Plugin
+Additionally, the benchmark and execution resources must be installed.
+
+### Install Detekt Code analysis Plugin
 
-Install https://plugins.jetbrains.com/plugin/10761-detekt
+Install <https://plugins.jetbrains.com/plugin/10761-detekt>
 
 - Install the plugin
 - Navigate to Settings/Preferences -> Tools -> Detekt
@@ -127,7 +152,7 @@ Install https://plugins.jetbrains.com/plugin/10761-detekt
 
 -> detekt issues will be annotated on-the-fly while coding
 
-**ingore Failures in build:** add
+**ingore Failures in build**: add
 
 ```ignoreFailures = true```
 
diff --git a/theodolite/crd/crd-benchmark.yaml b/theodolite/crd/crd-benchmark.yaml
index 7a861276a651af520ccec853b65cb57009a45cc5..7ab2e5f3b890a883f68dbbd36805f3791158f256 100644
--- a/theodolite/crd/crd-benchmark.yaml
+++ b/theodolite/crd/crd-benchmark.yaml
@@ -20,23 +20,124 @@ spec:
         properties:
           spec:
             type: object
-            required: ["appResource", "loadGenResource", "resourceTypes", "loadTypes", "kafkaConfig"]
+            required: ["sut", "loadGenerator", "resourceTypes", "loadTypes", "kafkaConfig"]
             properties:
               name:
                 description: This field exists only for technical reasons and should not be set by the user. The value of the field will be overwritten.
                 type: string
-              appResource:
-                description: A list of file names that reference Kubernetes resources that are deployed on the cluster for the system under test (SUT).
-                type: array
-                minItems: 1
-                items:
-                  type: string
-              loadGenResource:
-                description:  A list of file names that reference Kubernetes resources that are deployed on the cluster for the load generator.
-                type: array
-                minItems: 1
-                items:
-                  type: string
+                default: ""
+              infrastructure:
+                description: (Optional) A list of file names that reference Kubernetes resources that are deployed on the cluster to create the required infrastructure.
+                type: object
+                default: {}
+                properties:
+                  resources:
+                    type: array
+                    default: []
+                    items:
+                      type: object
+                      oneOf:
+                        - required: [ configMap ]
+                        - required: [ fileSystem ]
+                      properties:
+                        configMap:
+                          description: The configMap resourceSet loads the Kubernetes manifests from an Kubernetes configMap.
+                          type: object
+                          properties:
+                            name:
+                              description: The name of the configMap
+                              type: string
+                            files:
+                              description: (Optional) Specifies which files from the configMap should be loaded. If this field is not set, all files are loaded.
+                              type: array
+                              items:
+                                type: string
+                        fileSystem:
+                          description: The fileSystem resourceSet loads the Kubernetes manifests from the filesystem.
+                          type: object
+                          properties:
+                            path:
+                              description: The path to the folder which contains the Kubernetes manifests files.
+                              type: string
+                            files:
+                              description: (Optional) Specifies which files from the configMap should be loaded. If this field is not set, all files are loaded.
+                              type: array
+                              items:
+                                type: string
+              sut:
+                description: The appResourceSets specifies all Kubernetes resources required to start the sut. A resourceSet can be either a configMap resourceSet or a fileSystem resourceSet.
+                type: object
+                properties:
+                  resources:
+                    type: array
+                    default: [ ]
+                    items:
+                      type: object
+                      oneOf:
+                        - required: [ configMap ]
+                        - required: [ fileSystem ]
+                      properties:
+                        configMap:
+                          description: The configMap resourceSet loads the Kubernetes manifests from an Kubernetes configMap.
+                          type: object
+                          properties:
+                            name:
+                              description: The name of the configMap
+                              type: string
+                            files:
+                              description: (Optional) Specifies which files from the configMap should be loaded. If this field is not set, all files are loaded.
+                              type: array
+                              items:
+                                type: string
+                        fileSystem:
+                          description: The fileSystem resourceSet loads the Kubernetes manifests from the filesystem.
+                          type: object
+                          properties:
+                            path:
+                              description: The path to the folder which contains the Kubernetes manifests files.
+                              type: string
+                            files:
+                              description: (Optional) Specifies which files from the configMap should be loaded. If this field is not set, all files are loaded.
+                              type: array
+                              items:
+                                type: string
+              loadGenerator:
+                description: The loadGenResourceSets specifies all Kubernetes resources required to start the load generator. A resourceSet can be either a configMap resourceSet or a fileSystem resourceSet.
+                type: object
+                properties:
+                  resources:
+                    type: array
+                    default: []
+                    items:
+                      type: object
+                      oneOf:
+                        - required: [ configMap ]
+                        - required: [ fileSystem ]
+                      properties:
+                        configMap:
+                          description: The configMap resourceSet loads the Kubernetes manifests from an Kubernetes configMap.
+                          type: object
+                          properties:
+                            name:
+                              description: The name of the configMap
+                              type: string
+                            files:
+                              description: (Optional) Specifies which files from the configMap should be loaded. If this field is not set, all files are loaded.
+                              type: array
+                              items:
+                                type: string
+                        fileSystem:
+                          description: The fileSystem resourceSet loads the Kubernetes manifests from the filesystem.
+                          type: object
+                          properties:
+                            path:
+                              description: The path to the folder which contains the Kubernetes manifests files.
+                              type: string
+                            files:
+                              description: (Optional) Specifies which files from the configMap should be loaded. If this field is not set, all files are loaded.
+                              type: array
+                              items:
+                                type: string
               resourceTypes:
                 description: A list of resource types that can be scaled for this `benchmark` resource. For each resource type the concrete values are defined in the `execution` object.
                 type: array
@@ -50,7 +151,6 @@ spec:
                       type: string
                     patchers:
                       description: List of patchers used to scale this resource type.
-                      examples: test test test
                       type: array
                       minItems: 1
                       items:
@@ -136,10 +236,20 @@ spec:
                           description: Determines if this topic should only be deleted after each experiement. For removeOnly topics the name can be a RegEx describing the topic.
                           type: boolean
                           default: false
+          status:
+            type: object
+            properties:
+              resourceSetsState:
+                description: The status of a Benchmark indicates whether all resources are available to start the benchmark or not.
+                type: string
     additionalPrinterColumns:
     - name: Age
       type: date
       jsonPath: .metadata.creationTimestamp
+    - name: STATUS
+      type: string
+      description: The status of a Benchmark indicates whether all resources are available to start the benchmark or not.
+      jsonPath: .status.resourceSetsState
     subresources:
       status: {}
   scope: Namespaced
\ No newline at end of file
diff --git a/theodolite/crd/crd-execution.yaml b/theodolite/crd/crd-execution.yaml
index 47d0306f5150a8126f021c40bf3c4a4ce0e1abb1..d9cd41903bb2fdc18bd6640bdbe2eb764b2106ab 100644
--- a/theodolite/crd/crd-execution.yaml
+++ b/theodolite/crd/crd-execution.yaml
@@ -51,7 +51,7 @@ spec:
                     description: The type of the resource. It must match one of the resource types specified in the referenced benchmark.
                     type: string
                   resourceValues:
-                    descriptoin:  List of resource values for the specified resource type.
+                    description:  List of resource values for the specified resource type.
                     type: array
                     items:
                       type: integer
diff --git a/theodolite/examples/operator/example-benchmark.yaml b/theodolite/examples/operator/example-benchmark.yaml
index 91d9f8f1f7dfed31d9edcb59947af4e832ca2843..3452fff9c729d680890d6eafa685ce2f13b098d6 100644
--- a/theodolite/examples/operator/example-benchmark.yaml
+++ b/theodolite/examples/operator/example-benchmark.yaml
@@ -3,14 +3,19 @@ kind: benchmark
 metadata:
   name: uc1-kstreams
 spec:
-  appResource:
-    - "uc1-kstreams-deployment.yaml"
-    - "aggregation-service.yaml"
-    - "jmx-configmap.yaml"
-    - "uc1-service-monitor.yaml"
-  loadGenResource:
-    - "uc1-load-generator-deployment.yaml"
-    - "uc1-load-generator-service.yaml"
+  sut:
+    resources:
+      - configMap:
+         name: "example-configmap"
+         files:
+           - "uc1-kstreams-deployment.yaml"
+  loadGenerator:
+    resources:
+      - configMap:
+         name: "example-configmap"
+         files:
+            - uc1-load-generator-service.yaml
+            - uc1-load-generator-deployment.yaml
   resourceTypes:
     - typeName: "Instances"
       patchers:
diff --git a/theodolite/examples/operator/example-configmap.yaml b/theodolite/examples/operator/example-configmap.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..210ce32d3fc0f75b9ffce874d1fa0a1ea9bdc3cd
--- /dev/null
+++ b/theodolite/examples/operator/example-configmap.yaml
@@ -0,0 +1,87 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: example-configmap
+data:
+  uc1-kstreams-deployment.yaml: |-
+    apiVersion: apps/v1
+    kind: Deployment
+    metadata:
+      name: titan-ccp-aggregation
+    spec:
+      selector:
+        matchLabels:
+          app: titan-ccp-aggregation
+      replicas: 1
+      template:
+        metadata:
+          labels:
+            app: titan-ccp-aggregation
+        spec:
+          terminationGracePeriodSeconds: 0
+          containers:
+            - name: uc-application
+              image: ghcr.io/cau-se/theodolite-uc1-kstreams-app:latest
+              env:
+                - name: KAFKA_BOOTSTRAP_SERVERS
+                  value: "theodolite-cp-kafka:9092"
+                - name: SCHEMA_REGISTRY_URL
+                  value: "http://theodolite-cp-schema-registry:8081"
+                - name: JAVA_OPTS
+                  value: "-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=5555"
+                - name: COMMIT_INTERVAL_MS # Set as default for the applications
+                  value: "100"
+              resources:
+                limits:
+                  memory: 4Gi
+                  cpu: 1000m
+  uc1-load-generator-deployment.yaml: |
+    apiVersion: apps/v1
+    kind: Deployment
+    metadata:
+      name: titan-ccp-load-generator
+    spec:
+      selector:
+        matchLabels:
+          app: titan-ccp-load-generator
+      replicas: 1
+      template:
+        metadata:
+          labels:
+            app: titan-ccp-load-generator
+        spec:
+          terminationGracePeriodSeconds: 0
+          containers:
+            - name: workload-generator
+              image: ghcr.io/cau-se/theodolite-uc1-workload-generator:latest
+              ports:
+                - containerPort: 5701
+                  name: coordination
+              env:
+                - name: KUBERNETES_NAMESPACE
+                  valueFrom:
+                    fieldRef:
+                      fieldPath: metadata.namespace
+                - name: KUBERNETES_DNS_NAME
+                  value: "titan-ccp-load-generator.$(KUBERNETES_NAMESPACE).svc.cluster.local"
+                - name: KAFKA_BOOTSTRAP_SERVERS
+                  value: "theodolite-cp-kafka:9092"
+                - name: SCHEMA_REGISTRY_URL
+                  value: "http://theodolite-cp-schema-registry:8081"
+  uc1-load-generator-service.yaml: |
+    apiVersion: v1
+    kind: Service
+    metadata:
+      name: titan-ccp-load-generator
+      labels:
+        app: titan-ccp-load-generator
+    spec:
+      type: ClusterIP
+      clusterIP: None
+      selector:
+        app: titan-ccp-load-generator
+      ports:
+        - name: coordination
+          port: 5701
+          targetPort: 5701
+          protocol: TCP
\ No newline at end of file
diff --git a/theodolite/examples/resources/uc1-kstreams-deployment.yaml b/theodolite/examples/resources/uc1-kstreams-deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..fdd1ff867ac83beb10856baec53569c88169232e
--- /dev/null
+++ b/theodolite/examples/resources/uc1-kstreams-deployment.yaml
@@ -0,0 +1,34 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: titan-ccp-aggregation
+spec:
+  selector:
+    matchLabels:
+      app: titan-ccp-aggregation
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: titan-ccp-aggregation
+    spec:
+      terminationGracePeriodSeconds: 0
+      containers:
+        - name: uc-application
+          image: ghcr.io/cau-se/theodolite-uc1-kstreams-app:latest
+          ports:
+            - containerPort: 5555
+              name: jmx
+          env:
+            - name: KAFKA_BOOTSTRAP_SERVERS
+              value: "theodolite-cp-kafka:9092"
+            - name: SCHEMA_REGISTRY_URL
+              value: "http://theodolite-cp-schema-registry:8081"
+            - name: JAVA_OPTS
+              value: "-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=5555"
+            - name: COMMIT_INTERVAL_MS # Set as default for the applications
+              value: "100"
+          resources:
+            limits:
+              memory: 4Gi
+              cpu: 1000m
\ No newline at end of file
diff --git a/theodolite/examples/resources/uc1-load-generator-deployment.yaml b/theodolite/examples/resources/uc1-load-generator-deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..9f9ccc6ae39407bb1f027e1e23cb152944b869e0
--- /dev/null
+++ b/theodolite/examples/resources/uc1-load-generator-deployment.yaml
@@ -0,0 +1,32 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: titan-ccp-load-generator
+spec:
+  selector:
+    matchLabels:
+      app: titan-ccp-load-generator
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: titan-ccp-load-generator
+    spec:
+      terminationGracePeriodSeconds: 0
+      containers:
+        - name: workload-generator
+          image: ghcr.io/cau-se/theodolite-uc1-workload-generator:latest
+          ports:
+            - containerPort: 5701
+              name: coordination
+          env:
+            - name: KUBERNETES_NAMESPACE
+              valueFrom:
+                fieldRef:
+                  fieldPath: metadata.namespace
+            - name: KUBERNETES_DNS_NAME
+              value: "titan-ccp-load-generator.$(KUBERNETES_NAMESPACE).svc.cluster.local"
+            - name: KAFKA_BOOTSTRAP_SERVERS
+              value: "theodolite-cp-kafka:9092"
+            - name: SCHEMA_REGISTRY_URL
+              value: "http://theodolite-cp-schema-registry:8081"
diff --git a/theodolite/examples/resources/uc1-load-generator-service.yaml b/theodolite/examples/resources/uc1-load-generator-service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f8b26b3f6dece427f9c1ad4db94e351b042749b3
--- /dev/null
+++ b/theodolite/examples/resources/uc1-load-generator-service.yaml
@@ -0,0 +1,16 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: titan-ccp-load-generator
+  labels:
+    app: titan-ccp-load-generator
+spec:
+  type: ClusterIP
+  clusterIP: None
+  selector:
+    app: titan-ccp-load-generator
+  ports:
+    - name: coordination
+      port: 5701
+      targetPort: 5701
+      protocol: TCP
diff --git a/theodolite/examples/standalone/example-benchmark.yaml b/theodolite/examples/standalone/example-benchmark.yaml
index 83edce93834ca9b8eef5606c1e5884ce40bdd7d8..0d5df81b163c1285f12971d08518dddf4b451d0f 100644
--- a/theodolite/examples/standalone/example-benchmark.yaml
+++ b/theodolite/examples/standalone/example-benchmark.yaml
@@ -1,12 +1,18 @@
 name: "uc1-kstreams"
-appResource:
-  - "uc1-kstreams-deployment.yaml"
-  - "aggregation-service.yaml"
-  - "jmx-configmap.yaml"
-  - "uc1-service-monitor.yaml"
-loadGenResource:
-  - "uc1-load-generator-deployment.yaml"
-  - "uc1-load-generator-service.yaml"
+  infrastructure: []
+  sut:
+    resources:
+      - configMap:
+         name: "example-configmap"
+         files:
+           - "uc1-kstreams-deployment.yaml"
+  loadGenerator:
+    resources:
+      - configMap:
+         name: "example-configmap"
+         files:
+            - uc1-load-generator-service.yaml
+            - uc1-load-generator-deployment.yaml
 resourceTypes:
   - typeName: "Instances"
     patchers:
@@ -25,7 +31,7 @@ loadTypes:
         properties:
           loadGenMaxRecords: "15000"
 kafkaConfig:
-  bootstrapServer: "localhost:31290"
+  bootstrapServer: "theodolite-cp-kafka:9092"
   topics:
     - name: "input"
       numPartitions: 40
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/Benchmark.kt b/theodolite/src/main/kotlin/theodolite/benchmark/Benchmark.kt
index 05d021b1bcfb77fa8ffeb0522510d49e39ef501c..cf2fac7337d79c1c5daf2b0fac070200cf27f9a5 100644
--- a/theodolite/src/main/kotlin/theodolite/benchmark/Benchmark.kt
+++ b/theodolite/src/main/kotlin/theodolite/benchmark/Benchmark.kt
@@ -14,6 +14,9 @@ import theodolite.util.Resource
 @RegisterForReflection
 interface Benchmark {
 
+    fun setupInfrastructure()
+    fun teardownInfrastructure()
+
     /**
      * Builds a Deployment that can be deployed.
      * @return a BenchmarkDeployment.
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkDeployment.kt b/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkDeployment.kt
index 92d3f7a012517895fc61531026e4ea4f3e3cfb50..fd01ecd986775ef704949743fef0d19f5492e9a6 100644
--- a/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkDeployment.kt
+++ b/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkDeployment.kt
@@ -7,8 +7,7 @@ package theodolite.benchmark
 interface BenchmarkDeployment {
 
     /**
-     * Setup a benchmark. This method is responsible for deploying the resources
-     * and organize the needed infrastructure.
+     * Setup a benchmark. This method is responsible for deploying the resources of a benchmark.
      */
     fun setup()
 
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/ConfigMapResourceSet.kt b/theodolite/src/main/kotlin/theodolite/benchmark/ConfigMapResourceSet.kt
new file mode 100644
index 0000000000000000000000000000000000000000..273a13170e77ae9e2f5f09869ebbc5cc06185715
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/benchmark/ConfigMapResourceSet.kt
@@ -0,0 +1,75 @@
+package theodolite.benchmark
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize
+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
+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
+                .configMaps()
+                .withName(name)
+                .get()
+                .data
+                .filter { it.key.endsWith(".yaml") } // consider only yaml files, e.g. ignore readme files
+        } 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)
+        }
+
+        if (::files.isInitialized){
+            resources = resources
+                .filter { files.contains(it.key) }
+
+            if (resources.size != files.size) {
+                throw  DeploymentFailedException("Could not find all specified Kubernetes manifests files")
+            }
+        }
+
+        return try {
+            resources
+                .map { Pair(
+                    getKind(resource = it.value),
+                    it) }
+                .map {
+                    Pair(
+                        it.second.key,
+                        loader.loadK8sResource(it.first, it.second.value)) }
+        } catch (e: IllegalArgumentException) {
+            throw  DeploymentFailedException("Can not creat resource set from specified configmap", e)
+        }
+
+    }
+
+    private fun getKind(resource: String): String {
+        val parser = YamlParserFromString()
+        val resourceAsMap = parser.parse(resource, HashMap<String, String>()::class.java)
+
+        return try {
+            resourceAsMap?.get("kind") !!
+        } catch (e: NullPointerException) {
+            throw DeploymentFailedException( "Could not find field kind of Kubernetes resource: ${resourceAsMap?.get("name")}", e)
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/FileSystemResourceSet.kt b/theodolite/src/main/kotlin/theodolite/benchmark/FileSystemResourceSet.kt
new file mode 100644
index 0000000000000000000000000000000000000000..92df1bec3cd6f21b1f830e73b466f70e37a9f4c8
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/benchmark/FileSystemResourceSet.kt
@@ -0,0 +1,66 @@
+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
+import java.io.File
+import java.io.FileNotFoundException
+import java.lang.IllegalArgumentException
+
+private val logger = KotlinLogging.logger {}
+
+@RegisterForReflection
+@JsonDeserialize
+class FileSystemResourceSet: ResourceSet, KubernetesResource {
+    lateinit var path: String
+    lateinit var files: List<String>
+
+    override fun getResourceSet(client: NamespacedKubernetesClient): Collection<Pair<String, KubernetesResource>> {
+
+        //if files is set ...
+        if(::files.isInitialized){
+            return files
+                    .map { loadSingleResource(resourceURL = it, client = client) }
+        }
+
+        return try {
+            File(path)
+                .list() !!
+                .filter { it.endsWith(".yaml") } // consider only yaml files, e.g. ignore readme files
+                .map {
+                    loadSingleResource(resourceURL = it, client = client)
+                }
+        } catch (e: NullPointerException) {
+            throw  DeploymentFailedException("Could not load files located in $path", e)
+        }
+    }
+
+    private fun loadSingleResource(resourceURL: String, client: NamespacedKubernetesClient): Pair<String, KubernetesResource> {
+        val parser = YamlParserFromFile()
+        val loader = K8sResourceLoaderFromFile(client)
+        val resourcePath = "$path/$resourceURL"
+        lateinit var kind: String
+
+        try {
+            kind = parser.parse(resourcePath, HashMap<String, String>()::class.java)?.get("kind")!!
+        } catch (e: NullPointerException) {
+            throw DeploymentFailedException("Can not get Kind from resource $resourcePath", e)
+        } catch (e: FileNotFoundException){
+            throw DeploymentFailedException("File $resourcePath not found", e)
+
+        }
+
+        return try {
+            val k8sResource = loader.loadK8sResource(kind, resourcePath)
+            Pair(resourceURL, k8sResource)
+        } catch (e: IllegalArgumentException) {
+            throw DeploymentFailedException("Could not load resource: $resourcePath", e)
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt b/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt
index b9a2fc7f18b92664b4d93b11755280a9e18b170d..0b81f8701f92a95662efef6e0d58839c9a2f6f3b 100644
--- a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt
+++ b/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt
@@ -1,14 +1,18 @@
 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
+import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import io.quarkus.runtime.annotations.RegisterForReflection
 import mu.KotlinLogging
-import theodolite.k8s.K8sResourceLoader
+import theodolite.k8s.K8sManager
+import theodolite.k8s.resourceLoader.K8sResourceLoader
 import theodolite.patcher.PatcherFactory
 import theodolite.util.*
 
+
 private val logger = KotlinLogging.logger {}
 
 private var DEFAULT_NAMESPACE = "default"
@@ -34,34 +38,40 @@ private var DEFAULT_THEODOLITE_APP_RESOURCES = "./benchmark-resources"
 @RegisterForReflection
 class KubernetesBenchmark : KubernetesResource, Benchmark {
     lateinit var name: String
-    lateinit var appResource: List<String>
-    lateinit var loadGenResource: List<String>
     lateinit var resourceTypes: List<TypeName>
     lateinit var loadTypes: List<TypeName>
     lateinit var kafkaConfig: KafkaConfig
+    lateinit var infrastructure: Resources
+    lateinit var sut: Resources
+    lateinit var loadGenerator: Resources
     var namespace = System.getenv("NAMESPACE") ?: DEFAULT_NAMESPACE
 
+    @Transient
+    private val client: NamespacedKubernetesClient = DefaultKubernetesClient().inNamespace(namespace)
 
     /**
      * Loads [KubernetesResource]s.
-     * It first loads them via the [YamlParser] to check for their concrete type and afterwards initializes them using
+     * It first loads them via the [YamlParserFromFile] to check for their concrete type and afterwards initializes them using
      * the [K8sResourceLoader]
      */
-    private fun loadKubernetesResources(resources: List<String>): List<Pair<String, KubernetesResource>> {
-        val path = System.getenv("THEODOLITE_APP_RESOURCES") ?: DEFAULT_THEODOLITE_APP_RESOURCES
-        logger.info { "Using $path as resource path." }
+    fun loadKubernetesResources(resourceSet: List<ResourceSets>): Collection<Pair<String, KubernetesResource>> {
+        return resourceSet.flatMap { it.loadResourceSet(this.client) }
+    }
 
-        val parser = YamlParser()
-        val loader = K8sResourceLoader(DefaultKubernetesClient())
-        return resources
-            .map { resource ->
-                val resourcePath = "$path/$resource"
-                val kind = parser.parse(resourcePath, HashMap<String, String>()::class.java)?.get("kind")!!
-                val k8sResource = loader.loadK8sResource(kind, resourcePath)
-                Pair(resource, k8sResource)
-            }
+    override fun setupInfrastructure() {
+        val kubernetesManager = K8sManager(this.client)
+        loadKubernetesResources(this.infrastructure.resources)
+            .map{it.second}
+            .forEach { kubernetesManager.deploy(it) }
     }
 
+    override fun teardownInfrastructure() {
+        val kubernetesManager = K8sManager(this.client)
+        loadKubernetesResources(this.infrastructure.resources)
+            .map{it.second}
+            .forEach { kubernetesManager.remove(it) }
+        }
+
     /**
      * Builds a deployment.
      * First loads all required resources and then patches them to the concrete load and resources for the experiment.
@@ -80,8 +90,8 @@ class KubernetesBenchmark : KubernetesResource, Benchmark {
     ): BenchmarkDeployment {
         logger.info { "Using $namespace as namespace." }
 
-        val appResources = loadKubernetesResources(this.appResource)
-        val loadGenResources = loadKubernetesResources(this.loadGenResource)
+        val appResources = loadKubernetesResources(this.sut.resources)
+        val loadGenResources = loadKubernetesResources(this.loadGenerator.resources)
 
         val patcherFactory = PatcherFactory()
 
@@ -106,7 +116,7 @@ class KubernetesBenchmark : KubernetesResource, Benchmark {
             afterTeardownDelay = afterTeardownDelay,
             kafkaConfig = hashMapOf("bootstrap.servers" to kafkaConfig.bootstrapServer),
             topics = kafkaConfig.topics,
-            client = DefaultKubernetesClient().inNamespace(namespace)
+            client = this.client
         )
     }
 }
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSet.kt b/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSet.kt
new file mode 100644
index 0000000000000000000000000000000000000000..19fc85845ae99c7a5e4f7369db4b6cd383c3131b
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSet.kt
@@ -0,0 +1,13 @@
+package theodolite.benchmark
+
+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
+
+@RegisterForReflection
+@JsonDeserialize
+interface ResourceSet: KubernetesResource {
+
+    fun getResourceSet(client: NamespacedKubernetesClient): Collection<Pair<String, KubernetesResource>>
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSets.kt b/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSets.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a4fe443e7f304c411792ee06c32592ba3c9e692a
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSets.kt
@@ -0,0 +1,32 @@
+package theodolite.benchmark
+
+import com.fasterxml.jackson.annotation.JsonInclude
+import com.fasterxml.jackson.annotation.JsonProperty
+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
+@RegisterForReflection
+class ResourceSets: KubernetesResource {
+    @JsonProperty("configMap")
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    var  configMap: ConfigMapResourceSet? = null
+
+    @JsonProperty("fileSystem")
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    var fileSystem: FileSystemResourceSet? = null
+
+    fun loadResourceSet(client: NamespacedKubernetesClient): Collection<Pair<String, KubernetesResource>> {
+        return if (::configMap != null) {
+            configMap?.getResourceSet(client= client) !!
+            } else if (::fileSystem != null) {
+            fileSystem?.getResourceSet(client= client ) !!
+            } else {
+                throw  DeploymentFailedException("could not load resourceSet.")
+            }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/Resources.kt b/theodolite/src/main/kotlin/theodolite/benchmark/Resources.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0187735b8fd273419874942cb7ed68797732c84c
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/benchmark/Resources.kt
@@ -0,0 +1,13 @@
+package theodolite.benchmark
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize
+import com.fasterxml.jackson.databind.annotation.JsonSerialize
+import io.quarkus.runtime.annotations.RegisterForReflection
+
+@JsonDeserialize
+@RegisterForReflection
+class Resources {
+
+    lateinit var resources: List<ResourceSets>
+
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt b/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt
index 777ea1c0ed43ac3af244dc0aaf770c69c11718cf..281c68e318784ee8206473cd014f814b3f5152a9 100644
--- a/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt
+++ b/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt
@@ -2,6 +2,7 @@ package theodolite.evaluation
 
 import mu.KotlinLogging
 import theodolite.benchmark.BenchmarkExecution
+import theodolite.util.EvaluationFailedException
 import theodolite.util.IOHandler
 import theodolite.util.LoadDimension
 import theodolite.util.Resource
@@ -12,7 +13,6 @@ import java.util.*
 import java.util.regex.Pattern
 
 private val logger = KotlinLogging.logger {}
-private val RECORD_LAG_QUERY = "sum by(group)(kafka_consumergroup_group_lag >= 0)"
 
 /**
  * Contains the analysis. Fetches a metric from Prometheus, documents it, and evaluates it.
@@ -37,7 +37,7 @@ class AnalysisExecutor(
      *  @return true if the experiment succeeded.
      */
     fun analyze(load: LoadDimension, res: Resource, executionIntervals: List<Pair<Instant, Instant>>): Boolean {
-        var result = false
+        var result: Boolean
         var repetitionCounter = 1
 
         try {
@@ -50,7 +50,7 @@ class AnalysisExecutor(
                     fetcher.fetchMetric(
                         start = interval.first,
                         end = interval.second,
-                        query = RECORD_LAG_QUERY
+                        query = SloConfigHandler.getQueryString(sloType = slo.sloType)
                     )
                 }
 
@@ -58,7 +58,7 @@ class AnalysisExecutor(
                 ioHandler.writeToCSVFile(
                     fileURL = "${fileURL}_${repetitionCounter++}",
                     data = data.getResultAsList(),
-                    columns = listOf("group", "timestamp", "value")
+                    columns = listOf("labels", "timestamp", "value")
                 )
             }
 
@@ -71,8 +71,7 @@ class AnalysisExecutor(
             result = sloChecker.evaluate(prometheusData)
 
         } catch (e: Exception) {
-            // TODO(throw exception in order to make it possible to mark an experiment as unsuccessfully)
-            logger.error { "Evaluation failed for resource '${res.get()}' and load '${load.get()}'. Error: $e" }
+            throw EvaluationFailedException("Evaluation failed for resource '${res.get()}' and load '${load.get()} ", e)
         }
         return result
     }
diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/ExternalSloChecker.kt b/theodolite/src/main/kotlin/theodolite/evaluation/ExternalSloChecker.kt
index 448a2a05f8dbeb1aef153895360bfb40e7275224..d646286b70bc5880df1f603afdc2bda22bcc3259 100644
--- a/theodolite/src/main/kotlin/theodolite/evaluation/ExternalSloChecker.kt
+++ b/theodolite/src/main/kotlin/theodolite/evaluation/ExternalSloChecker.kt
@@ -36,13 +36,12 @@ class ExternalSloChecker(
      */
     override fun evaluate(fetchedData: List<PrometheusResponse>): Boolean {
         var counter = 0
-        val data = Gson().toJson(
-            mapOf(
-                "total_lags" to fetchedData.map { it.data?.result },
-                "threshold" to threshold,
-                "warmup" to warmup
-            )
-        )
+        val data = SloJson.Builder()
+            .results(fetchedData.map { it.data?.result })
+            .addMetadata("threshold", threshold)
+            .addMetadata( "warmup", warmup)
+            .build()
+            .toJson()
 
         while (counter < RETRIES) {
             val result = post(externalSlopeURL, data = data, timeout = TIMEOUT)
diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/MetricFetcher.kt b/theodolite/src/main/kotlin/theodolite/evaluation/MetricFetcher.kt
index 833d7d1e16c2fbc91b58817b319a7d02af7f5b2b..e54d79fe0f95b9f6079bd4295a74e81250b73a90 100644
--- a/theodolite/src/main/kotlin/theodolite/evaluation/MetricFetcher.kt
+++ b/theodolite/src/main/kotlin/theodolite/evaluation/MetricFetcher.kt
@@ -53,8 +53,7 @@ class MetricFetcher(private val prometheusURL: String, private val offset: Durat
             } else {
                 val values = parseValues(response)
                 if (values.data?.result.isNullOrEmpty()) {
-                    logger.error { "Empty query result: $values between $start and $end for query $query." }
-                    throw NoSuchFieldException()
+                    throw NoSuchFieldException("Empty query result: $values between $start and $end for query $query.")
                 }
                 return parseValues(response)
             }
diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/SloCheckerFactory.kt b/theodolite/src/main/kotlin/theodolite/evaluation/SloCheckerFactory.kt
index 93e8e6180f5a99486e500af022869d896067d128..64f9110cd931feef41dc65f88d6623e82f4e03a2 100644
--- a/theodolite/src/main/kotlin/theodolite/evaluation/SloCheckerFactory.kt
+++ b/theodolite/src/main/kotlin/theodolite/evaluation/SloCheckerFactory.kt
@@ -43,22 +43,23 @@ class SloCheckerFactory {
         properties: MutableMap<String, String>,
         load: LoadDimension
     ): SloChecker {
-        return when (sloType) {
-            "lag trend" -> ExternalSloChecker(
+        return when (sloType.toLowerCase()) {
+            SloTypes.LAG_TREND.value, SloTypes.DROPPED_RECORDS.value -> ExternalSloChecker(
                 externalSlopeURL = properties["externalSloUrl"]
                     ?: throw IllegalArgumentException("externalSloUrl expected"),
                 threshold = properties["threshold"]?.toInt() ?: throw IllegalArgumentException("threshold expected"),
                 warmup = properties["warmup"]?.toInt() ?: throw IllegalArgumentException("warmup expected")
             )
-            "lag trend ratio" -> {
-                var thresholdRatio =
+
+                SloTypes.LAG_TREND_RATIO.value, SloTypes.DROPPED_RECORDS_RATIO.value -> {
+                val thresholdRatio =
                     properties["ratio"]?.toDouble()
                         ?: throw IllegalArgumentException("ratio for threshold expected")
                 if (thresholdRatio < 0.0) {
                     throw IllegalArgumentException("Threshold ratio needs to be an Double greater or equal 0.0")
                 }
                 // cast to int, as rounding is not really necessary
-                var threshold = (load.get() * thresholdRatio).toInt()
+                val threshold = (load.get() * thresholdRatio).toInt()
 
                 ExternalSloChecker(
                     externalSlopeURL = properties["externalSloUrl"]
diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/SloConfigHandler.kt b/theodolite/src/main/kotlin/theodolite/evaluation/SloConfigHandler.kt
new file mode 100644
index 0000000000000000000000000000000000000000..93929218c822030ff065dafb19cce1fbaa69a179
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/evaluation/SloConfigHandler.kt
@@ -0,0 +1,20 @@
+package theodolite.evaluation
+
+import theodolite.util.InvalidPatcherConfigurationException
+import javax.enterprise.context.ApplicationScoped
+
+private const val CONSUMER_LAG_QUERY = "sum by(group)(kafka_consumergroup_group_lag >= 0)"
+private const val DROPPED_RECORDS_QUERY = "sum by(job) (kafka_streams_stream_task_metrics_dropped_records_total>=0)"
+
+@ApplicationScoped
+class SloConfigHandler() {
+    companion object {
+        fun getQueryString(sloType: String): String {
+            return when (sloType.toLowerCase()) {
+                SloTypes.LAG_TREND.value, SloTypes.LAG_TREND_RATIO.value -> CONSUMER_LAG_QUERY
+                SloTypes.DROPPED_RECORDS.value, SloTypes.DROPPED_RECORDS_RATIO.value -> DROPPED_RECORDS_QUERY
+                else -> throw  InvalidPatcherConfigurationException("Could not find Prometheus query string for slo type $sloType")
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/SloJson.kt b/theodolite/src/main/kotlin/theodolite/evaluation/SloJson.kt
new file mode 100644
index 0000000000000000000000000000000000000000..fc9fe17b255dbb5ae68881538d8d2a50a191edb1
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/evaluation/SloJson.kt
@@ -0,0 +1,63 @@
+package theodolite.evaluation
+
+import com.google.gson.Gson
+import theodolite.util.PromResult
+
+class SloJson private constructor(
+    val results: List<List<PromResult>?>? = null,
+    var metadata: MutableMap<String, Any>? = null
+) {
+
+    data class Builder(
+        var results:List<List<PromResult>?>? = null,
+        var metadata: MutableMap<String, Any>? = null
+    ) {
+
+        /**
+         *  Set the results
+         *
+         * @param results list of prometheus results
+         */
+        fun results(results: List<List<PromResult>?>) = apply { this.results = results }
+
+        /**
+         * Add metadata as key value pairs
+         *
+         * @param key key of the metadata to be added
+         * @param value value of the metadata to be added
+         */
+        fun addMetadata(key: String, value: String) = apply {
+            if (this.metadata.isNullOrEmpty()) {
+                this.metadata = mutableMapOf(key to value)
+            } else {
+                this.metadata!![key] = value
+            }
+        }
+
+        /**
+         * Add metadata as key value pairs
+         *
+         * @param key key of the metadata to be added
+         * @param value value of the metadata to be added
+         */
+        fun addMetadata(key: String, value: Int) = apply {
+            if (this.metadata.isNullOrEmpty()) {
+                this.metadata = mutableMapOf(key to value)
+            } else {
+                this.metadata!![key] = value
+            }
+        }
+
+        fun build() = SloJson(
+            results = results,
+            metadata = metadata
+        )
+    }
+
+   fun  toJson(): String {
+       return Gson().toJson(mapOf(
+           "results" to this.results,
+           "metadata" to this.metadata
+       ))
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/SloTypes.kt b/theodolite/src/main/kotlin/theodolite/evaluation/SloTypes.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ac9de35861b0bd9c012bfb0b8cfcb2e1aa5aed68
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/evaluation/SloTypes.kt
@@ -0,0 +1,10 @@
+package theodolite.evaluation
+
+enum class SloTypes(val value: String) {
+    LAG_TREND("lag trend"),
+    LAG_TREND_RATIO("lag trend ratio"),
+    DROPPED_RECORDS("dropped records"),
+    DROPPED_RECORDS_RATIO("dropped records ratio")
+
+
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt b/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt
index e7b511d8c83b5abccece1204aad2a4a9ecfdfd26..3238f447be06ce6486bb7f6ca1758700f36ba558 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt
@@ -25,11 +25,12 @@ abstract class BenchmarkExecutor(
     val results: Results,
     val executionDuration: Duration,
     val configurationOverrides: List<ConfigurationOverride?>,
-    val slo: BenchmarkExecution.Slo,
+    val slos: List<BenchmarkExecution.Slo>,
     val repetitions: Int,
     val executionId: Int,
     val loadGenerationDelay: Long,
-    val afterTeardownDelay: Long
+    val afterTeardownDelay: Long,
+    val executionName: String
 ) {
 
     var run: AtomicBoolean = AtomicBoolean(true)
diff --git a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt b/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt
index c54d1878d4957a0b8ec6a8fdfb18ec6342d7bfc1..2e938be3a6e503a5e7e3f94c18a9454e173db5b0 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt
@@ -5,10 +5,8 @@ import mu.KotlinLogging
 import theodolite.benchmark.Benchmark
 import theodolite.benchmark.BenchmarkExecution
 import theodolite.evaluation.AnalysisExecutor
-import theodolite.util.ConfigurationOverride
-import theodolite.util.LoadDimension
-import theodolite.util.Resource
-import theodolite.util.Results
+import theodolite.execution.operator.EventCreator
+import theodolite.util.*
 import java.time.Duration
 import java.time.Instant
 
@@ -20,29 +18,34 @@ class BenchmarkExecutorImpl(
     results: Results,
     executionDuration: Duration,
     configurationOverrides: List<ConfigurationOverride?>,
-    slo: BenchmarkExecution.Slo,
+    slos: List<BenchmarkExecution.Slo>,
     repetitions: Int,
     executionId: Int,
     loadGenerationDelay: Long,
-    afterTeardownDelay: Long
+    afterTeardownDelay: Long,
+    executionName: String
 ) : BenchmarkExecutor(
     benchmark,
     results,
     executionDuration,
     configurationOverrides,
-    slo,
+    slos,
     repetitions,
     executionId,
     loadGenerationDelay,
-    afterTeardownDelay
+    afterTeardownDelay,
+    executionName
 ) {
+    private val eventCreator = EventCreator()
+    private val mode = Configuration.EXECUTION_MODE
+
     override fun runExperiment(load: LoadDimension, res: Resource): Boolean {
         var result = false
         val executionIntervals: MutableList<Pair<Instant, Instant>> = ArrayList()
 
         for (i in 1.rangeTo(repetitions)) {
-            logger.info { "Run repetition $i/$repetitions" }
             if (this.run.get()) {
+                logger.info { "Run repetition $i/$repetitions" }
                 executionIntervals.add(runSingleExperiment(load, res))
             } else {
                 break
@@ -53,14 +56,23 @@ class BenchmarkExecutorImpl(
          * Analyse the experiment, if [run] is true, otherwise the experiment was canceled by the user.
          */
         if (this.run.get()) {
-            result = AnalysisExecutor(slo = slo, executionId = executionId)
-                .analyze(
-                    load = load,
-                    res = res,
-                    executionIntervals = executionIntervals
-                )
+            val experimentResults = slos.map {
+                AnalysisExecutor(slo = it, executionId = executionId)
+                    .analyze(
+                        load = load,
+                        res = res,
+                        executionIntervals = executionIntervals
+                    )
+            }
+
+            result = (false !in experimentResults)
             this.results.setResult(Pair(load, res), result)
         }
+
+        if(!this.run.get()) {
+            throw ExecutionFailedException("The execution was interrupted")
+        }
+
         return result
     }
 
@@ -73,22 +85,49 @@ class BenchmarkExecutorImpl(
             this.afterTeardownDelay
         )
         val from = Instant.now()
-        // TODO(restructure try catch in order to throw exceptions if there are significant problems by running a experiment)
+
         try {
             benchmarkDeployment.setup()
             this.waitAndLog()
+            if (mode == ExecutionModes.OPERATOR.value) {
+                eventCreator.createEvent(
+                    executionName = executionName,
+                    type = "NORMAL",
+                    reason = "Start experiment",
+                    message = "load: ${load.get()}, resources: ${res.get()}")
+            }
         } catch (e: Exception) {
-            logger.error { "Error while setup experiment." }
-            logger.error { "Error is: $e" }
             this.run.set(false)
+
+            if (mode == ExecutionModes.OPERATOR.value) {
+                eventCreator.createEvent(
+                    executionName = executionName,
+                    type = "WARNING",
+                    reason = "Start experiment failed",
+                    message = "load: ${load.get()}, resources: ${res.get()}")
+            }
+            throw ExecutionFailedException("Error during setup the experiment", e)
         }
         val to = Instant.now()
         try {
             benchmarkDeployment.teardown()
+            if (mode == ExecutionModes.OPERATOR.value) {
+                eventCreator.createEvent(
+                    executionName = executionName,
+                    type = "NORMAL",
+                    reason = "Stop experiment",
+                    message = "Teardown complete")
+            }
         } catch (e: Exception) {
-            logger.warn { "Error while tearing down the benchmark deployment." }
-            logger.debug { "Teardown failed, caused by: $e" }
+            if (mode == ExecutionModes.OPERATOR.value) {
+                eventCreator.createEvent(
+                    executionName = executionName,
+                    type = "WARNING",
+                    reason = "Stop experiment failed",
+                    message = "Teardown failed: ${e.message}")
+            }
+            throw ExecutionFailedException("Error during teardown the experiment", e)
         }
         return Pair(from, to)
     }
-}
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/execution/ExecutionModes.kt b/theodolite/src/main/kotlin/theodolite/execution/ExecutionModes.kt
new file mode 100644
index 0000000000000000000000000000000000000000..bf947be01b534fd000d3967f0b72ef25978d4110
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/execution/ExecutionModes.kt
@@ -0,0 +1,7 @@
+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 7d5fca859422a194e81468d9766a9e7ba29fb998..11f696ddd739e987e92ecec724390948714d898b 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/Main.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/Main.kt
@@ -3,6 +3,7 @@ package theodolite.execution
 import io.quarkus.runtime.annotations.QuarkusMain
 import mu.KotlinLogging
 import theodolite.execution.operator.TheodoliteOperator
+import theodolite.util.Configuration
 import kotlin.system.exitProcess
 
 private val logger = KotlinLogging.logger {}
@@ -13,13 +14,12 @@ object Main {
     @JvmStatic
     fun main(args: Array<String>) {
 
-        val mode = System.getenv("MODE") ?: "standalone"
+        val mode = Configuration.EXECUTION_MODE
         logger.info { "Start Theodolite with mode $mode" }
 
-        when (mode) {
-            "standalone" -> TheodoliteStandalone().start()
-            "yaml-executor" -> TheodoliteStandalone().start() // TODO remove (#209)
-            "operator" -> TheodoliteOperator().start()
+        when (mode.toLowerCase()) {
+            ExecutionModes.STANDALONE.value, ExecutionModes.YAML_EXECUTOR.value -> TheodoliteStandalone().start()  // TODO remove standalone (#209)
+            ExecutionModes.OPERATOR.value -> TheodoliteOperator().start()
             else -> {
                 logger.error { "MODE $mode not found" }
                 exitProcess(1)
diff --git a/theodolite/src/main/kotlin/theodolite/execution/Shutdown.kt b/theodolite/src/main/kotlin/theodolite/execution/Shutdown.kt
index e795ada3e3bcb2dba19f1e088f426f38a824f4a7..6dedc94af864269d7d15929c69ec54aa384fc8e3 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/Shutdown.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/Shutdown.kt
@@ -34,16 +34,15 @@ class Shutdown(private val benchmarkExecution: BenchmarkExecution, private val b
                     afterTeardownDelay = 5L
                 )
             deployment.teardown()
+            logger.info {
+                "Finished teardown of all benchmark resources."
+            }
         } catch (e: Exception) {
-            // TODO(throw exception in order to make it possible to mark an experiment as unsuccessfully)
             logger.warn {
                 "Could not delete all specified resources from Kubernetes. " +
                         "This could be the case, if not all resources are deployed and running."
             }
 
         }
-        logger.info {
-            "Finished teardown of all benchmark resources."
-        }
     }
 }
diff --git a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt b/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
index addf30acde31ee8e3e53c20a5e2b57a03587d08e..315d1cf1afe7fd2ffbfc1c437d725d4dff29f637 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
@@ -61,11 +61,12 @@ class TheodoliteExecutor(
                 results = results,
                 executionDuration = executionDuration,
                 configurationOverrides = config.configOverrides,
-                slo = config.slos[0],
+                slos = config.slos,
                 repetitions = config.execution.repetitions,
                 executionId = config.executionId,
                 loadGenerationDelay = config.execution.loadGenerationDelay,
-                afterTeardownDelay = config.execution.afterTeardownDelay
+                afterTeardownDelay = config.execution.afterTeardownDelay,
+                executionName = config.name
             )
 
         if (config.load.loadValues != config.load.loadValues.sorted()) {
@@ -112,6 +113,8 @@ class TheodoliteExecutor(
      * execution and benchmark objects.
      */
     fun run() {
+        kubernetesBenchmark.setupInfrastructure()
+
         val ioHandler = IOHandler()
         val resultsFolder = ioHandler.getResultFolderURL()
         this.config.executionId = getAndIncrementExecutionID(resultsFolder + "expID.txt")
@@ -123,15 +126,19 @@ class TheodoliteExecutor(
 
         val config = buildConfig()
         // execute benchmarks for each load
-        for (load in config.loads) {
-            if (executor.run.get()) {
-                config.compositeStrategy.findSuitableResource(load, config.resources)
+        try {
+            for (load in config.loads) {
+                if (executor.run.get()) {
+                    config.compositeStrategy.findSuitableResource(load, config.resources)
+                }
             }
+        } finally {
+            ioHandler.writeToJSONFile(
+                config.compositeStrategy.benchmarkExecutor.results,
+                "${resultsFolder}exp${this.config.executionId}-result"
+            )
         }
-        ioHandler.writeToJSONFile(
-            config.compositeStrategy.benchmarkExecutor.results,
-            "${resultsFolder}exp${this.config.executionId}-result"
-        )
+        kubernetesBenchmark.teardownInfrastructure()
     }
 
     private fun getAndIncrementExecutionID(fileURL: String): Int {
diff --git a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteStandalone.kt b/theodolite/src/main/kotlin/theodolite/execution/TheodoliteStandalone.kt
index 76fd7f707a3e190ff6c61052ae4b5aaf50459418..1bbf3e01f461a19dbe588aedd41be63b84c86162 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteStandalone.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/TheodoliteStandalone.kt
@@ -3,7 +3,9 @@ package theodolite.execution
 import mu.KotlinLogging
 import theodolite.benchmark.BenchmarkExecution
 import theodolite.benchmark.KubernetesBenchmark
-import theodolite.util.YamlParser
+import theodolite.util.YamlParserFromFile
+import theodolite.util.EvaluationFailedException
+import theodolite.util.ExecutionFailedException
 import kotlin.concurrent.thread
 import kotlin.system.exitProcess
 
@@ -26,7 +28,7 @@ private val logger = KotlinLogging.logger {}
  * @constructor Create empty Theodolite yaml executor
  */
 class TheodoliteStandalone {
-    private val parser = YamlParser()
+    private val parser = YamlParserFromFile()
 
     fun start() {
         logger.info { "Theodolite started" }
@@ -49,8 +51,14 @@ class TheodoliteStandalone {
         val shutdown = thread(start = false) { Shutdown(benchmarkExecution, benchmark).run() }
         Runtime.getRuntime().addShutdownHook(shutdown)
 
-        val executor = TheodoliteExecutor(benchmarkExecution, benchmark)
-        executor.run()
+        try {
+            TheodoliteExecutor(benchmarkExecution, benchmark).run()
+        } catch (e: EvaluationFailedException) {
+            logger.error { "Evaluation failed with error: ${e.message}" }
+        }catch (e: ExecutionFailedException) {
+            logger.error { "Execution failed with error: ${e.message}" }
+        }
+
         logger.info { "Theodolite finished" }
         Runtime.getRuntime().removeShutdownHook(shutdown)
         exitProcess(0)
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt
index 9d7436526f18081c7130870956d8a5eea5fc8997..0b5d6040bdea1316f8fb55bcc3f204c5443f6eee 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt
@@ -4,10 +4,13 @@ import io.fabric8.kubernetes.api.model.HasMetadata
 import io.fabric8.kubernetes.api.model.KubernetesResourceList
 import io.fabric8.kubernetes.api.model.Namespaced
 import io.fabric8.kubernetes.client.CustomResource
+import io.fabric8.kubernetes.client.KubernetesClientException
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import io.fabric8.kubernetes.client.dsl.MixedOperation
 import io.fabric8.kubernetes.client.dsl.Resource
+import mu.KotlinLogging
 import java.lang.Thread.sleep
+private val logger = KotlinLogging.logger {}
 
 abstract class AbstractStateHandler<T, L, D>(
     private val client: NamespacedKubernetesClient,
@@ -20,11 +23,15 @@ abstract class AbstractStateHandler<T, L, D>(
 
     @Synchronized
     override fun setState(resourceName: String, f: (T) -> T?) {
-        this.crdClient
-            .list().items
-            .filter { it.metadata.name == resourceName }
-            .map { customResource -> f(customResource) }
-            .forEach { this.crdClient.updateStatus(it) }
+        try {
+            this.crdClient
+                .list().items
+                .filter { it.metadata.name == resourceName }
+                .map { customResource -> f(customResource) }
+                .forEach { this.crdClient.updateStatus(it) }
+        } catch (e: KubernetesClientException) {
+            logger.warn { "Status cannot be set for resource $resourceName" }
+        }
     }
 
     @Synchronized
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateHandler.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateHandler.kt
new file mode 100644
index 0000000000000000000000000000000000000000..adca2a8b7fdb9b3e610f15e57c011679869df14c
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateHandler.kt
@@ -0,0 +1,28 @@
+package theodolite.execution.operator
+
+import io.fabric8.kubernetes.client.NamespacedKubernetesClient
+import theodolite.model.crd.*
+
+class BenchmarkStateHandler(val client: NamespacedKubernetesClient) :
+    AbstractStateHandler<BenchmarkCRD, KubernetesBenchmarkList, ExecutionStatus>(
+        client = client,
+        crd = BenchmarkCRD::class.java,
+        crdList = KubernetesBenchmarkList::class.java
+    ) {
+
+    private fun getBenchmarkResourceState() = { cr: BenchmarkCRD -> cr.status.resourceSetsState }
+
+    fun setResourceSetState(resourceName: String, status: BenchmarkStates): Boolean {
+        setState(resourceName) { cr -> cr.status.resourceSetsState = status.value; cr }
+        return blockUntilStateIsSet(resourceName, status.value, getBenchmarkResourceState())
+    }
+
+    fun getResourceSetState(resourceName: String): ExecutionStates {
+        val status = this.getState(resourceName, getBenchmarkResourceState())
+        return if (status.isNullOrBlank()) {
+            ExecutionStates.NO_STATE
+        } else {
+            ExecutionStates.values().first { it.value == status }
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt
index c3a2b7b25ed71e797c45d8b497bad6cad15e21e8..efca98f8bf72024daa0367c6c57574f0644872e4 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt
@@ -41,7 +41,7 @@ class ClusterSetup(
             .list()
             .items
             .asSequence()
-            .filter { it.status.executionState == States.RUNNING.value }
+            .filter { it.status.executionState == ExecutionStates.RUNNING.value }
             .forEach { execution ->
                 val benchmark = benchmarkCRDClient
                     .inNamespace(client.namespace)
@@ -54,11 +54,8 @@ class ClusterSetup(
                     benchmark.spec.name = benchmark.metadata.name
                     Shutdown(execution.spec, benchmark.spec).start()
                 } else {
-                    logger.error {
-                        "Execution with state ${States.RUNNING.value} was found, but no corresponding benchmark. " +
-                                "Could not initialize cluster."
-                    }
-                    throw IllegalStateException("Cluster state is invalid, required Benchmark for running execution not found.")
+                    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/EventCreator.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/EventCreator.kt
new file mode 100644
index 0000000000000000000000000000000000000000..fab098ebd5fe765a455d787ddb7fcbfbb6c9ffc7
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/EventCreator.kt
@@ -0,0 +1,60 @@
+package theodolite.execution.operator
+
+import io.fabric8.kubernetes.api.model.EventBuilder
+import io.fabric8.kubernetes.api.model.EventSource
+import io.fabric8.kubernetes.api.model.ObjectReference
+import io.fabric8.kubernetes.client.DefaultKubernetesClient
+import io.fabric8.kubernetes.client.NamespacedKubernetesClient
+import mu.KotlinLogging
+import theodolite.util.Configuration
+import java.time.Instant
+import java.util.*
+import kotlin.NoSuchElementException
+private val logger = KotlinLogging.logger {}
+
+class EventCreator {
+    val client: NamespacedKubernetesClient = DefaultKubernetesClient().inNamespace(Configuration.NAMESPACE)
+
+    fun createEvent(executionName: String, type: String, message: String, reason: String) {
+        val uuid = UUID.randomUUID().toString()
+        try {
+            val objectRef = buildObjectReference(executionName)
+            val event = EventBuilder()
+                .withNewMetadata()
+                .withName(uuid)
+                .endMetadata()
+                .withMessage(message)
+                .withReason(reason)
+                .withType(type)
+                .withFirstTimestamp(Instant.now().toString()) // TODO change datetime format
+                .build()
+
+            val source =  EventSource()
+            source.component = Configuration.COMPONENT_NAME
+            event.source = source
+
+            event.involvedObject = objectRef
+            client.v1().events().inNamespace(Configuration.NAMESPACE).createOrReplace(event)
+        } catch (e: NoSuchElementException) {
+                logger.warn {"Could not create event: type: $type, message: $message, reason: $reason, no corresponding execution found."}
+        }
+    }
+
+    private fun buildObjectReference(executionName: String): ObjectReference {
+        val exec = TheodoliteOperator()
+            .getExecutionClient(client = client)
+            .list()
+            .items
+            .first{it.metadata.name == executionName}
+
+        val objectRef = ObjectReference()
+        objectRef.apiVersion = exec.apiVersion
+        objectRef.kind = exec.kind
+        objectRef.uid = exec.metadata.uid
+        objectRef.name = exec.metadata.name
+        objectRef.namespace = exec.metadata.namespace
+        objectRef.resourceVersion = exec.metadata.resourceVersion
+
+        return objectRef
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt
index 1209195ee09cebe382f010f38e955dea1c860cd1..16c4ea98ba614bb3dcdd7d9f486f4e65ae70d380 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt
@@ -33,9 +33,9 @@ class ExecutionHandler(
         logger.info { "Add execution ${execution.metadata.name}" }
         execution.spec.name = execution.metadata.name
         when (this.stateHandler.getExecutionState(execution.metadata.name)) {
-            States.NO_STATE -> this.stateHandler.setExecutionState(execution.spec.name, States.PENDING)
-            States.RUNNING -> {
-                this.stateHandler.setExecutionState(execution.spec.name, States.RESTART)
+            ExecutionStates.NO_STATE -> this.stateHandler.setExecutionState(execution.spec.name, ExecutionStates.PENDING)
+            ExecutionStates.RUNNING -> {
+                this.stateHandler.setExecutionState(execution.spec.name, ExecutionStates.RESTART)
                 if (this.controller.isExecutionRunning(execution.spec.name)) {
                     this.controller.stop(restart = true)
                 }
@@ -58,15 +58,15 @@ class ExecutionHandler(
         if (gson.toJson(oldExecution.spec) != gson.toJson(newExecution.spec)) {
             logger.info { "Receive update event for execution ${oldExecution.metadata.name}" }
             when (this.stateHandler.getExecutionState(newExecution.metadata.name)) {
-                States.RUNNING -> {
-                    this.stateHandler.setExecutionState(newExecution.spec.name, States.RESTART)
+                ExecutionStates.RUNNING -> {
+                    this.stateHandler.setExecutionState(newExecution.spec.name, ExecutionStates.RESTART)
                     if (this.controller.isExecutionRunning(newExecution.spec.name)) {
                         this.controller.stop(restart = true)
                     }
                 }
-                States.RESTART -> {
+                ExecutionStates.RESTART -> {
                 } // should this set to pending?
-                else -> this.stateHandler.setExecutionState(newExecution.spec.name, States.PENDING)
+                else -> this.stateHandler.setExecutionState(newExecution.spec.name, ExecutionStates.PENDING)
             }
         }
     }
@@ -79,7 +79,7 @@ class ExecutionHandler(
     @Synchronized
     override fun onDelete(execution: ExecutionCRD, b: Boolean) {
         logger.info { "Delete execution ${execution.metadata.name}" }
-        if (execution.status.executionState == States.RUNNING.value
+        if (execution.status.executionState == ExecutionStates.RUNNING.value
             && this.controller.isExecutionRunning(execution.metadata.name)
         ) {
             this.controller.stop()
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt
index bcc86c8f2a9b233fa9a1972a866936e14688ecf8..9f49cf3ee4f9f62e7006dbf6697340e1af152f27 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt
@@ -4,7 +4,7 @@ import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import theodolite.model.crd.BenchmarkExecutionList
 import theodolite.model.crd.ExecutionCRD
 import theodolite.model.crd.ExecutionStatus
-import theodolite.model.crd.States
+import theodolite.model.crd.ExecutionStates
 import java.lang.Thread.sleep
 import java.time.Duration
 import java.time.Instant
@@ -23,17 +23,17 @@ class ExecutionStateHandler(val client: NamespacedKubernetesClient) :
 
     private fun getDurationLambda() = { cr: ExecutionCRD -> cr.status.executionDuration }
 
-    fun setExecutionState(resourceName: String, status: States): Boolean {
+    fun setExecutionState(resourceName: String, status: ExecutionStates): Boolean {
         setState(resourceName) { cr -> cr.status.executionState = status.value; cr }
         return blockUntilStateIsSet(resourceName, status.value, getExecutionLambda())
     }
 
-    fun getExecutionState(resourceName: String): States {
+    fun getExecutionState(resourceName: String): ExecutionStates {
         val status = this.getState(resourceName, getExecutionLambda())
         return if (status.isNullOrBlank()) {
-            States.NO_STATE
+            ExecutionStates.NO_STATE
         } else {
-            States.values().first { it.value == status }
+            ExecutionStates.values().first { it.value == status }
         }
     }
 
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
index eb51a445ee05f1811a8780ff64c570f0bbdff4d0..70e30cf84ef40796eb085a0d68eb2e323232fde9 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
@@ -28,7 +28,8 @@ const val CREATED_BY_LABEL_VALUE = "theodolite"
 class TheodoliteController(
     private val executionCRDClient: MixedOperation<ExecutionCRD, BenchmarkExecutionList, Resource<ExecutionCRD>>,
     private val benchmarkCRDClient: MixedOperation<BenchmarkCRD, KubernetesBenchmarkList, Resource<BenchmarkCRD>>,
-    private val executionStateHandler: ExecutionStateHandler
+    private val executionStateHandler: ExecutionStateHandler,
+    private val benchmarkStateHandler: BenchmarkStateHandler
 ) {
     lateinit var executor: TheodoliteExecutor
 
@@ -40,6 +41,7 @@ class TheodoliteController(
         sleep(5000) // wait until all states are correctly set
         while (true) {
             reconcile()
+            updateBenchmarkStatus()
             sleep(2000)
         }
     }
@@ -47,8 +49,10 @@ class TheodoliteController(
     private fun reconcile() {
         do {
             val execution = getNextExecution()
+            updateBenchmarkStatus()
             if (execution != null) {
                 val benchmark = getBenchmarks()
+                    .map { it.spec }
                     .firstOrNull { it.name == execution.benchmark }
                 if (benchmark != null) {
                     runExecution(execution, benchmark)
@@ -65,9 +69,11 @@ class TheodoliteController(
      * @see BenchmarkExecution
      */
     private fun runExecution(execution: BenchmarkExecution, benchmark: KubernetesBenchmark) {
-        val modifier = ConfigOverrideModifier(
+        try {
+            val modifier = ConfigOverrideModifier(
             execution = execution,
-            resources = benchmark.appResource + benchmark.loadGenResource
+            resources = benchmark.loadKubernetesResources(benchmark.sut.resources).map { it.first }
+                    + benchmark.loadKubernetesResources(benchmark.loadGenerator.resources).map { it.first }
         )
         modifier.setAdditionalLabels(
             labelValue = execution.name,
@@ -82,23 +88,31 @@ class TheodoliteController(
             labelName = CREATED_BY_LABEL_NAME
         )
 
-        executionStateHandler.setExecutionState(execution.name, States.RUNNING)
+        executionStateHandler.setExecutionState(execution.name, ExecutionStates.RUNNING)
         executionStateHandler.startDurationStateTimer(execution.name)
 
-        try {
             executor = TheodoliteExecutor(execution, benchmark)
             executor.run()
             when (executionStateHandler.getExecutionState(execution.name)) {
-                States.RESTART -> runExecution(execution, benchmark)
-                States.RUNNING -> {
-                    executionStateHandler.setExecutionState(execution.name, States.FINISHED)
+                ExecutionStates.RESTART -> runExecution(execution, benchmark)
+                ExecutionStates.RUNNING -> {
+                    executionStateHandler.setExecutionState(execution.name, ExecutionStates.FINISHED)
                     logger.info { "Execution of ${execution.name} is finally stopped." }
+                    }
+                else -> {
+                    executionStateHandler.setExecutionState(execution.name, ExecutionStates.FAILURE)
+                    logger.warn { "Unexpected execution state, set state to ${ExecutionStates.FAILURE.value}" }
                 }
             }
         } catch (e: Exception) {
+                EventCreator().createEvent(
+                executionName = execution.name,
+                type = "WARNING",
+                reason = "Execution failed",
+                message = "An error occurs while executing:  ${e.message}")
             logger.error { "Failure while executing execution ${execution.name} with benchmark ${benchmark.name}." }
             logger.error { "Problem is: $e" }
-            executionStateHandler.setExecutionState(execution.name, States.FAILURE)
+            executionStateHandler.setExecutionState(execution.name, ExecutionStates.FAILURE)
         }
         executionStateHandler.stopDurationStateTimer()
     }
@@ -107,7 +121,7 @@ class TheodoliteController(
     fun stop(restart: Boolean = false) {
         if (!::executor.isInitialized) return
         if (restart) {
-            executionStateHandler.setExecutionState(this.executor.getExecution().name, States.RESTART)
+            executionStateHandler.setExecutionState(this.executor.getExecution().name, ExecutionStates.RESTART)
         }
         this.executor.executor.run.set(false)
     }
@@ -115,30 +129,33 @@ class TheodoliteController(
     /**
      * @return all available [BenchmarkCRD]s
      */
-    private fun getBenchmarks(): List<KubernetesBenchmark> {
+    private fun getBenchmarks(): List<BenchmarkCRD> {
         return this.benchmarkCRDClient
             .list()
             .items
             .map {
                 it.spec.name = it.metadata.name
-                it.spec
+                it
             }
     }
 
+
     /**
      * Get the [BenchmarkExecution] for the next run. Which [BenchmarkExecution]
      * is selected for the next execution depends on three points:
      *
      * 1. Only executions are considered for which a matching benchmark is available on the cluster
-     * 2. The Status of the execution must be [States.PENDING] or [States.RESTART]
-     * 3. Of the remaining [BenchmarkCRD], those with status [States.RESTART] are preferred,
+     * 2. The Status of the execution must be [ExecutionStates.PENDING] or [ExecutionStates.RESTART]
+     * 3. Of the remaining [BenchmarkCRD], those with status [ExecutionStates.RESTART] are preferred,
      * then, if there is more than one, the oldest execution is chosen.
      *
      * @return the next execution or null
      */
     private fun getNextExecution(): BenchmarkExecution? {
-        val comparator = ExecutionStateComparator(States.RESTART)
+        val comparator = ExecutionStateComparator(ExecutionStates.RESTART)
         val availableBenchmarkNames = getBenchmarks()
+            .filter { it.status.resourceSetsState == BenchmarkStates.READY.value }
+            .map { it.spec }
             .map { it.name }
 
         return executionCRDClient
@@ -147,8 +164,8 @@ class TheodoliteController(
             .asSequence()
             .map { it.spec.name = it.metadata.name; it }
             .filter {
-                it.status.executionState == States.PENDING.value ||
-                        it.status.executionState == States.RESTART.value
+                it.status.executionState == ExecutionStates.PENDING.value ||
+                        it.status.executionState == ExecutionStates.RESTART.value
             }
             .filter { availableBenchmarkNames.contains(it.spec.benchmark) }
             .sortedWith(comparator.thenBy { it.metadata.creationTimestamp })
@@ -156,6 +173,35 @@ class TheodoliteController(
             .firstOrNull()
     }
 
+    private fun updateBenchmarkStatus() {
+        this.benchmarkCRDClient
+            .list()
+            .items
+            .map { it.spec.name = it.metadata.name; it }
+            .map { Pair(it, checkResource(it.spec)) }
+            .forEach { setState(it.first, it.second ) }
+    }
+
+    private fun setState(resource: BenchmarkCRD, state: BenchmarkStates) {
+        benchmarkStateHandler.setResourceSetState(resource.spec.name, state)
+    }
+
+    private fun checkResource(benchmark: KubernetesBenchmark): BenchmarkStates {
+        return try {
+            val appResources =
+                benchmark.loadKubernetesResources(resourceSet = benchmark.sut.resources)
+            val loadGenResources =
+                benchmark.loadKubernetesResources(resourceSet = benchmark.sut.resources)
+            if(appResources.isNotEmpty() && loadGenResources.isNotEmpty()) {
+                BenchmarkStates.READY
+            } else {
+                BenchmarkStates.PENDING
+            }
+        } catch (e: Exception) {
+            BenchmarkStates.PENDING
+        }
+    }
+
     fun isExecutionRunning(executionName: String): Boolean {
         if (!::executor.isInitialized) return false
         return this.executor.getExecution().name == executionName
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt
index 2aaba77c03884d94c4d5745db270e84324482878..4850a44fdddba117178e29d3170f44a95df646e7 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt
@@ -11,6 +11,7 @@ import theodolite.model.crd.BenchmarkCRD
 import theodolite.model.crd.BenchmarkExecutionList
 import theodolite.model.crd.ExecutionCRD
 import theodolite.model.crd.KubernetesBenchmarkList
+import theodolite.util.Configuration
 
 
 private const val DEFAULT_NAMESPACE = "default"
@@ -27,17 +28,18 @@ private val logger = KotlinLogging.logger {}
  * **See Also:** [Kubernetes Operator Pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/)
  */
 class TheodoliteOperator {
-    private val namespace = System.getenv("NAMESPACE") ?: DEFAULT_NAMESPACE
+    private val namespace = Configuration.NAMESPACE
 
     private val client: NamespacedKubernetesClient = DefaultKubernetesClient().inNamespace(namespace)
     private lateinit var controller: TheodoliteController
     private lateinit var executionStateHandler: ExecutionStateHandler
+    private lateinit var benchmarkStateHandler: BenchmarkStateHandler
 
 
     fun start() {
         LeaderElector(
             client = client,
-            name = "theodolite-operator" // TODO(make leaslock name configurable via env var)
+            name = Configuration.COMPONENT_NAME
         )
             .getLeadership(::startOperator)
     }
@@ -68,7 +70,9 @@ class TheodoliteOperator {
 
             controller = getController(
                 client = client,
-                executionStateHandler = getExecutionStateHandler(client = client)
+                executionStateHandler = getExecutionStateHandler(client = client),
+                benchmarkStateHandler = getBenchmarkStateHandler(client = client)
+
             )
             getExecutionEventHandler(controller, client).startAllRegisteredInformers()
             controller.run()
@@ -101,21 +105,30 @@ class TheodoliteOperator {
         return executionStateHandler
     }
 
+    fun getBenchmarkStateHandler(client: NamespacedKubernetesClient) : BenchmarkStateHandler {
+        if (!::benchmarkStateHandler.isInitialized) {
+            this.benchmarkStateHandler = BenchmarkStateHandler(client = client)
+        }
+        return benchmarkStateHandler
+    }
+
     fun getController(
         client: NamespacedKubernetesClient,
-        executionStateHandler: ExecutionStateHandler
+        executionStateHandler: ExecutionStateHandler,
+        benchmarkStateHandler: BenchmarkStateHandler
     ): TheodoliteController {
         if (!::controller.isInitialized) {
             this.controller = TheodoliteController(
                 benchmarkCRDClient = getBenchmarkClient(client),
                 executionCRDClient = getExecutionClient(client),
-                executionStateHandler = executionStateHandler
+                executionStateHandler = executionStateHandler,
+                benchmarkStateHandler = benchmarkStateHandler
             )
         }
         return this.controller
     }
 
-    private fun getExecutionClient(client: NamespacedKubernetesClient): MixedOperation<
+    fun getExecutionClient(client: NamespacedKubernetesClient): MixedOperation<
             ExecutionCRD,
             BenchmarkExecutionList,
             Resource<ExecutionCRD>> {
@@ -125,7 +138,7 @@ class TheodoliteOperator {
         )
     }
 
-    private fun getBenchmarkClient(client: NamespacedKubernetesClient): MixedOperation<
+    fun getBenchmarkClient(client: NamespacedKubernetesClient): MixedOperation<
             BenchmarkCRD,
             KubernetesBenchmarkList,
             Resource<BenchmarkCRD>> {
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/CustomResourceWrapper.kt b/theodolite/src/main/kotlin/theodolite/k8s/CustomResourceWrapper.kt
index ab355677ec53216072fb58a170610aa5f12dba28..797ed88389947d66aa626ba2ef3fdf6732f8369d 100644
--- a/theodolite/src/main/kotlin/theodolite/k8s/CustomResourceWrapper.kt
+++ b/theodolite/src/main/kotlin/theodolite/k8s/CustomResourceWrapper.kt
@@ -8,7 +8,7 @@ import mu.KotlinLogging
 private val logger = KotlinLogging.logger {}
 
 class CustomResourceWrapper(
-    private val crAsMap: Map<String, String>,
+    val crAsMap: Map<String, String>,
     private val context: CustomResourceDefinitionContext
 ) : KubernetesResource {
     /**
@@ -33,7 +33,7 @@ class CustomResourceWrapper(
             client.customResource(this.context)
                 .delete(client.configuration.namespace, this.getName())
         } catch (e: Exception) {
-            logger.warn { "Could not delete service monitor" }
+            logger.warn { "Could not delete custom resource" }
         }
     }
 
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/K8sResourceLoader.kt b/theodolite/src/main/kotlin/theodolite/k8s/K8sResourceLoader.kt
deleted file mode 100644
index faae5ade28deb579df6a463007cbdfbc9cc7706e..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/k8s/K8sResourceLoader.kt
+++ /dev/null
@@ -1,156 +0,0 @@
-package theodolite.k8s
-
-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.client.NamespacedKubernetesClient
-import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
-import mu.KotlinLogging
-import theodolite.util.YamlParser
-
-private val logger = KotlinLogging.logger {}
-
-/**
- * Used to load different Kubernetes resources.
- * Supports: Deployments, Services, ConfigMaps, and CustomResources.
- * @param client KubernetesClient used to deploy or remove.
- */
-class K8sResourceLoader(private val client: NamespacedKubernetesClient) {
-
-    /**
-     * Parses a Service from a service yaml
-     * @param path of the yaml file
-     * @return Service from fabric8
-     */
-    private fun loadService(path: String): Service {
-        return loadGenericResource(path) { client.services().load(it).get() }
-    }
-
-
-    /**
-     * Parses a CustomResource from a yaml
-     * @param path of the yaml file
-     * @param context specific crd context for this custom resource
-     * @return  CustomResourceWrapper from fabric8
-     */
-    private fun loadCustomResourceWrapper(
-        path: String,
-        context: CustomResourceDefinitionContext
-    ): CustomResourceWrapper {
-        return loadGenericResource(path) {
-            CustomResourceWrapper(
-                YamlParser().parse(
-                    path,
-                    HashMap<String, String>()::class.java
-                )!!,
-                context
-            )
-        }
-    }
-
-    private fun loadServiceMonitor(path: String): CustomResourceWrapper {
-        val context = K8sContextFactory().create(
-            api = "v1",
-            scope = "Namespaced",
-            group = "monitoring.coreos.com",
-            plural = "servicemonitors"
-        )
-        return loadCustomResourceWrapper(path, context)
-    }
-
-    private fun loadExecution(path: String): KubernetesResource {
-        val context = K8sContextFactory().create(
-            api = "v1",
-            scope = "Namespaced",
-            group = "theodolite.com",
-            plural = "executions"
-        )
-        return loadCustomResourceWrapper(path, context)
-    }
-
-    private fun loadBenchmark(path: String): KubernetesResource {
-        val context = K8sContextFactory().create(
-            api = "v1",
-            scope = "Namespaced",
-            group = "theodolite.com",
-            plural = "benchmarks"
-        )
-        return loadCustomResourceWrapper(path, context)
-    }
-
-
-    /**
-     * Parses a Deployment from a Deployment yaml
-     * @param path of the yaml file
-     * @return Deployment from fabric8
-     */
-    private fun loadDeployment(path: String): Deployment {
-        return loadGenericResource(path) { client.apps().deployments().load(it).get() }
-    }
-
-    /**
-     * Parses a ConfigMap from a ConfigMap yaml
-     * @param path of the yaml file
-     * @return ConfigMap from fabric8
-     */
-    private fun loadConfigmap(path: String): ConfigMap {
-        return loadGenericResource(path) { client.configMaps().load(it).get() }
-    }
-
-    /**
-     * Parses a StatefulSet from a StatefulSet yaml
-     * @param path of the yaml file
-     * @return StatefulSet from fabric8
-     */
-    private fun loadStatefulSet(path: String): KubernetesResource {
-        return loadGenericResource(path) { client.apps().statefulSets().load(it).get() }
-
-    }
-
-    /**
-     * Generic helper function to load a resource.
-     * @param path of the resource
-     * @param f function that is applied to the resource.
-     * @throws IllegalArgumentException If the resource could not be loaded.
-     */
-    private fun <T> loadGenericResource(path: String, f: (String) -> T): T {
-        var resource: T? = null
-
-        try {
-            resource = f(path)
-        } catch (e: Exception) {
-            logger.warn { "You potentially misspelled the path: $path" }
-            logger.warn { e }
-        }
-
-        if (resource == null) {
-            throw IllegalArgumentException("The Resource at path: $path could not be loaded")
-        }
-        return resource
-    }
-
-    /**
-     * Factory function used to load different k8s resources from a path.
-     * Supported kinds are: Deployments, Services, ServiceMonitors, ConfigMaps and CustomResources.
-     * Uses CustomResource as default if Kind is not supported.
-     * @param kind of the resource. CustomResource as default.
-     * @param path of the resource to be loaded.
-     * @throws Exception if the resource could not be loaded.
-     */
-    fun loadK8sResource(kind: String, path: String): KubernetesResource {
-        return when (kind) {
-            "Deployment" -> loadDeployment(path)
-            "Service" -> loadService(path)
-            "ServiceMonitor" -> loadServiceMonitor(path)
-            "ConfigMap" -> loadConfigmap(path)
-            "StatefulSet" -> loadStatefulSet(path)
-            "Execution" -> loadExecution(path)
-            "Benchmark" -> loadBenchmark(path)
-            else -> {
-                logger.error { "Error during loading of unspecified resource Kind" }
-                throw IllegalArgumentException("error while loading resource with kind: $kind")
-            }
-        }
-    }
-}
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/TopicManager.kt b/theodolite/src/main/kotlin/theodolite/k8s/TopicManager.kt
index 8e83883fc881db0f7e2b1b75b2fb7c7322a11a00..f2afd71f6e4b4cf8e7106a8fc8a9bd113d9f36e6 100644
--- a/theodolite/src/main/kotlin/theodolite/k8s/TopicManager.kt
+++ b/theodolite/src/main/kotlin/theodolite/k8s/TopicManager.kt
@@ -30,8 +30,7 @@ class TopicManager(private val kafkaConfig: Map<String, Any>) {
                 result = kafkaAdmin.createTopics(newTopics)
                 result.all().get() // wait for the future to be completed
             } catch (e: Exception) { // TopicExistsException
-                logger.warn(e) { "Error during topic creation." }
-                logger.debug { e } // TODO remove due to attached exception to warn log?
+                logger.warn { "Error during topic creation. Error is: ${e.message}" }
                 logger.info { "Remove existing topics." }
                 delete(newTopics.map { topic -> topic.name() }, kafkaAdmin)
                 logger.info { "Will retry the topic creation in ${RETRY_TIME / 1000} seconds." }
@@ -94,7 +93,7 @@ class TopicManager(private val kafkaConfig: Map<String, Any>) {
                     }"
                 }
             } catch (e: Exception) {
-                logger.error(e) { "Error while removing topics: $e" }
+                logger.error { "Error while removing topics: ${e.message}" }
                 logger.info { "Existing topics are: ${kafkaAdmin.listTopics().names().get()}." }
             }
 
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/AbstractK8sLoader.kt b/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/AbstractK8sLoader.kt
new file mode 100644
index 0000000000000000000000000000000000000000..862de14e2a7a4721e15215b0a1389e14f943fe24
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/AbstractK8sLoader.kt
@@ -0,0 +1,73 @@
+package theodolite.k8s.resourceLoader
+
+import io.fabric8.kubernetes.api.model.KubernetesResource
+import mu.KotlinLogging
+import theodolite.k8s.K8sContextFactory
+
+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())) {
+            "Deployment" -> loadDeployment(resourceString)
+            "Service" -> loadService(resourceString)
+            "ServiceMonitor" -> loadServiceMonitor(resourceString)
+            "ConfigMap" -> loadConfigmap(resourceString)
+            "StatefulSet" -> loadStatefulSet(resourceString)
+            "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")
+            }
+        }
+    }
+
+    fun <T> loadGenericResource(resourceString: String, f: (String) -> T): T {
+        var resource: T? = null
+
+        try {
+            resource = f(resourceString)
+        } catch (e: Exception) {
+            logger.warn { e }
+        }
+
+        if (resource == null) {
+            throw IllegalArgumentException("The Resource: $resourceString could not be loaded")
+        }
+        return resource
+    }
+
+
+
+    override fun loadServiceMonitor(resource: String): KubernetesResource {
+        val context = K8sContextFactory().create(
+            api = "v1",
+            scope = "Namespaced",
+            group = "monitoring.coreos.com",
+            plural = "servicemonitors"
+        )
+        return loadCustomResourceWrapper(resource, context)
+    }
+
+    override fun loadExecution(resource: String): KubernetesResource {
+        val context = K8sContextFactory().create(
+            api = "v1",
+            scope = "Namespaced",
+            group = "theodolite.com",
+            plural = "executions"
+        )
+        return loadCustomResourceWrapper(resource, context)
+    }
+
+    override fun loadBenchmark(resource: String): KubernetesResource {
+        val context = K8sContextFactory().create(
+            api = "v1",
+            scope = "Namespaced",
+            group = "theodolite.com",
+            plural = "benchmarks"
+        )
+        return loadCustomResourceWrapper(resource, context)
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoader.kt b/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoader.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c123ab2958132cb43ad188136f738b561e91310b
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoader.kt
@@ -0,0 +1,15 @@
+package theodolite.k8s.resourceLoader
+
+import io.fabric8.kubernetes.api.model.KubernetesResource
+import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
+
+interface K8sResourceLoader {
+    fun loadDeployment(resource: String): KubernetesResource
+    fun loadService(resource: String): KubernetesResource
+    fun loadStatefulSet(resource: String): KubernetesResource
+    fun loadExecution(resource: String): KubernetesResource
+    fun loadBenchmark(resource: String): KubernetesResource
+    fun loadConfigmap(resource: String): KubernetesResource
+    fun loadServiceMonitor(resource: String): KubernetesResource
+    fun loadCustomResourceWrapper(resource: String, context: CustomResourceDefinitionContext): KubernetesResource
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoaderFromFile.kt b/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoaderFromFile.kt
new file mode 100644
index 0000000000000000000000000000000000000000..08f34e1d67c9821c9f9a07a49f4ba8683a072611
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoaderFromFile.kt
@@ -0,0 +1,75 @@
+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.client.NamespacedKubernetesClient
+import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
+import theodolite.k8s.CustomResourceWrapper
+import theodolite.util.YamlParserFromFile
+
+/**
+ * Used to load different Kubernetes resources.
+ * Supports: Deployments, Services, ConfigMaps, and CustomResources.
+ * @param client KubernetesClient used to deploy or remove.
+ */
+class K8sResourceLoaderFromFile(private val client: NamespacedKubernetesClient): AbstractK8sLoader(),
+    K8sResourceLoader {
+
+    /**
+     * Parses a Service from a service yaml
+     * @param resource of the yaml file
+     * @return Service from fabric8
+     */
+    override fun loadService(resource: String): Service {
+        return loadGenericResource(resource) { x: String -> client.services().load(x).get() }
+    }
+
+
+    /**
+     * Parses a CustomResource from a yaml
+     * @param path of the yaml file
+     * @param context specific crd context for this custom resource
+     * @return  CustomResourceWrapper from fabric8
+     */
+    override fun loadCustomResourceWrapper(resource: String, context: CustomResourceDefinitionContext): CustomResourceWrapper {
+       return loadGenericResource(resource) {
+           CustomResourceWrapper(
+               YamlParserFromFile().parse(
+                   resource,
+                   HashMap<String, String>()::class.java
+               )!!,
+               context
+           )
+       }
+   }
+
+    /**
+     * Parses a Deployment from a Deployment yaml
+     * @param resource of the yaml file
+     * @return Deployment from fabric8
+     */
+    override fun loadDeployment(resource: String): Deployment {
+        return loadGenericResource(resource) { x: String -> client.apps().deployments().load(x).get() }
+    }
+
+    /**
+     * Parses a ConfigMap from a ConfigMap yaml
+     * @param resource of the yaml file
+     * @return ConfigMap from fabric8
+     */
+    override fun loadConfigmap(resource: String): ConfigMap {
+        return loadGenericResource(resource) { x: String -> client.configMaps().load(x).get() }
+    }
+
+    /**
+     * Parses a StatefulSet from a StatefulSet yaml
+     * @param resource of the yaml file
+     * @return StatefulSet from fabric8
+     */
+    override fun loadStatefulSet(resource: String): KubernetesResource {
+        return loadGenericResource(resource) { x: String -> client.apps().statefulSets().load(x).get() }
+
+    }
+}
diff --git a/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoaderFromString.kt b/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoaderFromString.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e9611aaa82870dfb676820029cf42c5aab63d672
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/k8s/resourceLoader/K8sResourceLoaderFromString.kt
@@ -0,0 +1,60 @@
+package theodolite.k8s.resourceLoader
+
+import io.fabric8.kubernetes.api.model.ConfigMap
+import io.fabric8.kubernetes.api.model.KubernetesResource
+import io.fabric8.kubernetes.api.model.apps.Deployment
+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
+
+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() }
+    }
+
+    @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() }
+    }
+
+    @OptIn(ExperimentalStdlibApi::class)
+    override fun loadConfigmap(resource: String): ConfigMap {
+        return loadGenericResource(resource) { x: String ->
+            val stream = ByteArrayInputStream(x.encodeToByteArray())
+            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() }
+    }
+
+    /**
+     * Parses a CustomResource from a yaml
+     * @param resource of the yaml file
+     * @param context specific crd context for this custom resource
+     * @return  CustomResourceWrapper from fabric8
+     */
+    override fun loadCustomResourceWrapper(resource: String, context: CustomResourceDefinitionContext): CustomResourceWrapper {
+        return loadGenericResource(resource) {
+            CustomResourceWrapper(
+                YamlParserFromString().parse(
+                    resource,
+                    HashMap<String, String>()::class.java
+                )!!,
+                context
+            )
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt b/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt
index 377708af7b7e1a50ae1e33064b2668c364e0685a..b6468fff523e57b124e144d5b9fef6477973655a 100644
--- a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt
+++ b/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt
@@ -14,5 +14,6 @@ import theodolite.benchmark.KubernetesBenchmark
 @Group("theodolite.com")
 @Kind("benchmark")
 class BenchmarkCRD(
-    var spec: KubernetesBenchmark = KubernetesBenchmark()
-) : CustomResource<KubernetesBenchmark, Void>(), Namespaced, HasMetadata
\ No newline at end of file
+    var spec: KubernetesBenchmark = KubernetesBenchmark(),
+    var status: BenchmarkStatus = BenchmarkStatus()
+) : CustomResource<KubernetesBenchmark, BenchmarkStatus>(), Namespaced, HasMetadata
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkStates.kt b/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkStates.kt
new file mode 100644
index 0000000000000000000000000000000000000000..f52f2c168765ebb8bcc4f390795aa470b968021b
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkStates.kt
@@ -0,0 +1,6 @@
+package theodolite.model.crd
+
+enum class BenchmarkStates(val value: String) {
+    PENDING("Pending"),
+    READY("Ready")
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkStatus.kt b/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkStatus.kt
new file mode 100644
index 0000000000000000000000000000000000000000..f51cb7a76d015d6ecd900279e68d41baa26e876a
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkStatus.kt
@@ -0,0 +1,11 @@
+package theodolite.model.crd
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize
+import io.fabric8.kubernetes.api.model.KubernetesResource
+import io.fabric8.kubernetes.api.model.Namespaced
+
+@JsonDeserialize
+class BenchmarkStatus: KubernetesResource, Namespaced {
+    var resourceSetsState = "-"
+
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStates.kt b/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStates.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ad68bf380b18af1a654c201817bb7fc982804c8b
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStates.kt
@@ -0,0 +1,12 @@
+package theodolite.model.crd
+
+enum class ExecutionStates(val value: String) {
+    // Execution states
+    RUNNING("Running"),
+    PENDING("Pending"),
+    FAILURE("Failure"),
+    FINISHED("Finished"),
+    RESTART("Restart"),
+    INTERRUPTED("Interrupted"),
+    NO_STATE("NoState"),
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/States.kt b/theodolite/src/main/kotlin/theodolite/model/crd/States.kt
deleted file mode 100644
index 79af297915b6703b209acb0c13913482e54db2be..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/model/crd/States.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package theodolite.model.crd
-
-enum class States(val value: String) {
-    RUNNING("RUNNING"),
-    PENDING("PENDING"),
-    FAILURE("FAILURE"),
-    FINISHED("FINISHED"),
-    RESTART("RESTART"),
-    INTERRUPTED("INTERRUPTED"),
-    NO_STATE("NoState")
-}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/patcher/PatcherFactory.kt b/theodolite/src/main/kotlin/theodolite/patcher/PatcherFactory.kt
index cdf115a0755e8794075884bf952db3b8d76f1f50..ebad5de74a6b819dbf7887dfad91faac37ed5074 100644
--- a/theodolite/src/main/kotlin/theodolite/patcher/PatcherFactory.kt
+++ b/theodolite/src/main/kotlin/theodolite/patcher/PatcherFactory.kt
@@ -26,7 +26,7 @@ class PatcherFactory {
      */
     fun createPatcher(
         patcherDefinition: PatcherDefinition,
-        k8sResources: List<Pair<String, KubernetesResource>>
+        k8sResources: Collection<Pair<String, KubernetesResource>>
     ): Patcher {
         val resource =
             k8sResources.filter { it.first == patcherDefinition.resource }
diff --git a/theodolite/src/main/kotlin/theodolite/util/Configuration.kt b/theodolite/src/main/kotlin/theodolite/util/Configuration.kt
new file mode 100644
index 0000000000000000000000000000000000000000..dac3b943e69bd7e208d318f2a788275f19db11e4
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/util/Configuration.kt
@@ -0,0 +1,18 @@
+package theodolite.util
+
+import theodolite.execution.ExecutionModes
+
+// Defaults
+private const val DEFAULT_NAMESPACE = "default"
+private const val DEFAULT_COMPONENT_NAME = "theodolite-operator"
+
+
+class Configuration(
+) {
+    companion object {
+        val NAMESPACE = System.getenv("NAMESPACE") ?: DEFAULT_NAMESPACE
+        val COMPONENT_NAME = System.getenv("COMPONENT_NAME") ?: DEFAULT_COMPONENT_NAME
+        val EXECUTION_MODE = System.getenv("MODE") ?: ExecutionModes.STANDALONE.value
+    }
+
+}
diff --git a/theodolite/src/main/kotlin/theodolite/util/DeploymentFailedException.kt b/theodolite/src/main/kotlin/theodolite/util/DeploymentFailedException.kt
index 639a7c86c641cbdcba361410cf5e25fa56dd795f..9f4caedf3db1e09dca7924bf0035c6ace0b835d7 100644
--- a/theodolite/src/main/kotlin/theodolite/util/DeploymentFailedException.kt
+++ b/theodolite/src/main/kotlin/theodolite/util/DeploymentFailedException.kt
@@ -1,4 +1,4 @@
 package theodolite.util
 
 
-class DeploymentFailedException(message: String) : Exception(message)
\ No newline at end of file
+open class DeploymentFailedException(message: String, e: Exception? = null) : TheodoliteException(message,e)
diff --git a/theodolite/src/main/kotlin/theodolite/util/EvaluationFailedException.kt b/theodolite/src/main/kotlin/theodolite/util/EvaluationFailedException.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c67ed7ffd79afc733a97dae05c3203f8e78722ea
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/util/EvaluationFailedException.kt
@@ -0,0 +1,4 @@
+package theodolite.util
+
+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
new file mode 100644
index 0000000000000000000000000000000000000000..6566a451a3e273214f59962531b6bd17b33a850d
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/util/ExecutionFailedException.kt
@@ -0,0 +1,4 @@
+package theodolite.util
+
+open class ExecutionFailedException(message: String, e: Exception? = null) : TheodoliteException(message,e) {
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/util/ExecutionStateComparator.kt b/theodolite/src/main/kotlin/theodolite/util/ExecutionStateComparator.kt
index 66ebe12d6505296682744c10c69f182f07d1a16e..8a6b0e9a49362afa401cf3c1279e7f7f6cddf85d 100644
--- a/theodolite/src/main/kotlin/theodolite/util/ExecutionStateComparator.kt
+++ b/theodolite/src/main/kotlin/theodolite/util/ExecutionStateComparator.kt
@@ -1,13 +1,13 @@
 package theodolite.util
 
 import theodolite.model.crd.ExecutionCRD
-import theodolite.model.crd.States
+import theodolite.model.crd.ExecutionStates
 
-class ExecutionStateComparator(private val preferredState: States): Comparator<ExecutionCRD> {
+class ExecutionStateComparator(private val preferredState: ExecutionStates): Comparator<ExecutionCRD> {
 
     /**
      * Simple comparator which can be used to order a list of [ExecutionCRD] such that executions with
-     * status [States.RESTART] are before all other executions.
+     * status [ExecutionStates.RESTART] are before all other executions.
      */
     override fun compare(p0: ExecutionCRD, p1: ExecutionCRD): Int {
        return when {
diff --git a/theodolite/src/main/kotlin/theodolite/util/InvalidPatcherConfigurationException.kt b/theodolite/src/main/kotlin/theodolite/util/InvalidPatcherConfigurationException.kt
index 81ea227d0d9871c2420a414d81749a34b97676b8..d02948ad341207051c4653ba9400ac0ffe5b03aa 100644
--- a/theodolite/src/main/kotlin/theodolite/util/InvalidPatcherConfigurationException.kt
+++ b/theodolite/src/main/kotlin/theodolite/util/InvalidPatcherConfigurationException.kt
@@ -1,4 +1,3 @@
 package theodolite.util
 
-class InvalidPatcherConfigurationException(message: String, e: Exception? = null) : Exception(message, e)
-
+class InvalidPatcherConfigurationException(message: String, e: Exception? = null) : DeploymentFailedException(message,e)
diff --git a/theodolite/src/main/kotlin/theodolite/util/PrometheusResponse.kt b/theodolite/src/main/kotlin/theodolite/util/PrometheusResponse.kt
index bf33fcf6104645727a13b92cf3a13d36e04a10c6..9b0b0dd4e0a5a48072ca576e874cb850c5f8df3b 100644
--- a/theodolite/src/main/kotlin/theodolite/util/PrometheusResponse.kt
+++ b/theodolite/src/main/kotlin/theodolite/util/PrometheusResponse.kt
@@ -23,7 +23,7 @@ data class PrometheusResponse(
      * The format of the returned list is: `[[ group, timestamp, value ], [ group, timestamp, value ], ... ]`
      */
     fun getResultAsList(): List<List<String>> {
-        val group = data?.result?.get(0)?.metric?.group.toString()
+        val group = data?.result?.get(0)?.metric?.toString()!!
         val values = data?.result?.get(0)?.values
         val result = mutableListOf<List<String>>()
 
@@ -64,18 +64,9 @@ data class PromResult(
     /**
      * Label of the metric
      */
-    var metric: PromMetric? = null,
+    var metric: Map<String, String>? = null,
     /**
      *  Values of the metric (e.g. [ [ <unix_time>, "<sample_value>" ], ... ])
      */
     var values: List<Any>? = null
-)
-
-/**
- * Corresponds to the metric field in the range-vector result format of a Prometheus range-query response.
- */
-@RegisterForReflection
-data class PromMetric(
-    var group: String? = null
-)
-
+)
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/util/TheodoliteException.kt b/theodolite/src/main/kotlin/theodolite/util/TheodoliteException.kt
new file mode 100644
index 0000000000000000000000000000000000000000..fc7453bae6aaa4c5c526eee72c006562ea887eb5
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/util/TheodoliteException.kt
@@ -0,0 +1,3 @@
+package theodolite.util
+
+open class TheodoliteException (message: String, e: Exception? = null) : Exception(message,e)
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/util/YamlParser.kt b/theodolite/src/main/kotlin/theodolite/util/YamlParserFromFile.kt
similarity index 92%
rename from theodolite/src/main/kotlin/theodolite/util/YamlParser.kt
rename to theodolite/src/main/kotlin/theodolite/util/YamlParserFromFile.kt
index ce69894e4145372aef07286ae315d11631a4df3f..ae36349e628621bb7ad287d8cf557fbefa3ff5c5 100644
--- a/theodolite/src/main/kotlin/theodolite/util/YamlParser.kt
+++ b/theodolite/src/main/kotlin/theodolite/util/YamlParserFromFile.kt
@@ -9,7 +9,7 @@ import java.io.InputStream
 /**
  * The YamlParser parses a YAML file
  */
-class YamlParser : Parser {
+class YamlParserFromFile : Parser {
     override fun <T> parse(path: String, E: Class<T>): T? {
         val input: InputStream = FileInputStream(File(path))
         val parser = Yaml(Constructor(E))
diff --git a/theodolite/src/main/kotlin/theodolite/util/YamlParserFromString.kt b/theodolite/src/main/kotlin/theodolite/util/YamlParserFromString.kt
new file mode 100644
index 0000000000000000000000000000000000000000..61db189ee99fa5fe36113b0fdecf589ad1114852
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/util/YamlParserFromString.kt
@@ -0,0 +1,17 @@
+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
+ */
+class YamlParserFromString : Parser {
+    override fun <T> parse(fileString: String, E: Class<T>): T? {
+        val parser = Yaml(Constructor(E))
+        return parser.loadAs(fileString, E)
+    }
+}
diff --git a/theodolite/src/test/kotlin/theodolite/CompositeStrategyTest.kt b/theodolite/src/test/kotlin/theodolite/CompositeStrategyTest.kt
index 49131352cfe517a382ddd7aa1be09d3fbe317466..580d9e747bde687a91ffb1bce2e7c9dfb6f166a2 100644
--- a/theodolite/src/test/kotlin/theodolite/CompositeStrategyTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/CompositeStrategyTest.kt
@@ -31,7 +31,7 @@ class CompositeStrategyTest {
         val results = Results()
         val benchmark = TestBenchmark()
         val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo()
-        val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, sloChecker, 0, 0, 5)
+        val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 5)
         val linearSearch = LinearSearch(benchmarkExecutor)
         val lowerBoundRestriction = LowerBoundRestriction(results)
         val strategy =
@@ -65,7 +65,7 @@ class CompositeStrategyTest {
         val benchmark = TestBenchmark()
         val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo()
         val benchmarkExecutorImpl =
-            TestBenchmarkExecutorImpl(mockResults, benchmark, results, sloChecker, 0, 0, 0)
+            TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 0)
         val binarySearch = BinarySearch(benchmarkExecutorImpl)
         val lowerBoundRestriction = LowerBoundRestriction(results)
         val strategy =
@@ -98,7 +98,7 @@ class CompositeStrategyTest {
         val results = Results()
         val benchmark = TestBenchmark()
         val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo()
-        val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, sloChecker, 0, 0, 0)
+        val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 0)
         val binarySearch = BinarySearch(benchmarkExecutor)
         val lowerBoundRestriction = LowerBoundRestriction(results)
         val strategy =
diff --git a/theodolite/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt b/theodolite/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt
index e88192dd7fe4393494a4fb76bd74d1123bd75f1d..46758583172c3fcd6417e17ff5bab85f8659734b 100644
--- a/theodolite/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt
@@ -5,7 +5,7 @@ import io.fabric8.kubernetes.client.DefaultKubernetesClient
 import io.quarkus.test.junit.QuarkusTest
 import io.smallrye.common.constraint.Assert.assertTrue
 import org.junit.jupiter.api.Test
-import theodolite.k8s.K8sResourceLoader
+import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
 import theodolite.patcher.PatcherFactory
 import theodolite.util.PatcherDefinition
 
@@ -22,7 +22,7 @@ import theodolite.util.PatcherDefinition
 @QuarkusTest
 class ResourceLimitPatcherTest {
     val testPath = "./src/test/resources/"
-    val loader = K8sResourceLoader(DefaultKubernetesClient().inNamespace(""))
+    val loader = K8sResourceLoaderFromFile(DefaultKubernetesClient().inNamespace(""))
     val patcherFactory = PatcherFactory()
 
     fun applyTest(fileName: String) {
diff --git a/theodolite/src/test/kotlin/theodolite/ResourceRequestPatcherTest.kt b/theodolite/src/test/kotlin/theodolite/ResourceRequestPatcherTest.kt
index 2af6c632567bf47e150a74808ab009bd0bc0598a..8794d4dc2d67b8af78f4fa409c727f882922d0b8 100644
--- a/theodolite/src/test/kotlin/theodolite/ResourceRequestPatcherTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/ResourceRequestPatcherTest.kt
@@ -5,7 +5,7 @@ import io.fabric8.kubernetes.client.DefaultKubernetesClient
 import io.quarkus.test.junit.QuarkusTest
 import io.smallrye.common.constraint.Assert.assertTrue
 import org.junit.jupiter.api.Test
-import theodolite.k8s.K8sResourceLoader
+import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
 import theodolite.patcher.PatcherFactory
 import theodolite.util.PatcherDefinition
 
@@ -22,7 +22,7 @@ import theodolite.util.PatcherDefinition
 @QuarkusTest
 class ResourceRequestPatcherTest {
     val testPath = "./src/test/resources/"
-    val loader = K8sResourceLoader(DefaultKubernetesClient().inNamespace(""))
+    val loader = K8sResourceLoaderFromFile(DefaultKubernetesClient().inNamespace(""))
     val patcherFactory = PatcherFactory()
 
     fun applyTest(fileName: String) {
diff --git a/theodolite/src/test/kotlin/theodolite/TestBenchmark.kt b/theodolite/src/test/kotlin/theodolite/TestBenchmark.kt
index 913a27a1b1c1412aa0a58baf9e11fafb1c7f4bd2..b08c1a18a3013e1573e4892f01698b5e509f9609 100644
--- a/theodolite/src/test/kotlin/theodolite/TestBenchmark.kt
+++ b/theodolite/src/test/kotlin/theodolite/TestBenchmark.kt
@@ -8,6 +8,12 @@ import theodolite.util.Resource
 
 class TestBenchmark : Benchmark {
 
+    override fun setupInfrastructure() {
+    }
+
+    override fun teardownInfrastructure() {
+    }
+
     override fun buildDeployment(
         load: LoadDimension,
         res: Resource,
diff --git a/theodolite/src/test/kotlin/theodolite/TestBenchmarkExecutorImpl.kt b/theodolite/src/test/kotlin/theodolite/TestBenchmarkExecutorImpl.kt
index cbd2d5926d61b0bfd4de6fab0c14422ddf88f190..2efddc48cb93a0870d1716c58a7018145c16e2ff 100644
--- a/theodolite/src/test/kotlin/theodolite/TestBenchmarkExecutorImpl.kt
+++ b/theodolite/src/test/kotlin/theodolite/TestBenchmarkExecutorImpl.kt
@@ -12,7 +12,7 @@ class TestBenchmarkExecutorImpl(
     private val mockResults: Array<Array<Boolean>>,
     benchmark: Benchmark,
     results: Results,
-    slo: BenchmarkExecution.Slo,
+    slo: List<BenchmarkExecution.Slo>,
     executionId: Int,
     loadGenerationDelay: Long,
     afterTeardownDelay: Long
@@ -22,11 +22,12 @@ class TestBenchmarkExecutorImpl(
         results,
         executionDuration = Duration.ofSeconds(1),
         configurationOverrides = emptyList(),
-        slo = slo,
+        slos = slo,
         repetitions = 1,
         executionId = executionId,
         loadGenerationDelay = loadGenerationDelay,
-        afterTeardownDelay = afterTeardownDelay
+        afterTeardownDelay = afterTeardownDelay,
+        executionName = "test-execution"
     ) {
 
     override fun runExperiment(load: LoadDimension, res: Resource): Boolean {
diff --git a/theodolite/src/test/kotlin/theodolite/benchmark/ConfigMapResourceSetTest.kt b/theodolite/src/test/kotlin/theodolite/benchmark/ConfigMapResourceSetTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..2cc8f931418e28ae8841b592f93df8d88440cf3c
--- /dev/null
+++ b/theodolite/src/test/kotlin/theodolite/benchmark/ConfigMapResourceSetTest.kt
@@ -0,0 +1,226 @@
+package theodolite.benchmark
+
+import com.google.gson.Gson
+import io.fabric8.kubernetes.api.model.*
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder
+import io.fabric8.kubernetes.api.model.apps.StatefulSet
+import io.fabric8.kubernetes.api.model.apps.StatefulSetBuilder
+import io.fabric8.kubernetes.client.server.mock.KubernetesServer
+import io.quarkus.test.junit.QuarkusTest
+import io.smallrye.common.constraint.Assert.assertTrue
+import junit.framework.Assert.assertEquals
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import theodolite.k8s.CustomResourceWrapper
+import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
+import theodolite.util.DeploymentFailedException
+
+private val testResourcePath = "./src/test/resources/k8s-resource-files/"
+
+@QuarkusTest
+class ConfigMapResourceSetTest {
+    private val server = KubernetesServer(false, true)
+
+    @BeforeEach
+    fun setUp() {
+        server.before()
+    }
+
+    @AfterEach
+    fun tearDown() {
+        server.after()
+    }
+
+    fun deployAndGetResource(resource: String): Collection<Pair<String, KubernetesResource>> {
+        val configMap1 = ConfigMapBuilder()
+            .withNewMetadata().withName("test-configmap").endMetadata()
+            .addToData("test-resource.yaml",resource)
+            .build()
+
+        server.client.configMaps().createOrReplace(configMap1)
+
+        val resourceSet = ConfigMapResourceSet()
+        resourceSet.name = "test-configmap"
+
+        return resourceSet.getResourceSet(server.client)
+    }
+
+
+    @Test
+    fun testLoadDeployment() {
+        val resourceBuilder = DeploymentBuilder()
+        resourceBuilder.withNewSpec().endSpec()
+        resourceBuilder.withNewMetadata().endMetadata()
+        val resource = resourceBuilder.build()
+        resource.metadata.name = "test-deployment"
+
+        val createdResource = deployAndGetResource(resource = Gson().toJson(resource))
+        assertEquals(1, createdResource.size)
+        assertTrue(createdResource.toMutableSet().first().second is Deployment)
+        assertTrue(createdResource.toMutableSet().first().second.toString().contains(other = resource.metadata.name))
+    }
+
+    @Test
+    fun testLoadStateFulSet() {
+        val resourceBuilder = StatefulSetBuilder()
+        resourceBuilder.withNewSpec().endSpec()
+        resourceBuilder.withNewMetadata().endMetadata()
+        val resource = resourceBuilder.build()
+        resource.metadata.name = "test-resource"
+
+        val createdResource = deployAndGetResource(resource = Gson().toJson(resource))
+        assertEquals(1, createdResource.size)
+        assertTrue(createdResource.toMutableSet().first().second is StatefulSet)
+        assertTrue(createdResource.toMutableSet().first().second.toString().contains(other = resource.metadata.name))
+    }
+
+    @Test
+    fun testLoadService() {
+        val resourceBuilder = ServiceBuilder()
+        resourceBuilder.withNewSpec().endSpec()
+        resourceBuilder.withNewMetadata().endMetadata()
+        val resource = resourceBuilder.build()
+        resource.metadata.name = "test-resource"
+
+        val createdResource = deployAndGetResource(resource = Gson().toJson(resource))
+        assertEquals(1, createdResource.size)
+        assertTrue(createdResource.toMutableSet().first().second is Service)
+        assertTrue(createdResource.toMutableSet().first().second.toString().contains(other = resource.metadata.name))
+    }
+
+    @Test
+    fun testLoadConfigMap() {
+        val resourceBuilder = ConfigMapBuilder()
+        resourceBuilder.withNewMetadata().endMetadata()
+        val resource = resourceBuilder.build()
+        resource.metadata.name = "test-resource"
+
+        val createdResource = deployAndGetResource(resource = Gson().toJson(resource))
+        assertEquals(1, createdResource.size)
+        assertTrue(createdResource.toMutableSet().first().second is ConfigMap)
+        assertTrue(createdResource.toMutableSet().first().second.toString().contains(other = resource.metadata.name))
+    }
+
+    @Test
+    fun testLoadExecution() {
+        val loader = K8sResourceLoaderFromFile(server.client)
+        val resource = loader.loadK8sResource("Execution", testResourcePath + "test-execution.yaml") as CustomResourceWrapper
+        val createdResource = deployAndGetResource(resource = Gson().toJson(resource.crAsMap))
+
+        assertEquals(1, createdResource.size)
+        assertTrue(createdResource.toMutableSet().first().second is CustomResourceWrapper)
+
+        val loadedResource = createdResource.toMutableSet().first().second
+        if (loadedResource is CustomResourceWrapper){
+            assertTrue(loadedResource.getName() == "example-execution")
+        }
+    }
+
+    @Test
+    fun testLoadBenchmark() {
+        val loader = K8sResourceLoaderFromFile(server.client)
+        val resource = loader.loadK8sResource("Benchmark", testResourcePath + "test-benchmark.yaml") as CustomResourceWrapper
+        val createdResource = deployAndGetResource(resource = Gson().toJson(resource.crAsMap))
+
+        assertEquals(1, createdResource.size)
+        assertTrue(createdResource.toMutableSet().first().second is CustomResourceWrapper)
+
+        val loadedResource = createdResource.toMutableSet().first().second
+        if (loadedResource is CustomResourceWrapper){
+            assertTrue(loadedResource.getName() == "example-benchmark")
+        }
+    }
+
+    @Test
+    fun testLoadServiceMonitor() {
+        val loader = K8sResourceLoaderFromFile(server.client)
+        val resource = loader.loadK8sResource("ServiceMonitor", testResourcePath + "test-service-monitor.yaml") as CustomResourceWrapper
+        val createdResource = deployAndGetResource(resource = Gson().toJson(resource.crAsMap))
+
+        assertEquals(1, createdResource.size)
+        assertTrue(createdResource.toMutableSet().first().second is CustomResourceWrapper)
+
+        val loadedResource = createdResource.toMutableSet().first().second
+        if (loadedResource is CustomResourceWrapper){
+            assertTrue(loadedResource.getName() == "test-service-monitor")
+        }
+    }
+
+    @Test
+    fun testMultipleFiles(){
+        val resourceBuilder = DeploymentBuilder()
+        resourceBuilder.withNewSpec().endSpec()
+        resourceBuilder.withNewMetadata().endMetadata()
+        val resource = resourceBuilder.build()
+        resource.metadata.name = "test-deployment"
+
+        val resourceBuilder1 = ConfigMapBuilder()
+        resourceBuilder1.withNewMetadata().endMetadata()
+        val resource1 = resourceBuilder1.build()
+        resource1.metadata.name = "test-configmap"
+
+        val configMap1 = ConfigMapBuilder()
+            .withNewMetadata().withName("test-configmap").endMetadata()
+            .addToData("test-deployment.yaml",Gson().toJson(resource))
+            .addToData("test-configmap.yaml",Gson().toJson(resource1))
+            .build()
+
+        server.client.configMaps().createOrReplace(configMap1)
+
+        val resourceSet = ConfigMapResourceSet()
+        resourceSet.name = "test-configmap"
+
+        val createdResourcesSet = resourceSet.getResourceSet(server.client)
+
+        assertEquals(2,createdResourcesSet.size )
+        assert(createdResourcesSet.toMutableList()[0].second is Deployment)
+        assert(createdResourcesSet.toMutableList()[1].second is ConfigMap)
+    }
+
+    @Test
+    fun testFileIsSet(){
+        val resourceBuilder = DeploymentBuilder()
+        resourceBuilder.withNewSpec().endSpec()
+        resourceBuilder.withNewMetadata().endMetadata()
+        val resource = resourceBuilder.build()
+        resource.metadata.name = "test-deployment"
+
+        val resourceBuilder1 = ConfigMapBuilder()
+        resourceBuilder1.withNewMetadata().endMetadata()
+        val resource1 = resourceBuilder1.build()
+        resource1.metadata.name = "test-configmap"
+
+        val configMap1 = ConfigMapBuilder()
+            .withNewMetadata().withName("test-configmap").endMetadata()
+            .addToData("test-deployment.yaml",Gson().toJson(resource))
+            .addToData("test-configmap.yaml",Gson().toJson(resource1))
+            .build()
+
+        server.client.configMaps().createOrReplace(configMap1)
+
+        val resourceSet = ConfigMapResourceSet()
+        resourceSet.name = "test-configmap"
+        resourceSet.files = listOf("test-deployment.yaml")
+
+        val createdResourcesSet = resourceSet.getResourceSet(server.client)
+
+        assertEquals(1,createdResourcesSet.size )
+        assert(createdResourcesSet.toMutableSet().first().second is Deployment)
+    }
+
+
+    @Test()
+    fun testConfigMapNotExist() {
+        val resourceSet = ConfigMapResourceSet()
+        resourceSet.name = "test-configmap1"
+        lateinit var ex: Exception
+        try {
+            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
new file mode 100644
index 0000000000000000000000000000000000000000..59ad2be3248f67442ce352788f8b94b26f3b6b90
--- /dev/null
+++ b/theodolite/src/test/kotlin/theodolite/benchmark/FileSystemResourceSetTest.kt
@@ -0,0 +1,115 @@
+package theodolite.benchmark
+
+import io.fabric8.kubernetes.api.model.ConfigMap
+import io.fabric8.kubernetes.api.model.Service
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.fabric8.kubernetes.api.model.apps.StatefulSet
+import io.fabric8.kubernetes.client.server.mock.KubernetesServer
+import io.smallrye.common.constraint.Assert.assertTrue
+import junit.framework.Assert.assertEquals
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import theodolite.k8s.CustomResourceWrapper
+import theodolite.util.DeploymentFailedException
+import java.lang.IllegalStateException
+
+private val testResourcePath = "./src/test/resources/k8s-resource-files/"
+
+class FileSystemResourceSetTest {
+
+    private val server = KubernetesServer(false, true)
+
+    @BeforeEach
+    fun setUp() {
+        server.before()
+    }
+
+    @AfterEach
+    fun tearDown() {
+        server.after()
+    }
+
+    @Test
+    fun testLoadDeployment() {
+        val resourceSet = FileSystemResourceSet()
+        resourceSet.path = testResourcePath
+        resourceSet.files = listOf("test-deployment.yaml")
+        assertEquals(1,resourceSet.getResourceSet(server.client).size)
+        assertTrue(resourceSet.getResourceSet(server.client).toMutableSet().first().second is Deployment)
+    }
+
+    @Test
+    fun testLoadService() {
+        val resourceSet = FileSystemResourceSet()
+        resourceSet.path = testResourcePath
+        resourceSet.files = listOf("test-service.yaml")
+        assertEquals(1,resourceSet.getResourceSet(server.client).size)
+        assertTrue(resourceSet.getResourceSet(server.client).toMutableSet().first().second is Service)
+    }
+
+    @Test
+    fun testLoadStatefulSet() {
+        val resourceSet = FileSystemResourceSet()
+        resourceSet.path = testResourcePath
+        resourceSet.files = listOf("test-statefulset.yaml")
+        assertEquals(1,resourceSet.getResourceSet(server.client).size)
+        assertTrue(resourceSet.getResourceSet(server.client).toMutableSet().first().second is StatefulSet)
+    }
+
+    @Test
+    fun testLoadConfigMap() {
+        val resourceSet = FileSystemResourceSet()
+        resourceSet.path = testResourcePath
+        resourceSet.files = listOf("test-configmap.yaml")
+        assertEquals(1,resourceSet.getResourceSet(server.client).size)
+        assertTrue(resourceSet.getResourceSet(server.client).toMutableSet().first().second is ConfigMap)
+    }
+
+    @Test
+    fun testLoadServiceMonitor() {
+        val resourceSet = FileSystemResourceSet()
+        resourceSet.path = testResourcePath
+        resourceSet.files = listOf("test-service-monitor.yaml")
+        assertEquals(1,resourceSet.getResourceSet(server.client).size)
+        assertTrue(resourceSet.getResourceSet(server.client).toMutableSet().first().second is CustomResourceWrapper)
+    }
+
+    @Test
+    fun testLoadBenchmark() {
+        val resourceSet = FileSystemResourceSet()
+        resourceSet.path = testResourcePath
+        resourceSet.files = listOf("test-benchmark.yaml")
+        assertEquals(1,resourceSet.getResourceSet(server.client).size)
+        assertTrue(resourceSet.getResourceSet(server.client).toMutableSet().first().second is CustomResourceWrapper)
+    }
+
+    @Test
+    fun testLoadExecution() {
+        val resourceSet = FileSystemResourceSet()
+        resourceSet.path = testResourcePath
+        resourceSet.files = listOf("test-execution.yaml")
+        assertEquals(1,resourceSet.getResourceSet(server.client).size)
+        assertTrue(resourceSet.getResourceSet(server.client).toMutableSet().first().second is CustomResourceWrapper)
+    }
+
+    @Test
+    fun testFilesNotSet() {
+        val resourceSet = FileSystemResourceSet()
+        resourceSet.path = testResourcePath
+        assertEquals(9,resourceSet.getResourceSet(server.client).size)
+    }
+
+    @Test
+    fun testWrongPath() {
+        val resourceSet = FileSystemResourceSet()
+        resourceSet.path = "/abc/not-exist"
+        lateinit var ex: Exception
+        try {
+            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 f3fd06a16e38439a2a694b415edc4d8b332ffd4d..e294ea539ea60104cc00e9f73de790302ad52670 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkCRDummy.kt
+++ b/theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkCRDummy.kt
@@ -1,6 +1,7 @@
 package theodolite.execution.operator
 
 import theodolite.benchmark.KubernetesBenchmark
+import theodolite.benchmark.Resources
 import theodolite.model.crd.BenchmarkCRD
 import theodolite.util.KafkaConfig
 
@@ -24,8 +25,15 @@ class BenchmarkCRDummy(name: String) {
         benchmarkCR.kind = "Benchmark"
         benchmarkCR.apiVersion = "v1"
 
-        benchmark.appResource = emptyList()
-        benchmark.loadGenResource = emptyList()
+
+        benchmark.infrastructure = Resources()
+        benchmark.sut = Resources()
+        benchmark.loadGenerator = Resources()
+
+        benchmark.infrastructure.resources = emptyList()
+        benchmark.sut.resources = emptyList()
+        benchmark.loadGenerator.resources = emptyList()
+
         benchmark.resourceTypes = emptyList()
         benchmark.loadTypes = emptyList()
         benchmark.kafkaConfig = kafkaConfig
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt b/theodolite/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt
index 7350f564a71e2f0cbf640b782f5dbf19cbdc7ecb..7e0532aff36cac2fb1a1c718415315b8f54052c2 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt
@@ -13,6 +13,7 @@ import org.junit.jupiter.api.Test
 import theodolite.benchmark.BenchmarkExecution
 import theodolite.benchmark.KubernetesBenchmark
 import theodolite.model.crd.BenchmarkCRD
+import theodolite.model.crd.BenchmarkStates
 import theodolite.model.crd.ExecutionCRD
 
 @QuarkusTest
@@ -33,11 +34,13 @@ class ControllerTest {
         server.before()
         this.controller = TheodoliteOperator().getController(
             client = server.client,
-            executionStateHandler = ExecutionStateHandler(server.client)
+            executionStateHandler = ExecutionStateHandler(server.client),
+            benchmarkStateHandler =  BenchmarkStateHandler(server.client)
         )
 
         // benchmark
         val benchmark1 = BenchmarkCRDummy(name = "Test-Benchmark")
+        benchmark1.getCR().status.resourceSetsState = BenchmarkStates.READY.value
         val benchmark2 = BenchmarkCRDummy(name = "Test-Benchmark-123")
         benchmarkResourceList.items = listOf(benchmark1.getCR(), benchmark2.getCR())
 
@@ -111,12 +114,12 @@ class ControllerTest {
             .getDeclaredMethod("getBenchmarks")
         method.isAccessible = true
 
-        val result = method.invoke(controller) as List<KubernetesBenchmark>
+        val result = method.invoke(controller) as List<BenchmarkCRD>
 
         assertEquals(2, result.size)
         assertEquals(
             gson.toJson(benchmark),
-            gson.toJson(result.firstOrNull())
+            gson.toJson(result.firstOrNull()?.spec)
         )
     }
 
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt
index 56d46279e8effe1f0b5bf307cd896ebd5b7eb2ee..51347d41b396bf375c14d5580b0f2619ce5b518c 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt
+++ b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt
@@ -3,7 +3,7 @@ package theodolite.execution.operator
 import theodolite.benchmark.BenchmarkExecution
 import theodolite.model.crd.ExecutionCRD
 import theodolite.model.crd.ExecutionStatus
-import theodolite.model.crd.States
+import theodolite.model.crd.ExecutionStates
 
 class ExecutionCRDummy(name: String, benchmark: String) {
 
@@ -51,6 +51,6 @@ class ExecutionCRDummy(name: String, benchmark: String) {
         execution.configOverrides = mutableListOf()
         execution.name = executionCR.metadata.name
 
-        executionState.executionState = States.PENDING.value
+        executionState.executionState = ExecutionStates.PENDING.value
     }
 }
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt
index 5598f48a2d291db4eab8563dd3325534f49b2eb6..d8db7ab3b64ce3856984ddbc279ef148aa325e73 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt
@@ -10,8 +10,8 @@ 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.K8sResourceLoader
-import theodolite.model.crd.States
+import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
+import theodolite.model.crd.ExecutionStates
 import java.lang.Thread.sleep
 
 
@@ -36,16 +36,17 @@ class ExecutionEventHandlerTest {
         val operator = TheodoliteOperator()
         this.controller = operator.getController(
             client = server.client,
-            executionStateHandler = ExecutionStateHandler(client = server.client)
+            executionStateHandler = ExecutionStateHandler(client = server.client),
+            benchmarkStateHandler = BenchmarkStateHandler(client = server.client)
         )
 
         this.factory = operator.getExecutionEventHandler(this.controller, server.client)
         this.stateHandler = TheodoliteOperator().getExecutionStateHandler(client = server.client)
 
-        this.executionVersion1 = K8sResourceLoader(server.client)
+        this.executionVersion1 = K8sResourceLoaderFromFile(server.client)
             .loadK8sResource("Execution", testResourcePath + "test-execution.yaml")
 
-        this.executionVersion2 = K8sResourceLoader(server.client)
+        this.executionVersion2 = K8sResourceLoaderFromFile(server.client)
             .loadK8sResource("Execution", testResourcePath + "test-execution-update.yaml")
 
         this.stateHandler = operator.getExecutionStateHandler(server.client)
@@ -81,7 +82,7 @@ class ExecutionEventHandlerTest {
         factory.startAllRegisteredInformers()
         sleep(500)
         assertEquals(
-            States.PENDING,
+            ExecutionStates.PENDING,
             stateHandler.getExecutionState(
                 resourceName = executionName
             )
@@ -95,12 +96,12 @@ class ExecutionEventHandlerTest {
         stateHandler
             .setExecutionState(
                 resourceName = executionName,
-                status = States.RUNNING
+                status = ExecutionStates.RUNNING
             )
         factory.startAllRegisteredInformers()
         sleep(500)
         assertEquals(
-            States.RESTART,
+            ExecutionStates.RESTART,
             stateHandler.getExecutionState(
                 resourceName = executionName
             )
@@ -116,7 +117,7 @@ class ExecutionEventHandlerTest {
         sleep(500)
 
         assertEquals(
-            States.PENDING,
+            ExecutionStates.PENDING,
             stateHandler.getExecutionState(
                 resourceName = executionName
             )
@@ -124,7 +125,7 @@ class ExecutionEventHandlerTest {
 
         manager.deploy(executionVersion2)
         assertEquals(
-            States.PENDING,
+            ExecutionStates.PENDING,
             stateHandler.getExecutionState(
                 resourceName = executionName
             )
@@ -140,14 +141,14 @@ class ExecutionEventHandlerTest {
 
         stateHandler.setExecutionState(
             resourceName = executionName,
-            status = States.FINISHED
+            status = ExecutionStates.FINISHED
         )
 
         manager.deploy(executionVersion2)
         sleep(500)
 
         assertEquals(
-            States.PENDING,
+            ExecutionStates.PENDING,
             stateHandler.getExecutionState(
                 resourceName = executionName
             )
@@ -163,14 +164,14 @@ class ExecutionEventHandlerTest {
 
         stateHandler.setExecutionState(
             resourceName = executionName,
-            status = States.FAILURE
+            status = ExecutionStates.FAILURE
         )
 
         manager.deploy(executionVersion2)
         sleep(500)
 
         assertEquals(
-            States.PENDING,
+            ExecutionStates.PENDING,
             stateHandler.getExecutionState(
                 resourceName = executionName
             )
@@ -187,14 +188,14 @@ class ExecutionEventHandlerTest {
 
         stateHandler.setExecutionState(
             resourceName = executionName,
-            status = States.RUNNING
+            status = ExecutionStates.RUNNING
         )
 
         manager.deploy(executionVersion2)
         sleep(500)
 
         assertEquals(
-            States.RESTART,
+            ExecutionStates.RESTART,
             stateHandler.getExecutionState(
                 resourceName = executionName
             )
@@ -210,14 +211,14 @@ class ExecutionEventHandlerTest {
 
         stateHandler.setExecutionState(
             resourceName = executionName,
-            status = States.RESTART
+            status = ExecutionStates.RESTART
         )
 
         manager.deploy(executionVersion2)
         sleep(500)
 
         assertEquals(
-            States.RESTART,
+            ExecutionStates.RESTART,
             stateHandler.getExecutionState(
                 resourceName = executionName
             )
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt b/theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt
index 24cb6c90d8ea222c90a398e12c7a50a2f6058a93..a54f4ed6db559f8f7f15ae82deecf3fedf8b4abe 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt
@@ -8,8 +8,8 @@ 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.K8sResourceLoader
-import theodolite.model.crd.States
+import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
+import theodolite.model.crd.ExecutionStates
 import java.time.Duration
 
 class StateHandlerTest {
@@ -19,7 +19,7 @@ class StateHandlerTest {
     @BeforeEach
     fun setUp() {
         server.before()
-        val executionResource = K8sResourceLoader(server.client)
+        val executionResource = K8sResourceLoaderFromFile(server.client)
             .loadK8sResource("Execution", testResourcePath + "test-execution.yaml")
 
         K8sManager(server.client).deploy(executionResource)
@@ -47,7 +47,7 @@ class StateHandlerTest {
     @DisplayName("Test empty execution state")
     fun executionWithoutExecutionStatusTest() {
         val handler = ExecutionStateHandler(client = server.client)
-        assertEquals(States.NO_STATE, handler.getExecutionState("example-execution"))
+        assertEquals(ExecutionStates.NO_STATE, handler.getExecutionState("example-execution"))
     }
 
     @Test
@@ -62,8 +62,8 @@ class StateHandlerTest {
     fun executionStatusTest() {
         val handler = ExecutionStateHandler(client = server.client)
 
-        assertTrue(handler.setExecutionState("example-execution", States.INTERRUPTED))
-        assertEquals(States.INTERRUPTED, handler.getExecutionState("example-execution"))
+        assertTrue(handler.setExecutionState("example-execution", ExecutionStates.INTERRUPTED))
+        assertEquals(ExecutionStates.INTERRUPTED, handler.getExecutionState("example-execution"))
     }
 
     @Test
diff --git a/theodolite/src/test/kotlin/theodolite/k8s/K8sManagerTest.kt b/theodolite/src/test/kotlin/theodolite/k8s/K8sManagerTest.kt
index dc2bf016994d79b1021bebdc751102e291d60682..7c69618de03f730f5b6f1cb83c5df544e2cd120c 100644
--- a/theodolite/src/test/kotlin/theodolite/k8s/K8sManagerTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/k8s/K8sManagerTest.kt
@@ -15,6 +15,7 @@ import org.junit.jupiter.api.Assertions.assertEquals
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.DisplayName
 import org.junit.jupiter.api.Test
+import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
 
 
 private val logger = KotlinLogging.logger {}
@@ -125,7 +126,7 @@ class K8sManagerTest {
     @DisplayName("Test handling of custom resources")
     fun handleCustomResourcesTest() {
         val manager = K8sManager(server.client)
-        val servicemonitor = K8sResourceLoader(server.client)
+        val servicemonitor = K8sResourceLoaderFromFile(server.client)
             .loadK8sResource("ServiceMonitor", testResourcePath + "test-service-monitor.yaml")
 
         val serviceMonitorContext = K8sContextFactory().create(
diff --git a/theodolite/src/test/kotlin/theodolite/k8s/K8sResourceLoaderTest.kt b/theodolite/src/test/kotlin/theodolite/k8s/K8sResourceLoaderTest.kt
index 7c2aa50007274ff9b4d49f1c0cc05ae45a37d323..4a41dac8b27b9d4ddcfb9915f759b14ea4eaba4a 100644
--- a/theodolite/src/test/kotlin/theodolite/k8s/K8sResourceLoaderTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/k8s/K8sResourceLoaderTest.kt
@@ -12,6 +12,7 @@ import org.junit.jupiter.api.Assertions.assertTrue
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.DisplayName
 import org.junit.jupiter.api.Test
+import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
 
 @QuarkusTest
 class K8sResourceLoaderTest {
@@ -31,7 +32,7 @@ class K8sResourceLoaderTest {
     @Test
     @DisplayName("Test loading of Deployments")
     fun loadDeploymentTest() {
-        val loader = K8sResourceLoader(server.client)
+        val loader = K8sResourceLoaderFromFile(server.client)
         val resource = loader.loadK8sResource("Deployment", testResourcePath + "test-deployment.yaml")
 
         assertTrue(resource is Deployment)
@@ -41,7 +42,7 @@ class K8sResourceLoaderTest {
     @Test
     @DisplayName("Test loading of StatefulSet")
     fun loadStatefulSetTest() {
-        val loader = K8sResourceLoader(server.client)
+        val loader = K8sResourceLoaderFromFile(server.client)
         val resource = loader.loadK8sResource("StatefulSet", testResourcePath + "test-statefulset.yaml")
 
         assertTrue(resource is StatefulSet)
@@ -51,7 +52,7 @@ class K8sResourceLoaderTest {
     @Test
     @DisplayName("Test loading of Service")
     fun loadServiceTest() {
-        val loader = K8sResourceLoader(server.client)
+        val loader = K8sResourceLoaderFromFile(server.client)
         val resource = loader.loadK8sResource("Service", testResourcePath + "test-service.yaml")
 
         assertTrue(resource is Service)
@@ -61,7 +62,7 @@ class K8sResourceLoaderTest {
     @Test
     @DisplayName("Test loading of ConfigMap")
     fun loadConfigMapTest() {
-        val loader = K8sResourceLoader(server.client)
+        val loader = K8sResourceLoaderFromFile(server.client)
         val resource = loader.loadK8sResource("ConfigMap", testResourcePath + "test-configmap.yaml")
 
         assertTrue(resource is ConfigMap)
@@ -71,7 +72,7 @@ class K8sResourceLoaderTest {
     @Test
     @DisplayName("Test loading of ServiceMonitors")
     fun loadServiceMonitorTest() {
-        val loader = K8sResourceLoader(server.client)
+        val loader = K8sResourceLoaderFromFile(server.client)
         val resource = loader.loadK8sResource("ServiceMonitor", testResourcePath + "test-service-monitor.yaml")
 
         assertTrue(resource is CustomResourceWrapper)
@@ -84,7 +85,7 @@ class K8sResourceLoaderTest {
     @Test
     @DisplayName("Test loading of Executions")
     fun loadExecutionTest() {
-        val loader = K8sResourceLoader(server.client)
+        val loader = K8sResourceLoaderFromFile(server.client)
         val resource = loader.loadK8sResource("Execution", testResourcePath + "test-execution.yaml")
 
         assertTrue(resource is CustomResourceWrapper)
@@ -97,7 +98,7 @@ class K8sResourceLoaderTest {
     @Test
     @DisplayName("Test loading of Benchmarks")
     fun loadBenchmarkTest() {
-        val loader = K8sResourceLoader(server.client)
+        val loader = K8sResourceLoaderFromFile(server.client)
         val resource = loader.loadK8sResource("Benchmark", testResourcePath + "test-benchmark.yaml")
 
         assertTrue(resource is CustomResourceWrapper)
diff --git a/theodolite/src/test/kotlin/theodolite/patcher/ConfigOverrideModifierTest.kt b/theodolite/src/test/kotlin/theodolite/patcher/ConfigOverrideModifierTest.kt
index 739fadd3f02bfd1e60fd67e7afc695bf99e68d31..1db1122e1caa5a783159ecaba849b99963e3c2a9 100644
--- a/theodolite/src/test/kotlin/theodolite/patcher/ConfigOverrideModifierTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/patcher/ConfigOverrideModifierTest.kt
@@ -27,11 +27,10 @@ class ConfigOverrideModifierTest {
 
     @Test
     fun setAdditionalLabelsTest() {
-        this.benchmark.appResource = listOf("test-resource.yaml")
 
         val modifier = ConfigOverrideModifier(
             execution = this.execution,
-            resources = this.benchmark.appResource
+            resources = listOf("test-resource.yaml")
         )
 
         modifier.setAdditionalLabels(
diff --git a/theodolite/src/test/kotlin/theodolite/util/ExecutionStateComparatorTest.kt b/theodolite/src/test/kotlin/theodolite/util/ExecutionStateComparatorTest.kt
index eec029f3878171eb2fd502bf68f549cfce793f23..7332e53f9e1814f28b8ff37a595b31b0eb931ea7 100644
--- a/theodolite/src/test/kotlin/theodolite/util/ExecutionStateComparatorTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/util/ExecutionStateComparatorTest.kt
@@ -1,14 +1,10 @@
 package theodolite.util
 
 import io.quarkus.test.junit.QuarkusTest
-import org.junit.Rule
-import org.junit.jupiter.api.Assertions
 import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
 import theodolite.execution.operator.ExecutionCRDummy
-import theodolite.model.crd.ExecutionCRD
-import theodolite.model.crd.States
+import theodolite.model.crd.ExecutionStates
 
 
 @QuarkusTest
@@ -16,11 +12,11 @@ class ExecutionStateComparatorTest {
 
     @Test
     fun testCompare() {
-        val comparator = ExecutionStateComparator(States.RESTART)
+        val comparator = ExecutionStateComparator(ExecutionStates.RESTART)
         val execution1 = ExecutionCRDummy("dummy1", "default-benchmark")
         val execution2 = ExecutionCRDummy("dummy2", "default-benchmark")
-        execution1.getStatus().executionState = States.RESTART.value
-        execution2.getStatus().executionState = States.PENDING.value
+        execution1.getStatus().executionState = ExecutionStates.RESTART.value
+        execution2.getStatus().executionState = ExecutionStates.PENDING.value
         val list = listOf(execution2.getCR(), execution1.getCR())
 
 
diff --git a/theodolite/src/test/resources/k8s-resource-files/test-execution-1.yaml b/theodolite/src/test/resources/k8s-resource-files/test-execution-1.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..1407a9952b7454053d204454841d51cfb4d7dbf4
--- /dev/null
+++ b/theodolite/src/test/resources/k8s-resource-files/test-execution-1.yaml
@@ -0,0 +1,28 @@
+apiVersion: theodolite.com/v1
+kind: Execution
+metadata:
+  name: example-execution
+spec:
+  name: test
+  benchmark: "uc1-kstreams"
+  load:
+    loadType: "NumSensors"
+    loadValues: [25000, 50000, 75000, 100000, 125000, 150000]
+  resources:
+    resourceType: "Instances"
+    resourceValues: [1, 2, 3, 4, 5]
+  slos:
+    - sloType: "lag trend"
+      threshold: 2000
+      prometheusUrl: "http://prometheus-operated:9090"
+      externalSloUrl: "http://localhost:80/evaluate-slope"
+      offset: 0
+      warmup: 60 # in seconds
+  execution:
+    strategy: "LinearSearch"
+    duration: 300 # in seconds
+    repetitions: 1
+    loadGenerationDelay: 30 # in seconds
+    restrictions:
+      - "LowerBound"
+  configOverrides: []