From 0968e10ba1961d9049b10d981d967f6bb45c784f Mon Sep 17 00:00:00 2001 From: "stu126940@mail.uni-kiel.de" <stu126940@mail.uni-kiel.de> Date: Thu, 3 Jun 2021 18:50:51 +0200 Subject: [PATCH] change patcherDefinition in order to use a map for all configuration params --- .../operator/TheodoliteController.kt | 2 +- .../theodolite/patcher/AbstractPatcher.kt | 4 +- .../theodolite/patcher/EnvVarPatcher.kt | 2 +- .../kotlin/theodolite/patcher/ImagePatcher.kt | 2 +- .../kotlin/theodolite/patcher/LabelPatcher.kt | 3 +- .../theodolite/patcher/NodeSelectorPatcher.kt | 2 +- ...NestedGroupsLoadGeneratorReplicaPatcher.kt | 13 ++--- .../NumSensorsLoadGeneratorReplicaPatcher.kt | 8 +-- .../theodolite/patcher/PatcherFactory.kt | 51 ++++++++++++++----- .../patcher/ResourceLimitPatcher.kt | 2 +- .../patcher/ResourceRequestPatcher.kt | 2 +- .../InvalidPatcherConfigurationException.kt | 5 ++ .../theodolite/util/PatcherDefinition.kt | 28 +++++++--- .../main/resources/operator/benchmarkCRD.yaml | 34 ++++++++----- .../example-benchmark-k8s-resource.yaml | 7 ++- .../example-execution-k8s-resource.yaml | 11 ++-- .../main/resources/operator/executionCRD.yaml | 17 ++++--- 17 files changed, 123 insertions(+), 70 deletions(-) create mode 100644 theodolite-quarkus/src/main/kotlin/theodolite/util/InvalidPatcherConfigurationException.kt 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 1e3929da9..0113ff669 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.config = mutableListOf(hashMapOf("key" to "variableName", "value" 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 c0d17244b..df80e9cbd 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 b640df1da..416aec74a 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 b29d8d992..8f6753372 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 d9feff007..5ee5807cd 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 0a668a908..0e8cd553a 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 d7136740a..65489a969 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 d29280a64..f6a06324e 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 58dd95e9d..29171e53d 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherFactory.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherFactory.kt @@ -28,27 +28,50 @@ 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) + "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( - resource, - patcherDefinition.container, - patcherDefinition.variableName + k8sResource = resource, + container = patcherDefinition.getValueByKey("container"), + limitedResource = patcherDefinition.getValueByKey("limitedResource") ) "ResourceRequestPatcher" -> ResourceRequestPatcher( - resource, - patcherDefinition.container, - patcherDefinition.variableName + k8sResource = resource, + container = patcherDefinition.getValueByKey("container"), + requestedResource = patcherDefinition.getValueByKey("requestedResource") + ) + "SchedulerNamePatcher" -> SchedulerNamePatcher( + k8sResource = resource + ) + "LabelPatcher" -> LabelPatcher( + k8sResource = resource, + variableName = patcherDefinition.getValueByKey("variableName") ) - "SchedulerNamePatcher" -> SchedulerNamePatcher(resource) - "LabelPatcher" -> LabelPatcher(resource, patcherDefinition.variableName) else -> throw IllegalArgumentException("Patcher type ${patcherDefinition.type} not found") } } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ResourceLimitPatcher.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ResourceLimitPatcher.kt index 30f82e804..1a6fa35a9 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 24b2a6d40..9bf8c3c72 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 000000000..c103ef1f3 --- /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 b24f887d6..508f6264e 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,24 @@ class PatcherDefinition { */ lateinit var resource: String - /** - * The container which the patcher is applied to - */ - lateinit var container: String + @JsonSerialize + lateinit var config: MutableList<Map<String, String>> - /** - * The variable name for the patcher - */ - lateinit var variableName: 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() + } + } } diff --git a/theodolite-quarkus/src/main/resources/operator/benchmarkCRD.yaml b/theodolite-quarkus/src/main/resources/operator/benchmarkCRD.yaml index 4e481c512..9d3220216 100644 --- a/theodolite-quarkus/src/main/resources/operator/benchmarkCRD.yaml +++ b/theodolite-quarkus/src/main/resources/operator/benchmarkCRD.yaml @@ -54,12 +54,17 @@ spec: resource: type: string default: "" - container: - type: string - default: "" - variableName: - type: string - default: "" + config: + type: array + items: + type: object + properties: + key: + type: string + default: "" + value: + type: string + default: "" loadTypes: type: array minItems: 1 @@ -80,12 +85,17 @@ spec: resource: type: string default: "" - container: - type: string - default: "" - variableName: - type: string - default: "" + config: + type: array + items: + type: object + properties: + key: + type: string + default: "" + value: + type: string + 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 16c14b665..e0df9e462 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,11 @@ spec: patchers: - type: "EnvVarPatcher" resource: "uc1-load-generator-deployment.yaml" - container: "workload-generator" - variableName: "NUM_SENSORS" + config: + - key: container + value: "workload-generator" + - key: variableName + value: "NUM_SENSORS" 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 4227020e7..5d7596663 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 @@ -27,15 +27,10 @@ spec: 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" + config: + - key: variableName + value: env value: "prod" diff --git a/theodolite-quarkus/src/main/resources/operator/executionCRD.yaml b/theodolite-quarkus/src/main/resources/operator/executionCRD.yaml index 8e1189572..140140d09 100644 --- a/theodolite-quarkus/src/main/resources/operator/executionCRD.yaml +++ b/theodolite-quarkus/src/main/resources/operator/executionCRD.yaml @@ -95,12 +95,17 @@ spec: resource: type: string default: "" - container: - type: string - default: "" - variableName: - type: string - default: "" + config: + type: array + items: + type: object + properties: + key: + type: string + default: "" + value: + type: string + default: "" value: type: string status: -- GitLab