diff --git a/docs/crd-docu.md b/docs/crd-docu.md index 400e888af53a59353e68440ceb34d32c6a72506f..73d85c951fc2958aee25cde2cdff652034643c1a 100644 --- a/docs/crd-docu.md +++ b/docs/crd-docu.md @@ -51,6 +51,13 @@ Resource Types: <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> @@ -62,6 +69,33 @@ Resource Types: </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> @@ -92,6 +126,8 @@ Resource Types: <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> diff --git a/theodolite/crd/crd-benchmark.yaml b/theodolite/crd/crd-benchmark.yaml index befab6f98c2d376218de49bf88e5a037ec13d525..7ab2e5f3b890a883f68dbbd36805f3791158f256 100644 --- a/theodolite/crd/crd-benchmark.yaml +++ b/theodolite/crd/crd-benchmark.yaml @@ -25,6 +25,7 @@ spec: 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 + 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 @@ -235,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/src/main/kotlin/theodolite/benchmark/ConfigMapResourceSet.kt b/theodolite/src/main/kotlin/theodolite/benchmark/ConfigMapResourceSet.kt index 1f89549fb4eabb86fa1a766627abe3bf7c1b3cc6..273a13170e77ae9e2f5f09869ebbc5cc06185715 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/ConfigMapResourceSet.kt +++ b/theodolite/src/main/kotlin/theodolite/benchmark/ConfigMapResourceSet.kt @@ -23,9 +23,6 @@ class ConfigMapResourceSet: ResourceSet, KubernetesResource { @OptIn(ExperimentalStdlibApi::class) override fun getResourceSet(client: NamespacedKubernetesClient): Collection<Pair<String, KubernetesResource>> { val loader = K8sResourceLoaderFromString(client) - - logger.info {"use namespace: ${client.namespace} in configmap resource set" } - var resources: Map<String, String> try { @@ -44,6 +41,10 @@ class ConfigMapResourceSet: ResourceSet, KubernetesResource { 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 { diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt b/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt index 5b6f956ec236ac8113a426dc22d0d08a968ca7b9..0b81f8701f92a95662efef6e0d58839c9a2f6f3b 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt +++ b/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt @@ -1,5 +1,6 @@ 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 diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSets.kt b/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSets.kt index 19c0808093f6729978f98940641031d8e425c349..a4fe443e7f304c411792ee06c32592ba3c9e692a 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSets.kt +++ b/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSets.kt @@ -11,19 +11,20 @@ import theodolite.util.DeploymentFailedException @JsonDeserialize @RegisterForReflection -@JsonInclude(JsonInclude.Include.NON_NULL) class ResourceSets: KubernetesResource { @JsonProperty("configMap") - lateinit var configMap: ConfigMapResourceSet + @JsonInclude(JsonInclude.Include.NON_NULL) + var configMap: ConfigMapResourceSet? = null @JsonProperty("fileSystem") - lateinit var fileSystem: FileSystemResourceSet + @JsonInclude(JsonInclude.Include.NON_NULL) + var fileSystem: FileSystemResourceSet? = null fun loadResourceSet(client: NamespacedKubernetesClient): Collection<Pair<String, KubernetesResource>> { - return if (::configMap.isInitialized) { - configMap.getResourceSet(client= client) - } else if (::fileSystem.isInitialized) { - fileSystem.getResourceSet(client= client ) + return if (::configMap != null) { + configMap?.getResourceSet(client= client) !! + } else if (::fileSystem != null) { + fileSystem?.getResourceSet(client= client ) !! } else { throw DeploymentFailedException("could not load resourceSet.") } 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 6987372f96a6d956378a928011be9b5406590a16..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,7 +54,7 @@ class ClusterSetup( benchmark.spec.name = benchmark.metadata.name Shutdown(execution.spec, benchmark.spec).start() } else { - throw IllegalStateException("Execution with state ${States.RUNNING.value} was found, but no corresponding benchmark. " + + 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/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 14d13160909817dc43d118173bf3ceee9bb47520..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) @@ -84,20 +88,20 @@ class TheodoliteController( labelName = CREATED_BY_LABEL_NAME ) - executionStateHandler.setExecutionState(execution.name, States.RUNNING) + executionStateHandler.setExecutionState(execution.name, ExecutionStates.RUNNING) executionStateHandler.startDurationStateTimer(execution.name) 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, States.FAILURE) - logger.warn { "Unexpected execution state, set state to ${States.FAILURE.value}" } + executionStateHandler.setExecutionState(execution.name, ExecutionStates.FAILURE) + logger.warn { "Unexpected execution state, set state to ${ExecutionStates.FAILURE.value}" } } } } catch (e: Exception) { @@ -108,7 +112,7 @@ class TheodoliteController( 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() } @@ -117,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) } @@ -125,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 @@ -157,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 }) @@ -166,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 d078b52c4c72d71d4f9f773831ea1a0736be6c99..4850a44fdddba117178e29d3170f44a95df646e7 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt +++ b/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt @@ -33,6 +33,7 @@ class TheodoliteOperator { private val client: NamespacedKubernetesClient = DefaultKubernetesClient().inNamespace(namespace) private lateinit var controller: TheodoliteController private lateinit var executionStateHandler: ExecutionStateHandler + private lateinit var benchmarkStateHandler: BenchmarkStateHandler fun start() { @@ -69,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() @@ -102,15 +105,24 @@ 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 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/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/test/kotlin/theodolite/execution/operator/ControllerTest.kt b/theodolite/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt index 73a8b9b54813be51937bc17d873ca67dc5ae8724..7e0532aff36cac2fb1a1c718415315b8f54052c2 100644 --- a/theodolite/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt +++ b/theodolite/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt @@ -2,7 +2,6 @@ package theodolite.execution.operator import com.google.gson.Gson import com.google.gson.GsonBuilder -import io.fabric8.kubernetes.api.model.Service import io.fabric8.kubernetes.client.CustomResourceList import io.fabric8.kubernetes.client.server.mock.KubernetesServer import io.quarkus.test.junit.QuarkusTest @@ -14,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 @@ -34,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()) @@ -112,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 6c94d9734b3d5f6d1cb4901d2b3bc9a473d90e79..d8db7ab3b64ce3856984ddbc279ef148aa325e73 100644 --- a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt +++ b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt @@ -11,7 +11,7 @@ import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import theodolite.k8s.K8sManager import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile -import theodolite.model.crd.States +import theodolite.model.crd.ExecutionStates import java.lang.Thread.sleep @@ -36,7 +36,8 @@ 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) @@ -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 b435b47fddcb58d6444e1fc31304bd355a9e7783..a54f4ed6db559f8f7f15ae82deecf3fedf8b4abe 100644 --- a/theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt +++ b/theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt @@ -9,7 +9,7 @@ import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import theodolite.k8s.K8sManager import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile -import theodolite.model.crd.States +import theodolite.model.crd.ExecutionStates import java.time.Duration class StateHandlerTest { @@ -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/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())