From 61654c2b42f78c3b9277887bd6d497da2cace0cf Mon Sep 17 00:00:00 2001
From: "stu126940@mail.uni-kiel.de" <stu126940@mail.uni-kiel.de>
Date: Tue, 16 Feb 2021 19:40:50 +0100
Subject: [PATCH] Enable loading of configurations from yaml

load yaml BenchmarkContext
load yaml BenchmarkType
load K8s resourcs based on the the loaded configurations
---
 .../kotlin/theodolite/benchmark/Benchmark.kt  |  2 +-
 .../theodolite/benchmark/BenchmarkContext.kt  | 26 +++++++
 .../benchmark/BenchmarkYamlParser.kt          |  8 +--
 .../benchmark/KubernetesBenchmark.kt          | 35 +++++++++-
 .../kotlin/theodolite/benchmark/Parser.kt     |  4 +-
 .../benchmark/TheodoliteBenchmarkExecutor.kt  | 70 +++++++++++++++++++
 .../benchmark/TheodoliteYamlExecutor.kt       | 18 ++++-
 .../theodolite/execution/BenchmarkExecutor.kt |  5 +-
 .../execution/BenchmarkExecutorImpl.kt        |  9 ++-
 .../execution/TestBenchmarkExecutorImpl.kt    |  8 ++-
 .../execution/TheodoliteExecutor.kt           |  3 +-
 .../main/kotlin/theodolite/k8s/YamlLoader.kt  | 12 ++++
 .../kotlin/theodolite/util/TestBenchmark.kt   | 13 +++-
 13 files changed, 193 insertions(+), 20 deletions(-)
 create mode 100644 theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkContext.kt
 create mode 100644 theodolite-quarkus/src/main/kotlin/theodolite/benchmark/TheodoliteBenchmarkExecutor.kt

diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/Benchmark.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/Benchmark.kt
index 8ec30b157..1c8b98f81 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/Benchmark.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/Benchmark.kt
@@ -4,5 +4,5 @@ import theodolite.util.LoadDimension
 import theodolite.util.Resource
 
 interface Benchmark {
-    fun buildDeployment(load: LoadDimension, res: Resource): BenchmarkDeployment
+    fun buildDeployment(load: LoadDimension, res: Resource, override: Map<String, String>): BenchmarkDeployment
 }
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkContext.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkContext.kt
new file mode 100644
index 000000000..1680e2173
--- /dev/null
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkContext.kt
@@ -0,0 +1,26 @@
+package theodolite.benchmark
+
+import kotlin.properties.Delegates
+
+
+class BenchmarkContext() {
+    lateinit var name: String
+    lateinit var benchmark: String
+    lateinit var loads: List<Int>
+    lateinit var resources: List<Int>
+    lateinit var slos: List<Slo>
+    lateinit var execution: Execution
+    lateinit var configOverrides: Map<String, String>
+
+    class Execution() {
+        lateinit var  strategy: String
+        var duration by Delegates.notNull<Long>()
+        var repititions by Delegates.notNull<Int>()
+        lateinit var restrictions: List<String>
+    }
+
+    class Slo(){
+        lateinit var sloType: String
+        var threshold by Delegates.notNull<Int>()
+    }
+}
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkYamlParser.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkYamlParser.kt
index 9e5b4456f..723898d76 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkYamlParser.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkYamlParser.kt
@@ -8,10 +8,10 @@ import java.io.FileInputStream
 import java.io.InputStream
 
 
