diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/Main.kt b/theodolite-quarkus/src/main/kotlin/theodolite/Main.kt index 3aae49e5a805c62284c54d0a905eabf89c306588..89c9ac1fe0bef683e14ed071c1c749564115d522 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/Main.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/Main.kt @@ -1,8 +1,8 @@ package theodolite import io.quarkus.runtime.annotations.QuarkusMain -import theodolite.execution.TheodoliteExecutor import mu.KotlinLogging +import theodolite.benchmark.TheodoliteYamlExecutor private val logger = KotlinLogging.logger {} @@ -10,7 +10,8 @@ private val logger = KotlinLogging.logger {} object Main { @JvmStatic fun main(args: Array<String>) { - val theodolite = TheodoliteExecutor() + //val theodolite = TheodoliteExecutor() + val theodolite = TheodoliteYamlExecutor() theodolite.run() logger.info("Application started") } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/Benchmark.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/Benchmark.kt new file mode 100644 index 0000000000000000000000000000000000000000..8ec30b15781bfae858a291282fadc031476d57c8 --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/Benchmark.kt @@ -0,0 +1,8 @@ +package theodolite.benchmark + +import theodolite.util.LoadDimension +import theodolite.util.Resource + +interface Benchmark { + fun buildDeployment(load: LoadDimension, res: Resource): BenchmarkDeployment +} \ No newline at end of file diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkDeployment.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkDeployment.kt new file mode 100644 index 0000000000000000000000000000000000000000..5cba87f9b52d2b16a9fcf46d650758ff00d86a49 --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkDeployment.kt @@ -0,0 +1,6 @@ +package theodolite.benchmark + +interface BenchmarkDeployment { + fun setup() + fun teardown() +} \ No newline at end of file diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkYamlParser.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkYamlParser.kt new file mode 100644 index 0000000000000000000000000000000000000000..8ce10af336c105977eeac2526b3487017cba369c --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkYamlParser.kt @@ -0,0 +1,15 @@ +package theodolite.benchmark + +import org.yaml.snakeyaml.Yaml +import java.io.File +import java.io.FileInputStream +import java.io.InputStream + + +class BenchmarkYamlParser<T>: Parser<T> { + override fun parse(path: String): T { + val input: InputStream = FileInputStream(File(path)) + val parser = Yaml() + return parser.load<T>(input) + } +} \ 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 new file mode 100644 index 0000000000000000000000000000000000000000..9ca4796933d5b8e017664252a70c934f694cf48f --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt @@ -0,0 +1,12 @@ +package theodolite.benchmark + +import theodolite.util.LoadDimension +import theodolite.util.Resource + +class KubernetesBenchmark(): Benchmark { + lateinit var name: String + + override fun buildDeployment(load: LoadDimension, res: Resource): BenchmarkDeployment { + TODO("Not yet implemented") + } +} \ No newline at end of file diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmarkDeployment.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmarkDeployment.kt new file mode 100644 index 0000000000000000000000000000000000000000..ac7ab1b010cec0419c460d47658861967a96ae1f --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmarkDeployment.kt @@ -0,0 +1,37 @@ +package theodolite.benchmark + +import io.fabric8.kubernetes.api.model.KubernetesResource +import io.fabric8.kubernetes.client.DefaultKubernetesClient +import org.apache.kafka.clients.admin.NewTopic +import theodolite.k8s.K8sManager +import theodolite.k8s.TopicManager +import theodolite.k8s.WorkloadGeneratorStateCleaner + +class KubernetesBenchmarkDeployment( + val resources: List<KubernetesResource>, // List of already patched resources + private val kafkaConfig: HashMap<String, Any>, + private val zookeeperConfig: String, + private val topics: Collection<NewTopic> + // Maybe more +): BenchmarkDeployment { + private val workloadGeneratorStateCleaner = WorkloadGeneratorStateCleaner(this.zookeeperConfig) + private val kafkaController = TopicManager(this.kafkaConfig) + private val kubernetesManager = K8sManager(DefaultKubernetesClient().inNamespace("default")) // Maybe per resource type + + override fun setup() { + this.workloadGeneratorStateCleaner.deleteState() + kafkaController.createTopics(this.topics) + resources.forEach { + kubernetesManager.deploy(it) + } + } + + override fun teardown() { + this.workloadGeneratorStateCleaner.deleteState() + kafkaController.removeTopics(this.topics.map { topic -> topic.name() }) + resources.forEach { + kubernetesManager.remove(it) + } + + } +} diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/Parser.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/Parser.kt new file mode 100644 index 0000000000000000000000000000000000000000..1af3006a390def5d06d6cceb4c08deffa250992a --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/Parser.kt @@ -0,0 +1,5 @@ +package theodolite.benchmark + +interface Parser<T> { + fun parse(path: String): T //Yaml +} \ No newline at end of file diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/TheodoliteYamlExecutor.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/TheodoliteYamlExecutor.kt new file mode 100644 index 0000000000000000000000000000000000000000..66c3de474966d747ae769ad5bada9556d4361bc7 --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/TheodoliteYamlExecutor.kt @@ -0,0 +1,9 @@ +package theodolite.benchmark + +class TheodoliteYamlExecutor { + fun run() { + val parser = BenchmarkYamlParser<KubernetesBenchmark>() + val benchmark= parser.parse("./../../../resources/main/yaml/test.yaml") + System.out.println(benchmark.name) + } +} \ No newline at end of file diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/K8sManager.kt b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/K8sManager.kt new file mode 100644 index 0000000000000000000000000000000000000000..3a9f64089409586eb37725c9d103ec106642f1b7 --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/K8sManager.kt @@ -0,0 +1,41 @@ +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.Volume +import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinition +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.fabric8.kubernetes.api.model.apps.StatefulSet +import io.fabric8.kubernetes.client.NamespacedKubernetesClient +import java.lang.IllegalArgumentException + +class K8sManager(private val client: NamespacedKubernetesClient) { + fun deploy(resource: KubernetesResource) { + when (resource) { + is Deployment -> + this.client.apps().deployments().createOrReplace(resource) + is Service -> + this.client.services().createOrReplace(resource) + is ConfigMap -> + this.client.configMaps().createOrReplace(resource) + is StatefulSet -> + this.client.apps().statefulSets().createOrReplace(resource) + else -> throw IllegalArgumentException("Unknown kubernetes resource.") + } + } + + fun remove(resource: KubernetesResource) { + when (resource) { + is Deployment -> + this.client.apps().deployments().delete(resource) + is Service -> + this.client.services().delete(resource) + is ConfigMap -> + this.client.configMaps().delete(resource) + is StatefulSet -> + this.client.apps().statefulSets().delete(resource) + else -> throw IllegalArgumentException("Unknown kubernetes resource.") + } + } +} \ No newline at end of file diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/TopicManager.kt b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/TopicManager.kt index fe1f4f89c1b853d967f3cc8b94fcf4900d1e5f91..9b5ac759cb2a670b38a16ead740b953b153caee5 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/TopicManager.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/TopicManager.kt @@ -12,13 +12,12 @@ private val logger = KotlinLogging.logger {} * Manages the topics related tasks * @param bootstrapServers Ip of the kafka server */ -class TopicManager(bootstrapServers: String) { - private val props = hashMapOf<String, Any>(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG to bootstrapServers) +class TopicManager(kafkaConfig: HashMap<String, Any>) { lateinit var kafkaAdmin: AdminClient init { try { - kafkaAdmin = AdminClient.create(props) + kafkaAdmin = AdminClient.create(kafkaConfig) } catch (e: Exception) { logger.error { e.toString() } } @@ -29,19 +28,12 @@ class TopicManager(bootstrapServers: String) { * @param topics Map that holds a numPartition for each topic it should create * @param replicationFactor */ - fun createTopics(topics: Map<String, Int>, replicationFactor: Short) { - - val newTopics = mutableSetOf<NewTopic>() - for (i in topics) { - val tops = NewTopic(i.key, i.value, replicationFactor) - newTopics.add(tops) - } + fun createTopics(newTopics: Collection<NewTopic>) { kafkaAdmin.createTopics(newTopics) logger.info { "Topics created" } } fun createTopics(topics: List<String>, numPartitions: Int, replicationFactor: Short) { - val newTopics = mutableSetOf<NewTopic>() for (i in topics) { val tops = NewTopic(i, numPartitions, replicationFactor) @@ -52,10 +44,10 @@ class TopicManager(bootstrapServers: String) { } /** - * Deletes topics. + * Removes topics. * @param topics */ - fun deleteTopics(topics: List<String>) { + fun removeTopics(topics: List<String>) { val result = kafkaAdmin.deleteTopics(topics) @@ -64,7 +56,7 @@ class TopicManager(bootstrapServers: String) { } catch (ex: Exception) { logger.error { ex.toString() } } - logger.info { "Topics deleted" } + logger.info { "Topics removed" } } fun getTopics(): ListTopicsResult? { diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/UC1Benchmark.kt b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/UC1Benchmark.kt index 23a712bfa72c08cf19c0e4845a33714755a6e2d0..af81e75b7f39f43e7430ae007f08dc8393eb00f7 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/UC1Benchmark.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/UC1Benchmark.kt @@ -29,8 +29,8 @@ class UC1Benchmark(config: Config) : AbstractBenchmark(config) { init { this.workloadGeneratorStateCleaner = - WorkloadGeneratorStateCleaner(this.config.externalZookeeperConnectionString, path = "/workload-generation") - this.topicManager = TopicManager(this.config.externalKafkaConnectionString) + WorkloadGeneratorStateCleaner(this.config.externalZookeeperConnectionString) + this.topicManager = TopicManager(hashMapOf("bootstrap.servers" to this.config.externalKafkaConnectionString)) this.kubernetesClient = DefaultKubernetesClient().inNamespace("default") this.yamlLoader = YamlLoader(this.kubernetesClient) this.deploymentManager = DeploymentManager(this.kubernetesClient) @@ -43,8 +43,8 @@ class UC1Benchmark(config: Config) : AbstractBenchmark(config) { } override fun clearClusterEnvironment() { - this.workloadGeneratorStateCleaner.deleteAll() - this.topicManager.deleteTopics(this.config.kafkaTopics) + this.workloadGeneratorStateCleaner.deleteState() + this.topicManager.removeTopics(this.config.kafkaTopics) this.deploymentManager.delete(this.ucDeployment) this.serviceManager.delete(this.ucService) this.deploymentManager.delete(this.wgDeployment) @@ -57,7 +57,6 @@ class UC1Benchmark(config: Config) : AbstractBenchmark(config) { this.config.kafkaReplication ) } - override fun startSUT(resources: Resource) { this.deploymentManager.setImageName(ucDeployment, "uc-application", this.config.ucImageURL) diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/WorkloadGeneratorStateCleaner.kt b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/WorkloadGeneratorStateCleaner.kt index 7b1f8c29d60032e7e0980af2192d2928cf8c0cf6..8c2d105260ff0a87b59a85a5f82293f33442b3cb 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/WorkloadGeneratorStateCleaner.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/WorkloadGeneratorStateCleaner.kt @@ -12,24 +12,25 @@ private val logger = KotlinLogging.logger {} /** * Resets the workloadgenerator states in zookeper (and potentially watches for Zookeper events) * - * @param ip of zookeeper + * @param connectionString of zookeeper * @param path path of the zookeeper node */ -class WorkloadGeneratorStateCleaner(ip: String, val path: String) { +class WorkloadGeneratorStateCleaner(connectionString: String) { private val timeout: Duration = Duration.ofMillis(500) private val retryAfter: Duration = Duration.ofSeconds(5) lateinit var zookeeperClient: ZooKeeper + private val path = "/workload-generation" init { try { val watcher: Watcher = ZookeeperWatcher() // defined below - zookeeperClient = ZooKeeper(ip, timeout.toMillis().toInt(), watcher) + zookeeperClient = ZooKeeper(connectionString, timeout.toMillis().toInt(), watcher) } catch (e: Exception) { logger.error { e.toString() } } } - fun deleteAll() { + fun deleteState() { deleteRecusiveAll(this.path) logger.info { "ZooKeeper reset was successful" } } diff --git a/theodolite-quarkus/src/main/resources/yaml/test.yaml b/theodolite-quarkus/src/main/resources/yaml/test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d966e0e68fc7174c9a7e0159c146dd08b9454591 --- /dev/null +++ b/theodolite-quarkus/src/main/resources/yaml/test.yaml @@ -0,0 +1 @@ +name: "theodolite ist cool" \ No newline at end of file