diff --git a/helm/preconfigs/oci.yaml b/helm/preconfigs/oci.yaml index dd070a1d7983404add85cf75ded0a057a76e854f..35fe5dcf423eed77cb2d3d4298088738125fa9fe 100644 --- a/helm/preconfigs/oci.yaml +++ b/helm/preconfigs/oci.yaml @@ -1,4 +1,6 @@ operator: resultsVolume: - storageClassName: "oci-bv" - size: 50Gi # minimal size in OCI \ No newline at end of file + persistent: + enabled: true + storageClassName: "oci-bv" + size: 50Gi # minimal size in OCI diff --git a/helm/templates/_helpers.tpl b/helm/templates/_helpers.tpl index b530b553ea90671aba8154cc250a20924bae0183..569cf454a950f3f621c23472f0346c8bbd52229d 100644 --- a/helm/templates/_helpers.tpl +++ b/helm/templates/_helpers.tpl @@ -65,5 +65,5 @@ Create the name of the service account to use Create the name of the results volume to use */}} {{- define "theodolite.resultsClaimName" -}} -{{- default (printf "%s-results" (include "theodolite.fullname" .)) .Values.operator.resultsVolume.existingClaim }} +{{- default (printf "%s-results" (include "theodolite.fullname" .)) .Values.operator.resultsVolume.persistent.existingClaim }} {{- end }} diff --git a/helm/templates/theodolite/results-volume/pvc.yaml b/helm/templates/theodolite/results-volume/pvc.yaml index 6dda16bc85d308c8bf0c9c41dd55cca3582f0793..26ac56e42889ccaebbc669791ad4d318b8318fec 100644 --- a/helm/templates/theodolite/results-volume/pvc.yaml +++ b/helm/templates/theodolite/results-volume/pvc.yaml @@ -1,18 +1,18 @@ -{{- if and .Values.operator.resultsVolume.enabled (not .Values.operator.resultsVolume.existingClaim) -}} +{{- if and .Values.operator.resultsVolume.persistent.enabled (not .Values.operator.resultsVolume.persistent.existingClaim) -}} apiVersion: v1 kind: PersistentVolumeClaim metadata: name: {{ include "theodolite.resultsClaimName" . }} spec: - {{- if .Values.operator.resultsVolume.storageClassName }} - storageClassName: {{ .Values.operator.resultsVolume.storageClassName }} + {{- if .Values.operator.resultsVolume.persistent.storageClassName }} + storageClassName: {{ .Values.operator.resultsVolume.persistent.storageClassName }} {{- end }} accessModes: - ReadWriteOnce - {{- range .Values.operator.resultsVolume.accessModes }} + {{- range .Values.operator.resultsVolume.persistent.accessModes }} - {{ . | quote }} {{- end }} resources: requests: - storage: {{ .Values.operator.resultsVolume.size | quote }} + storage: {{ .Values.operator.resultsVolume.persistent.size | quote }} {{- end }} \ No newline at end of file diff --git a/helm/templates/theodolite/theodolite-operator.yaml b/helm/templates/theodolite/theodolite-operator.yaml index 52ddcd500ab8d050187028026def84e9d057c252..3d1d186306a5d1103a921b4c39e1425621548db8 100644 --- a/helm/templates/theodolite/theodolite-operator.yaml +++ b/helm/templates/theodolite/theodolite-operator.yaml @@ -31,10 +31,8 @@ spec: - name: RESULTS_FOLDER value: "./results" volumeMounts: - {{- if .Values.operator.resultsVolume.enabled }} - - name: theodolite-pv-storage + - name: theodolite-results-volume mountPath: "/deployments/results" - {{- end }} - name: benchmark-resources-uc1-kstreams mountPath: /deployments/benchmark-resources/uc1-kstreams - name: benchmark-resources-uc2-kstreams @@ -77,7 +75,7 @@ spec: - name: LOG_LEVEL value: INFO {{- end }} - {{- if and .Values.operator.resultsVolume.enabled .Values.operator.resultsVolume.accessSidecar.enabled }} + {{- if .Values.operator.resultsVolume.accessSidecar.enabled }} - name: results-access image: busybox:stable image: "{{ .Values.operator.resultsVolume.accessSidecar.image }}:{{ .Values.operator.resultsVolume.accessSidecar.imageTag }}" @@ -88,14 +86,16 @@ spec: - exec tail -f /dev/null volumeMounts: - mountPath: /results - name: theodolite-pv-storage + name: theodolite-results-volume {{- end }} volumes: - {{- if .Values.operator.resultsVolume.enabled }} - - name: theodolite-pv-storage + - name: theodolite-results-volume + {{- if .Values.operator.resultsVolume.persistent.enabled }} persistentVolumeClaim: claimName: {{ include "theodolite.resultsClaimName" . | quote }} - {{- end }} + {{- else }} + emptyDir: {} + {{- end }} - name: benchmark-resources-uc1-kstreams configMap: name: benchmark-resources-uc1-kstreams diff --git a/helm/values.yaml b/helm/values.yaml index b0ce0faeaa7989872fdedc308d3d4c507894e0e7..6c20f4bab35825e66412381b454df5c9dedec0fc 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -155,7 +155,10 @@ cp-helm-charts: ### kafka-lag-exporter: enabled: true + image: + pullPolicy: IfNotPresent nodeSelector: {} + clusters: - name: "theodolite-cp-kafka" bootstrapBrokers: "theodolite-cp-kafka:9092" @@ -263,12 +266,13 @@ operator: imagePullPolicy: Always resultsVolume: - enabled: true - # existingClaim: - # storageClassName: - accessModes: - - ReadWriteOnce - size: 1Gi + persistent: + enabled: false + # existingClaim: + # storageClassName: + accessModes: + - ReadWriteOnce + size: 1Gi accessSidecar: enabled: true image: busybox diff --git a/theodolite/README.md b/theodolite/README.md index 26efe96b4756316971378be810f69f6138613958..e0d7b9b46473a877d982e912cb85e2455e09be79 100644 --- a/theodolite/README.md +++ b/theodolite/README.md @@ -2,13 +2,13 @@ This project uses Quarkus, the Supersonic Subatomic Java Framework. -If you want to learn more about Quarkus, please visit its website: https://quarkus.io/ . +If you want to learn more about Quarkus, please visit its website: <https://quarkus.io/> . ## Running the application in dev mode You can run your application in dev mode using: -```shell script +```sh ./gradlew quarkusDev ``` @@ -16,7 +16,7 @@ You can run your application in dev mode using: The application can be packaged using: -```shell script +```sh ./gradlew build ``` @@ -25,7 +25,7 @@ an _über-jar_ as the dependencies are copied into the `build/lib` directory. If you want to build an _über-jar_, execute the following command: -```shell script +```sh ./gradlew build -Dquarkus.package.type=uber-jar ``` @@ -33,92 +33,108 @@ The application is now runnable using `java -jar build/theodolite-1.0.0-SNAPSHOT ## Creating a native executable +It is recommended to use the native GraalVM images to create executable jars from Theodolite. For more information please visit the [Native Image guide](https://www.graalvm.org/reference-manual/native-image/). + You can create a native executable using: -```shell script +```sh ./gradlew build -Dquarkus.package.type=native ``` Or, if you don't have GraalVM installed, you can run the native executable build in a container using: -```shell script +```sh ./gradlew build -Dquarkus.package.type=native -Dquarkus.native.container-build=true ``` You can then execute your native executable with: ```./build/theodolite-1.0.0-SNAPSHOT-runner``` -If you want to learn more about building native executables, please consult https://quarkus.io/guides/gradle-tooling. +If you want to learn more about building native executables, please consult <https://quarkus.io/guides/gradle-tooling>. ## Build docker images For the jvm version use: -```shell script +```sh ./gradlew build docker build -f src/main/docker/Dockerfile.jvm -t theodolite-jvm . ``` For the native image version use: -```shell script +```sh ./gradlew build -Dquarkus.package.type=native docker build -f src/main/docker/Dockerfile.native -t theodolite-native . ``` -## Execute docker images: +## Execute docker images Remember to set the environment variables first. Jvm version: -```shell script +```sh docker run -i --rm theodolite-jvm ``` Native image version: -```shell script +```sh docker run -i --rm theodolite-native ``` ## Environment variables -**Production:** (Docker-Container) +**Execution in Docker**: | Variables name | Default value |Usage | | -----------------------------|:----------------------------------:| ------------:| | `NAMESPACE` | `default` |Determines the namespace of the Theodolite will be executed in. Used in the KubernetesBenchmark| -| `THEODOLITE_EXECUTION` | `./config/BenchmarkExecution.yaml`|The complete path to the benchmarkExecution file. Used in the TheodoliteYamlExecutor. | -| `THEODOLITE_BENCHMARK_TYPE` | `./config/BenchmarkType.yaml` |The complete path to the benchmarkType file. Used in the TheodoliteYamlExecutor.| -| `THEODOLITE_APP_RESOURCES` | `./config` |The path under which the yamls for the resources for the subexperiments are found. Used in the KubernetesBenchmark| -| `MODE` | `yaml-executor` | Defines the mode of operation: either `yaml-executor` or `operator`| +| `THEODOLITE_EXECUTION` | `execution/execution.yaml` |The complete path to the benchmarkExecution file. Used in the TheodoliteYamlExecutor. | +| `THEODOLITE_BENCHMARK_TYPE` | `benchmark/benchmark.yaml` |The complete path to the benchmarkType file. Used in the TheodoliteYamlExecutor.| +| `THEODOLITE_APP_RESOURCES` | `./benchmark-resources` |The path under which the yamls for the resources for the subexperiments are found. Used in the KubernetesBenchmark| +| `MODE` | `standalone` |Defines the mode of operation: either `standalone` or `operator` -**Development:** (local via Intellij) +**Execution in IntelliJ**: When running Theodolite from within IntelliJ via -[Run Configurations](https://www.jetbrains.com/help/idea/work-with-gradle-tasks.html#gradle_run_config), set the * -Environment variables* field to: +[Run Configurations](https://www.jetbrains.com/help/idea/work-with-gradle-tasks.html#gradle_run_config), set the *Environment variables* field to: + +Set the following environment variables to run the example in the `standalone` mode within the IDE: + +```sh +THEODOLITE_BENCHMARK=./../../../../examples/standalone/example-benchmark.yaml;THEODOLITE_EXECUTION=./../../../../examples/standalone/example-execution.yaml;THEODOLITE_APP_RESOURCES=./../../../../examples/resources; +``` + +Alternative: +``` sh +export THEODOLITE_BENCHMARK=./../../../../examples/standalone/example-benchmark.yaml +export THEODOLITE_APP_RESOURCES=./../../../../examples/resources; +export THEODOLITE_EXECUTION=./../../../../examples/standalone/example-execution.yaml +./gradlew quarkusDev ``` -NAMESPACE=default;THEODOLITE_BENCHMARK=./../../../../config/BenchmarkType.yaml;THEODOLITE_APP_RESOURCES=./../../../../config;THEODOLITE_EXECUTION=./../../../../config/BenchmarkExecution.yaml;MODE=operator + +Set the following environment variables to run the example in the `operator` mode within the IDE: + +```sh +THEODOLITE_APP_RESOURCES=./../../../../examples/resources;MODE=operator ``` Alternative: ``` sh -export NAMESPACE=default -export THEODOLITE_BENCHMARK=./../../../../config/BenchmarkType.yaml -export THEODOLITE_APP_RESOURCES=./../../../../config -export THEODOLITE_EXECUTION=./../../../../config/BenchmarkExecution.yaml +export THEODOLITE_APP_RESOURCES=./../../../../examples/resources; export MODE=operator ./gradlew quarkusDev - ``` -#### Install Detekt Code analysis Plugin +Additionally, the benchmark and execution resources must be installed. + +### Install Detekt Code analysis Plugin -Install https://plugins.jetbrains.com/plugin/10761-detekt +Install <https://plugins.jetbrains.com/plugin/10761-detekt> - Install the plugin - Navigate to Settings/Preferences -> Tools -> Detekt @@ -127,7 +143,7 @@ Install https://plugins.jetbrains.com/plugin/10761-detekt -> detekt issues will be annotated on-the-fly while coding -**ingore Failures in build:** add +**ingore Failures in build**: add ```ignoreFailures = true``` diff --git a/theodolite/examples/operator/example-benchmark.yaml b/theodolite/examples/operator/example-benchmark.yaml index 91d9f8f1f7dfed31d9edcb59947af4e832ca2843..2bd75f3299f3504a6d156c185162acad7e19b8cf 100644 --- a/theodolite/examples/operator/example-benchmark.yaml +++ b/theodolite/examples/operator/example-benchmark.yaml @@ -5,9 +5,6 @@ metadata: spec: appResource: - "uc1-kstreams-deployment.yaml" - - "aggregation-service.yaml" - - "jmx-configmap.yaml" - - "uc1-service-monitor.yaml" loadGenResource: - "uc1-load-generator-deployment.yaml" - "uc1-load-generator-service.yaml" diff --git a/theodolite/examples/resources/uc1-kstreams-deployment.yaml b/theodolite/examples/resources/uc1-kstreams-deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..fdd1ff867ac83beb10856baec53569c88169232e --- /dev/null +++ b/theodolite/examples/resources/uc1-kstreams-deployment.yaml @@ -0,0 +1,34 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: titan-ccp-aggregation +spec: + selector: + matchLabels: + app: titan-ccp-aggregation + replicas: 1 + template: + metadata: + labels: + app: titan-ccp-aggregation + spec: + terminationGracePeriodSeconds: 0 + containers: + - name: uc-application + image: ghcr.io/cau-se/theodolite-uc1-kstreams-app:latest + ports: + - containerPort: 5555 + name: jmx + env: + - name: KAFKA_BOOTSTRAP_SERVERS + value: "theodolite-cp-kafka:9092" + - name: SCHEMA_REGISTRY_URL + value: "http://theodolite-cp-schema-registry:8081" + - name: JAVA_OPTS + value: "-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=5555" + - name: COMMIT_INTERVAL_MS # Set as default for the applications + value: "100" + resources: + limits: + memory: 4Gi + cpu: 1000m \ No newline at end of file diff --git a/theodolite/examples/resources/uc1-load-generator-deployment.yaml b/theodolite/examples/resources/uc1-load-generator-deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9f9ccc6ae39407bb1f027e1e23cb152944b869e0 --- /dev/null +++ b/theodolite/examples/resources/uc1-load-generator-deployment.yaml @@ -0,0 +1,32 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: titan-ccp-load-generator +spec: + selector: + matchLabels: + app: titan-ccp-load-generator + replicas: 1 + template: + metadata: + labels: + app: titan-ccp-load-generator + spec: + terminationGracePeriodSeconds: 0 + containers: + - name: workload-generator + image: ghcr.io/cau-se/theodolite-uc1-workload-generator:latest + ports: + - containerPort: 5701 + name: coordination + env: + - name: KUBERNETES_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: KUBERNETES_DNS_NAME + value: "titan-ccp-load-generator.$(KUBERNETES_NAMESPACE).svc.cluster.local" + - name: KAFKA_BOOTSTRAP_SERVERS + value: "theodolite-cp-kafka:9092" + - name: SCHEMA_REGISTRY_URL + value: "http://theodolite-cp-schema-registry:8081" diff --git a/theodolite/examples/resources/uc1-load-generator-service.yaml b/theodolite/examples/resources/uc1-load-generator-service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f8b26b3f6dece427f9c1ad4db94e351b042749b3 --- /dev/null +++ b/theodolite/examples/resources/uc1-load-generator-service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: titan-ccp-load-generator + labels: + app: titan-ccp-load-generator +spec: + type: ClusterIP + clusterIP: None + selector: + app: titan-ccp-load-generator + ports: + - name: coordination + port: 5701 + targetPort: 5701 + protocol: TCP diff --git a/theodolite/examples/standalone/example-benchmark.yaml b/theodolite/examples/standalone/example-benchmark.yaml index 83edce93834ca9b8eef5606c1e5884ce40bdd7d8..e3b37a348c592e065937abf6c8ca99556804867b 100644 --- a/theodolite/examples/standalone/example-benchmark.yaml +++ b/theodolite/examples/standalone/example-benchmark.yaml @@ -1,9 +1,6 @@ name: "uc1-kstreams" appResource: - "uc1-kstreams-deployment.yaml" - - "aggregation-service.yaml" - - "jmx-configmap.yaml" - - "uc1-service-monitor.yaml" loadGenResource: - "uc1-load-generator-deployment.yaml" - "uc1-load-generator-service.yaml" @@ -25,7 +22,7 @@ loadTypes: properties: loadGenMaxRecords: "15000" kafkaConfig: - bootstrapServer: "localhost:31290" + bootstrapServer: "theodolite-cp-kafka:9092" topics: - name: "input" numPartitions: 40 diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt b/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt index 5d5e1e621c6305aea1dab6abcfc9c2b8e01b70ad..281c68e318784ee8206473cd014f814b3f5152a9 100644 --- a/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt +++ b/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt @@ -2,6 +2,7 @@ package theodolite.evaluation import mu.KotlinLogging import theodolite.benchmark.BenchmarkExecution +import theodolite.util.EvaluationFailedException import theodolite.util.IOHandler import theodolite.util.LoadDimension import theodolite.util.Resource @@ -36,7 +37,7 @@ class AnalysisExecutor( * @return true if the experiment succeeded. */ fun analyze(load: LoadDimension, res: Resource, executionIntervals: List<Pair<Instant, Instant>>): Boolean { - var result = false + var result: Boolean var repetitionCounter = 1 try { @@ -70,8 +71,7 @@ class AnalysisExecutor( result = sloChecker.evaluate(prometheusData) } catch (e: Exception) { - // TODO(throw exception in order to make it possible to mark an experiment as unsuccessfully) - logger.error { "Evaluation failed for resource '${res.get()}' and load '${load.get()}'. Error: $e" } + throw EvaluationFailedException("Evaluation failed for resource '${res.get()}' and load '${load.get()} ", e) } return result } diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/MetricFetcher.kt b/theodolite/src/main/kotlin/theodolite/evaluation/MetricFetcher.kt index 833d7d1e16c2fbc91b58817b319a7d02af7f5b2b..e54d79fe0f95b9f6079bd4295a74e81250b73a90 100644 --- a/theodolite/src/main/kotlin/theodolite/evaluation/MetricFetcher.kt +++ b/theodolite/src/main/kotlin/theodolite/evaluation/MetricFetcher.kt @@ -53,8 +53,7 @@ class MetricFetcher(private val prometheusURL: String, private val offset: Durat } else { val values = parseValues(response) if (values.data?.result.isNullOrEmpty()) { - logger.error { "Empty query result: $values between $start and $end for query $query." } - throw NoSuchFieldException() + throw NoSuchFieldException("Empty query result: $values between $start and $end for query $query.") } return parseValues(response) } diff --git a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt b/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt index 78306337418e8caa2617ee68ad02a01767134719..9fc2a5817d776af602807028f5011ad5d15a1c71 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt +++ b/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt @@ -5,10 +5,7 @@ import mu.KotlinLogging import theodolite.benchmark.Benchmark import theodolite.benchmark.BenchmarkExecution import theodolite.evaluation.AnalysisExecutor -import theodolite.util.ConfigurationOverride -import theodolite.util.LoadDimension -import theodolite.util.Resource -import theodolite.util.Results +import theodolite.util.* import java.time.Duration import java.time.Instant @@ -65,6 +62,11 @@ class BenchmarkExecutorImpl( result = (false !in experimentResults) this.results.setResult(Pair(load, res), result) } + + if(!this.run.get()) { + throw ExecutionFailedException("The execution was interrupted") + } + return result } @@ -77,21 +79,19 @@ class BenchmarkExecutorImpl( 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() } catch (e: Exception) { - logger.error { "Error while setup experiment." } - logger.error { "Error is: $e" } this.run.set(false) + throw ExecutionFailedException("Error during setup the experiment", e) } val to = Instant.now() try { benchmarkDeployment.teardown() } catch (e: Exception) { - logger.warn { "Error while tearing down the benchmark deployment." } - logger.debug { "Teardown failed, caused by: $e" } + throw ExecutionFailedException("Error during teardown the experiment", e) } return Pair(from, to) } diff --git a/theodolite/src/main/kotlin/theodolite/execution/Shutdown.kt b/theodolite/src/main/kotlin/theodolite/execution/Shutdown.kt index e795ada3e3bcb2dba19f1e088f426f38a824f4a7..6dedc94af864269d7d15929c69ec54aa384fc8e3 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/Shutdown.kt +++ b/theodolite/src/main/kotlin/theodolite/execution/Shutdown.kt @@ -34,16 +34,15 @@ class Shutdown(private val benchmarkExecution: BenchmarkExecution, private val b afterTeardownDelay = 5L ) deployment.teardown() + logger.info { + "Finished teardown of all benchmark resources." + } } 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 { - "Finished teardown of all benchmark resources." - } } } diff --git a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt b/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt index 6a9a850c32ade111d07765bac7fdf5f69b6a1ed5..4c468987dd731adcb3aed53398631147396d86b3 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt +++ b/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt @@ -123,15 +123,18 @@ class TheodoliteExecutor( val config = buildConfig() // execute benchmarks for each load - for (load in config.loads) { - if (executor.run.get()) { - config.compositeStrategy.findSuitableResource(load, config.resources) + try { + for (load in config.loads) { + if (executor.run.get()) { + config.compositeStrategy.findSuitableResource(load, config.resources) + } } + } finally { + ioHandler.writeToJSONFile( + config.compositeStrategy.benchmarkExecutor.results, + "${resultsFolder}exp${this.config.executionId}-result" + ) } - ioHandler.writeToJSONFile( - config.compositeStrategy.benchmarkExecutor.results, - "${resultsFolder}exp${this.config.executionId}-result" - ) } private fun getAndIncrementExecutionID(fileURL: String): Int { diff --git a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteStandalone.kt b/theodolite/src/main/kotlin/theodolite/execution/TheodoliteStandalone.kt index 76fd7f707a3e190ff6c61052ae4b5aaf50459418..1160132fdc4a7130a05861d72c5f688f0fb5af9b 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteStandalone.kt +++ b/theodolite/src/main/kotlin/theodolite/execution/TheodoliteStandalone.kt @@ -3,6 +3,8 @@ package theodolite.execution import mu.KotlinLogging import theodolite.benchmark.BenchmarkExecution import theodolite.benchmark.KubernetesBenchmark +import theodolite.util.EvaluationFailedException +import theodolite.util.ExecutionFailedException import theodolite.util.YamlParser import kotlin.concurrent.thread import kotlin.system.exitProcess @@ -49,8 +51,14 @@ class TheodoliteStandalone { val shutdown = thread(start = false) { Shutdown(benchmarkExecution, benchmark).run() } Runtime.getRuntime().addShutdownHook(shutdown) - val executor = TheodoliteExecutor(benchmarkExecution, benchmark) - executor.run() + try { + TheodoliteExecutor(benchmarkExecution, benchmark).run() + } catch (e: EvaluationFailedException) { + logger.error { "Evaluation failed with error: ${e.message}" } + }catch (e: ExecutionFailedException) { + logger.error { "Execution failed with error: ${e.message}" } + } + logger.info { "Theodolite finished" } Runtime.getRuntime().removeShutdownHook(shutdown) exitProcess(0) diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt index c3a2b7b25ed71e797c45d8b497bad6cad15e21e8..6987372f96a6d956378a928011be9b5406590a16 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt +++ b/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt @@ -54,11 +54,8 @@ class ClusterSetup( benchmark.spec.name = benchmark.metadata.name Shutdown(execution.spec, benchmark.spec).start() } else { - logger.error { - "Execution with state ${States.RUNNING.value} was found, but no corresponding benchmark. " + - "Could not initialize cluster." - } - throw IllegalStateException("Cluster state is invalid, required Benchmark for running execution not found.") + throw IllegalStateException("Execution with state ${States.RUNNING.value} was found, but no corresponding benchmark. " + + "Could not initialize cluster.") } } } diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt index eb51a445ee05f1811a8780ff64c570f0bbdff4d0..8966b43609b52f60388111b1c9f82e741d012f53 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt +++ b/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt @@ -8,6 +8,7 @@ import theodolite.benchmark.KubernetesBenchmark import theodolite.execution.TheodoliteExecutor import theodolite.model.crd.* import theodolite.patcher.ConfigOverrideModifier +import theodolite.util.ExecutionFailedException import theodolite.util.ExecutionStateComparator import java.lang.Thread.sleep @@ -93,6 +94,10 @@ class TheodoliteController( States.RUNNING -> { executionStateHandler.setExecutionState(execution.name, States.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}" } } } } catch (e: Exception) { diff --git a/theodolite/src/main/kotlin/theodolite/k8s/CustomResourceWrapper.kt b/theodolite/src/main/kotlin/theodolite/k8s/CustomResourceWrapper.kt index ab355677ec53216072fb58a170610aa5f12dba28..dd416ccd90166fa570aad2f9ed8095e6a20dea02 100644 --- a/theodolite/src/main/kotlin/theodolite/k8s/CustomResourceWrapper.kt +++ b/theodolite/src/main/kotlin/theodolite/k8s/CustomResourceWrapper.kt @@ -33,7 +33,7 @@ class CustomResourceWrapper( client.customResource(this.context) .delete(client.configuration.namespace, this.getName()) } catch (e: Exception) { - logger.warn { "Could not delete service monitor" } + logger.warn { "Could not delete custom resource" } } } diff --git a/theodolite/src/main/kotlin/theodolite/k8s/K8sResourceLoader.kt b/theodolite/src/main/kotlin/theodolite/k8s/K8sResourceLoader.kt index faae5ade28deb579df6a463007cbdfbc9cc7706e..3fa727bc92720059e9a65dcbd1fa90a3b88cfd58 100644 --- a/theodolite/src/main/kotlin/theodolite/k8s/K8sResourceLoader.kt +++ b/theodolite/src/main/kotlin/theodolite/k8s/K8sResourceLoader.kt @@ -7,6 +7,7 @@ import io.fabric8.kubernetes.api.model.apps.Deployment import io.fabric8.kubernetes.client.NamespacedKubernetesClient import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext import mu.KotlinLogging +import theodolite.util.DeploymentFailedException import theodolite.util.YamlParser private val logger = KotlinLogging.logger {} @@ -120,10 +121,8 @@ class K8sResourceLoader(private val client: NamespacedKubernetesClient) { try { resource = f(path) } catch (e: Exception) { - logger.warn { "You potentially misspelled the path: $path" } - logger.warn { e } + throw IllegalArgumentException("The Resource at path: $path could not be loaded", e) } - if (resource == null) { throw IllegalArgumentException("The Resource at path: $path could not be loaded") } @@ -147,10 +146,7 @@ class K8sResourceLoader(private val client: NamespacedKubernetesClient) { "StatefulSet" -> loadStatefulSet(path) "Execution" -> loadExecution(path) "Benchmark" -> loadBenchmark(path) - else -> { - logger.error { "Error during loading of unspecified resource Kind" } - throw IllegalArgumentException("error while loading resource with kind: $kind") - } + else -> throw IllegalArgumentException("error while loading resource with kind: $kind") } } } diff --git a/theodolite/src/main/kotlin/theodolite/k8s/TopicManager.kt b/theodolite/src/main/kotlin/theodolite/k8s/TopicManager.kt index 8e83883fc881db0f7e2b1b75b2fb7c7322a11a00..f2afd71f6e4b4cf8e7106a8fc8a9bd113d9f36e6 100644 --- a/theodolite/src/main/kotlin/theodolite/k8s/TopicManager.kt +++ b/theodolite/src/main/kotlin/theodolite/k8s/TopicManager.kt @@ -30,8 +30,7 @@ class TopicManager(private val kafkaConfig: Map<String, Any>) { result = kafkaAdmin.createTopics(newTopics) result.all().get() // wait for the future to be completed } catch (e: Exception) { // TopicExistsException - logger.warn(e) { "Error during topic creation." } - logger.debug { e } // TODO remove due to attached exception to warn log? + logger.warn { "Error during topic creation. Error is: ${e.message}" } logger.info { "Remove existing topics." } delete(newTopics.map { topic -> topic.name() }, kafkaAdmin) logger.info { "Will retry the topic creation in ${RETRY_TIME / 1000} seconds." } @@ -94,7 +93,7 @@ class TopicManager(private val kafkaConfig: Map<String, Any>) { }" } } catch (e: Exception) { - logger.error(e) { "Error while removing topics: $e" } + logger.error { "Error while removing topics: ${e.message}" } logger.info { "Existing topics are: ${kafkaAdmin.listTopics().names().get()}." } } diff --git a/theodolite/src/main/kotlin/theodolite/util/DeploymentFailedException.kt b/theodolite/src/main/kotlin/theodolite/util/DeploymentFailedException.kt index 639a7c86c641cbdcba361410cf5e25fa56dd795f..6fbb5e768c4ef65a7b50345818aecd9050afd0b7 100644 --- a/theodolite/src/main/kotlin/theodolite/util/DeploymentFailedException.kt +++ b/theodolite/src/main/kotlin/theodolite/util/DeploymentFailedException.kt @@ -1,4 +1,4 @@ package theodolite.util -class DeploymentFailedException(message: String) : Exception(message) \ No newline at end of file +open class DeploymentFailedException(message: String, e: Exception? = null) : TheodoliteException(message,e) \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/util/EvaluationFailedException.kt b/theodolite/src/main/kotlin/theodolite/util/EvaluationFailedException.kt new file mode 100644 index 0000000000000000000000000000000000000000..c67ed7ffd79afc733a97dae05c3203f8e78722ea --- /dev/null +++ b/theodolite/src/main/kotlin/theodolite/util/EvaluationFailedException.kt @@ -0,0 +1,4 @@ +package theodolite.util + +class EvaluationFailedException(message: String, e: Exception? = null) : ExecutionFailedException(message,e) { +} diff --git a/theodolite/src/main/kotlin/theodolite/util/ExecutionFailedException.kt b/theodolite/src/main/kotlin/theodolite/util/ExecutionFailedException.kt new file mode 100644 index 0000000000000000000000000000000000000000..6566a451a3e273214f59962531b6bd17b33a850d --- /dev/null +++ b/theodolite/src/main/kotlin/theodolite/util/ExecutionFailedException.kt @@ -0,0 +1,4 @@ +package theodolite.util + +open class ExecutionFailedException(message: String, e: Exception? = null) : TheodoliteException(message,e) { +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/util/InvalidPatcherConfigurationException.kt b/theodolite/src/main/kotlin/theodolite/util/InvalidPatcherConfigurationException.kt index 81ea227d0d9871c2420a414d81749a34b97676b8..d02948ad341207051c4653ba9400ac0ffe5b03aa 100644 --- a/theodolite/src/main/kotlin/theodolite/util/InvalidPatcherConfigurationException.kt +++ b/theodolite/src/main/kotlin/theodolite/util/InvalidPatcherConfigurationException.kt @@ -1,4 +1,3 @@ package theodolite.util -class InvalidPatcherConfigurationException(message: String, e: Exception? = null) : Exception(message, e) - +class InvalidPatcherConfigurationException(message: String, e: Exception? = null) : DeploymentFailedException(message,e) diff --git a/theodolite/src/main/kotlin/theodolite/util/TheodoliteException.kt b/theodolite/src/main/kotlin/theodolite/util/TheodoliteException.kt new file mode 100644 index 0000000000000000000000000000000000000000..fc7453bae6aaa4c5c526eee72c006562ea887eb5 --- /dev/null +++ b/theodolite/src/main/kotlin/theodolite/util/TheodoliteException.kt @@ -0,0 +1,3 @@ +package theodolite.util + +open class TheodoliteException (message: String, e: Exception? = null) : Exception(message,e) \ No newline at end of file