diff --git a/docs/api-reference/crds.md b/docs/api-reference/crds.md index 6bcd35d095ecd988c45c6c6eb201e2c5203f627f..c6600bb051223d2bf41e033a7011f368f54b2968 100644 --- a/docs/api-reference/crds.md +++ b/docs/api-reference/crds.md @@ -2089,20 +2089,6 @@ Specifies the scaling resource that is benchmarked. The name of the SLO. It must match a SLO specified in the Benchmark.<br/> </td> <td>true</td> - </tr><tr> - <td><b>offset</b></td> - <td>integer</td> - <td> - Hours by which the start and end timestamp will be shifted (for different timezones).<br/> - </td> - <td>false</td> - </tr><tr> - <td><b>prometheusUrl</b></td> - <td>string</td> - <td> - Connection string for Promehteus.<br/> - </td> - <td>false</td> </tr><tr> <td><b>properties</b></td> <td>map[string]string</td> @@ -2111,14 +2097,7 @@ Specifies the scaling resource that is benchmarked. <br/> <i>Default</i>: map[]<br/> </td> - <td>false</td> - </tr><tr> - <td><b>sloType</b></td> - <td>string</td> - <td> - The type of the SLO. It must match 'lag trend'.<br/> - </td> - <td>false</td> + <td>true</td> </tr></tbody> </table> diff --git a/theodolite/crd/crd-execution.yaml b/theodolite/crd/crd-execution.yaml index bc73b84c3dcce8ff90862f26c70e017782a02d15..a9da4644e35509d36afccfa173fe9c0d794e2105 100644 --- a/theodolite/crd/crd-execution.yaml +++ b/theodolite/crd/crd-execution.yaml @@ -60,21 +60,11 @@ spec: type: array items: type: object - required: ["name"] + required: ["name", "properties"] properties: name: description: The name of the SLO. It must match a SLO specified in the Benchmark. type: string - # TODO Do we need to keep it here or just move to the Benchmark? Does it make sense to override the type at this point? - sloType: - description: The type of the SLO. It must match 'lag trend'. - type: string - prometheusUrl: - description: Connection string for Promehteus. - type: string - offset: - description: Hours by which the start and end timestamp will be shifted (for different timezones). - type: integer properties: description: (Optional) SLO specific additional arguments. type: object diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt b/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt index 02e9553d2fd4c156b3dff41f2dd2d9e08352b97d..5ab220bb8edde9752eb8e7f83117dae5addf26ca 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt +++ b/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt @@ -14,7 +14,7 @@ import kotlin.properties.Delegates * - The [benchmark] that should be executed. * - The [load] that should be checked in the benchmark. * - The [resources] that should be checked in the benchmark. - * - A list of [slos] that are used for the evaluation of the experiments. + * - The [slos] further restrict the Benchmark SLOs for the evaluation of the experiments. * - An [execution] that encapsulates: the strategy, the duration, and the restrictions * for the execution of the benchmark. * - [configOverrides] additional configurations. @@ -30,7 +30,7 @@ class BenchmarkExecution : KubernetesResource { lateinit var benchmark: String lateinit var load: LoadDefinition lateinit var resources: ResourceDefinition - lateinit var slos: List<Slo> + lateinit var slos: List<SloConfiguration> lateinit var execution: Execution lateinit var configOverrides: MutableList<ConfigurationOverride?> @@ -50,19 +50,12 @@ class BenchmarkExecution : KubernetesResource { } /** - * Measurable metric. - * It is evaluated using the [theodolite.evaluation.ExternalSloChecker] by data measured by Prometheus. - * The evaluation checks if a [threshold] is reached or not. - * [offset] determines the shift in hours by which the start and end timestamps should be shifted. - * The [warmup] determines after which time the metric should be evaluated to avoid starting interferences. - * The [warmup] time unit depends on the Slo: for the lag trend it is in seconds. + * Further SLO configurations for the SLOs specified in the Benchmark. */ @JsonDeserialize @RegisterForReflection - class Slo : KubernetesResource { + class SloConfiguration : KubernetesResource { lateinit var name: String - var prometheusUrl: String? = null - var offset : Int? = null var properties: MutableMap<String, String>? = null } diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt b/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt index d4f9f58fc5b8e43dbfc0e827e105fad8ddc3ebcd..ef692c103d885e9fbc5eef4f414918758c799d77 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt +++ b/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt @@ -10,7 +10,6 @@ import theodolite.k8s.K8sManager import theodolite.k8s.resourceLoader.K8sResourceLoader import theodolite.patcher.PatcherFactory import theodolite.util.* -import kotlin.properties.Delegates private val logger = KotlinLogging.logger {} @@ -47,25 +46,6 @@ class KubernetesBenchmark : KubernetesResource, Benchmark { lateinit var loadGenerator: Resources private var namespace = System.getenv("NAMESPACE") ?: DEFAULT_NAMESPACE - /** - * Measurable metric. - * [sloType] determines the type of the metric. - * It is evaluated using the [theodolite.evaluation.ExternalSloChecker] by data measured by Prometheus. - * The evaluation checks if a [threshold] is reached or not. - * [offset] determines the shift in hours by which the start and end timestamps should be shifted. - * The [warmup] determines after which time the metric should be evaluated to avoid starting interferences. - * The [warmup] time unit depends on the Slo: for the lag trend it is in seconds. - */ - @JsonDeserialize - @RegisterForReflection - class Slo : KubernetesResource { - lateinit var name: String - lateinit var sloType: String - lateinit var prometheusUrl: String - var offset by Delegates.notNull<Int>() - lateinit var properties: MutableMap<String, String> - } - @Transient private var client: NamespacedKubernetesClient = DefaultKubernetesClient().inNamespace(namespace) diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/Slo.kt b/theodolite/src/main/kotlin/theodolite/benchmark/Slo.kt new file mode 100644 index 0000000000000000000000000000000000000000..c9aac4a1b68692669f0db577003856b964ade4ec --- /dev/null +++ b/theodolite/src/main/kotlin/theodolite/benchmark/Slo.kt @@ -0,0 +1,25 @@ +package theodolite.benchmark + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import io.fabric8.kubernetes.api.model.KubernetesResource +import io.quarkus.runtime.annotations.RegisterForReflection +import kotlin.properties.Delegates + +/** + * Measurable metric. + * [sloType] determines the type of the metric. + * It is evaluated using the [theodolite.evaluation.ExternalSloChecker] by data measured by Prometheus. + * The evaluation checks if a [threshold] is reached or not. + * [offset] determines the shift in hours by which the start and end timestamps should be shifted. + * The [warmup] determines after which time the metric should be evaluated to avoid starting interferences. + * The [warmup] time unit depends on the Slo: for the lag trend it is in seconds. + */ +@JsonDeserialize +@RegisterForReflection +class Slo : KubernetesResource { + lateinit var name: String + lateinit var sloType: String + lateinit var prometheusUrl: String + var offset by Delegates.notNull<Int>() + lateinit var properties: MutableMap<String, String> +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt b/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt index 9ac78b78f947233abe56c67a040d370df0ae2322..c630b49846b09cb21dfd64a90a6f909701579a51 100644 --- a/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt +++ b/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt @@ -1,6 +1,6 @@ package theodolite.evaluation -import theodolite.benchmark.KubernetesBenchmark +import theodolite.benchmark.Slo import theodolite.util.EvaluationFailedException import theodolite.util.IOHandler import theodolite.util.LoadDimension @@ -16,7 +16,7 @@ import java.util.regex.Pattern * @param slo Slo that is used for the analysis. */ class AnalysisExecutor( - private val slo: KubernetesBenchmark.Slo, + private val slo: Slo, private val executionId: Int ) { diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/SloConfigHandler.kt b/theodolite/src/main/kotlin/theodolite/evaluation/SloConfigHandler.kt index b3e13362b079d387ba0dde32adc8b49ad82198d8..77968d6ce98b922bd65b704ce62642def6fa6b25 100644 --- a/theodolite/src/main/kotlin/theodolite/evaluation/SloConfigHandler.kt +++ b/theodolite/src/main/kotlin/theodolite/evaluation/SloConfigHandler.kt @@ -1,6 +1,6 @@ package theodolite.evaluation -import theodolite.benchmark.KubernetesBenchmark +import theodolite.benchmark.Slo import theodolite.util.InvalidPatcherConfigurationException import javax.enterprise.context.ApplicationScoped @@ -10,7 +10,7 @@ private const val DROPPED_RECORDS_QUERY = "sum by(job) (kafka_streams_stream_tas @ApplicationScoped class SloConfigHandler { companion object { - fun getQueryString(slo: KubernetesBenchmark.Slo): String { + fun getQueryString(slo: Slo): String { return when (slo.sloType.lowercase()) { SloTypes.GENERIC.value -> slo.properties["promQLQuery"] ?: throw IllegalArgumentException("promQLQuery expected") SloTypes.LAG_TREND.value, SloTypes.LAG_TREND_RATIO.value -> CONSUMER_LAG_QUERY diff --git a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt b/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt index 95b2abeaafcb6537e216fceb27186058be04400a..f66d4b76e3a55820bf2d6fb7b328cd36b14002e3 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt +++ b/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt @@ -2,7 +2,7 @@ package theodolite.execution import mu.KotlinLogging import theodolite.benchmark.Benchmark -import theodolite.benchmark.KubernetesBenchmark +import theodolite.benchmark.Slo import theodolite.util.ConfigurationOverride import theodolite.util.LoadDimension import theodolite.util.Resource @@ -25,7 +25,7 @@ abstract class BenchmarkExecutor( val results: Results, val executionDuration: Duration, val configurationOverrides: List<ConfigurationOverride?>, - val slos: List<KubernetesBenchmark.Slo>, + val slos: List<Slo>, val repetitions: Int, val executionId: Int, val loadGenerationDelay: Long, diff --git a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt b/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt index 415fd1976a4cafe8a71a6b13fc62dff8d73b7ecf..0b7c56f1b8ac748a99f0c87522cf43e77d956a02 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt +++ b/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt @@ -3,7 +3,7 @@ package theodolite.execution import io.quarkus.runtime.annotations.RegisterForReflection import mu.KotlinLogging import theodolite.benchmark.Benchmark -import theodolite.benchmark.KubernetesBenchmark +import theodolite.benchmark.Slo import theodolite.evaluation.AnalysisExecutor import theodolite.execution.operator.EventCreator import theodolite.util.* @@ -18,7 +18,7 @@ class BenchmarkExecutorImpl( results: Results, executionDuration: Duration, configurationOverrides: List<ConfigurationOverride?>, - slos: List<KubernetesBenchmark.Slo>, + slos: List<Slo>, repetitions: Int, executionId: Int, loadGenerationDelay: Long, diff --git a/theodolite/src/main/kotlin/theodolite/execution/SloFactory.kt b/theodolite/src/main/kotlin/theodolite/execution/SloFactory.kt index 966e19bdc5089f70e593a49dbc556ae3424fbbe6..b990828fa1db09532767b9f9255aa53e9c9e894a 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/SloFactory.kt +++ b/theodolite/src/main/kotlin/theodolite/execution/SloFactory.kt @@ -2,22 +2,19 @@ package theodolite.execution import theodolite.benchmark.BenchmarkExecution import theodolite.benchmark.KubernetesBenchmark +import theodolite.benchmark.Slo class SloFactory { - fun createSlos(execution: BenchmarkExecution, benchmark: KubernetesBenchmark): List<KubernetesBenchmark.Slo> { + fun createSlos(execution: BenchmarkExecution, benchmark: KubernetesBenchmark): List<Slo> { var benchmarkSlos = benchmark.slos var executionSlos = execution.slos for(executionSlo in executionSlos) { - for(i in 0..benchmarkSlos.size) { - if(executionSlo.name == benchmarkSlos[i].name) { - benchmarkSlos[i].offset = executionSlo.offset ?: benchmarkSlos[i].offset - benchmarkSlos[i].prometheusUrl = executionSlo.prometheusUrl ?: benchmarkSlos[i].prometheusUrl - if (executionSlo.properties != null) { - for (executionProperty in executionSlo.properties!!) { - benchmarkSlos[i].properties[executionProperty.key] = executionProperty.value - } + for(i in 0 until benchmarkSlos.size) { + if(executionSlo.name == benchmarkSlos[i].name && executionSlo.properties != null) { + for (executionProperty in executionSlo.properties!!) { + benchmarkSlos[i].properties[executionProperty.key] = executionProperty.value } } } diff --git a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt b/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt index 6f6227fb7b7074e8e8d96cbef7fada1b86ad9226..da88d47392480625cae8c940d459528ee91a5445 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt +++ b/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt @@ -16,13 +16,13 @@ private val logger = KotlinLogging.logger {} /** * The Theodolite executor runs all the experiments defined with the given execution and benchmark configuration. * - * @property config Configuration of a execution + * @property benchmarkExecution Configuration of a execution * @property kubernetesBenchmark Configuration of a benchmark * @constructor Create empty Theodolite executor */ class TheodoliteExecutor( - private val config: BenchmarkExecution, - private val kubernetesBenchmark: KubernetesBenchmark + private val benchmarkExecution: BenchmarkExecution, + private val kubernetesBenchmark: KubernetesBenchmark ) { /** * An executor object, configured with the specified benchmark, evaluation method, experiment duration @@ -41,56 +41,55 @@ class TheodoliteExecutor( val results = Results() val strategyFactory = StrategyFactory() - val executionDuration = Duration.ofSeconds(config.execution.duration) + val executionDuration = Duration.ofSeconds(benchmarkExecution.execution.duration) val resourcePatcherDefinition = PatcherDefinitionFactory().createPatcherDefinition( - config.resources.resourceType, + benchmarkExecution.resources.resourceType, this.kubernetesBenchmark.resourceTypes ) val loadDimensionPatcherDefinition = PatcherDefinitionFactory().createPatcherDefinition( - config.load.loadType, + benchmarkExecution.load.loadType, this.kubernetesBenchmark.loadTypes ) - val slos = SloFactory().createSlos(this.config, this.kubernetesBenchmark) + val slos = SloFactory().createSlos(this.benchmarkExecution, this.kubernetesBenchmark) - // TODO not config.slos!, maybe change naming here cause its kinda missleading due to the Config.kt file executor = BenchmarkExecutorImpl( benchmark = kubernetesBenchmark, results = results, executionDuration = executionDuration, - configurationOverrides = config.configOverrides, + configurationOverrides = benchmarkExecution.configOverrides, slos = slos, - repetitions = config.execution.repetitions, - executionId = config.executionId, - loadGenerationDelay = config.execution.loadGenerationDelay, - afterTeardownDelay = config.execution.afterTeardownDelay, - executionName = config.name + repetitions = benchmarkExecution.execution.repetitions, + executionId = benchmarkExecution.executionId, + loadGenerationDelay = benchmarkExecution.execution.loadGenerationDelay, + afterTeardownDelay = benchmarkExecution.execution.afterTeardownDelay, + executionName = benchmarkExecution.name ) - if (config.load.loadValues != config.load.loadValues.sorted()) { - config.load.loadValues = config.load.loadValues.sorted() + if (benchmarkExecution.load.loadValues != benchmarkExecution.load.loadValues.sorted()) { + benchmarkExecution.load.loadValues = benchmarkExecution.load.loadValues.sorted() logger.info { "Load values are not sorted correctly, Theodolite sorts them in ascending order." + - "New order is: ${config.load.loadValues}" + "New order is: ${benchmarkExecution.load.loadValues}" } } - if (config.resources.resourceValues != config.resources.resourceValues.sorted()) { - config.resources.resourceValues = config.resources.resourceValues.sorted() + if (benchmarkExecution.resources.resourceValues != benchmarkExecution.resources.resourceValues.sorted()) { + benchmarkExecution.resources.resourceValues = benchmarkExecution.resources.resourceValues.sorted() logger.info { "Load values are not sorted correctly, Theodolite sorts them in ascending order." + - "New order is: ${config.resources.resourceValues}" + "New order is: ${benchmarkExecution.resources.resourceValues}" } } return Config( - loads = config.load.loadValues.map { load -> LoadDimension(load, loadDimensionPatcherDefinition) }, - resources = config.resources.resourceValues.map { resource -> + loads = benchmarkExecution.load.loadValues.map { load -> LoadDimension(load, loadDimensionPatcherDefinition) }, + resources = benchmarkExecution.resources.resourceValues.map { resource -> Resource( resource, resourcePatcherDefinition @@ -98,17 +97,17 @@ class TheodoliteExecutor( }, compositeStrategy = CompositeStrategy( benchmarkExecutor = executor, - searchStrategy = strategyFactory.createSearchStrategy(executor, config.execution.strategy), + searchStrategy = strategyFactory.createSearchStrategy(executor, benchmarkExecution.execution.strategy), restrictionStrategies = strategyFactory.createRestrictionStrategy( results, - config.execution.restrictions + benchmarkExecution.execution.restrictions ) ) ) } fun getExecution(): BenchmarkExecution { - return this.config + return this.benchmarkExecution } /** @@ -120,11 +119,11 @@ class TheodoliteExecutor( val ioHandler = IOHandler() val resultsFolder = ioHandler.getResultFolderURL() - this.config.executionId = getAndIncrementExecutionID(resultsFolder + "expID.txt") - ioHandler.writeToJSONFile(this.config, "${resultsFolder}exp${this.config.executionId}-execution-configuration") + this.benchmarkExecution.executionId = getAndIncrementExecutionID(resultsFolder + "expID.txt") + ioHandler.writeToJSONFile(this.benchmarkExecution, "${resultsFolder}exp${this.benchmarkExecution.executionId}-execution-configuration") ioHandler.writeToJSONFile( kubernetesBenchmark, - "${resultsFolder}exp${this.config.executionId}-benchmark-configuration" + "${resultsFolder}exp${this.benchmarkExecution.executionId}-benchmark-configuration" ) val config = buildConfig() @@ -138,11 +137,11 @@ class TheodoliteExecutor( } finally { ioHandler.writeToJSONFile( config.compositeStrategy.benchmarkExecutor.results, - "${resultsFolder}exp${this.config.executionId}-result" + "${resultsFolder}exp${this.benchmarkExecution.executionId}-result" ) // Create expXYZ_demand.csv file ioHandler.writeToCSVFile( - "${resultsFolder}exp${this.config.executionId}_demand", + "${resultsFolder}exp${this.benchmarkExecution.executionId}_demand", calculateDemandMetric(config.loads, config.compositeStrategy.benchmarkExecutor.results), listOf("load","resources") ) diff --git a/theodolite/src/test/kotlin/theodolite/CompositeStrategyTest.kt b/theodolite/src/test/kotlin/theodolite/CompositeStrategyTest.kt index 1d8823e288cbf81a0342813f6eb017feec064343..1d261894533d49c86e6c9abf70e38243916f4023 100644 --- a/theodolite/src/test/kotlin/theodolite/CompositeStrategyTest.kt +++ b/theodolite/src/test/kotlin/theodolite/CompositeStrategyTest.kt @@ -3,7 +3,7 @@ package theodolite import io.quarkus.test.junit.QuarkusTest import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import theodolite.benchmark.KubernetesBenchmark +import theodolite.benchmark.Slo import theodolite.strategies.restriction.LowerBoundRestriction import theodolite.strategies.searchstrategy.BinarySearch import theodolite.strategies.searchstrategy.CompositeStrategy @@ -30,7 +30,7 @@ class CompositeStrategyTest { val mockResources: List<Resource> = (0..6).map { number -> Resource(number, emptyList()) } val results = Results() val benchmark = TestBenchmark() - val sloChecker: KubernetesBenchmark.Slo = KubernetesBenchmark.Slo() + val sloChecker: Slo = Slo() val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 5) val linearSearch = LinearSearch(benchmarkExecutor) val lowerBoundRestriction = LowerBoundRestriction(results) @@ -63,7 +63,7 @@ class CompositeStrategyTest { val mockResources: List<Resource> = (0..6).map { number -> Resource(number, emptyList()) } val results = Results() val benchmark = TestBenchmark() - val sloChecker: KubernetesBenchmark.Slo = KubernetesBenchmark.Slo() + val sloChecker: Slo = Slo() val benchmarkExecutorImpl = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 0) val binarySearch = BinarySearch(benchmarkExecutorImpl) @@ -97,7 +97,7 @@ class CompositeStrategyTest { val mockResources: List<Resource> = (0..7).map { number -> Resource(number, emptyList()) } val results = Results() val benchmark = TestBenchmark() - val sloChecker: KubernetesBenchmark.Slo = KubernetesBenchmark.Slo() + val sloChecker: Slo = Slo() val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 0) val binarySearch = BinarySearch(benchmarkExecutor) val lowerBoundRestriction = LowerBoundRestriction(results) diff --git a/theodolite/src/test/kotlin/theodolite/InitialGuessSearchStrategyTest.kt b/theodolite/src/test/kotlin/theodolite/InitialGuessSearchStrategyTest.kt index 81f2107620f7ebd2174520783157acd6bdbd1b49..3f416db39d264574e828715a3e48aa26db880369 100644 --- a/theodolite/src/test/kotlin/theodolite/InitialGuessSearchStrategyTest.kt +++ b/theodolite/src/test/kotlin/theodolite/InitialGuessSearchStrategyTest.kt @@ -8,7 +8,7 @@ import theodolite.util.LoadDimension import theodolite.util.Resource import theodolite.util.Results import mu.KotlinLogging -import theodolite.benchmark.KubernetesBenchmark +import theodolite.benchmark.Slo import theodolite.strategies.searchstrategy.PrevResourceMinGuess private val logger = KotlinLogging.logger {} @@ -32,7 +32,7 @@ class InitialGuessSearchStrategyTest { val results = Results() val benchmark = TestBenchmark() val guessStrategy = PrevResourceMinGuess() - val sloChecker: KubernetesBenchmark.Slo = KubernetesBenchmark.Slo() + val sloChecker: Slo = Slo() val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 5) val strategy = InitialGuessSearchStrategy(benchmarkExecutor,guessStrategy, results) @@ -70,7 +70,7 @@ class InitialGuessSearchStrategyTest { val results = Results() val benchmark = TestBenchmark() val guessStrategy = PrevResourceMinGuess() - val sloChecker: KubernetesBenchmark.Slo = KubernetesBenchmark.Slo() + val sloChecker: Slo = Slo() val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 5) val strategy = InitialGuessSearchStrategy(benchmarkExecutor,guessStrategy, results) @@ -108,7 +108,7 @@ class InitialGuessSearchStrategyTest { val results = Results() val benchmark = TestBenchmark() val guessStrategy = PrevResourceMinGuess() - val sloChecker: KubernetesBenchmark.Slo = KubernetesBenchmark.Slo() + val sloChecker: Slo = Slo() val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 5) val strategy = InitialGuessSearchStrategy(benchmarkExecutor, guessStrategy, results) diff --git a/theodolite/src/test/kotlin/theodolite/TestBenchmarkExecutorImpl.kt b/theodolite/src/test/kotlin/theodolite/TestBenchmarkExecutorImpl.kt index 72fdc4a11733117272995169f13a5acfbd59355c..a1d9564c27453a74ebacbe5583f225884b5187ed 100644 --- a/theodolite/src/test/kotlin/theodolite/TestBenchmarkExecutorImpl.kt +++ b/theodolite/src/test/kotlin/theodolite/TestBenchmarkExecutorImpl.kt @@ -1,7 +1,7 @@ package theodolite import theodolite.benchmark.Benchmark -import theodolite.benchmark.KubernetesBenchmark +import theodolite.benchmark.Slo import theodolite.execution.BenchmarkExecutor import theodolite.util.LoadDimension import theodolite.util.Resource @@ -12,7 +12,7 @@ class TestBenchmarkExecutorImpl( private val mockResults: Array<Array<Boolean>>, benchmark: Benchmark, results: Results, - slo: List<KubernetesBenchmark.Slo>, + slo: List<Slo>, executionId: Int, loadGenerationDelay: Long, afterTeardownDelay: Long diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/SloFactoryTest.kt b/theodolite/src/test/kotlin/theodolite/execution/operator/SloFactoryTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..c3dcd1b9529b6f24bd5b0deda920ba3e3ebb2978 --- /dev/null +++ b/theodolite/src/test/kotlin/theodolite/execution/operator/SloFactoryTest.kt @@ -0,0 +1,72 @@ +package theodolite.execution.operator + +import io.quarkus.test.junit.QuarkusTest +import org.junit.jupiter.api.Test +import theodolite.benchmark.BenchmarkExecution +import theodolite.benchmark.BenchmarkExecution.SloConfiguration +import theodolite.benchmark.KubernetesBenchmark +import theodolite.benchmark.Slo +import theodolite.execution.SloFactory +import org.junit.jupiter.api.Assertions.* + +@QuarkusTest +internal class SloFactoryTest { + + @Test + fun overwriteSloTest() { + + val benchmark = KubernetesBenchmark() + val execution = BenchmarkExecution() + + // Define Benchmark SLOs + val slo = Slo() + slo.name="test" + slo.sloType="lag trend" + slo.prometheusUrl="test.de" + slo.offset=0 + + val benchmarkSloProperties = mutableMapOf<String, String>() + benchmarkSloProperties["threshold"] = "2000" + benchmarkSloProperties["externalSloUrl"] = "http://localhost:80/evaluate-slope" + benchmarkSloProperties["warmup"] = "60" + + slo.properties=benchmarkSloProperties + + benchmark.slos = mutableListOf(slo) + + + // Define Execution SLOs, benchmark SLO values for these properties should be overwritten + val sloConfig = SloConfiguration() + sloConfig.name = "test" + + val executionSloProperties = mutableMapOf<String, String>() + // overwriting properties 'threshold' and 'warmup' and adding property 'extensionTest' + executionSloProperties["threshold"] = "3000" + executionSloProperties["warmup"] = "80" + executionSloProperties["extensionTest"] = "extended" + + sloConfig.properties = executionSloProperties + + // SLO has 'name' that isn't defined in the benchmark, therefore it will be ignored by the SloFactory + val sloConfig2 = SloConfiguration() + sloConfig2.name = "test2" + sloConfig2.properties = executionSloProperties + + execution.slos = listOf(sloConfig, sloConfig2) + + val sloFactory = SloFactory() + val combinedSlos = sloFactory.createSlos(execution,benchmark) + + assertEquals(1, combinedSlos.size) + assertEquals("test", combinedSlos[0].name) + assertEquals("lag trend", combinedSlos[0].sloType) + assertEquals("test.de", combinedSlos[0].prometheusUrl) + assertEquals(0, combinedSlos[0].offset) + + assertEquals(4, combinedSlos[0].properties.size) + assertEquals("3000", combinedSlos[0].properties["threshold"]) + assertEquals("http://localhost:80/evaluate-slope", combinedSlos[0].properties["externalSloUrl"]) + assertEquals("80", combinedSlos[0].properties["warmup"]) + assertEquals("extended", combinedSlos[0].properties["extensionTest"]) + } +} \ No newline at end of file