Skip to content
Snippets Groups Projects
Commit a919a926 authored by Benedikt Wetzel's avatar Benedikt Wetzel
Browse files

Introduce a PatchManager and make it possible to set the load as environment variable

parent 14a594a1
No related branches found
No related tags found
4 merge requests!159Re-implementation of Theodolite with Kotlin/Quarkus,!157Update Graal Image in CI pipeline,!85Introduce new Benchmark class and Patcher,!83WIP: Re-implementation of Theodolite with Kotlin/Quarkus
Showing with 131 additions and 36 deletions
package theodolite.benchmark
import io.fabric8.kubernetes.api.model.KubernetesResource
import io.fabric8.kubernetes.api.model.apps.Deployment
import io.fabric8.kubernetes.client.DefaultKubernetesClient
import org.yaml.snakeyaml.Yaml
import theodolite.k8s.YamlLoader
import theodolite.patcher.AbstractPatcher
import theodolite.patcher.Patcher
import theodolite.patcher.ReplicaPatcher
import theodolite.patcher.PatcherManager
import theodolite.util.LoadDimension
import theodolite.util.PatcherDefinition
import theodolite.util.Resource
import theodolite.util.TypeName
import java.io.File
import java.io.FileInputStream
import java.io.InputStream
import java.lang.IllegalArgumentException
class KubernetesBenchmark(): Benchmark {
lateinit var name: String
lateinit var appResource: List<String>
lateinit var loadGenResource: List<String>
lateinit var resourceTypes: List<TypeName>
lateinit var loadTypes: List<TypeName>
private fun loadKubernetesResources(resources: List<String>): List<Pair<String, KubernetesResource?>> {
private fun loadKubernetesResources(resources: List<String>): List<Pair<String, KubernetesResource>> {
val basePath = "./../../../resources/main/yaml/"
var parser = theodolite.benchmark.BenchmarkYamlParser()
val loader = YamlLoader(DefaultKubernetesClient().inNamespace("default"))
return resources
.map { resource ->
val resourcePath = "$basePath/$resource"
val kind = parser.parse(resourcePath, HashMap<String, String>()::class.java) !!
val k8sResource = kind["kind"]?.let { loader.loadK8sResource(it, resourcePath) }
Pair<String, KubernetesResource?>(resource, k8sResource)
val kind = parser.parse(resourcePath, HashMap<String, String>()::class.java)?.get("kind") !!
val k8sResource = loader.loadK8sResource(kind , resourcePath)
Pair<String, KubernetesResource>(resource, k8sResource)
}
}
private fun createK8sPatcher(patcherDefinition: PatcherDefinition, k8sResources: List<Pair<String, KubernetesResource>>): Patcher<Int> {
return when(patcherDefinition.type) {
"ReplicaPatcher" -> ReplicaPatcher(k8sResources.filter { it.first == patcherDefinition.resource}.map { resource -> resource.second }[0])
"EnvVarPatcher" -> TODO("create env var patcher")
else -> throw IllegalArgumentException("Patcher type ${patcherDefinition.type} not fount")
}
TODO("Use reflection to load patchers")
}
override fun buildDeployment(load: LoadDimension, res: Resource, override: Map<String, String>): BenchmarkDeployment {
// TODO("set node selector")
val resources = loadKubernetesResources(this.appResource + this.loadGenResource)
val patchers = this.resourceTypes.map { patcherDef -> createK8sPatcher(patcherDef.patchers[0],
resources as List<Pair<String, KubernetesResource>>
) }
// exemplary only for replica patcher
patchers.forEach{ patcher -> patcher.patch(res.get()) }
val patcherManager = PatcherManager()
// patch res and load
patcherManager.applyPatcher(res.getType(), this.resourceTypes, resources, res.get())
patcherManager.applyPatcher(load.getType(), this.loadTypes, resources, load.get().toString())
resources.forEach {x -> println(x)}
// handle overrides (resource, container, variableName, variableValue)
return KubernetesBenchmarkDeployment(emptyList(), hashMapOf<String, Any>(), "", emptyList())
}
}
......@@ -2,5 +2,5 @@ package theodolite.patcher
import io.fabric8.kubernetes.api.model.KubernetesResource
abstract class AbstractPatcher<T>(k8sResource: KubernetesResource): Patcher<T> {
abstract class AbstractPatcher(k8sResource: KubernetesResource, container: String? = null, variableName: String? = null): Patcher {
}
package theodolite.patcher
import io.fabric8.kubernetes.api.model.Container
import io.fabric8.kubernetes.api.model.EnvVar
import io.fabric8.kubernetes.api.model.EnvVarSource
import io.fabric8.kubernetes.api.model.KubernetesResource
import io.fabric8.kubernetes.api.model.apps.Deployment
class EnvVarPatcher(private val k8sResource: KubernetesResource, private val container: String, private val variableName: String): AbstractPatcher(k8sResource, container, variableName) {
override fun <String> patch(value: String) {
if (k8sResource is Deployment) {
this.setEnv(k8sResource, this.container,
mapOf(this.variableName to value) as Map<kotlin.String, kotlin.String>)
}
}
/**
* Sets the ContainerEvironmentVariables, creates new if variable don t exist.
* @param container - The Container
* @param map - Map of k=Name,v =Value of EnviromentVariables
*/
private fun setContainerEnv(container: Container, map: Map<String, String>) {
map.forEach { k, v ->
// filter for mathing name and set value
val x = container.env.filter { envVar -> envVar.name == k }
if (x.isEmpty()) {
val newVar = EnvVar(k, v, EnvVarSource())
container.env.add(newVar)
} else {
x.forEach {
it.value = v
}
}
}
}
/**
* Set the environment Variable for a container
*/
private fun setEnv(workloadDeployment: Deployment, containerName: String, map: Map<String, String>) {
workloadDeployment.spec.template.spec.containers.filter { it.name == containerName }
.forEach { it: Container ->
setContainerEnv(it, map)
}
}
}
\ No newline at end of file
package theodolite.patcher
interface Patcher<T> {
fun patch(value: T)
interface Patcher {
fun <T> patch(value: T)
}
\ No newline at end of file
package theodolite.patcher
import io.fabric8.kubernetes.api.model.KubernetesResource
import theodolite.util.PatcherDefinition
import theodolite.util.TypeName
import java.lang.IllegalArgumentException
class PatcherManager {
private fun createK8sPatcher(patcherDefinition: PatcherDefinition, k8sResources: List<Pair<String, KubernetesResource>>): Patcher {
return when(patcherDefinition.type) {
"ReplicaPatcher" -> ReplicaPatcher(k8sResources.filter { it.first == patcherDefinition.resource}.map { resource -> resource.second }[0])
"EnvVarPatcher" -> EnvVarPatcher(k8sResources.filter { it.first == patcherDefinition.resource}.map { resource -> resource.second }[0],
patcherDefinition.container,
patcherDefinition.variableName)
else -> throw IllegalArgumentException("Patcher type ${patcherDefinition.type} not found")
}
}
private fun getPatcherDef(requiredType: String, resourceTypes: List<TypeName>): List<PatcherDefinition> {
return resourceTypes
.filter { type -> type.typeName == requiredType}
.flatMap { type -> type.patchers}
}
fun applyPatcher(type: String, resourceTypes: List<TypeName>, resources: List<Pair<String, KubernetesResource>>, value: Any) {
this.getPatcherDef(type, resourceTypes)
.forEach {patcherDef ->
createK8sPatcher(patcherDef, resources).patch(value) }
}
}
\ No newline at end of file
......@@ -3,9 +3,12 @@ package theodolite.patcher
import io.fabric8.kubernetes.api.model.KubernetesResource
import io.fabric8.kubernetes.api.model.apps.Deployment
class ReplicaPatcher(private val k8sResource: KubernetesResource): AbstractPatcher<Int>(k8sResource){
override fun patch(replicas: Int) {
if (k8sResource is Deployment)
this.k8sResource.spec.replicas = replicas
class ReplicaPatcher(private val k8sResource: KubernetesResource): AbstractPatcher(k8sResource){
override fun <Int> patch(replicas: Int) {
if (k8sResource is Deployment) {
if (replicas is kotlin.Int) {
this.k8sResource.spec.replicas = replicas
}
}
}
}
\ No newline at end of file
......@@ -4,4 +4,8 @@ data class LoadDimension(private val number: Int) {
public fun get(): Int {
return this.number;
}
public fun getType(): String {
return "NumSensors"
}
}
......@@ -4,4 +4,8 @@ data class Resource(private val number: Int) {
public fun get(): Int {
return this.number;
}
public fun getType(): String {
return "Instances"
}
}
\ No newline at end of file
......@@ -8,4 +8,15 @@ resourceTypes:
- typeName: "Instances"
patchers:
- type: "ReplicaPatcher"
resource: "aggregation-deployment.yaml"
\ No newline at end of file
resource: "aggregation-deployment.yaml"
loadTypes:
- typeName: "NumSensors"
patchers:
- type: "EnvVarPatcher"
resource: "workloadGenerator.yaml"
container: "workload-generator"
variableName: "NUM_SENSORS"
EnvVars:
- typeName: "override"
patchers:
- type: "EnvVarPatcher"
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment