From 79c9b6f76894273db1c9c037ea780bd3b4a227c3 Mon Sep 17 00:00:00 2001
From: "stu126940@mail.uni-kiel.de" <stu126940@mail.uni-kiel.de>
Date: Mon, 7 Jun 2021 15:25:15 +0200
Subject: [PATCH] Use normal map type to configure patchers.

---
 .../templates/theodolite/crd-benchmark.yaml   | 24 +++---
 .../templates/theodolite/crd-execution.yaml   | 17 ++--
 .../example-benchmark-yaml-resource.yaml      | 11 +--
 .../example-execution-yaml-resource.yaml      | 20 ++---
 .../config/example-operator-benchmark.yaml    |  9 +-
 .../config/example-operator-execution.yaml    | 68 +++++++--------
 .../operator/TheodoliteController.kt          |  2 +-
 .../theodolite/patcher/PatcherFactory.kt      | 86 ++++++++++---------
 .../theodolite/util/PatcherDefinition.kt      | 20 +----
 .../main/resources/operator/benchmarkCRD.yaml | 30 +++----
 .../example-benchmark-k8s-resource.yaml       | 10 ++-
 .../main/resources/operator/executionCRD.yaml | 15 ++--
 12 files changed, 134 insertions(+), 178 deletions(-)

diff --git a/execution/helm/templates/theodolite/crd-benchmark.yaml b/execution/helm/templates/theodolite/crd-benchmark.yaml
index 848ecb372..319eee18c 100644
--- a/execution/helm/templates/theodolite/crd-benchmark.yaml
+++ b/execution/helm/templates/theodolite/crd-benchmark.yaml
@@ -55,12 +55,12 @@ spec:
                           resource:
                             type: string
                             default: ""
-                          container:
-                            type: string
-                            default: ""
-                          variableName:
-                            type: string
-                            default: ""
+                          config:
+                            type: object
+                            additionalProperties: true
+                            x-kubernetes-map-type: "granular"
+                            default: 
+                              "": ""
               loadTypes:
                 type: array
                 minItems: 1
@@ -81,12 +81,12 @@ spec:
                           resource:
                             type: string
                             default: ""
-                          container:
-                            type: string
-                            default: ""
-                          variableName:
-                            type: string
-                            default: ""
+                          config:
+                            type: object
+                            additionalProperties: true
+                            x-kubernetes-map-type: "granular"
+                            default: 
+                              "": ""
               kafkaConfig:
                 type: object
                 properties:
diff --git a/execution/helm/templates/theodolite/crd-execution.yaml b/execution/helm/templates/theodolite/crd-execution.yaml
index 92835ee1d..41ba1b0b5 100644
--- a/execution/helm/templates/theodolite/crd-execution.yaml
+++ b/execution/helm/templates/theodolite/crd-execution.yaml
@@ -1,4 +1,3 @@
-{{- if .Values.executionCRD.create -}}
 apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
@@ -96,12 +95,12 @@ spec:
                         resource:
                           type: string
                           default: ""
-                        container:
-                          type: string
-                          default: ""
-                        variableName:
-                          type: string
-                          default: ""
+                        config:
+                            type: object
+                            additionalProperties: true
+                            x-kubernetes-map-type: "granular"
+                            default: 
+                              "": ""
                     value:
                       type: string
           status:
@@ -127,6 +126,4 @@ spec:
       jsonPath: .metadata.creationTimestamp
     subresources:
       status: {}
-  scope: Namespaced
-  status: {}
-{{- end }}
\ No newline at end of file
+  scope: Namespaced
\ No newline at end of file
diff --git a/theodolite-quarkus/config/example-benchmark-yaml-resource.yaml b/theodolite-quarkus/config/example-benchmark-yaml-resource.yaml
index c92ffcf78..ec788031c 100644
--- a/theodolite-quarkus/config/example-benchmark-yaml-resource.yaml
+++ b/theodolite-quarkus/config/example-benchmark-yaml-resource.yaml
@@ -18,15 +18,12 @@ loadTypes:
       - type: "EnvVarPatcher"
         resource: "uc1-load-generator-deployment.yaml"
         config:
