diff --git a/execution/helm/templates/theodolite/crd-benchmark.yaml b/execution/helm/templates/theodolite/crd-benchmark.yaml index 848ecb37213f2810853a47fd45d3869198acd720..319eee18cee87d12cd7051e5fc3414f99c8d8a30 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 92835ee1d5a016d0fe6e2db874ae222d7f49f461..41ba1b0b5b19b53d9b7caec48241285edf4ba396 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/README.md b/theodolite-quarkus/config/README.md index 4f53d87ba9ac12099091faa315913cf93ed62bb7..23337d77375ebba8f624e7a11f714502fe3d5e67 100644 --- a/theodolite-quarkus/config/README.md +++ b/theodolite-quarkus/config/README.md @@ -19,14 +19,16 @@ resourceTypes: patchers: - type: String resources: String - <Patcher Arguments> ... + properties: + <Patcher Arguments> ... ... loadTypes: - typeName: String patchers: - type: String resources: String - <Patcher Arguments> ... + properties: + <Patcher Arguments> ... ... kafkaConfig: bootstrapServer: String @@ -49,7 +51,7 @@ The properties have the following definitions: * **patchers**: List of [patchers](#Patchers) used to scale this resource type. Each patcher has the following structure: * **type**: Type of the [patcher](#Patchers). The concrete types can be looked up in the list of [patchers](#Patchers). * **resources**: Specifies the Kubernetes resource to be patched. - * **Patcher Arguments**: (Optional) Patcher specific additional arguments. + * **properties**: *Patcher Arguments*: (Optional) Patcher specific additional arguments. * **loadTypes**: 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. Each load type has the following structure: * **typeName**: Name of the load type. * **patchers**: List of patchers used to scale * **resourceTypes**: A list of resource types that can be scaled for this *benchmark*. For each resource type the concrete values are defined in the *execution* resource object.Each resource type has the following structure: @@ -57,7 +59,7 @@ The properties have the following definitions: * **patchers**: List of patchers used to scale this resource type. Each patcher has the following structure: * **type**: Type of the Patcher. The concrete types can be looked up in the list of patchers. * **resources**: Specifies the Kubernetes resource to be patched. - * **Patcher Arguments**: (Optional) Patcher specific additional arguments. + * **properties**: *Patcher Arguments*: (Optional) Patcher specific additional arguments as Map<String, String>. * **kafkaConfig**: Contains the Kafka configuration. * **bootstrapServers**: The bootstrap servers connection string. * **topics**: List of topics to be created for each [experiment](#Experiment). Alternative theodolite offers the possibility to remove certain topics after each experiment. @@ -105,7 +107,8 @@ configurationOverrides: - patcher: type: String resource: String - <Patcher Arguments> ... + properties: + <Patcher Arguments> ... ... ``` @@ -136,7 +139,7 @@ The properties have the following definitions: * **patcher**: Patcher used to patch a resource. Each patcher has the following structure: * **type**: Type of the Patcher. The concrete types can be looked up in the list of patchers. * **resources**: Specifies the Kubernetes resource to be patched. - * **Patcher Arguments**: (Optional) Patcher specific additional arguments. + * **properties**: *Patcher Arguments*: (Optional) Patcher specific additional arguments. ## Patchers @@ -159,19 +162,22 @@ The properties have the following definitions: * **EnvVarPatcher**: Allows to modify the value of an environment variable for a container in a kubernetes deployment. * **type**: "EnvVarPatcher" * **resource**: "uc1-load-generator-deployment.yaml" - * **container**: "workload-generator" - * **variableName**: "NUM_SENSORS" + * **properties**: + * container: "workload-generator" + * variableName: "NUM_SENSORS" * **NodeSelectorPatcher**: Changes the node selection field in kubernetes resources. * **type**: "NodeSelectorPatcher" * **resource**: "uc1-load-generator-deployment.yaml" - * **variableName**: "env" + * **properties**: + * variableName: "env" * **value**: "prod" * **ResourceLimitPatcher**: Changes the resource limit for a kubernetes resource. * **resource**: "uc1-kstreams-deployment.yaml" - * **container**: "uc-application" - * **variableName**: "cpu" or "memory" + * **properties**: + * container: "uc-application" + * variableName: "cpu" or "memory" * **value**:"1000m" or "2Gi" * **SchedulerNamePatcher**: Changes the sheduler for kubernetes resources. @@ -182,7 +188,8 @@ The properties have the following definitions: * **ImagePatcher**: Changes the image of a kubernetes resource. Currently not fully implemented. * **type**: "ImagePatcher" * **resource**: "uc1-kstreams-deployment.yaml" - * **container**: "uc-application" + * **properties**: + * container: "uc-application" * **value**: "dockerhubrepo/imagename" diff --git a/theodolite-quarkus/config/example-benchmark-yaml-resource.yaml b/theodolite-quarkus/config/example-benchmark-yaml-resource.yaml index cdc2122d9e6b568f1a75b0d55eff8a0af6450983..623df71121b11b670584a83e153b4dd2962525e7 100644 --- a/theodolite-quarkus/config/example-benchmark-yaml-resource.yaml +++ b/theodolite-quarkus/config/example-benchmark-yaml-resource.yaml @@ -17,10 +17,13 @@ loadTypes: patchers: - type: "EnvVarPatcher" resource: "uc1-load-generator-deployment.yaml" - container: "workload-generator" - variableName: "NUM_SENSORS" + properties: + variableName: "NUM_SENSORS" + container: "workload-generator" - type: "NumSensorsLoadGeneratorReplicaPatcher" resource: "uc1-load-generator-deployment.yaml" + properties: + 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 e0b327a022099410fea8028fb5d37fee5672a857..e46a6cf417442b851650fe9699f73e1367dcc794 100644 --- a/theodolite-quarkus/config/example-execution-yaml-resource.yaml +++ b/theodolite-quarkus/config/example-execution-yaml-resource.yaml @@ -20,29 +20,33 @@ execution: loadGenerationDelay: 30 # in seconds, optional field, default is 0 seconds restrictions: - "LowerBound" -configOverrides: [] -# - patcher: -# type: "NodeSelectorPatcher" -# resource: "uc1-load-generator-deployment.yaml" -# variableName: "env" -# value: "prod" -# - patcher: -# type: "NodeSelectorPatcher" -# resource: "uc1-kstreams-deployment.yaml" -# variableName: "env" -# value: "prod" -# - patcher: -# type: "ResourceLimitPatcher" -# resource: "uc1-kstreams-deployment.yaml" -# container: "uc-application" -# variableName: "cpu" -# value: "1000m" -# - patcher: -# type: "ResourceLimitPatcher" -# resource: "uc1-kstreams-deployment.yaml" -# container: "uc-application" -# variableName: "memory" -# value: "2Gi" +configOverrides: + - patcher: + type: "NodeSelectorPatcher" + resource: "uc1-load-generator-deployment.yaml" + properties: + variableName: "env" + value: "prod" + - patcher: + type: "NodeSelectorPatcher" + resource: "uc1-kstreams-deployment.yaml" + properties: + variableName: "env" + value: "prod" + - patcher: + type: "ResourceLimitPatcher" + resource: "uc1-kstreams-deployment.yaml" + properties: + container: "uc-application" + limitedResource: "cpu" + value: "1000m" + - patcher: + type: "ResourceLimitPatcher" + resource: "uc1-kstreams-deployment.yaml" + properties: + container: "uc-application" + limitedResource: "memory" + value: "2Gi" # - patcher: # type: "SchedulerNamePatcher" # resource: "uc1-kstreams-deployment.yaml" diff --git a/theodolite-quarkus/config/example-operator-benchmark.yaml b/theodolite-quarkus/config/example-operator-benchmark.yaml index 5cf39492a8d88dc0260db8bf98a966b4ce1bccb7..8f9af3e955fe18de26326b0094578a71517a5aef 100644 --- a/theodolite-quarkus/config/example-operator-benchmark.yaml +++ b/theodolite-quarkus/config/example-operator-benchmark.yaml @@ -17,14 +17,17 @@ spec: - type: "ReplicaPatcher" resource: "uc1-kstreams-deployment.yaml" loadTypes: - - typeName: "NumSensors" - patchers: - - type: "EnvVarPatcher" - resource: "uc1-load-generator-deployment.yaml" - container: "workload-generator" - variableName: "NUM_SENSORS" - - type: "NumSensorsLoadGeneratorReplicaPatcher" - resource: "uc1-load-generator-deployment.yaml" + - typeName: "NumSensors" + patchers: + - type: "EnvVarPatcher" + resource: "uc1-load-generator-deployment.yaml" + properties: + variableName: "NUM_SENSORS" + container: "workload-generator" + - type: "NumSensorsLoadGeneratorReplicaPatcher" + resource: "uc1-load-generator-deployment.yaml" + properties: + 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 e01ea377e0762a56132a709a73fb418e4c914e26..9b2a1facbd8be3411407dfcf3cad39fd9f3de6b6 100644 --- a/theodolite-quarkus/config/example-operator-execution.yaml +++ b/theodolite-quarkus/config/example-operator-execution.yaml @@ -21,33 +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-deployment.yaml" - # variableName: "env" - # value: "prod" - # - patcher: - # type: "NodeSelectorPatcher" - # resource: "uc1-kstreams-deployment.yaml" - # variableName: "env" - # value: "prod" - # - patcher: - # type: "ResourceLimitPatcher" - # resource: "uc1-kstreams-deployment.yaml" - # container: "uc-application" - # variableName: "cpu" - # value: "1000m" - # - patcher: - # type: "ResourceLimitPatcher" - # resource: "uc1-kstreams-deployment.yaml" - # container: "uc-application" - # variableName: "memory" - # value: "2Gi" - # - patcher: - # type: "SchedulerNamePatcher" - # resource: "uc1-kstreams-deployment.yaml" - # value: "random-scheduler" + configOverrides: + # - patcher: + # type: "NodeSelectorPatcher" + # resource: "uc1-load-generator-deployment.yaml" + # properties: + # variableName: "env" + # value: "prod" + # - patcher: + # type: "NodeSelectorPatcher" + # resource: "uc1-kstreams-deployment.yaml" + # properties: + # variableName: "env" + # value: "prod" + # - patcher: + # type: "ResourceLimitPatcher" + # resource: "uc1-kstreams-deployment.yaml" + # properties: + # container: "uc-application" + # limitedResource: "cpu" + # value: "1000m" + # - patcher: + # type: "ResourceLimitPatcher" + # resource: "uc1-kstreams-deployment.yaml" + # properties: + # 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 1e3929da98be060e2cbebf305dbae2f25519798a..3053c364e2d6d9bc9797c190f0a87d861089b556 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.variableName = labelName + configurationOverride.patcher.properties = mutableMapOf("variableName" to labelName) configurationOverride.patcher.resource = it configurationOverride.value = labelValue additionalConfigOverrides.add(configurationOverride) diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/AbstractPatcher.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/AbstractPatcher.kt index c0d17244b6a7a3f37b8d8a57713659b85b9b65b1..df80e9cbd2503685a7dbed35db5319920dfc42cb 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/AbstractPatcher.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/AbstractPatcher.kt @@ -20,7 +20,5 @@ import io.fabric8.kubernetes.api.model.KubernetesResource * */ abstract class AbstractPatcher( - k8sResource: KubernetesResource, - container: String? = null, - variableName: String? = null + k8sResource: KubernetesResource ) : Patcher diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/EnvVarPatcher.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/EnvVarPatcher.kt index b640df1da2ca1c139bb5b02e9e42bad9e7d08d74..416aec74a3af9b74594f5e6cd018682bf91cbf63 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/EnvVarPatcher.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/EnvVarPatcher.kt @@ -16,7 +16,7 @@ class EnvVarPatcher( private val k8sResource: KubernetesResource, private val container: String, private val variableName: String -) : AbstractPatcher(k8sResource, container, variableName) { +) : AbstractPatcher(k8sResource) { override fun <String> patch(value: String) { if (k8sResource is Deployment) { diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ImagePatcher.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ImagePatcher.kt index b29d8d9925311aa25b7336dcd6805783ca62c3e7..8f6753372076c119324dc962112928253633b6b0 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ImagePatcher.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ImagePatcher.kt @@ -11,7 +11,7 @@ import io.fabric8.kubernetes.api.model.apps.StatefulSet * @param container Container to be patched. */ class ImagePatcher(private val k8sResource: KubernetesResource, private val container: String) : - AbstractPatcher(k8sResource, container) { + AbstractPatcher(k8sResource) { override fun <String> patch(imagePath: String) { if (k8sResource is Deployment) { diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/LabelPatcher.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/LabelPatcher.kt index d9feff00726c8c73483118276eeae7b7975d8c8e..5ee5807cd8378c9f2bbd62435203208d61131f15 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/LabelPatcher.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/LabelPatcher.kt @@ -8,10 +8,9 @@ import io.fabric8.kubernetes.api.model.apps.StatefulSet import io.fabric8.kubernetes.client.CustomResource class LabelPatcher(private val k8sResource: KubernetesResource, val variableName: String) : - AbstractPatcher(k8sResource, variableName) { + AbstractPatcher(k8sResource) { override fun <String> patch(labelValue: String) { - println("call patcher for resource $k8sResource !") if(labelValue is kotlin.String){ when(k8sResource){ is Deployment -> { diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/NodeSelectorPatcher.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/NodeSelectorPatcher.kt index 0a668a908e66577f96ea1268b85a38ad73bb16a7..0e8cd553a6c6a9ed6fa2c8cc1b84e4cfebe79d73 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/NodeSelectorPatcher.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/NodeSelectorPatcher.kt @@ -10,7 +10,7 @@ import io.fabric8.kubernetes.api.model.apps.Deployment * @param variableName The `label-key` of the node for which the `label-value` is to be patched. */ class NodeSelectorPatcher(private val k8sResource: KubernetesResource, private val variableName: String) : - AbstractPatcher(k8sResource, variableName) { + AbstractPatcher(k8sResource) { override fun <String> patch(value: String) { if (k8sResource is Deployment) { k8sResource.spec.template.spec.nodeSelector = mapOf(variableName to value as kotlin.String) diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/NumNestedGroupsLoadGeneratorReplicaPatcher.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/NumNestedGroupsLoadGeneratorReplicaPatcher.kt index d7136740a7e17f956eed16bc6e3fcd4954ab91b8..65489a96974ad566fe7cbd88cf6ff7fb49135e1d 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/NumNestedGroupsLoadGeneratorReplicaPatcher.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/NumNestedGroupsLoadGeneratorReplicaPatcher.kt @@ -4,16 +4,17 @@ import io.fabric8.kubernetes.api.model.KubernetesResource import io.fabric8.kubernetes.api.model.apps.Deployment import kotlin.math.pow -private const val NUM_SENSORS = 4.0 -private const val LOAD_GEN_MAX_RECORDS = 150000 - -class NumNestedGroupsLoadGeneratorReplicaPatcher(private val k8sResource: KubernetesResource) : +class NumNestedGroupsLoadGeneratorReplicaPatcher( + private val k8sResource: KubernetesResource, + private val numSensors: String, + private val loadGenMaxRecords: String + ) : AbstractPatcher(k8sResource) { override fun <String> patch(value: String) { if (k8sResource is Deployment) { if (value is kotlin.String) { - val approxNumSensors = NUM_SENSORS.pow(Integer.parseInt(value).toDouble()) - val loadGenInstances = (approxNumSensors + LOAD_GEN_MAX_RECORDS - 1) / LOAD_GEN_MAX_RECORDS + val approxNumSensors = numSensors.toDouble().pow(Integer.parseInt(value).toDouble()) + val loadGenInstances = (approxNumSensors + loadGenMaxRecords.toDouble() - 1) / loadGenMaxRecords.toDouble() this.k8sResource.spec.replicas = loadGenInstances.toInt() } } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/NumSensorsLoadGeneratorReplicaPatcher.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/NumSensorsLoadGeneratorReplicaPatcher.kt index d29280a648cd4c912b8e2717b51c4f9c3f8a2271..f6a06324e36d7942d3944a492fee263f428376c1 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/NumSensorsLoadGeneratorReplicaPatcher.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/NumSensorsLoadGeneratorReplicaPatcher.kt @@ -3,14 +3,16 @@ package theodolite.patcher import io.fabric8.kubernetes.api.model.KubernetesResource import io.fabric8.kubernetes.api.model.apps.Deployment -private const val LOAD_GEN_MAX_RECORDS = 150000 -class NumSensorsLoadGeneratorReplicaPatcher(private val k8sResource: KubernetesResource) : +class NumSensorsLoadGeneratorReplicaPatcher( + private val k8sResource: KubernetesResource, + private val loadGenMaxRecords: String +) : AbstractPatcher(k8sResource) { override fun <String> patch(value: String) { if (k8sResource is Deployment) { if (value is kotlin.String) { - val loadGenInstances = (Integer.parseInt(value) + LOAD_GEN_MAX_RECORDS - 1) / LOAD_GEN_MAX_RECORDS + val loadGenInstances = (Integer.parseInt(value) + loadGenMaxRecords.toInt() - 1) / loadGenMaxRecords.toInt() this.k8sResource.spec.replicas = loadGenInstances } } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherFactory.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherFactory.kt index 58dd95e9d582911a209a1173a0f58f8fac729c86..45e50113c964d671962fadc718994a29b2da81f4 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 /** @@ -28,28 +29,56 @@ class PatcherFactory { k8sResources: List<Pair<String, KubernetesResource>> ): Patcher { val resource = - k8sResources.filter { it.first == patcherDefinition.resource }.map { resource -> resource.second }.firstOrNull() + k8sResources.filter { it.first == patcherDefinition.resource } + .map { resource -> resource.second } + .firstOrNull() ?: throw DeploymentFailedException("Could not find resource ${patcherDefinition.resource}") - return when (patcherDefinition.type) { - "ReplicaPatcher" -> ReplicaPatcher(resource) - "NumNestedGroupsLoadGeneratorReplicaPatcher" -> NumNestedGroupsLoadGeneratorReplicaPatcher(resource) - "NumSensorsLoadGeneratorReplicaPatcher" -> NumSensorsLoadGeneratorReplicaPatcher(resource) - "EnvVarPatcher" -> EnvVarPatcher(resource, patcherDefinition.container, patcherDefinition.variableName) - "NodeSelectorPatcher" -> NodeSelectorPatcher(resource, patcherDefinition.variableName) - "ResourceLimitPatcher" -> ResourceLimitPatcher( - resource, - patcherDefinition.container, - patcherDefinition.variableName - ) - "ResourceRequestPatcher" -> ResourceRequestPatcher( - resource, - patcherDefinition.container, - patcherDefinition.variableName - ) - "SchedulerNamePatcher" -> SchedulerNamePatcher(resource) - "LabelPatcher" -> LabelPatcher(resource, patcherDefinition.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.properties["loadGenMaxRecords"] !!, + numSensors = patcherDefinition.properties["numSensors"] !! + ) + "NumSensorsLoadGeneratorReplicaPatcher" -> NumSensorsLoadGeneratorReplicaPatcher( + k8sResource = resource, + loadGenMaxRecords = patcherDefinition.properties["loadGenMaxRecords"] !! + ) + "EnvVarPatcher" -> EnvVarPatcher( + k8sResource = resource, + container = patcherDefinition.properties["container"] !!, + variableName = patcherDefinition.properties["variableName"] !! + ) + "NodeSelectorPatcher" -> NodeSelectorPatcher( + k8sResource = resource, + variableName = patcherDefinition.properties["variableName"] !! + ) + "ResourceLimitPatcher" -> ResourceLimitPatcher( + k8sResource = resource, + container = patcherDefinition.properties["container"] !!, + limitedResource = patcherDefinition.properties["limitedResource"] !! + ) + "ResourceRequestPatcher" -> ResourceRequestPatcher( + k8sResource = resource, + container = patcherDefinition.properties["container"] !!, + requestedResource = patcherDefinition.properties["requestedResource"] !! + ) + "SchedulerNamePatcher" -> SchedulerNamePatcher( + k8sResource = resource + ) + "LabelPatcher" -> LabelPatcher( + k8sResource = resource, + variableName = patcherDefinition.properties["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/patcher/ResourceLimitPatcher.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ResourceLimitPatcher.kt index 30f82e804f23b770457ec968f25ba7c00d72aefd..1a6fa35a944d00634ec0607b0bff34f4cb9d9b9c 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ResourceLimitPatcher.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ResourceLimitPatcher.kt @@ -18,7 +18,7 @@ class ResourceLimitPatcher( private val k8sResource: KubernetesResource, private val container: String, private val limitedResource: String -) : AbstractPatcher(k8sResource, container, limitedResource) { +) : AbstractPatcher(k8sResource) { override fun <String> patch(value: String) { when (k8sResource) { diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ResourceRequestPatcher.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ResourceRequestPatcher.kt index 24b2a6d40525f16448b77c50fba8aba0969d075a..9bf8c3c72f656d326ca3070cd5843778e5cdff42 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ResourceRequestPatcher.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ResourceRequestPatcher.kt @@ -18,7 +18,7 @@ class ResourceRequestPatcher( private val k8sResource: KubernetesResource, private val container: String, private val requestedResource: String -) : AbstractPatcher(k8sResource, container, requestedResource) { +) : AbstractPatcher(k8sResource) { override fun <String> patch(value: String) { when (k8sResource) { diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/util/InvalidPatcherConfigurationException.kt b/theodolite-quarkus/src/main/kotlin/theodolite/util/InvalidPatcherConfigurationException.kt new file mode 100644 index 0000000000000000000000000000000000000000..c103ef1f35a1b3ffa56dad50c7cf6c1db51eb57f --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/util/InvalidPatcherConfigurationException.kt @@ -0,0 +1,5 @@ +package theodolite.util + +class InvalidPatcherConfigurationException(message:String): Exception(message) { +} + diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/util/PatcherDefinition.kt b/theodolite-quarkus/src/main/kotlin/theodolite/util/PatcherDefinition.kt index b24f887d6ff6e3096a2e740f541861d76804775b..6ec0cce36751ec0343d40aa49fefa44f4c7fc918 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/util/PatcherDefinition.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/util/PatcherDefinition.kt @@ -1,6 +1,7 @@ package theodolite.util import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize import io.quarkus.runtime.annotations.RegisterForReflection /** @@ -19,13 +20,6 @@ class PatcherDefinition { */ lateinit var resource: String - /** - * The container which the patcher is applied to - */ - lateinit var container: String - - /** - * The variable name for the patcher - */ - lateinit var variableName: String + @JsonSerialize + lateinit var properties: MutableMap<String, String> } diff --git a/theodolite-quarkus/src/main/resources/operator/benchmarkCRD.yaml b/theodolite-quarkus/src/main/resources/operator/benchmarkCRD.yaml index 4e481c51231999e2e7a1e75ecbc018d40db75c91..b76821f6e7cca5408f604ba9bbf83cf1b43a37de 100644 --- a/theodolite-quarkus/src/main/resources/operator/benchmarkCRD.yaml +++ b/theodolite-quarkus/src/main/resources/operator/benchmarkCRD.yaml @@ -54,12 +54,11 @@ spec: resource: type: string default: "" - container: - type: string - default: "" - variableName: - type: string - default: "" + properties: + type: object + additionalProperties: true + x-kubernetes-map-type: "granular" + default: {} loadTypes: type: array minItems: 1 @@ -80,12 +79,11 @@ spec: resource: type: string default: "" - container: - type: string - default: "" - variableName: - type: string - default: "" + properties: + 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 16c14b665b99a4863279880d9ad6c03c7435578c..7a728d97c52a84d81bcc44fd9f20c56e6b574527 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 @@ -22,8 +22,13 @@ spec: patchers: - type: "EnvVarPatcher" resource: "uc1-load-generator-deployment.yaml" - container: "workload-generator" - variableName: "NUM_SENSORS" + properties: + container: "workload-generator" + variableName: "NUM_SENSORS" + - type: "NumSensorsLoadGeneratorReplicaPatcher" + resource: "uc1-load-generator-deployment.yaml" + properties: + loadGenMaxRecords: "15000" kafkaConfig: bootstrapServer: "localhost:31290" topics: diff --git a/theodolite-quarkus/src/main/resources/operator/example-execution-k8s-resource.yaml b/theodolite-quarkus/src/main/resources/operator/example-execution-k8s-resource.yaml index 4227020e7750c8e93f92c469d7796e381eb452e3..b81bbcd442834136283dc080f5f6a79bbc1cd415 100644 --- a/theodolite-quarkus/src/main/resources/operator/example-execution-k8s-resource.yaml +++ b/theodolite-quarkus/src/main/resources/operator/example-execution-k8s-resource.yaml @@ -26,16 +26,4 @@ spec: loadGenerationDelay: 30 # in seconds restrictions: - "LowerBound" - configOverrides: - - patcher: - type: "NodeSelectorPatcher" - resource: "uc1-load-generator-deployment.yaml" - container: "" - variableName: "env" - value: "prod" - - patcher: - type: "NodeSelectorPatcher" - resource: "uc1-kstreams-deployment.yaml" - container: "" - variableName: "env" - value: "prod" + configOverrides: [] \ No newline at end of file diff --git a/theodolite-quarkus/src/main/resources/operator/executionCRD.yaml b/theodolite-quarkus/src/main/resources/operator/executionCRD.yaml index 8e1189572ee993c37dd565fc62a66996654766f2..b984f3ebe5ca7c8868adb9d3593e5d87d73fc2bd 100644 --- a/theodolite-quarkus/src/main/resources/operator/executionCRD.yaml +++ b/theodolite-quarkus/src/main/resources/operator/executionCRD.yaml @@ -95,12 +95,11 @@ spec: resource: type: string default: "" - container: - type: string - default: "" - variableName: - type: string - default: "" + properties: + type: object + additionalProperties: true + x-kubernetes-map-type: "granular" + default: {} value: type: string status: diff --git a/theodolite-quarkus/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt b/theodolite-quarkus/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt index 4f4308a35df598dc4932a8ac89a6c07fb967e416..4ae9ce23b31204b366dce7bcf000e4114d7f3f8f 100644 --- a/theodolite-quarkus/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt +++ b/theodolite-quarkus/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt @@ -31,27 +31,32 @@ class ResourceLimitPatcherTest { val k8sResource = loader.loadK8sResource("Deployment", testPath + fileName) as Deployment val defCPU = PatcherDefinition() - defCPU.variableName = "cpu" defCPU.resource = "cpu-memory-deployment.yaml" - defCPU.container = "uc-application" defCPU.type = "ResourceLimitPatcher" + defCPU.properties = mutableMapOf( + "limitedResource" to "cpu", + "container" to "application" + ) val defMEM = PatcherDefinition() - defMEM.variableName = "memory" defMEM.resource = "cpu-memory-deployment.yaml" - defMEM.container = "uc-application" defMEM.type = "ResourceLimitPatcher" + defMEM.properties = mutableMapOf( + "limitedResource" to "memory", + "container" to "uc-application" + ) patcherFactory.createPatcher( patcherDefinition = defCPU, k8sResources = listOf(Pair("cpu-memory-deployment.yaml", k8sResource)) ).patch(value = cpuValue) + patcherFactory.createPatcher( patcherDefinition = defMEM, k8sResources = listOf(Pair("cpu-memory-deployment.yaml", k8sResource)) ).patch(value = memValue) - k8sResource.spec.template.spec.containers.filter { it.name == defCPU.container } + k8sResource.spec.template.spec.containers.filter { it.name == defCPU.properties["container"] !! } .forEach { assertTrue(it.resources.limits["cpu"].toString() == cpuValue) assertTrue(it.resources.limits["memory"].toString() == memValue) diff --git a/theodolite-quarkus/src/test/kotlin/theodolite/ResourceRequestPatcherTest.kt b/theodolite-quarkus/src/test/kotlin/theodolite/ResourceRequestPatcherTest.kt index 7214422705a64f507a196a4b5f9b334665407422..6f232961871c9d11929fc912a483e6e805cc7daf 100644 --- a/theodolite-quarkus/src/test/kotlin/theodolite/ResourceRequestPatcherTest.kt +++ b/theodolite-quarkus/src/test/kotlin/theodolite/ResourceRequestPatcherTest.kt @@ -31,16 +31,20 @@ class ResourceRequestPatcherTest { val k8sResource = loader.loadK8sResource("Deployment", testPath + fileName) as Deployment val defCPU = PatcherDefinition() - defCPU.variableName = "cpu" defCPU.resource = "cpu-memory-deployment.yaml" - defCPU.container = "uc-application" defCPU.type = "ResourceRequestPatcher" + defCPU.properties = mutableMapOf( + "requestedResource" to "cpu", + "container" to "application" + ) val defMEM = PatcherDefinition() - defMEM.variableName = "memory" defMEM.resource = "cpu-memory-deployment.yaml" - defMEM.container = "uc-application" defMEM.type = "ResourceRequestPatcher" + defMEM.properties = mutableMapOf( + "requestedResource" to "memory", + "container" to "application" + ) patcherFactory.createPatcher( patcherDefinition = defCPU, @@ -51,7 +55,7 @@ class ResourceRequestPatcherTest { k8sResources = listOf(Pair("cpu-memory-deployment.yaml", k8sResource)) ).patch(value = memValue) - k8sResource.spec.template.spec.containers.filter { it.name == defCPU.container } + k8sResource.spec.template.spec.containers.filter { it.name == defCPU.properties["container"] !! } .forEach { assertTrue(it.resources.requests["cpu"].toString() == cpuValue) assertTrue(it.resources.requests["memory"].toString() == memValue)