diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt index 1e2d9a2e675bee3817c493e5afc89333ca508ed8..995f35e2613036de4b3d50f797e4974a5ec7ba85 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt @@ -4,7 +4,7 @@ import io.fabric8.kubernetes.api.model.KubernetesResource import io.fabric8.kubernetes.client.DefaultKubernetesClient import mu.KotlinLogging import theodolite.k8s.K8sResourceLoader -import theodolite.patcher.PatcherManager +import theodolite.patcher.PatcherFactory import theodolite.util.* private val logger = KotlinLogging.logger {} @@ -43,20 +43,20 @@ class KubernetesBenchmark : Benchmark { configurationOverrides: List<ConfigurationOverride> ): BenchmarkDeployment { val resources = loadKubernetesResources(this.appResource + this.loadGenResource) - val patcherManager = PatcherManager() + val patcherFactory = PatcherFactory() - // patch res and load - patcherManager.createAndApplyPatcher(res.getType(), this.resourceTypes, resources, res.get()) - patcherManager.createAndApplyPatcher(load.getType(), this.loadTypes, resources, load.get().toString()) + // patch the load dimension + load.getType().map { patcherDefinition -> patcherFactory.createPatcher(patcherDefinition, resources) } + .forEach { patcher -> patcher.patch(load.get().toString()) } - // patch overrides + // patch the resources + res.getType().map { patcherDefinition -> patcherFactory.createPatcher(patcherDefinition, resources) } + .forEach { patcher -> patcher.patch(res.get().toString()) } + + // Patch the given overrides configurationOverrides.forEach { override -> - patcherManager.applyPatcher( - listOf(override.patcher), - resources, - override.value - ) - } + patcherFactory.createPatcher(override.patcher, resources).patch(override.value) } + return KubernetesBenchmarkDeployment( namespace = namespace, diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt index 87388cb61cf8fcb93a1028d20d2e3b68d322ab3d..da569e792660b2ec66fb7e7542103b242a733cb2 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt @@ -2,6 +2,7 @@ package theodolite.execution import theodolite.benchmark.BenchmarkExecution import theodolite.benchmark.KubernetesBenchmark +import theodolite.patcher.PatcherDefinitionFactory import theodolite.strategies.StrategyFactory import theodolite.strategies.searchstrategy.CompositeStrategy import theodolite.util.Config @@ -21,11 +22,12 @@ class TheodoliteExecutor( val executionDuration = Duration.ofSeconds(config.execution.duration) val executor = BenchmarkExecutorImpl(kubernetesBenchmark, results, executionDuration, config.configOverrides) + val resourcePatcherDefinition = PatcherDefinitionFactory().createPatcherDefinition(config.resources.resourceType, this.kubernetesBenchmark.resourceTypes) + val loadDimensionPatcherDefinition = PatcherDefinitionFactory().createPatcherDefinition(config.load.loadType, this.kubernetesBenchmark.loadTypes) return Config( - loads = config.load.loadValues.map { load -> LoadDimension(load, config.load.loadType) }, - resources = config.resources.resourceValues.map - { resource -> Resource(resource, config.resources.resourceType) }, + loads = config.load.loadValues.map { load -> LoadDimension(load, loadDimensionPatcherDefinition) }, + resources = config.resources.resourceValues.map { resource -> Resource(resource, resourcePatcherDefinition) }, compositeStrategy = CompositeStrategy( benchmarkExecutor = executor, searchStrategy = strategyFactory.createSearchStrategy(executor, config.execution.strategy), diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteYamlExecutor.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteYamlExecutor.kt index ecc202542a0472808f70f9c5dd9696e2de370ea1..f6c109dac52ea4a4faeb30b8041329bc86812552 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteYamlExecutor.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteYamlExecutor.kt @@ -5,6 +5,8 @@ import mu.KotlinLogging import theodolite.benchmark.BenchmarkExecution import theodolite.benchmark.KubernetesBenchmark import theodolite.util.YamlParser +import kotlin.system.exitProcess + private val logger = KotlinLogging.logger {} @QuarkusMain(name = "TheodoliteYamlExecutor") @@ -23,5 +25,6 @@ object TheodoliteYamlExecutor { val executor = TheodoliteExecutor(benchmarkExecution, benchmark) executor.run() logger.info { "Theodolite finished" } + exitProcess(0) } } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherDefinitionFactory.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherDefinitionFactory.kt new file mode 100644 index 0000000000000000000000000000000000000000..0882b8d96a5d8bfe0c2537b66335aba9bda810ab --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherDefinitionFactory.kt @@ -0,0 +1,21 @@ +package theodolite.patcher + +import theodolite.util.PatcherDefinition +import theodolite.util.TypeName + +class PatcherDefinitionFactory { + fun createPatcherDefinition(requiredType: String, patcherTypes: List<TypeName>) : List<PatcherDefinition> { + return patcherTypes + .filter { type -> type.typeName == requiredType } + .flatMap { type -> type.patchers } + } + + fun getEmptyPatcherDefinition(): PatcherDefinition { + val emptyDef = PatcherDefinition() + emptyDef.type = "" + emptyDef.resource = "" + emptyDef.container = "" + emptyDef.variableName = "" + return emptyDef + } +} \ No newline at end of file diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherFactory.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherFactory.kt new file mode 100644 index 0000000000000000000000000000000000000000..1a3e56bfe7aaf01526dc8ce4ed2c106383e1f8b7 --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherFactory.kt @@ -0,0 +1,28 @@ +package theodolite.patcher + +import io.fabric8.kubernetes.api.model.KubernetesResource +import theodolite.util.PatcherDefinition + +class PatcherFactory { + fun createPatcher(patcherDefinition: PatcherDefinition, + k8sResources: List<Pair<String, KubernetesResource>>) : Patcher { + val resource = + k8sResources.filter { it.first == patcherDefinition.resource }.map { resource -> resource.second }[0] + return when (patcherDefinition.type) { + "ReplicaPatcher" -> ReplicaPatcher(resource) + "EnvVarPatcher" -> EnvVarPatcher(resource, patcherDefinition.container, patcherDefinition.variableName) + "NodeSelectorPatcher" -> NodeSelectorPatcher(resource, patcherDefinition.variableName) + "ResourceLimitPatcher" -> ResourceLimitPatcher( + resource, + patcherDefinition.container, + patcherDefinition.variableName + ) + "ResourceRequestPatcher" -> ResourceRequestPatcher( + resource, + patcherDefinition.container, + patcherDefinition.variableName + ) + else -> throw IllegalArgumentException("Patcher type ${patcherDefinition.type} not found") + } + } +} \ No newline at end of file diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherManager.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherManager.kt deleted file mode 100644 index 5557eb4b98d5da3bbc8b8d82227de29335c5da67..0000000000000000000000000000000000000000 --- a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherManager.kt +++ /dev/null @@ -1,73 +0,0 @@ -package theodolite.patcher - -import io.fabric8.kubernetes.api.model.KubernetesResource -import theodolite.util.PatcherDefinition -import theodolite.util.TypeName - -class PatcherManager { - private fun createK8sPatcher( - patcherDefinition: PatcherDefinition, - k8sResources: List<Pair<String, KubernetesResource>> - ): Patcher { - val resource = - k8sResources.filter { it.first == patcherDefinition.resource }.map { resource -> resource.second }[0] - return when (patcherDefinition.type) { - "ReplicaPatcher" -> ReplicaPatcher(resource) - "EnvVarPatcher" -> EnvVarPatcher(resource, patcherDefinition.container, patcherDefinition.variableName) - "NodeSelectorPatcher" -> NodeSelectorPatcher(resource, patcherDefinition.variableName) - "ResourceLimitPatcher" -> ResourceLimitPatcher( - resource, - patcherDefinition.container, - patcherDefinition.variableName - ) - "ResourceRequestPatcher" -> ResourceRequestPatcher( - resource, - patcherDefinition.container, - patcherDefinition.variableName - ) - else -> throw IllegalArgumentException("Patcher type ${patcherDefinition.type} not found") - } - } - - private fun getPatcherDef(requiredType: String, patcherTypes: List<TypeName>): List<PatcherDefinition> { - return patcherTypes - .filter { type -> type.typeName == requiredType } - .flatMap { type -> type.patchers } - } - - /** - * This function first creates a patcher definition and - * then patches the list of resources based on this patcher definition - * - * @param type Patcher type, for example "EnvVarPatcher" - * @param patcherTypes List of patcher types definitions, for example for resources and threads - * @param resources List of K8s resources, a patcher takes the resources that are needed - * @param value The value to patch - */ - fun createAndApplyPatcher( - type: String, - patcherTypes: List<TypeName>, - resources: List<Pair<String, KubernetesResource>>, - value: Any - ) { - this.getPatcherDef(type, patcherTypes) - .forEach { patcherDef -> - createK8sPatcher(patcherDef, resources).patch(value) - } - } - - /** - * Patch a resource based on the given patcher definition, a list of resources and a value to patch - * - * @param patcherDefinition The patcher definition - * @param resources List of patcher types definitions, for example for resources and threads - * @param value The value to patch - */ - fun applyPatcher( - patcherDefinition: List<PatcherDefinition>, - resources: List<Pair<String, KubernetesResource>>, - value: Any - ) { - patcherDefinition.forEach { def -> this.createK8sPatcher(def, resources).patch(value) } - } -} diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/strategies/restriction/LowerBoundRestriction.kt b/theodolite-quarkus/src/main/kotlin/theodolite/strategies/restriction/LowerBoundRestriction.kt index dfd6bc8052b8ca44ac8a9220fbf1e3c8df43b93d..2a0cd9c841a282d31b71d7567e7607efb8632815 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/strategies/restriction/LowerBoundRestriction.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/strategies/restriction/LowerBoundRestriction.kt @@ -1,5 +1,6 @@ package theodolite.strategies.restriction +import theodolite.patcher.PatcherDefinitionFactory import theodolite.util.LoadDimension import theodolite.util.Resource import theodolite.util.Results @@ -13,7 +14,7 @@ import theodolite.util.Results class LowerBoundRestriction(results: Results) : RestrictionStrategy(results) { override fun next(load: LoadDimension, resources: List<Resource>): List<Resource> { val maxLoad: LoadDimension? = this.results.getMaxBenchmarkedLoad(load) - var lowerBound: Resource? = this.results.getMinRequiredInstances(maxLoad, resources[0].getType()) + var lowerBound: Resource? = this.results.getMinRequiredInstances(maxLoad, listOf(PatcherDefinitionFactory().getEmptyPatcherDefinition())) if (lowerBound == null) { lowerBound = resources[0] } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/util/LoadDimension.kt b/theodolite-quarkus/src/main/kotlin/theodolite/util/LoadDimension.kt index 29d47460bc49ec44e9a46a129e3dab3246f305b6..43cb861b2d6bbbe457a61d6f98f42487aad1d216 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/util/LoadDimension.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/util/LoadDimension.kt @@ -1,11 +1,11 @@ package theodolite.util -data class LoadDimension(private val number: Int, private val type: String) { +data class LoadDimension(private val number: Int, private val type: List<PatcherDefinition>) { fun get(): Int { return this.number } - fun getType(): String { + fun getType(): List<PatcherDefinition> { return this.type } } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/util/Resource.kt b/theodolite-quarkus/src/main/kotlin/theodolite/util/Resource.kt index cb172e0b8de4cff5fc08828a177f3dd9d58bbb53..094e89ebb0d4566499068331ca2fc890f3335597 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/util/Resource.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/util/Resource.kt @@ -1,11 +1,11 @@ package theodolite.util -data class Resource(private val number: Int, private val type: String) { +data class Resource(private val number: Int, private val type: List<PatcherDefinition>) { fun get(): Int { return this.number } - fun getType(): String { + fun getType(): List<PatcherDefinition> { return this.type } } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/util/Results.kt b/theodolite-quarkus/src/main/kotlin/theodolite/util/Results.kt index 91bde71792fdca383fc9511658bab39aa58d12ce..34fcfc047756e116c5e94c2c4148498f0f45cd4b 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/util/Results.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/util/Results.kt @@ -11,7 +11,7 @@ class Results { return this.results[experiment] } - fun getMinRequiredInstances(load: LoadDimension?, resourceTyp: String): Resource? { + fun getMinRequiredInstances(load: LoadDimension?, resourceTyp: List<PatcherDefinition>): Resource? { if (this.results.isEmpty()) return Resource(Int.MIN_VALUE, resourceTyp) var requiredInstances: Resource? = Resource(Int.MAX_VALUE, resourceTyp) diff --git a/theodolite-quarkus/src/test/kotlin/theodolite/CompositeStrategyTest.kt b/theodolite-quarkus/src/test/kotlin/theodolite/CompositeStrategyTest.kt index 31eaa40fbe5424cf4df00860623e91fa5f1a9408..d50541c2e7b07a6e8efa7c9846661de1cbb450bf 100644 --- a/theodolite-quarkus/src/test/kotlin/theodolite/CompositeStrategyTest.kt +++ b/theodolite-quarkus/src/test/kotlin/theodolite/CompositeStrategyTest.kt @@ -3,6 +3,7 @@ package theodolite import io.quarkus.test.junit.QuarkusTest import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import theodolite.patcher.PatcherDefinitionFactory import theodolite.strategies.restriction.LowerBoundRestriction import theodolite.strategies.searchstrategy.BinarySearch import theodolite.strategies.searchstrategy.CompositeStrategy @@ -25,8 +26,9 @@ class CompositeStrategyTest { arrayOf(false, false, false, false, false, false, true), arrayOf(false, false, false, false, false, false, false) ) - val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, "NumSensors") } - val mockResources: List<Resource> = (0..6).map { number -> Resource(number, "Instances") } + val emptyPatcherDefinition = PatcherDefinitionFactory().getEmptyPatcherDefinition() + val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, listOf(emptyPatcherDefinition)) } + val mockResources: List<Resource> = (0..6).map { number -> Resource(number, listOf(emptyPatcherDefinition)) } val results = Results() val benchmark = TestBenchmark() val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results) @@ -36,7 +38,7 @@ class CompositeStrategyTest { CompositeStrategy(benchmarkExecutor, linearSearch, setOf(lowerBoundRestriction)) val actual: ArrayList<Resource?> = ArrayList() - val expected: ArrayList<Resource?> = ArrayList(listOf(0, 2, 2, 3, 4, 6).map { x -> Resource(x, "Instances") }) + val expected: ArrayList<Resource?> = ArrayList(listOf(0, 2, 2, 3, 4, 6).map { x -> Resource(x, listOf(emptyPatcherDefinition)) }) expected.add(null) for (load in mockLoads) { @@ -57,8 +59,9 @@ class CompositeStrategyTest { arrayOf(false, false, false, false, false, false, true), arrayOf(false, false, false, false, false, false, false) ) - val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, "NumSensors") } - val mockResources: List<Resource> = (0..6).map { number -> Resource(number, "Instances") } + val emptyPatcherDefinition = PatcherDefinitionFactory().getEmptyPatcherDefinition() + val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, listOf(emptyPatcherDefinition)) } + val mockResources: List<Resource> = (0..6).map { number -> Resource(number, listOf(emptyPatcherDefinition)) } val results = Results() val benchmark = TestBenchmark() val benchmarkExecutorImpl = @@ -69,7 +72,7 @@ class CompositeStrategyTest { CompositeStrategy(benchmarkExecutorImpl, binarySearch, setOf(lowerBoundRestriction)) val actual: ArrayList<Resource?> = ArrayList() - val expected: ArrayList<Resource?> = ArrayList(listOf(0, 2, 2, 3, 4, 6).map { x -> Resource(x, "Instances") }) + val expected: ArrayList<Resource?> = ArrayList(listOf(0, 2, 2, 3, 4, 6).map { x -> Resource(x, listOf(emptyPatcherDefinition)) }) expected.add(null) for (load in mockLoads) { @@ -90,8 +93,9 @@ class CompositeStrategyTest { arrayOf(false, false, false, false, false, false, true, true), arrayOf(false, false, false, false, false, false, false, true) ) - val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, "NumSensors") } - val mockResources: List<Resource> = (0..7).map { number -> Resource(number, "Instances") } + val emptyPatcherDefinition = PatcherDefinitionFactory().getEmptyPatcherDefinition() + val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, listOf(emptyPatcherDefinition)) } + val mockResources: List<Resource> = (0..7).map { number -> Resource(number, listOf(emptyPatcherDefinition)) } val results = Results() val benchmark = TestBenchmark() val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results) @@ -102,7 +106,7 @@ class CompositeStrategyTest { val actual: ArrayList<Resource?> = ArrayList() val expected: ArrayList<Resource?> = - ArrayList(listOf(0, 2, 2, 3, 4, 6, 7).map { x -> Resource(x, "Instances") }) + ArrayList(listOf(0, 2, 2, 3, 4, 6, 7).map { x -> Resource(x, listOf(emptyPatcherDefinition)) }) for (load in mockLoads) { actual.add(strategy.findSuitableResource(load, mockResources)) diff --git a/theodolite-quarkus/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt b/theodolite-quarkus/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt index 2170a6a54cf12433b18cc621d78a8608f3f71d63..79d6efe47fbe6bf40626a7135097c583d4699a59 100644 --- a/theodolite-quarkus/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt +++ b/theodolite-quarkus/src/test/kotlin/theodolite/ResourceLimitPatcherTest.kt @@ -6,7 +6,7 @@ import io.quarkus.test.junit.QuarkusTest import io.smallrye.common.constraint.Assert.assertTrue import org.junit.jupiter.api.Test import theodolite.k8s.K8sResourceLoader -import theodolite.patcher.PatcherManager +import theodolite.patcher.PatcherFactory import theodolite.util.PatcherDefinition /** @@ -23,7 +23,7 @@ import theodolite.util.PatcherDefinition class ResourceLimitPatcherTest { val testPath = "./src/main/resources/testYaml/" val loader = K8sResourceLoader(DefaultKubernetesClient().inNamespace("")) - val manager = PatcherManager() + val patcherFactory = PatcherFactory() fun applyTest(fileName: String) { val cpuValue = "50m" @@ -42,16 +42,14 @@ class ResourceLimitPatcherTest { defMEM.container = "uc-application" defMEM.type = "ResourceLimitPatcher" - manager.applyPatcher( - patcherDefinition = listOf(defCPU), - resources = listOf(Pair("cpu-memory-deployment.yaml", k8sResource)), - value = cpuValue - ) - manager.applyPatcher( - patcherDefinition = listOf(defMEM), - resources = listOf(Pair("cpu-memory-deployment.yaml", k8sResource)), - value = memValue - ) + patcherFactory.createPatcher( + patcherDefinition = defCPU, + k8sResources = listOf(Pair("cpu-memory-deployment.yaml", k8sResource)) + ).patch(value = cpuValue) + patcherFactory.createPatcher( + patcherDefinition = defMEM, + k8sResources = listOf(Pair("cpu-memory-deployment.yaml", k8sResource)) + ).patch(value = memValue) k8sResource.spec.template.spec.containers.filter { it.name == defCPU.container } .forEach { diff --git a/theodolite-quarkus/src/test/kotlin/theodolite/ResourceRequestPatcherTest.kt b/theodolite-quarkus/src/test/kotlin/theodolite/ResourceRequestPatcherTest.kt index 108142843949913eb6db34bb268eab2e91fda3cf..9ca9a83aa96de1b141cfa5b97c0fab1c071a708c 100644 --- a/theodolite-quarkus/src/test/kotlin/theodolite/ResourceRequestPatcherTest.kt +++ b/theodolite-quarkus/src/test/kotlin/theodolite/ResourceRequestPatcherTest.kt @@ -6,7 +6,7 @@ import io.quarkus.test.junit.QuarkusTest import io.smallrye.common.constraint.Assert.assertTrue import org.junit.jupiter.api.Test import theodolite.k8s.K8sResourceLoader -import theodolite.patcher.PatcherManager +import theodolite.patcher.PatcherFactory import theodolite.util.PatcherDefinition /** @@ -23,7 +23,7 @@ import theodolite.util.PatcherDefinition class ResourceRequestPatcherTest { val testPath = "./src/main/resources/testYaml/" val loader = K8sResourceLoader(DefaultKubernetesClient().inNamespace("")) - val manager = PatcherManager() + val patcherFactory = PatcherFactory() fun applyTest(fileName: String) { val cpuValue = "50m" @@ -42,16 +42,14 @@ class ResourceRequestPatcherTest { defMEM.container = "uc-application" defMEM.type = "ResourceRequestPatcher" - manager.applyPatcher( - patcherDefinition = listOf(defCPU), - resources = listOf(Pair("cpu-memory-deployment.yaml", k8sResource)), - value = cpuValue - ) - manager.applyPatcher( - patcherDefinition = listOf(defMEM), - resources = listOf(Pair("cpu-memory-deployment.yaml", k8sResource)), - value = memValue - ) + patcherFactory.createPatcher( + patcherDefinition = defCPU, + k8sResources = listOf(Pair("cpu-memory-deployment.yaml", k8sResource)) + ).patch(value = cpuValue) + patcherFactory.createPatcher( + patcherDefinition = defMEM, + k8sResources = listOf(Pair("cpu-memory-deployment.yaml", k8sResource)) + ).patch(value = memValue) k8sResource.spec.template.spec.containers.filter { it.name == defCPU.container } .forEach {