diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/ResourceByLabelRemover.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/ResourceByLabelRemover.kt deleted file mode 100644 index db242b6a7e170d1eb93225e6c019d0ae1f71d281..0000000000000000000000000000000000000000 --- a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/ResourceByLabelRemover.kt +++ /dev/null @@ -1,24 +0,0 @@ -package theodolite.benchmark - -import io.fabric8.kubernetes.client.NamespacedKubernetesClient -import mu.KotlinLogging - -private val logger = KotlinLogging.logger {} - -/** - * Used to reset the KafkaLagExporter by deleting the pod. - * @param client NamespacedKubernetesClient used for the deletion. - */ -// TODO(Maybe we can add support to delete arbitrary resources (kinds), -// then we can use this class also inside the ClusterSetup class instead of the clearByLabel function.) -class ResourceByLabelRemover(private val client: NamespacedKubernetesClient) { - - /** - * Deletes all pods with the selected label. - * @param [label] of the pod that should be deleted. - */ - fun removePod(label: String) { - this.client.pods().withLabel(label).delete() - logger.info { "Pod with label: $label deleted" } - } -} diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt index 3afc85f0a8cb67011763498a662b447ce2c07f0f..4908cfa31b855e7968fda2a62df463ab9e1a3efc 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt @@ -5,7 +5,10 @@ import mu.KotlinLogging import theodolite.benchmark.Benchmark import theodolite.benchmark.BenchmarkExecution import theodolite.evaluation.AnalysisExecutor -import theodolite.util.* +import theodolite.util.ConfigurationOverride +import theodolite.util.LoadDimension +import theodolite.util.Resource +import theodolite.util.Results import java.time.Duration import java.time.Instant @@ -53,6 +56,7 @@ class BenchmarkExecutorImpl( private fun runSingleExperiment(load: LoadDimension, res: Resource): Pair<Instant, Instant> { val benchmarkDeployment = benchmark.buildDeployment(load, res, this.configurationOverrides, this.loadGenerationDelay, this.afterTeardownDelay) val from = Instant.now() + // TODO(restructure try catch in order to throw exceptions if there are significant problems by running a experiment) try { benchmarkDeployment.setup() this.waitAndLog() diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/Main.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/Main.kt index bf883529967a8b24229fe8256ba0e4edd11b342c..7d5fca859422a194e81468d9766a9e7ba29fb998 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/Main.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/Main.kt @@ -17,8 +17,8 @@ object Main { logger.info { "Start Theodolite with mode $mode" } when (mode) { - "standalone" -> TheodoliteYamlExecutor().start() - "yaml-executor" -> TheodoliteYamlExecutor().start() // TODO remove (#209) + "standalone" -> TheodoliteStandalone().start() + "yaml-executor" -> TheodoliteStandalone().start() // TODO remove (#209) "operator" -> TheodoliteOperator().start() else -> { logger.error { "MODE $mode not found" } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/Shutdown.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/Shutdown.kt index 0ff8379a0af4b11154214dde021d7c60609631d1..8317ba980eb36eed46ee5954d1e41fb20e9caf37 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/Shutdown.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/Shutdown.kt @@ -5,7 +5,6 @@ import theodolite.benchmark.BenchmarkExecution import theodolite.benchmark.KubernetesBenchmark import theodolite.util.LoadDimension import theodolite.util.Resource -import java.lang.Exception private val logger = KotlinLogging.logger {} @@ -36,11 +35,12 @@ class Shutdown(private val benchmarkExecution: BenchmarkExecution, private val b ) deployment.teardown() } catch (e: Exception) { + // TODO(throw exception in order to make it possible to mark an experiment as unsuccessfully) logger.warn { "Could not delete all specified resources from Kubernetes. " + "This could be the case, if not all resources are deployed and running." } } - logger.info { "Teardown everything deployed" } - logger.info { "Teardown completed" } + logger.info { "Teardown everything deployed. " + + "\n Teardown completed" } } } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt index c73aaae08489c25a40163d4edb1607247fae010a..97d658743580ad78c989b9f61da74bf4e3292e45 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt @@ -103,10 +103,6 @@ class TheodoliteExecutor( return this.config } - fun getBenchmark(): KubernetesBenchmark { - return this.kubernetesBenchmark - } - /** * Run all experiments which are specified in the corresponding * execution and benchmark objects. diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteStandalone.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteStandalone.kt index 847d9c30666283df6233d3d791a6dca9b81eeb7a..941868e9b19b3059ee1260e05a1b3df0b27b04f5 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteStandalone.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteStandalone.kt @@ -25,8 +25,7 @@ private val logger = KotlinLogging.logger {} * * @constructor Create empty Theodolite yaml executor */ -// TODO(rename class to standaloneMode or similar) -class TheodoliteYamlExecutor { +class TheodoliteStandalone { private val parser = YamlParser() fun start() { diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt index a7a40cd569f8034f3b8e062dad3031d5643a12e3..5ff822e794445eb070f9755590485ab9754fe716 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt @@ -4,13 +4,13 @@ import io.fabric8.kubernetes.api.model.HasMetadata import io.fabric8.kubernetes.api.model.KubernetesResourceList import io.fabric8.kubernetes.api.model.Namespaced import io.fabric8.kubernetes.client.CustomResource -import io.fabric8.kubernetes.client.KubernetesClient +import io.fabric8.kubernetes.client.NamespacedKubernetesClient import io.fabric8.kubernetes.client.dsl.MixedOperation import io.fabric8.kubernetes.client.dsl.Resource import java.lang.Thread.sleep abstract class AbstractStateHandler<T,L,D>( - private val client: KubernetesClient, + private val client: NamespacedKubernetesClient, private val crd: Class<T>, private val crdList: Class<L> ): StateHandler<T> where T : CustomResource<*, *>?, T: HasMetadata, T: Namespaced, L: KubernetesResourceList<T> { @@ -21,9 +21,8 @@ abstract class AbstractStateHandler<T,L,D>( @Synchronized override fun setState(resourceName: String, f: (T) -> T?) { this.crdClient - .inNamespace(this.client.namespace) .list().items - .filter { item -> item.metadata.name == resourceName } + .filter {it.metadata.name == resourceName } .map { customResource -> f(customResource) } .forEach { this.crdClient.updateStatus(it) } } @@ -31,9 +30,8 @@ abstract class AbstractStateHandler<T,L,D>( @Synchronized override fun getState(resourceName: String, f: (T) -> String?): String? { return this.crdClient - .inNamespace(this.client.namespace) .list().items - .filter { item -> item.metadata.name == resourceName } + .filter {it.metadata.name == resourceName } .map { customResource -> f(customResource) } .firstOrNull() } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt index df5e77695d1beb562408f1b5830f6f4353543c75..425127eeab097a06e9543594db7e1182f8dd946e 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt @@ -1,6 +1,6 @@ package theodolite.execution.operator -import io.fabric8.kubernetes.client.KubernetesClient +import io.fabric8.kubernetes.client.NamespacedKubernetesClient import theodolite.model.crd.BenchmarkExecutionList import theodolite.model.crd.ExecutionCRD import theodolite.model.crd.ExecutionStatus @@ -10,7 +10,7 @@ import java.time.Duration import java.time.Instant import java.util.concurrent.atomic.AtomicBoolean -class ExecutionStateHandler(val client: KubernetesClient): +class ExecutionStateHandler(val client: NamespacedKubernetesClient): AbstractStateHandler<ExecutionCRD, BenchmarkExecutionList, ExecutionStatus >( client = client, crd = ExecutionCRD::class.java, diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/LeaderElector.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/LeaderElector.kt index 9d093e4851e5c43d29a3fea3057ccf01be612e63..98aea0444987126840d2c3ebbe713284cfb2f8c0 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/LeaderElector.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/LeaderElector.kt @@ -17,6 +17,7 @@ class LeaderElector( val name: String ) { + // TODO(what is the name of the lock? .withName() or LeaseLock(..,name..) ?) fun getLeadership(leader: KFunction0<Unit>) { val lockIdentity: String = UUID.randomUUID().toString() DefaultKubernetesClient().use { kc -> 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 6bcff9aeed2e756f115f27fbf25cc2aa35230d2d..751ceb9a94220e7cdda86b81b3431a970b69858d 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt @@ -7,8 +7,8 @@ import theodolite.benchmark.BenchmarkExecution import theodolite.benchmark.KubernetesBenchmark import theodolite.execution.TheodoliteExecutor import theodolite.model.crd.* -import theodolite.util.ConfigurationOverride -import theodolite.util.PatcherDefinition +import theodolite.patcher.ConfigOverrideModifier +import theodolite.util.ExecutionComparator import java.lang.Thread.sleep private val logger = KotlinLogging.logger {} @@ -22,7 +22,6 @@ private val logger = KotlinLogging.logger {} */ class TheodoliteController( - val path: String, private val executionCRDClient: MixedOperation<ExecutionCRD, BenchmarkExecutionList, Resource<ExecutionCRD>>, private val benchmarkCRDClient: MixedOperation<BenchmarkCRD, KubernetesBenchmarkList, Resource<BenchmarkCRD>>, private val executionStateHandler: ExecutionStateHandler @@ -61,18 +60,21 @@ class TheodoliteController( * @see BenchmarkExecution */ private fun runExecution(execution: BenchmarkExecution, benchmark: KubernetesBenchmark) { - setAdditionalLabels(execution.name, - "deployed-for-execution", - benchmark.appResource + benchmark.loadGenResource, - execution) - setAdditionalLabels(benchmark.name, - "deployed-for-benchmark", - benchmark.appResource + benchmark.loadGenResource, - execution) - setAdditionalLabels("theodolite", - "app.kubernetes.io/created-by", - benchmark.appResource + benchmark.loadGenResource, - execution) + val modifier = ConfigOverrideModifier( + execution = execution, + resources = benchmark.appResource + benchmark.loadGenResource) + modifier.setAdditionalLabels( + labelValue = execution.name, + labelName = "deployed-for-execution" + ) + modifier.setAdditionalLabels( + labelValue = benchmark.name, + labelName = "deployed-for-benchmark" + ) + modifier.setAdditionalLabels( + labelValue = "theodolite", + labelName = "app.kubernetes.io/created-by" + ) executionStateHandler.setExecutionState(execution.name, States.RUNNING) executionStateHandler.startDurationStateTimer(execution.name) @@ -100,9 +102,6 @@ class TheodoliteController( if (!::executor.isInitialized) return if (restart) { executionStateHandler.setExecutionState(this.executor.getExecution().name, States.RESTART) - } else { - executionStateHandler.setExecutionState(this.executor.getExecution().name, States.INTERRUPTED) - logger.warn { "Execution ${executor.getExecution().name} unexpected interrupted" } } this.executor.executor.run.set(false) } @@ -114,9 +113,10 @@ class TheodoliteController( return this.benchmarkCRDClient .list() .items - .map { it.spec.name = it.metadata.name; it } - .map { it.spec.path = path; it } // TODO check if we can remove the path field from the KubernetesBenchmark - .map { it.spec } + .map { + it.spec.name = it.metadata.name; + it.spec + } } /** @@ -131,6 +131,7 @@ class TheodoliteController( * @return the next execution or null */ private fun getNextExecution(): BenchmarkExecution? { + val comparator = ExecutionComparator().compareByState(States.RESTART) val availableBenchmarkNames = getBenchmarks() .map { it.name } @@ -144,46 +145,13 @@ class TheodoliteController( it.status.executionState == States.RESTART.value } .filter { availableBenchmarkNames.contains(it.spec.benchmark) } - .sortedWith(stateComparator().thenBy { it.metadata.creationTimestamp }) + .sortedWith(comparator.thenBy { it.metadata.creationTimestamp }) .map { it.spec } .firstOrNull() } - /** - * Simple comparator which can be used to order a list of [ExecutionCRD] such that executions with - * status [States.RESTART] are before all other executions. - */ - private fun stateComparator() = Comparator<ExecutionCRD> { a, b -> - when { - (a == null && b == null) -> 0 - (a.status.executionState == States.RESTART.value) -> -1 - else -> 1 - } - } - fun isExecutionRunning(executionName: String): Boolean { if (!::executor.isInitialized) return false return this.executor.getExecution().name == executionName } - - private fun setAdditionalLabels( - labelValue: String, - labelName: String, - resources: List<String>, - execution: BenchmarkExecution - ) { - val additionalConfigOverrides = mutableListOf<ConfigurationOverride>() - resources.forEach { - run { - val configurationOverride = ConfigurationOverride() - configurationOverride.patcher = PatcherDefinition() - configurationOverride.patcher.type = "LabelPatcher" - configurationOverride.patcher.properties = mutableMapOf("variableName" to labelName) - configurationOverride.patcher.resource = it - configurationOverride.value = labelValue - additionalConfigOverrides.add(configurationOverride) - } - } - execution.configOverrides.addAll(additionalConfigOverrides) - } } \ No newline at end of file diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt index 5318abc174d9204c19466729698a63f2ad29a54c..7896e5908ac96236fda1ab7a4020d09645aedc56 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt @@ -28,7 +28,6 @@ private val logger = KotlinLogging.logger {} */ class TheodoliteOperator { private val namespace = System.getenv("NAMESPACE") ?: DEFAULT_NAMESPACE - private val appResource = System.getenv("THEODOLITE_APP_RESOURCES") ?: "./config" private val client: NamespacedKubernetesClient = DefaultKubernetesClient().inNamespace(namespace) private lateinit var controller: TheodoliteController @@ -38,7 +37,7 @@ class TheodoliteOperator { fun start() { LeaderElector( client = client, - name = "theodolite-operator" + name = "theodolite-operator" // TODO(make leaslock name configurable via env var) ) .getLeadership(::startOperator) } @@ -105,7 +104,6 @@ class TheodoliteOperator { ): TheodoliteController { if (!::controller.isInitialized) { this.controller = TheodoliteController( - path = this.appResource, benchmarkCRDClient = getBenchmarkClient(client), executionCRDClient = getExecutionClient(client), executionStateHandler = executionStateHandler diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/ResourceByLabelHandler.kt b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/ResourceByLabelHandler.kt new file mode 100644 index 0000000000000000000000000000000000000000..be0247d5b0351d2c7acec84d5bdad99376f7d9a7 --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/ResourceByLabelHandler.kt @@ -0,0 +1,68 @@ +package theodolite.k8s + +import io.fabric8.kubernetes.client.NamespacedKubernetesClient +import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext +import mu.KotlinLogging +import org.json.JSONObject + +private val logger = KotlinLogging.logger {} + +/** + * Used to reset the KafkaLagExporter by deleting the pod. + * @param client NamespacedKubernetesClient used for the deletion. + */ +// TODO(Maybe we can add support to delete arbitrary resources (kinds), +// then we can use this class also inside the ClusterSetup class instead of the clearByLabel function.) +class ResourceByLabelRemover(private val client: NamespacedKubernetesClient) { + + /** + * Deletes all pods with the selected label. + * @param [label] of the pod that should be deleted. + */ + fun removePods(label: String) { + this.client.pods().withLabel(label).delete() + logger.info { "Pod with label: $label deleted" } + } + + fun removeServices(labelName: String, labelValue: String) { + this.client + .services() + .withLabel("$labelName=$labelValue") + .delete() + } + + fun removeDeployments(labelName: String, labelValue: String){ + this.client + .apps() + .deployments() + .withLabel("$labelName=$labelValue") + .delete() + + } + fun removeStateFulSets(labelName: String, labelValue: String) { + this.client + .apps() + .statefulSets() + .withLabel("$labelName=$labelValue") + .delete() + } + + fun removeConfigMaps(labelName: String, labelValue: String){ + this.client + .configMaps() + .withLabel("$labelName=$labelValue") + .delete() + } + + fun removeCR(labelName: String, labelValue: String, context: CustomResourceDefinitionContext) { + val customResources = JSONObject( + this.client.customResource(context) + .list(client.namespace, mapOf(Pair(labelName, labelValue))) + ) + .getJSONArray("items") + + (0 until customResources.length()) + .map { customResources.getJSONObject(it).getJSONObject("metadata").getString("name") } + .forEach { this.client.customResource(context).delete(client.namespace, it) } + } +} diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ConfigOverrideModifier.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ConfigOverrideModifier.kt new file mode 100644 index 0000000000000000000000000000000000000000..447194d9af3b816e30ef435403b3056a4aecfeb4 --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ConfigOverrideModifier.kt @@ -0,0 +1,39 @@ +package theodolite.patcher + +import theodolite.benchmark.BenchmarkExecution +import theodolite.util.ConfigurationOverride +import theodolite.util.PatcherDefinition + +/** + * The ConfigOverrideModifier makes it possible to update the configuration overrides of a execution. + * + * @property execution execution for which the config overrides should be updated + * @property resources list of all resources that should be updated. + */ +class ConfigOverrideModifier(val execution: BenchmarkExecution, val resources: List<String>) { + + /** + * Adds a [LabelPatcher] to the configOverrides. + * + * @param labelValue value argument for the label patcher + * @param labelName label name argument for the label patcher + */ + fun setAdditionalLabels( + labelValue: String, + labelName: String + ) { + val additionalConfigOverrides = mutableListOf<ConfigurationOverride>() + resources.forEach { + run { + val configurationOverride = ConfigurationOverride() + configurationOverride.patcher = PatcherDefinition() + configurationOverride.patcher.type = "LabelPatcher" + configurationOverride.patcher.properties = mutableMapOf("variableName" to labelName) + configurationOverride.patcher.resource = it + configurationOverride.value = labelValue + additionalConfigOverrides.add(configurationOverride) + } + } + execution.configOverrides.addAll(additionalConfigOverrides) + } +} \ No newline at end of file diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherFactory.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherFactory.kt index 45e50113c964d671962fadc718994a29b2da81f4..6ba34d1507be488fb99a2ddf75aa3bc12f627bb3 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherFactory.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherFactory.kt @@ -74,6 +74,10 @@ class PatcherFactory { k8sResource = resource, variableName = patcherDefinition.properties["variableName"] !! ) + "ImagePatcher" -> ImagePatcher( + k8sResource = resource, + container = patcherDefinition.properties["container"] !! + ) else -> throw InvalidPatcherConfigurationException("Patcher type ${patcherDefinition.type} not found.") } } catch (e: Exception) { diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ResourceLimitPatcher.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ResourceLimitPatcher.kt index 1a6fa35a944d00634ec0607b0bff34f4cb9d9b9c..9dcdffa0407dd4fdaf2d9b0a898bcdf6cebe5a8b 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ResourceLimitPatcher.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ResourceLimitPatcher.kt @@ -6,6 +6,7 @@ import io.fabric8.kubernetes.api.model.Quantity import io.fabric8.kubernetes.api.model.ResourceRequirements import io.fabric8.kubernetes.api.model.apps.Deployment import io.fabric8.kubernetes.api.model.apps.StatefulSet +import theodolite.util.InvalidPatcherConfigurationException /** * The Resource limit [Patcher] set resource limits for deployments and statefulSets. @@ -33,7 +34,7 @@ class ResourceLimitPatcher( } } else -> { - throw IllegalArgumentException("ResourceLimitPatcher not applicable for $k8sResource") + throw InvalidPatcherConfigurationException("ResourceLimitPatcher not applicable for $k8sResource") } } } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ResourceRequestPatcher.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ResourceRequestPatcher.kt index 9bf8c3c72f656d326ca3070cd5843778e5cdff42..24cdde40f7f78bd67d115b2dc44f47e180f51ee2 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ResourceRequestPatcher.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ResourceRequestPatcher.kt @@ -6,6 +6,7 @@ import io.fabric8.kubernetes.api.model.Quantity import io.fabric8.kubernetes.api.model.ResourceRequirements import io.fabric8.kubernetes.api.model.apps.Deployment import io.fabric8.kubernetes.api.model.apps.StatefulSet +import theodolite.util.InvalidPatcherConfigurationException /** * The Resource request [Patcher] set resource limits for deployments and statefulSets. @@ -33,7 +34,7 @@ class ResourceRequestPatcher( } } else -> { - throw IllegalArgumentException("ResourceRequestPatcher not applicable for $k8sResource") + throw InvalidPatcherConfigurationException("ResourceRequestPatcher not applicable for $k8sResource") } } } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/util/ExecutionComparator.kt b/theodolite-quarkus/src/main/kotlin/theodolite/util/ExecutionComparator.kt new file mode 100644 index 0000000000000000000000000000000000000000..ab3b80768533a9de4826503cfebcce22fcf835ac --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/util/ExecutionComparator.kt @@ -0,0 +1,19 @@ +package theodolite.util + +import theodolite.model.crd.ExecutionCRD +import theodolite.model.crd.States + +class ExecutionComparator { + + /** + * Simple comparator which can be used to order a list of [ExecutionCRD] such that executions with + * status [States.RESTART] are before all other executions. + */ + fun compareByState(preferredState: States) = Comparator<ExecutionCRD> { a, b -> + when { + (a == null && b == null) -> 0 + (a.status.executionState == preferredState.value) -> -1 + else -> 1 + } + } +} \ No newline at end of file diff --git a/theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt b/theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt index 7ed868c7adc4afcd7a6a606d22124c92910ecd89..53316422147280df7518585ffa9f3d2c375acf3d 100644 --- a/theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt +++ b/theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt @@ -132,43 +132,4 @@ class ControllerTest { gson.toJson(result) ) } - - @Test - fun setAdditionalLabelsTest() { - val method = controller - .javaClass - .getDeclaredMethod( - "setAdditionalLabels", - String::class.java, - String::class.java, - List::class.java, - BenchmarkExecution::class.java - ) - method.isAccessible = true - - this.benchmark.appResource = listOf("test-resource.yaml") - - method.invoke( - controller, - "test-value", - "test-name", - this.benchmark.appResource, - this.execution - ) as BenchmarkExecution? - - assertEquals( - "test-name", - this.execution - .configOverrides.firstOrNull() - ?.patcher - ?.properties - ?.get("variableName") - ) - assertEquals( - "test-value", - this.execution - .configOverrides.firstOrNull() - ?.value - ) - } } \ No newline at end of file