diff --git a/theodolite/crd/crd-benchmark.yaml b/theodolite/crd/crd-benchmark.yaml index 60c777c7d508e6d89a2678dd101678bbf40627c4..8fc7d08eef62ceb90b79328c3d55839bce81ecdd 100644 --- a/theodolite/crd/crd-benchmark.yaml +++ b/theodolite/crd/crd-benchmark.yaml @@ -66,14 +66,59 @@ spec: type: string beforeActions: type: array - properties: + default: [] + items: + type: object + properties: + selector: + type: object + properties: + pod: + type: object + properties: + matchLabels: + type: object + additionalProperties: true + x-kubernetes-map-type: "granular" + default: { } + container: + type: string + exec: + type: object + properties: + command: + type: string + afterActions: + type: array + default: [] + items: + type: object + properties: + selector: + type: object + properties: + pod: + type: object + properties: + matchLabels: + type: object + additionalProperties: true + x-kubernetes-map-type: "granular" + default: { } + container: + type: string + exec: + type: object + properties: + command: + 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: [ ] + default: [] items: type: object oneOf: @@ -104,6 +149,54 @@ spec: type: array items: type: string + beforeActions: + type: array + default: [] + items: + type: object + properties: + selector: + type: object + properties: + pod: + type: object + properties: + matchLabels: + type: object + additionalProperties: true + x-kubernetes-map-type: "granular" + default: { } + container: + type: string + exec: + type: object + properties: + command: + type: string + afterActions: + type: array + default: [] + items: + type: object + properties: + selector: + type: object + properties: + pod: + type: object + properties: + matchLabels: + type: object + additionalProperties: true + x-kubernetes-map-type: "granular" + default: { } + container: + type: string + exec: + type: object + properties: + command: + 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 @@ -141,6 +234,54 @@ spec: type: array items: type: string + beforeActions: + type: array + default: [ ] + items: + type: object + properties: + selector: + type: object + properties: + pod: + type: object + properties: + matchLabels: + type: object + additionalProperties: true + x-kubernetes-map-type: "granular" + default: { } + container: + type: string + exec: + type: object + properties: + command: + type: string + afterActions: + type: array + default: [] + items: + type: object + properties: + selector: + type: object + properties: + pod: + type: object + properties: + matchLabels: + type: object + additionalProperties: true + x-kubernetes-map-type: "granular" + default: { } + container: + type: string + exec: + type: object + properties: + command: + 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 diff --git a/theodolite/examples/operator/example-benchmark.yaml b/theodolite/examples/operator/example-benchmark.yaml index 3452fff9c729d680890d6eafa685ce2f13b098d6..87b3d83c1993d7a36078d7fec1836837e3a9c009 100644 --- a/theodolite/examples/operator/example-benchmark.yaml +++ b/theodolite/examples/operator/example-benchmark.yaml @@ -9,6 +9,14 @@ spec: name: "example-configmap" files: - "uc1-kstreams-deployment.yaml" + beforeActions: + - selector: + pod: + matchLabels: + app: kafka-client + container: "abc" # optional (if there is only one container or there exists something like a default container) + exec: + command: "kafka-topics.sh --create --topic abc" # or list loadGenerator: resources: - configMap: @@ -16,6 +24,14 @@ spec: files: - uc1-load-generator-service.yaml - uc1-load-generator-deployment.yaml + beforeActions: + - selector: + pod: + matchLabels: + app: kafka-client + container: "abc" # optional (if there is only one container or there exists something like a default container) + exec: + command: "kafka-topics.sh --create --topic abc" # or list resourceTypes: - typeName: "Instances" patchers: diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/Action.kt b/theodolite/src/main/kotlin/theodolite/benchmark/Action.kt index 55add765e8d0d7d3299d9e8f940a122ead899caf..653a71bd9c12d462a0a944221dd491978d2ae58b 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/Action.kt +++ b/theodolite/src/main/kotlin/theodolite/benchmark/Action.kt @@ -1,7 +1,13 @@ package theodolite.benchmark +import com.fasterxml.jackson.annotation.JsonInclude +import com.fasterxml.jackson.databind.annotation.JsonDeserialize import io.fabric8.kubernetes.client.NamespacedKubernetesClient +import io.quarkus.runtime.annotations.RegisterForReflection +@JsonDeserialize +@RegisterForReflection +@JsonInclude(JsonInclude.Include.NON_NULL) class Action { lateinit var selector: ActionSelector @@ -17,15 +23,19 @@ class Action { } } +@JsonDeserialize +@RegisterForReflection class ActionSelector { lateinit var pod: PodSelector lateinit var container: String } - +@JsonDeserialize +@RegisterForReflection class PodSelector { lateinit var matchLabels: MutableMap<String, String> } - +@JsonDeserialize +@RegisterForReflection class Command { lateinit var command: String } \ 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 0b81f8701f92a95662efef6e0d58839c9a2f6f3b..c5e0e38465c13318a79f0d5f8d6b3288f8be6d21 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt +++ b/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt @@ -110,6 +110,10 @@ class KubernetesBenchmark : KubernetesResource, Benchmark { } } return KubernetesBenchmarkDeployment( + sutBeforeActions = sut.beforeActions, + sutAfterActions = sut.beforeActions, + loadGenBeforeActions = loadGenerator.beforeActions, + loadGenAfterActions = loadGenerator.afterActions, appResources = appResources.map { it.second }, loadGenResources = loadGenResources.map { it.second }, loadGenerationDelay = loadGenerationDelay, diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmarkDeployment.kt b/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmarkDeployment.kt index 423ac92c654ff55057796d9642c2cb408bc62fe5..db90f0e24416531d39b0865e47c54220f8af7b11 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmarkDeployment.kt +++ b/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmarkDeployment.kt @@ -23,6 +23,10 @@ private val logger = KotlinLogging.logger {} */ @RegisterForReflection class KubernetesBenchmarkDeployment( + private val sutBeforeActions: List<Action>, + private val sutAfterActions: List<Action>, + private val loadGenBeforeActions: List<Action>, + private val loadGenAfterActions: List<Action>, val appResources: List<KubernetesResource>, val loadGenResources: List<KubernetesResource>, private val loadGenerationDelay: Long, @@ -36,12 +40,17 @@ class KubernetesBenchmarkDeployment( private val LAG_EXPORTER_POD_LABEL_NAME = "app.kubernetes.io/name" private val LAG_EXPORTER_POD_LABEL_VALUE = "kafka-lag-exporter" + + /** * Setup a [KubernetesBenchmark] using the [TopicManager] and the [K8sManager]: * - Create the needed topics. * - Deploy the needed resources. */ override fun setup() { + sutBeforeActions.forEach { it.exec } + loadGenBeforeActions.forEach { it.exec } + val kafkaTopics = this.topics.filter { !it.removeOnly } .map { NewTopic(it.name, it.numPartitions, it.replicationFactor) } kafkaController.createTopics(kafkaTopics) @@ -65,6 +74,8 @@ class KubernetesBenchmarkDeployment( labelName = LAG_EXPORTER_POD_LABEL_NAME, labelValue = LAG_EXPORTER_POD_LABEL_VALUE ) + sutAfterActions.forEach { it.exec } + loadGenAfterActions.forEach { it.exec } logger.info { "Teardown complete. Wait $afterTeardownDelay ms to let everything come down." } Thread.sleep(Duration.ofSeconds(afterTeardownDelay).toMillis()) } diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/Resources.kt b/theodolite/src/main/kotlin/theodolite/benchmark/Resources.kt index 738fb60148d9a218454314dd9395fc8a5ea9b5c2..a5a30c4cdf9dfad2efaf0fd90aa0a2ca0390a5b7 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/Resources.kt +++ b/theodolite/src/main/kotlin/theodolite/benchmark/Resources.kt @@ -1,5 +1,6 @@ package theodolite.benchmark +import com.fasterxml.jackson.annotation.JsonInclude import com.fasterxml.jackson.databind.annotation.JsonDeserialize import com.fasterxml.jackson.databind.annotation.JsonSerialize import io.quarkus.runtime.annotations.RegisterForReflection diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt index 70e30cf84ef40796eb085a0d68eb2e323232fde9..6933fb16375bdd98559d8d0c03711df1c93b2b62 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt +++ b/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt @@ -72,8 +72,8 @@ class TheodoliteController( try { val modifier = ConfigOverrideModifier( execution = execution, - resources = benchmark.loadKubernetesResources(benchmark.sut.resources).map { it.first } - + benchmark.loadKubernetesResources(benchmark.loadGenerator.resources).map { it.first } + resources = benchmark.loadKubernetesResources(benchmark.sut.resources !!).map { it.first } + + benchmark.loadKubernetesResources(benchmark.loadGenerator.resources !!).map { it.first } ) modifier.setAdditionalLabels( labelValue = execution.name, @@ -186,6 +186,7 @@ class TheodoliteController( benchmarkStateHandler.setResourceSetState(resource.spec.name, state) } + // TODO(Should we check, if actions could be performed or not (all pods are up and running...))? private fun checkResource(benchmark: KubernetesBenchmark): BenchmarkStates { return try { val appResources =