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 package theodolite.benchmark
import io.fabric8.kubernetes.api.model.KubernetesResource import io.fabric8.kubernetes.api.model.KubernetesResource
import io.fabric8.kubernetes.api.model.apps.Deployment
import io.fabric8.kubernetes.client.DefaultKubernetesClient import io.fabric8.kubernetes.client.DefaultKubernetesClient
import org.yaml.snakeyaml.Yaml
import theodolite.k8s.YamlLoader import theodolite.k8s.YamlLoader
import theodolite.patcher.AbstractPatcher import theodolite.patcher.PatcherManager
import theodolite.patcher.Patcher
import theodolite.patcher.ReplicaPatcher
import theodolite.util.LoadDimension import theodolite.util.LoadDimension
import theodolite.util.PatcherDefinition
import theodolite.util.Resource import theodolite.util.Resource
import theodolite.util.TypeName import theodolite.util.TypeName
import java.io.File
import java.io.FileInputStream
import java.io.InputStream
import java.lang.IllegalArgumentException
class KubernetesBenchmark(): Benchmark { class KubernetesBenchmark(): Benchmark {
lateinit var name: String lateinit var name: String
lateinit var appResource: List<String> lateinit var appResource: List<String>
lateinit var loadGenResource: List<String> lateinit var loadGenResource: List<String>
lateinit var resourceTypes: List<TypeName> 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/" val basePath = "./../../../resources/main/yaml/"
var parser = theodolite.benchmark.BenchmarkYamlParser() var parser = theodolite.benchmark.BenchmarkYamlParser()
val loader = YamlLoader(DefaultKubernetesClient().inNamespace("default")) val loader = YamlLoader(DefaultKubernetesClient().inNamespace("default"))
return resources return resources
.map { resource -> .map { resource ->
val resourcePath = "$basePath/$resource" val resourcePath = "$basePath/$resource"
val kind = parser.parse(resourcePath, HashMap<String, String>()::class.java) !! val kind = parser.parse(resourcePath, HashMap<String, String>()::class.java)?.get("kind") !!
val k8sResource = kind["kind"]?.let { loader.loadK8sResource(it, resourcePath) } val k8sResource = loader.loadK8sResource(kind , resourcePath)
Pair<String, KubernetesResource?>(resource, k8sResource) 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 { override fun buildDeployment(load: LoadDimension, res: Resource, override: Map<String, String>): BenchmarkDeployment {
// TODO("set node selector") // TODO("set node selector")
val resources = loadKubernetesResources(this.appResource + this.loadGenResource) val resources = loadKubernetesResources(this.appResource + this.loadGenResource)
val patchers = this.resourceTypes.map { patcherDef -> createK8sPatcher(patcherDef.patchers[0], val patcherManager = PatcherManager()
resources as List<Pair<String, KubernetesResource>>
) } // patch res and load
// exemplary only for replica patcher patcherManager.applyPatcher(res.getType(), this.resourceTypes, resources, res.get())
patchers.forEach{ patcher -> patcher.patch(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()) return KubernetesBenchmarkDeployment(emptyList(), hashMapOf<String, Any>(), "", emptyList())
} }
} }
...@@ -2,5 +2,5 @@ package theodolite.patcher ...@@ -2,5 +2,5 @@ package theodolite.patcher
import io.fabric8.kubernetes.api.model.KubernetesResource 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 package theodolite.patcher
interface Patcher<T> { interface Patcher {
fun patch(value: T) 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 ...@@ -3,9 +3,12 @@ package theodolite.patcher
import io.fabric8.kubernetes.api.model.KubernetesResource import io.fabric8.kubernetes.api.model.KubernetesResource
import io.fabric8.kubernetes.api.model.apps.Deployment import io.fabric8.kubernetes.api.model.apps.Deployment
class ReplicaPatcher(private val k8sResource: KubernetesResource): AbstractPatcher<Int>(k8sResource){ class ReplicaPatcher(private val k8sResource: KubernetesResource): AbstractPatcher(k8sResource){
override fun patch(replicas: Int) { override fun <Int> patch(replicas: Int) {
if (k8sResource is Deployment) if (k8sResource is Deployment) {
this.k8sResource.spec.replicas = replicas 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) { ...@@ -4,4 +4,8 @@ data class LoadDimension(private val number: Int) {
public fun get(): Int { public fun get(): Int {
return this.number; return this.number;
} }
public fun getType(): String {
return "NumSensors"
}
} }
...@@ -4,4 +4,8 @@ data class Resource(private val number: Int) { ...@@ -4,4 +4,8 @@ data class Resource(private val number: Int) {
public fun get(): Int { public fun get(): Int {
return this.number; return this.number;
} }
public fun getType(): String {
return "Instances"
}
} }
\ No newline at end of file
...@@ -8,4 +8,15 @@ resourceTypes: ...@@ -8,4 +8,15 @@ resourceTypes:
- typeName: "Instances" - typeName: "Instances"
patchers: patchers:
- type: "ReplicaPatcher" - type: "ReplicaPatcher"
resource: "aggregation-deployment.yaml" resource: "aggregation-deployment.yaml"
\ No newline at end of file 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