-class BenchmarkYamlParser<T>: Parser<T> {
-    override fun parse(path: String): KubernetesBenchmark? {
+class BenchmarkYamlParser: Parser {
+    override fun <T> parse(path: String, E: Class<T>): T? {
         val input: InputStream = FileInputStream(File(path))
-        val parser = Yaml(Constructor(KubernetesBenchmark::class.java))
-        return parser.loadAs(input, KubernetesBenchmark::class.java)
+        val parser = Yaml(Constructor(E))
+        return parser.loadAs(input, E)
     }
 }
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt
index 9ca479693..09e820e51 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt
@@ -1,12 +1,43 @@
 package theodolite.benchmark
 
+import io.fabric8.kubernetes.api.model.KubernetesResource
+import io.fabric8.kubernetes.client.DefaultKubernetesClient
+import org.yaml.snakeyaml.Yaml
+import theodolite.k8s.YamlLoader
 import theodolite.util.LoadDimension
 import theodolite.util.Resource
+import java.io.File
+import java.io.FileInputStream
+import java.io.InputStream
 
 class KubernetesBenchmark(): Benchmark {
     lateinit var name: String
+    lateinit var appResource: List<String>
+    lateinit var loadGenResource: List<String>
 
-    override fun buildDeployment(load: LoadDimension, res: Resource): BenchmarkDeployment {
-        TODO("Not yet implemented")
+
+    private fun loadKubernetesResources(): List<KubernetesResource?> {
+        val basePath = "./../../../resources/main/yaml/"
+        var parser = theodolite.benchmark.BenchmarkYamlParser()
+        val loader = YamlLoader(DefaultKubernetesClient().inNamespace("default"))
+        return this.appResource
+            .map { resource -> "$basePath/$resource" }
+            .map { resourcePath ->
+                val kind = parser.parse(resourcePath, HashMap<String, String>()::class.java) !!
+                kind["kind"]?.let { loader.loadK8sResource(it, resourcePath) }
+        }
+    }
+
+    private fun patchKubernetesResources() {
+
+    }
+
+
+    override fun buildDeployment(load: LoadDimension, res: Resource, override: Map<String, String>): BenchmarkDeployment {
+        // TODO("")
+       val resources = loadKubernetesResources()
+        resources.forEach {x -> println(x.toString())}
+        // Return KubernetesBenchmarkDeployment with individual parametrisation
+        return KubernetesBenchmarkDeployment(emptyList(), hashMapOf<String, Any>(), "", emptyList() )
     }
 }
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/Parser.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/Parser.kt
index df6655b7e..93bf4a795 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/Parser.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/Parser.kt
@@ -1,5 +1,5 @@
 package theodolite.benchmark
 
-interface Parser<T> {
-    fun parse(path: String): KubernetesBenchmark? //Yaml
+interface Parser {
+    fun <T> parse(path: String, E:Class<T>): T? //Yaml
 }
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/TheodoliteBenchmarkExecutor.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/TheodoliteBenchmarkExecutor.kt
new file mode 100644
index 000000000..a56eeee1a
--- /dev/null
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/TheodoliteBenchmarkExecutor.kt
@@ -0,0 +1,70 @@
+package theodolite.benchmark
+
+import theodolite.execution.BenchmarkExecutor
+import theodolite.execution.BenchmarkExecutorImpl
+import theodolite.strategies.restriction.LowerBoundRestriction
+import theodolite.strategies.restriction.RestrictionStrategy
+import theodolite.strategies.searchstrategy.BinarySearch
+import theodolite.strategies.searchstrategy.CompositeStrategy
+import theodolite.strategies.searchstrategy.LinearSearch
+import theodolite.strategies.searchstrategy.SearchStrategy
+import theodolite.util.Config
+import theodolite.util.LoadDimension
+import theodolite.util.Resource
+import theodolite.util.Results
+import java.lang.IllegalArgumentException
+import java.time.Duration
+
+class TheodoliteBenchmarkExecutor(
+    private val benchmarkContext: BenchmarkContext,
+    private val kubernetesBenchmark: KubernetesBenchmark)
+{
+    private fun createSearchStrategy(executor: BenchmarkExecutor): SearchStrategy {
+       return when (this.benchmarkContext.execution.strategy) {
+           "LinearSearch" -> LinearSearch(executor)
+           "BinarySearch" -> BinarySearch(executor)
+           else -> throw  IllegalArgumentException("Search Strategy ${this.benchmarkContext.execution.strategy} not found")
+       }
+    }
+
+    private fun createRestrictionStrategy(results: Results): Set<RestrictionStrategy> {
+        var strategies = emptyList<RestrictionStrategy>()
+        strategies = this.benchmarkContext.execution.restrictions.map { restriction ->
+          when (restriction) {
+                "LowerBound" -> LowerBoundRestriction(results)
+                else -> throw  IllegalArgumentException("Restriction Strategy ${this.benchmarkContext.execution.restrictions} not found")
+            }
+        }
+        return strategies.toSet()
+    }
+
+    private fun buildConfig(): Config{
+       val results = Results()
+       val executionDuration = Duration.ofSeconds(this.benchmarkContext.execution.duration)
+       val executor: BenchmarkExecutor = BenchmarkExecutorImpl(kubernetesBenchmark, results, executionDuration, this.benchmarkContext.configOverrides)
+
+        return Config(
+           loads = benchmarkContext.loads.map { number -> LoadDimension(number) },
+           resources = benchmarkContext.resources.map { number -> Resource(number) },
+           compositeStrategy = CompositeStrategy(
+               benchmarkExecutor = executor,
+               searchStrategy = createSearchStrategy(executor),
+               restrictionStrategies = createRestrictionStrategy(results)
+           ),
+           executionDuration = executionDuration
+       )
+
+    }
+
+
+
+    fun run() {
+        val config = buildConfig()
+
+        // execute benchmarks for each load
+        for (load in config.loads) {
+            config.compositeStrategy.findSuitableResource(load, config.resources)
+        }
+
+    }
+}
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/TheodoliteYamlExecutor.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/TheodoliteYamlExecutor.kt
index 04d0bd306..e80f98de8 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/TheodoliteYamlExecutor.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/TheodoliteYamlExecutor.kt
@@ -2,8 +2,20 @@ package theodolite.benchmark
 
 class TheodoliteYamlExecutor {
     fun run() {
-        val parser = theodolite.benchmark.BenchmarkYamlParser<KubernetesBenchmark>()
-        val benchmark= parser.parse("./../../../resources/main/yaml/test.yaml")
-        System.out.println(benchmark?.name)
+
+        // load the Benchmark context and the benchmark type
+        var parser = theodolite.benchmark.BenchmarkYamlParser()
+        val benchmarkContext = parser.parse("./../../../resources/main/yaml/testContext.yaml", BenchmarkContext::class.java) !!
+        val benchmark = parser.parse("./../../../resources/main/yaml/testBenchmarkType.yaml", KubernetesBenchmark::class.java) !!
+
+        // TheodoliteExecutor benchmarkContext, benchmark
+        val executor = TheodoliteBenchmarkExecutor(benchmarkContext, benchmark)
+        executor.run()
+
+
+
+        System.out.println(benchmark.name)
+        System.out.println(benchmarkContext.name)
+
     }
 }
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt
index 82a409089..4905766d3 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt
@@ -1,6 +1,8 @@
 package theodolite.execution
 
 import mu.KotlinLogging
+import theodolite.benchmark.Benchmark
+import theodolite.benchmark.KubernetesBenchmark
 import theodolite.util.AbstractBenchmark
 import theodolite.util.LoadDimension
 import theodolite.util.Resource
@@ -17,7 +19,8 @@ private val logger = KotlinLogging.logger {}
  * @property executionDuration
  * @constructor Create empty Benchmark executor
  */
-abstract class BenchmarkExecutor(val benchmark: AbstractBenchmark, val results: Results, val executionDuration: Duration) {
+abstract class BenchmarkExecutor(val benchmark: Benchmark, val results: Results, val executionDuration: Duration, override: Map<String, String>) {
+
     /**
      * Run a experiment for the given parametrization, evaluate the experiment and save the result.
      *
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt
index a975085bf..d782ed9a5 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt
@@ -1,16 +1,19 @@
 package theodolite.execution
 
+import theodolite.benchmark.Benchmark
+import theodolite.benchmark.KubernetesBenchmark
 import theodolite.util.AbstractBenchmark
 import theodolite.util.LoadDimension
 import theodolite.util.Resource
 import theodolite.util.Results
 import java.time.Duration
 
-class BenchmarkExecutorImpl(benchmark: AbstractBenchmark, results: Results, executionDuration: Duration) : BenchmarkExecutor(benchmark, results, executionDuration) {
+class BenchmarkExecutorImpl(benchmark: Benchmark, results: Results, executionDuration: Duration, private val overrides: Map<String, String>) : BenchmarkExecutor(benchmark, results, executionDuration, overrides) {
     override fun runExperiment(load: LoadDimension, res: Resource): Boolean {
-        benchmark.start(load, res)
+        val benchmarkDeployment = benchmark.buildDeployment(load, res, this.overrides)
+        benchmarkDeployment.setup()
         this.waitAndLog()
-        benchmark.clearClusterEnvironment()
+        benchmarkDeployment.teardown()
         // todo evaluate
         val result = false // if success else false
         this.results.setResult(Pair(load, res), result)
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TestBenchmarkExecutorImpl.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TestBenchmarkExecutorImpl.kt
index 9823c4dd5..db2084a85 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TestBenchmarkExecutorImpl.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TestBenchmarkExecutorImpl.kt
@@ -1,13 +1,17 @@
 package theodolite.execution
 
+import theodolite.benchmark.Benchmark
+import theodolite.benchmark.KubernetesBenchmark
 import theodolite.util.AbstractBenchmark
 import theodolite.util.LoadDimension
 import theodolite.util.Resource
 import theodolite.util.Results
 import java.time.Duration
 
-class TestBenchmarkExecutorImpl(private val mockResults: Array<Array<Boolean>>, benchmark: AbstractBenchmark, results: Results):
-    BenchmarkExecutor(benchmark, results, executionDuration = Duration.ofSeconds(1)) {
+class TestBenchmarkExecutorImpl(private val mockResults: Array<Array<Boolean>>, benchmark: Benchmark, results: Results):
+    BenchmarkExecutor(benchmark, results, executionDuration = Duration.ofSeconds(1),
+        override = emptyMap<String,String>()
+    ) {
 
     override fun runExperiment(load: LoadDimension, res: Resource): Boolean {
         val result = this.mockResults[load.get()][res.get()]
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
index ed5a65159..3db21a87a 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
@@ -1,5 +1,5 @@
 package theodolite.execution
-
+/*
 import mu.KotlinLogging
 import theodolite.k8s.UC1Benchmark
 import theodolite.strategies.restriction.LowerBoundRestriction
@@ -66,3 +66,4 @@ class TheodoliteExecutor() {
         }
     }
 }
+*/
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/YamlLoader.kt b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/YamlLoader.kt
index 5e37e97df..1624c6d4e 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/YamlLoader.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/YamlLoader.kt
@@ -1,9 +1,11 @@
 package theodolite.k8s
 
 import io.fabric8.kubernetes.api.model.ConfigMap
+import io.fabric8.kubernetes.api.model.KubernetesResource
 import io.fabric8.kubernetes.api.model.Service
 import io.fabric8.kubernetes.api.model.apiextensions.v1beta1.CustomResourceDefinition
 import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.fabric8.kubernetes.api.model.apps.StatefulSet
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import mu.KotlinLogging
 
@@ -68,4 +70,14 @@ class YamlLoader(private val client: NamespacedKubernetesClient) {
 
         return resource
     }
+
+    public fun loadK8sResource(kind: String, path: String): KubernetesResource {
+        return when (kind){
+            "Deployment" -> loadDeployment(path)
+            "Service" -> loadService(path)
+            "ServiceMonitor" -> loadServiceMonitor(path)
+            "ConfigMap" -> loadConfigmap(path)
+            else -> return loadConfigmap(path) // throw java.lang.IllegalArgumentException("Resource typ $kind not known")
+        }
+    }
 }
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/util/TestBenchmark.kt b/theodolite-quarkus/src/main/kotlin/theodolite/util/TestBenchmark.kt
index 0358ff1a6..a5bc49c6c 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/util/TestBenchmark.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/util/TestBenchmark.kt
@@ -1,5 +1,8 @@
 package theodolite.util
 
+import theodolite.benchmark.Benchmark
+import theodolite.benchmark.BenchmarkDeployment
+
 class TestBenchmark : AbstractBenchmark(
     AbstractBenchmark.Config(
         clusterZookeeperConnectionString = "",
@@ -17,7 +20,7 @@ class TestBenchmark : AbstractBenchmark(
         ucImageURL = "",
         wgImageURL = ""
     )
-) {
+), Benchmark  {
 
     override fun initializeClusterEnvironment() {
         TODO("Not yet implemented")
@@ -34,4 +37,12 @@ class TestBenchmark : AbstractBenchmark(
     override fun startWorkloadGenerator(load: LoadDimension) {
         TODO("Not yet implemented")
     }
+
+    override fun buildDeployment(
+        load: LoadDimension,
+        res: Resource,
+        override: Map<String, String>
+    ): BenchmarkDeployment {
+        TODO("Not yet implemented")
+    }
 }
-- 
GitLab