-          - key: "variableName"
-            value: "NUM_SENSORS"
-          - key: "container"
-            value: "workload-generator"
+          variableName: "NUM_SENSORS"
+          container: "workload-generator"
       - type: "NumSensorsLoadGeneratorReplicaPatcher"
-        resource: "uc1-load-generator-deploym ent.yaml"
+        resource: "uc1-load-generator-deployment.yaml"
         config:
-          - key: "loadGenMaxRecords"
-            value: "15000"
+          loadGenMaxRecords: "15000"
 kafkaConfig:
   bootstrapServer: "localhost:31290"
   topics:
diff --git a/theodolite-quarkus/config/example-execution-yaml-resource.yaml b/theodolite-quarkus/config/example-execution-yaml-resource.yaml
index 88013ef84..0f1e0fc03 100644
--- a/theodolite-quarkus/config/example-execution-yaml-resource.yaml
+++ b/theodolite-quarkus/config/example-execution-yaml-resource.yaml
@@ -25,33 +25,27 @@ configOverrides:
       type: "NodeSelectorPatcher"
       resource: "uc1-load-generator-deployment.yaml"
       config:
-        - key: "variableName"
-          value: "env"
+        variableName: "env"
     value: "prod"
   - patcher:
       type: "NodeSelectorPatcher"
       resource: "uc1-kstreams-deployment.yaml"
       config:
-        - key: "variableName"
-          value: "env"
+        variableName: "env"
     value: "prod"
   - patcher:
       type: "ResourceLimitPatcher"
       resource: "uc1-kstreams-deployment.yaml"
-      config: 
-        - key: "container" 
-          value: "uc-application"
-        - key: "limitedResource"
-          value:  "cpu"
+      config:
+        container: "uc-application"
+        limitedResource: "cpu"
     value: "1000m"
   - patcher:
       type: "ResourceLimitPatcher"
       resource: "uc1-kstreams-deployment.yaml"
       config:
-        - key: "container"
-          value: "uc-application"
-        - key: "limitedResource"
-          value: "memory"
+        container: "uc-application"
+        limitedResource: "memory"
     value: "2Gi"
 #  - patcher:
 #      type: "SchedulerNamePatcher"
diff --git a/theodolite-quarkus/config/example-operator-benchmark.yaml b/theodolite-quarkus/config/example-operator-benchmark.yaml
index 5b56c9b5e..fcde4a510 100644
--- a/theodolite-quarkus/config/example-operator-benchmark.yaml
+++ b/theodolite-quarkus/config/example-operator-benchmark.yaml
@@ -22,15 +22,12 @@ spec:
           - type: "EnvVarPatcher"
             resource: "uc1-load-generator-deployment.yaml"
             config:
-              - key: "variableName"
-                value: "NUM_SENSORS"
-              - key: "container"
-                value: "workload-generator"
+               variableName: "NUM_SENSORS"
+               container: "workload-generator"
           - type: "NumSensorsLoadGeneratorReplicaPatcher"
             resource: "uc1-load-generator-deployment.yaml"
             config:
-              - key: "loadGenMaxRecords"
-                value: "15000"
+              loadGenMaxRecords: "15000"
   kafkaConfig:
     bootstrapServer: "theodolite-cp-kafka:9092"
     topics:
diff --git a/theodolite-quarkus/config/example-operator-execution.yaml b/theodolite-quarkus/config/example-operator-execution.yaml
index 10927fb83..168522430 100644
--- a/theodolite-quarkus/config/example-operator-execution.yaml
+++ b/theodolite-quarkus/config/example-operator-execution.yaml
@@ -21,41 +21,37 @@ spec:
     strategy: "LinearSearch"
     duration: 300 # in seconds
     repetitions: 1
-    delay: 30 # in seconds
+    loadGenerationDelay: 30 # in seconds
     restrictions:
       - "LowerBound"
-  configOverrides: []
-#   - patcher:
-#       type: "NodeSelectorPatcher"
-#       resource: "uc1-load-generator-deployment123.yaml"
-#       variableName: "env"
-#     value: "prod"
-#  - patcher:
-#      type: "NodeSelectorPatcher"
-#      resource: "uc1-kstreams-deployment.yaml"
-#      config:
-#       - key: "variableName"
-#         value: "env"
-#    value: "prod"
-#  - patcher:
-#      type: "ResourceLimitPatcher"
-#      resource: "uc1-kstreams-deployment.yaml"
-#      config: 
-#       - key: "container" 
-#         value: "uc-application"
-#       - key: "variableName"
-#         value:  "cpu"
-#    value: "1000m"
-#  - patcher:
-#      type: "ResourceLimitPatcher"
-#      resource: "uc1-kstreams-deployment.yaml"
-#      config:
-#       - key: "container"
-#         value: "uc-application"
-#       - key: "variableName"
-#         value: "memory"
-#    value: "2Gi"
-#  - patcher:
-#      type: "SchedulerNamePatcher"
-#      resource: "uc1-kstreams-deployment.yaml"
-#    value: "random-scheduler"
+  configOverrides:
+    # - patcher:
+    #     type: "NodeSelectorPatcher"
+    #     resource: "uc1-load-generator-deployment.yaml"
+    #     config:
+    #       variableName: "env"
+    #     value: "prod"
+    # - patcher:
+    #     type: "NodeSelectorPatcher"
+    #     resource: "uc1-kstreams-deployment.yaml"
+    #     config:
+    #       variableName: "env"
+    #   value: "prod"
+    # - patcher:
+    #     type: "ResourceLimitPatcher"
+    #     resource: "uc1-kstreams-deployment.yaml"
+    #     config:
+    #       container: "uc-application"
+    #       limitedResource: "cpu"
+    #   value: "1000m"
+    # - patcher:
+    #     type: "ResourceLimitPatcher"
+    #     resource: "uc1-kstreams-deployment.yaml"
+    #     config:
+    #       container: "uc-application"
+    #       limitedResource: "memory"
+    #   value: "2Gi"
+    #  - patcher:
+    #      type: "SchedulerNamePatcher"
+    #      resource: "uc1-kstreams-deployment.yaml"
+    #    value: "random-scheduler"
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
index 0113ff669..9b27dd44d 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
@@ -183,7 +183,7 @@ class TheodoliteController(
                 val configurationOverride = ConfigurationOverride()
                 configurationOverride.patcher = PatcherDefinition()
                 configurationOverride.patcher.type = "LabelPatcher"
-                configurationOverride.patcher.config = mutableListOf(hashMapOf("key" to "variableName",  "value" to labelName))
+                configurationOverride.patcher.config = mapOf("variableName" to labelName)
                 configurationOverride.patcher.resource = it
                 configurationOverride.value = labelValue
                 additionalConfigOverrides.add(configurationOverride)
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherFactory.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherFactory.kt
index 29171e53d..be9a04245 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherFactory.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherFactory.kt
@@ -2,6 +2,7 @@ package theodolite.patcher
 
 import io.fabric8.kubernetes.api.model.KubernetesResource
 import theodolite.util.DeploymentFailedException
+import theodolite.util.InvalidPatcherConfigurationException
 import theodolite.util.PatcherDefinition
 
 /**
@@ -33,46 +34,51 @@ class PatcherFactory {
                 .firstOrNull()
                 ?: throw DeploymentFailedException("Could not find resource ${patcherDefinition.resource}")
 
-
-        return when (patcherDefinition.type) {
-            "ReplicaPatcher" -> ReplicaPatcher(
-                k8sResource = resource
-            )
-            "NumNestedGroupsLoadGeneratorReplicaPatcher" -> NumNestedGroupsLoadGeneratorReplicaPatcher(
-                k8sResource = resource,
-                loadGenMaxRecords = patcherDefinition.getValueByKey("loadGenMaxRecords"),
-                numSensors = patcherDefinition.getValueByKey("numSensors")
-            )
-            "NumSensorsLoadGeneratorReplicaPatcher" -> NumSensorsLoadGeneratorReplicaPatcher(
-                k8sResource = resource,
-                loadGenMaxRecords = patcherDefinition.getValueByKey("loadGenMaxRecords")
-            )
-            "EnvVarPatcher" -> EnvVarPatcher(
-                k8sResource = resource,
-                container = patcherDefinition.getValueByKey("container"),
-                variableName = patcherDefinition.getValueByKey("variableName")
-            )
-            "NodeSelectorPatcher" -> NodeSelectorPatcher(
-                k8sResource = resource,
-                variableName = patcherDefinition.getValueByKey("variableName"))
-            "ResourceLimitPatcher" -> ResourceLimitPatcher(
-                k8sResource = resource,
-                container = patcherDefinition.getValueByKey("container"),
-                limitedResource = patcherDefinition.getValueByKey("limitedResource")
-            )
-            "ResourceRequestPatcher" -> ResourceRequestPatcher(
-                k8sResource = resource,
-                container = patcherDefinition.getValueByKey("container"),
-                requestedResource = patcherDefinition.getValueByKey("requestedResource")
-            )
-            "SchedulerNamePatcher" -> SchedulerNamePatcher(
-                k8sResource = resource
-            )
-            "LabelPatcher" -> LabelPatcher(
-                k8sResource = resource,
-                variableName = patcherDefinition.getValueByKey("variableName")
-            )
-            else -> throw IllegalArgumentException("Patcher type ${patcherDefinition.type} not found")
+        return try {
+            when (patcherDefinition.type) {
+                "ReplicaPatcher" -> ReplicaPatcher(
+                    k8sResource = resource
+                )
+                "NumNestedGroupsLoadGeneratorReplicaPatcher" -> NumNestedGroupsLoadGeneratorReplicaPatcher(
+                    k8sResource = resource,
+                    loadGenMaxRecords = patcherDefinition.config["loadGenMaxRecords"] !!,
+                    numSensors = patcherDefinition.config["numSensors"] !!
+                )
+                "NumSensorsLoadGeneratorReplicaPatcher" -> NumSensorsLoadGeneratorReplicaPatcher(
+                    k8sResource = resource,
+                    loadGenMaxRecords = patcherDefinition.config["loadGenMaxRecords"] !!
+                )
+                "EnvVarPatcher" -> EnvVarPatcher(
+                    k8sResource = resource,
+                    container = patcherDefinition.config["container"] !!,
+                    variableName = patcherDefinition.config["variableName"] !!
+                )
+                "NodeSelectorPatcher" -> NodeSelectorPatcher(
+                    k8sResource = resource,
+                    variableName = patcherDefinition.config["variableName"] !!
+                )
+                "ResourceLimitPatcher" -> ResourceLimitPatcher(
+                    k8sResource = resource,
+                    container = patcherDefinition.config["container"] !!,
+                    limitedResource = patcherDefinition.config["limitedResource"] !!
+                )
+                "ResourceRequestPatcher" -> ResourceRequestPatcher(
+                    k8sResource = resource,
+                    container = patcherDefinition.config["container"] !!,
+                    requestedResource = patcherDefinition.config["requestedResource"] !!
+                )
+                "SchedulerNamePatcher" -> SchedulerNamePatcher(
+                    k8sResource = resource
+                )
+                "LabelPatcher" -> LabelPatcher(
+                    k8sResource = resource,
+                    variableName = patcherDefinition.config["variableName"] !!
+                )
+                else -> throw InvalidPatcherConfigurationException("Patcher type ${patcherDefinition.type} not found.")
+            }
+        } catch (e: Exception) {
+            throw InvalidPatcherConfigurationException("Could not create patcher with type ${patcherDefinition.type}" +
+                    " Probably a required patcher argument was not specified." )
         }
     }
 }
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/util/PatcherDefinition.kt b/theodolite-quarkus/src/main/kotlin/theodolite/util/PatcherDefinition.kt
index 508f6264e..62625b6da 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/util/PatcherDefinition.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/util/PatcherDefinition.kt
@@ -21,23 +21,5 @@ class PatcherDefinition {
     lateinit var resource: String
 
     @JsonSerialize
-    lateinit var config: MutableList<Map<String, String>>
-
-    fun getValueByKey(key: String): String {
-        val value = this.config
-            .filter { it["key"] == key }
-            .map {
-                try {
-                    it.getValue("value")
-                } catch (e: Exception) {
-                    throw InvalidPatcherConfigurationException("No value found for key $key.")
-                }
-            }
-
-        return when {
-            value.isEmpty() -> throw InvalidPatcherConfigurationException("Required argument $key missing.")
-            value.size > 1 -> throw InvalidPatcherConfigurationException("Can not handle duplicate declaration for key $key.")
-            else -> value.first()
-        }
-    }
+    lateinit var config: MutableMap<String, String>
 }
diff --git a/theodolite-quarkus/src/main/resources/operator/benchmarkCRD.yaml b/theodolite-quarkus/src/main/resources/operator/benchmarkCRD.yaml
index 9d3220216..56dec9bb7 100644
--- a/theodolite-quarkus/src/main/resources/operator/benchmarkCRD.yaml
+++ b/theodolite-quarkus/src/main/resources/operator/benchmarkCRD.yaml
@@ -55,16 +55,11 @@ spec:
                             type: string
                             default: ""
                           config:
-                            type: array
-                            items:
-                              type: object
-                              properties:
-                                key:
-                                  type: string
-                                  default: ""
-                                value:
-                                  type: string
-                                  default: ""
+                            type: object
+                            additionalProperties: true
+                            x-kubernetes-map-type: "granular"
+                            default:
+                              "": ""
               loadTypes:
                 type: array
                 minItems: 1
@@ -86,16 +81,11 @@ spec:
                             type: string
                             default: ""
                           config:
-                            type: array
-                            items:
-                              type: object
-                              properties:
-                                key:
-                                  type: string
-                                  default: ""
-                                value:
-                                  type: string
-                                  default: ""
+                            type: object
+                            additionalProperties: true
+                            x-kubernetes-map-type: "granular"
+                            default:
+                              "": ""
               kafkaConfig:
                 type: object
                 properties:
diff --git a/theodolite-quarkus/src/main/resources/operator/example-benchmark-k8s-resource.yaml b/theodolite-quarkus/src/main/resources/operator/example-benchmark-k8s-resource.yaml
index f6a7dc333..0118fcd84 100644
--- a/theodolite-quarkus/src/main/resources/operator/example-benchmark-k8s-resource.yaml
+++ b/theodolite-quarkus/src/main/resources/operator/example-benchmark-k8s-resource.yaml
@@ -23,10 +23,12 @@ spec:
         - type: "EnvVarPatcher"
           resource: "uc1-load-generator-deployment.yaml"
           config:
-            - key: "container"
-              value: "workload-generator"
-            - key: "variableName"
-              value: "NUM_SENSORS"
+            container: "workload-generator"
+            variableName: "NUM_SENSORS"
+        - type: "NumSensorsLoadGeneratorReplicaPatcher"
+          resource: "uc1-load-generator-deployment.yaml"
+          config:
+            loadGenMaxRecords: "15000"
   kafkaConfig:
     bootstrapServer: "localhost:31290"
     topics:
diff --git a/theodolite-quarkus/src/main/resources/operator/executionCRD.yaml b/theodolite-quarkus/src/main/resources/operator/executionCRD.yaml
index 140140d09..bf2eb1279 100644
--- a/theodolite-quarkus/src/main/resources/operator/executionCRD.yaml
+++ b/theodolite-quarkus/src/main/resources/operator/executionCRD.yaml
@@ -96,16 +96,11 @@ spec:
                           type: string
                           default: ""
                         config:
-                          type: array
-                          items:
-                            type: object
-                            properties:
-                              key:
-                                type: string
-                                default: ""
-                              value:
-                                type: string
-                                default: ""
+                          type: object
+                          additionalProperties: true
+                          x-kubernetes-map-type: "granular"
+                          default:
+                            "": ""
                     value:
                       type: string
           status:
-- 
GitLab