Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • she/theodolite
1 result
Show changes
Showing
with 268 additions and 503 deletions
...@@ -7,7 +7,6 @@ import io.fabric8.kubernetes.client.dsl.ExecListener ...@@ -7,7 +7,6 @@ import io.fabric8.kubernetes.client.dsl.ExecListener
import io.fabric8.kubernetes.client.dsl.ExecWatch import io.fabric8.kubernetes.client.dsl.ExecWatch
import io.fabric8.kubernetes.client.utils.Serialization import io.fabric8.kubernetes.client.utils.Serialization
import mu.KotlinLogging import mu.KotlinLogging
import okhttp3.Response
import theodolite.util.ActionCommandFailedException import theodolite.util.ActionCommandFailedException
import theodolite.util.Configuration import theodolite.util.Configuration
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
...@@ -145,10 +144,8 @@ class ActionCommand(val client: NamespacedKubernetesClient) { ...@@ -145,10 +144,8 @@ class ActionCommand(val client: NamespacedKubernetesClient) {
} }
private class ActionCommandListener(val execLatch: CountDownLatch) : ExecListener { private class ActionCommandListener(val execLatch: CountDownLatch) : ExecListener {
override fun onOpen(response: Response) {
}
override fun onFailure(throwable: Throwable, response: Response) { override fun onFailure(throwable: Throwable, response: ExecListener.Response) {
execLatch.countDown() execLatch.countDown()
throw ActionCommandFailedException("Some error encountered while executing action, caused ${throwable.message})") throw ActionCommandFailedException("Some error encountered while executing action, caused ${throwable.message})")
} }
......
package theodolite.benchmark package theodolite.benchmark
import com.fasterxml.jackson.databind.annotation.JsonDeserialize import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import io.fabric8.kubernetes.api.model.HasMetadata
import io.fabric8.kubernetes.api.model.KubernetesResource import io.fabric8.kubernetes.api.model.KubernetesResource
import io.fabric8.kubernetes.client.KubernetesClientException import io.fabric8.kubernetes.client.KubernetesClientException
import io.fabric8.kubernetes.client.NamespacedKubernetesClient import io.fabric8.kubernetes.client.NamespacedKubernetesClient
import io.quarkus.runtime.annotations.RegisterForReflection import io.quarkus.runtime.annotations.RegisterForReflection
import theodolite.k8s.resourceLoader.K8sResourceLoaderFromString
import theodolite.util.DeploymentFailedException import theodolite.util.DeploymentFailedException
import theodolite.util.YamlParserFromString
import java.lang.IllegalArgumentException import java.lang.IllegalArgumentException
@RegisterForReflection @RegisterForReflection
@JsonDeserialize @JsonDeserialize
class ConfigMapResourceSet : ResourceSet, KubernetesResource { class ConfigMapResourceSet : ResourceSet, KubernetesResource {
lateinit var name: String lateinit var name: String
lateinit var files: List<String> // load all files, iff files is not set var files: List<String>? = null // load all files, iff files is not set
override fun getResourceSet(client: NamespacedKubernetesClient): Collection<Pair<String, KubernetesResource>> { override fun getResourceSet(client: NamespacedKubernetesClient): Collection<Pair<String, HasMetadata>> {
val loader = K8sResourceLoaderFromString(client)
var resources: Map<String, String> var resources: Map<String, String>
try { try {
...@@ -31,9 +29,9 @@ class ConfigMapResourceSet : ResourceSet, KubernetesResource { ...@@ -31,9 +29,9 @@ class ConfigMapResourceSet : ResourceSet, KubernetesResource {
throw DeploymentFailedException("Cannot find or read ConfigMap with name '$name'.", e) throw DeploymentFailedException("Cannot find or read ConfigMap with name '$name'.", e)
} }
if (::files.isInitialized) { files?.run {
val filteredResources = resources.filter { files.contains(it.key) } val filteredResources = resources.filter { this.contains(it.key) }
if (filteredResources.size != files.size) { if (filteredResources.size != this.size) {
throw DeploymentFailedException("Could not find all specified Kubernetes manifests files") throw DeploymentFailedException("Could not find all specified Kubernetes manifests files")
} }
resources = filteredResources resources = filteredResources
...@@ -43,14 +41,8 @@ class ConfigMapResourceSet : ResourceSet, KubernetesResource { ...@@ -43,14 +41,8 @@ class ConfigMapResourceSet : ResourceSet, KubernetesResource {
resources resources
.map { .map {
Pair( Pair(
getKind(resource = it.value), it.key, // filename
it client.resource(it.value).get()
)
}
.map {
Pair(
it.second.key,
loader.loadK8sResource(it.first, it.second.value)
) )
} }
} catch (e: IllegalArgumentException) { } catch (e: IllegalArgumentException) {
...@@ -59,11 +51,4 @@ class ConfigMapResourceSet : ResourceSet, KubernetesResource { ...@@ -59,11 +51,4 @@ class ConfigMapResourceSet : ResourceSet, KubernetesResource {
} }
private fun getKind(resource: String): String {
val parser = YamlParserFromString()
val resourceAsMap = parser.parse(resource, HashMap<String, String>()::class.java)
return resourceAsMap?.get("kind")
?: throw DeploymentFailedException("Could not find field kind of Kubernetes resource: ${resourceAsMap?.get("name")}")
}
} }
\ No newline at end of file
package theodolite.benchmark package theodolite.benchmark
import com.fasterxml.jackson.databind.annotation.JsonDeserialize import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import io.fabric8.kubernetes.api.model.HasMetadata
import io.fabric8.kubernetes.api.model.KubernetesResource import io.fabric8.kubernetes.api.model.KubernetesResource
import io.fabric8.kubernetes.client.NamespacedKubernetesClient import io.fabric8.kubernetes.client.NamespacedKubernetesClient
import io.quarkus.runtime.annotations.RegisterForReflection import io.quarkus.runtime.annotations.RegisterForReflection
import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
import theodolite.util.DeploymentFailedException import theodolite.util.DeploymentFailedException
import theodolite.util.YamlParserFromFile import java.io.BufferedReader
import java.io.File import java.io.FileInputStream
import java.io.FileNotFoundException import java.io.FileNotFoundException
import java.lang.IllegalArgumentException import java.io.InputStreamReader
import java.nio.charset.StandardCharsets
import java.nio.file.Path
import java.nio.file.Paths
import java.util.stream.Collectors
import kotlin.io.path.listDirectoryEntries
@RegisterForReflection @RegisterForReflection
@JsonDeserialize @JsonDeserialize
class FileSystemResourceSet: ResourceSet, KubernetesResource { class FileSystemResourceSet: ResourceSet, KubernetesResource {
lateinit var path: String lateinit var path: String
lateinit var files: List<String> var files: List<String>? = null
override fun getResourceSet(client: NamespacedKubernetesClient): Collection<Pair<String, KubernetesResource>> { override fun getResourceSet(client: NamespacedKubernetesClient): Collection<Pair<String, HasMetadata>> {
// if files is set ...
//if files is set ... return files?.run {
if(::files.isInitialized){ return this
return files .map { Paths.get(path, it) }
.map { loadSingleResource(resourceURL = it, client = client) } .map { loadSingleResource(resource = it, client = client) }
} } ?:
try {
return try { Paths.get(path)
File(path) .listDirectoryEntries()
.list() !! .filter { it.toString().endsWith(".yaml") || it.toString().endsWith(".yml") }
.filter { it.endsWith(".yaml") || it.endsWith(".yml") } .map { loadSingleResource(resource = it, client = client) }
.map { } catch (e: java.nio.file.NoSuchFileException) { // not to be confused with Kotlin exception
loadSingleResource(resourceURL = it, client = client)
}
} catch (e: NullPointerException) {
throw DeploymentFailedException("Could not load files located in $path", e) throw DeploymentFailedException("Could not load files located in $path", e)
} }
} }
private fun loadSingleResource(resourceURL: String, client: NamespacedKubernetesClient): Pair<String, KubernetesResource> { private fun loadSingleResource(resource: Path, client: NamespacedKubernetesClient): Pair<String, HasMetadata> {
val parser = YamlParserFromFile()
val loader = K8sResourceLoaderFromFile(client)
val resourcePath = "$path/$resourceURL"
lateinit var kind: String
try {
kind = parser.parse(resourcePath, HashMap<String, String>()::class.java)?.get("kind")!!
} catch (e: NullPointerException) {
throw DeploymentFailedException("Can not get Kind from resource $resourcePath", e)
} catch (e: FileNotFoundException){
throw DeploymentFailedException("File $resourcePath not found", e)
}
return try { return try {
val k8sResource = loader.loadK8sResource(kind, resourcePath) val stream = FileInputStream(resource.toFile())
Pair(resourceURL, k8sResource) val text = BufferedReader(
InputStreamReader(stream, StandardCharsets.UTF_8)
).lines().collect(Collectors.joining("\n"))
val k8sResource = client.resource(text).get()
Pair(resource.last().toString(), k8sResource)
} catch (e: FileNotFoundException){
throw DeploymentFailedException("File $resource not found.", e)
} catch (e: IllegalArgumentException) { } catch (e: IllegalArgumentException) {
throw DeploymentFailedException("Could not load resource: $resourcePath", e) throw DeploymentFailedException("Could not load resource: $resource.", e)
} }
} }
} }
\ No newline at end of file
package theodolite.benchmark package theodolite.benchmark
import com.fasterxml.jackson.databind.annotation.JsonDeserialize import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import io.fabric8.kubernetes.api.model.HasMetadata
import io.fabric8.kubernetes.api.model.KubernetesResource import io.fabric8.kubernetes.api.model.KubernetesResource
import io.fabric8.kubernetes.client.DefaultKubernetesClient import io.fabric8.kubernetes.client.DefaultKubernetesClient
import io.fabric8.kubernetes.client.NamespacedKubernetesClient import io.fabric8.kubernetes.client.NamespacedKubernetesClient
import io.quarkus.runtime.annotations.RegisterForReflection import io.quarkus.runtime.annotations.RegisterForReflection
import mu.KotlinLogging import mu.KotlinLogging
import theodolite.k8s.K8sManager import theodolite.k8s.K8sManager
import theodolite.k8s.resourceLoader.K8sResourceLoader
import theodolite.patcher.PatcherFactory import theodolite.patcher.PatcherFactory
import theodolite.util.* import theodolite.util.*
...@@ -53,22 +53,27 @@ class KubernetesBenchmark : KubernetesResource, Benchmark { ...@@ -53,22 +53,27 @@ class KubernetesBenchmark : KubernetesResource, Benchmark {
* It first loads them via the [YamlParserFromFile] to check for their concrete type and afterwards initializes them using * It first loads them via the [YamlParserFromFile] to check for their concrete type and afterwards initializes them using
* the [K8sResourceLoader] * the [K8sResourceLoader]
*/ */
fun loadKubernetesResources(resourceSet: List<ResourceSets>): Collection<Pair<String, KubernetesResource>> { @Deprecated("Use `loadResourceSet` from `ResourceSets`")
fun loadKubernetesResources(resourceSet: List<ResourceSets>): Collection<Pair<String, HasMetadata>> {
return loadResources(resourceSet)
}
private fun loadResources(resourceSet: List<ResourceSets>): Collection<Pair<String, HasMetadata>> {
return resourceSet.flatMap { it.loadResourceSet(this.client) } return resourceSet.flatMap { it.loadResourceSet(this.client) }
} }
override fun setupInfrastructure() { override fun setupInfrastructure() {
this.infrastructure.beforeActions.forEach { it.exec(client = client) } this.infrastructure.beforeActions.forEach { it.exec(client = client) }
val kubernetesManager = K8sManager(this.client) val kubernetesManager = K8sManager(this.client)
loadKubernetesResources(this.infrastructure.resources) loadResources(this.infrastructure.resources)
.map{it.second} .map { it.second }
.forEach { kubernetesManager.deploy(it) } .forEach { kubernetesManager.deploy(it) }
} }
override fun teardownInfrastructure() { override fun teardownInfrastructure() {
val kubernetesManager = K8sManager(this.client) val kubernetesManager = K8sManager(this.client)
loadKubernetesResources(this.infrastructure.resources) loadResources(this.infrastructure.resources)
.map{it.second} .map { it.second }
.forEach { kubernetesManager.remove(it) } .forEach { kubernetesManager.remove(it) }
this.infrastructure.afterActions.forEach { it.exec(client = client) } this.infrastructure.afterActions.forEach { it.exec(client = client) }
} }
...@@ -91,8 +96,8 @@ class KubernetesBenchmark : KubernetesResource, Benchmark { ...@@ -91,8 +96,8 @@ class KubernetesBenchmark : KubernetesResource, Benchmark {
): BenchmarkDeployment { ): BenchmarkDeployment {
logger.info { "Using $namespace as namespace." } logger.info { "Using $namespace as namespace." }
val appResources = loadKubernetesResources(this.sut.resources) val appResources = loadResources(this.sut.resources)
val loadGenResources = loadKubernetesResources(this.loadGenerator.resources) val loadGenResources = loadResources(this.loadGenerator.resources)
val patcherFactory = PatcherFactory() val patcherFactory = PatcherFactory()
...@@ -122,7 +127,7 @@ class KubernetesBenchmark : KubernetesResource, Benchmark { ...@@ -122,7 +127,7 @@ class KubernetesBenchmark : KubernetesResource, Benchmark {
loadGenResources = loadGenResources.map { it.second }, loadGenResources = loadGenResources.map { it.second },
loadGenerationDelay = loadGenerationDelay, loadGenerationDelay = loadGenerationDelay,
afterTeardownDelay = afterTeardownDelay, afterTeardownDelay = afterTeardownDelay,
kafkaConfig = if (kafkaConfig != null) hashMapOf("bootstrap.servers" to kafkaConfig.bootstrapServer) else mapOf(), kafkaConfig = if (kafkaConfig != null) mapOf("bootstrap.servers" to kafkaConfig.bootstrapServer) else mapOf(),
topics = kafkaConfig?.topics ?: listOf(), topics = kafkaConfig?.topics ?: listOf(),
client = this.client client = this.client
) )
......
package theodolite.benchmark package theodolite.benchmark
import io.fabric8.kubernetes.api.model.HasMetadata
import io.fabric8.kubernetes.api.model.KubernetesResource import io.fabric8.kubernetes.api.model.KubernetesResource
import io.fabric8.kubernetes.client.NamespacedKubernetesClient import io.fabric8.kubernetes.client.NamespacedKubernetesClient
import io.quarkus.runtime.annotations.RegisterForReflection import io.quarkus.runtime.annotations.RegisterForReflection
...@@ -27,8 +28,8 @@ class KubernetesBenchmarkDeployment( ...@@ -27,8 +28,8 @@ class KubernetesBenchmarkDeployment(
private val sutAfterActions: List<Action>, private val sutAfterActions: List<Action>,
private val loadGenBeforeActions: List<Action>, private val loadGenBeforeActions: List<Action>,
private val loadGenAfterActions: List<Action>, private val loadGenAfterActions: List<Action>,
val appResources: List<KubernetesResource>, val appResources: List<HasMetadata>,
val loadGenResources: List<KubernetesResource>, val loadGenResources: List<HasMetadata>,
private val loadGenerationDelay: Long, private val loadGenerationDelay: Long,
private val afterTeardownDelay: Long, private val afterTeardownDelay: Long,
private val kafkaConfig: Map<String, Any>, private val kafkaConfig: Map<String, Any>,
......
...@@ -3,6 +3,7 @@ package theodolite.benchmark ...@@ -3,6 +3,7 @@ package theodolite.benchmark
import com.fasterxml.jackson.annotation.JsonInclude import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.annotation.JsonDeserialize import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import io.fabric8.kubernetes.api.model.HasMetadata
import io.fabric8.kubernetes.api.model.KubernetesResource import io.fabric8.kubernetes.api.model.KubernetesResource
import io.fabric8.kubernetes.client.NamespacedKubernetesClient import io.fabric8.kubernetes.client.NamespacedKubernetesClient
import io.quarkus.runtime.annotations.RegisterForReflection import io.quarkus.runtime.annotations.RegisterForReflection
...@@ -19,13 +20,14 @@ class ResourceSets: KubernetesResource { ...@@ -19,13 +20,14 @@ class ResourceSets: KubernetesResource {
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
var fileSystem: FileSystemResourceSet? = null var fileSystem: FileSystemResourceSet? = null
fun loadResourceSet(client: NamespacedKubernetesClient): Collection<Pair<String, KubernetesResource>> { fun loadResourceSet(client: NamespacedKubernetesClient): Collection<Pair<String, HasMetadata>> {
// TODO Find out whether field access (::configMap) is really what we want to do here (see #362)
return if (::configMap != null) { return if (::configMap != null) {
configMap?.getResourceSet(client= client) !! configMap?.getResourceSet(client= client) !!
} else if (::fileSystem != null) { } else if (::fileSystem != null) {
fileSystem?.getResourceSet(client= client ) !! fileSystem?.getResourceSet(client= client ) !!
} else { } else {
throw DeploymentFailedException("could not load resourceSet.") throw DeploymentFailedException("Could not load resourceSet.")
} }
} }
} }
\ No newline at end of file
...@@ -25,7 +25,12 @@ abstract class AbstractStateHandler<S : HasMetadata>( ...@@ -25,7 +25,12 @@ abstract class AbstractStateHandler<S : HasMetadata>(
val resource = this.crdClient.withName(resourceName).get() val resource = this.crdClient.withName(resourceName).get()
if (resource != null) { if (resource != null) {
val resourcePatched = setter(resource) val resourcePatched = setter(resource)
this.crdClient.patchStatus(resourcePatched) // TODO replace with this.crdClient.replaceStatus(resourcePatched) with upcoming fabric8 release (> 5.12.1)
// find out the difference between patchStatus and replaceStatus
// see also https://github.com/fabric8io/kubernetes-client/pull/3798
if (resourcePatched != null) {
this.crdClient.withName(resourcePatched.metadata.name).patchStatus(resourcePatched)
}
} }
} catch (e: KubernetesClientException) { } catch (e: KubernetesClientException) {
logger.warn(e) { "Status cannot be set for resource $resourceName." } logger.warn(e) { "Status cannot be set for resource $resourceName." }
......
...@@ -130,8 +130,7 @@ class TheodoliteController( ...@@ -130,8 +130,7 @@ class TheodoliteController(
.list() .list()
.items .items
.map { .map {
it.spec.name = it.metadata.name it.apply { it.spec.name = it.metadata.name }
it
} }
} }
......
package theodolite.k8s
import io.fabric8.kubernetes.api.model.KubernetesResource
import io.fabric8.kubernetes.client.NamespacedKubernetesClient
import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
import mu.KotlinLogging
private val logger = KotlinLogging.logger {}
class CustomResourceWrapper(
val crAsMap: Map<String, String>,
private val context: CustomResourceDefinitionContext
) : KubernetesResource {
/**
* Deploy a service monitor
*
* @param client a namespaced Kubernetes client which are used to deploy the CR object.
*
* @throws java.io.IOException if the resource could not be deployed.
*/
fun deploy(client: NamespacedKubernetesClient) {
client.customResource(this.context)
.createOrReplace(client.configuration.namespace, this.crAsMap as Map<String, Any>)
}
/**
* Delete a service monitor
*
* @param client a namespaced Kubernetes client which are used to delete the CR object.
*/
fun delete(client: NamespacedKubernetesClient) {
try {
client.customResource(this.context)
.delete(client.configuration.namespace, this.getName())
} catch (e: Exception) {
logger.warn { "Could not delete custom resource" }
}
}
/**
* @throws NullPointerException if name or metadata is null
*/
fun getName(): String {
val metadataAsMap = this.crAsMap["metadata"]!! as Map<String, String>
return metadataAsMap["name"]!!
}
}
...@@ -7,6 +7,7 @@ import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext ...@@ -7,6 +7,7 @@ import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
* *
* @see CustomResourceDefinitionContext * @see CustomResourceDefinitionContext
*/ */
@Deprecated("Use `CustomResourceDefinitionContext.Builder` instead.")
class K8sContextFactory { class K8sContextFactory {
/** /**
......
package theodolite.k8s package theodolite.k8s
import io.fabric8.kubernetes.api.model.ConfigMap import io.fabric8.kubernetes.api.model.ConfigMap
import io.fabric8.kubernetes.api.model.HasMetadata
import io.fabric8.kubernetes.api.model.KubernetesResource import io.fabric8.kubernetes.api.model.KubernetesResource
import io.fabric8.kubernetes.api.model.Service import io.fabric8.kubernetes.api.model.Service
import io.fabric8.kubernetes.api.model.apps.Deployment import io.fabric8.kubernetes.api.model.apps.Deployment
...@@ -21,49 +22,31 @@ class K8sManager(private val client: NamespacedKubernetesClient) { ...@@ -21,49 +22,31 @@ class K8sManager(private val client: NamespacedKubernetesClient) {
* Deploys different k8s resources using the client. * Deploys different k8s resources using the client.
* @throws IllegalArgumentException if KubernetesResource not supported. * @throws IllegalArgumentException if KubernetesResource not supported.
*/ */
fun deploy(resource: KubernetesResource) { fun deploy(resource: HasMetadata) {
when (resource) { client.resource(resource).createOrReplace()
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)
is CustomResourceWrapper -> resource.deploy(client)
else -> throw IllegalArgumentException("Unknown Kubernetes resource.")
}
} }
/** /**
* Removes different k8s resources using the client. * Removes different k8s resources using the client.
* @throws IllegalArgumentException if KubernetesResource not supported. * @throws IllegalArgumentException if KubernetesResource not supported.
*/ */
fun remove(resource: KubernetesResource) { fun remove(resource: HasMetadata) {
client.resource(resource).delete()
when (resource) { when (resource) {
is Deployment -> { is Deployment -> {
this.client.apps().deployments().delete(resource)
ResourceByLabelHandler(client = client) ResourceByLabelHandler(client = client)
.blockUntilPodsDeleted( .blockUntilPodsDeleted(
matchLabels = resource.spec.selector.matchLabels matchLabels = resource.spec.selector.matchLabels
) )
logger.info { "Deployment '${resource.metadata.name}' deleted." } logger.info { "Deployment '${resource.metadata.name}' deleted." }
} }
is Service ->
this.client.services().delete(resource)
is ConfigMap ->
this.client.configMaps().delete(resource)
is StatefulSet -> { is StatefulSet -> {
this.client.apps().statefulSets().delete(resource)
ResourceByLabelHandler(client = client) ResourceByLabelHandler(client = client)
.blockUntilPodsDeleted( .blockUntilPodsDeleted(
matchLabels = resource.spec.selector.matchLabels matchLabels = resource.spec.selector.matchLabels
) )
logger.info { "StatefulSet '$resource.metadata.name' deleted." } logger.info { "StatefulSet '$resource.metadata.name' deleted." }
} }
is CustomResourceWrapper -> resource.delete(client)
else -> throw IllegalArgumentException("Unknown Kubernetes resource.")
} }
} }
} }
package theodolite.k8s.resourceLoader
import io.fabric8.kubernetes.api.model.KubernetesResource
import mu.KotlinLogging
import theodolite.k8s.K8sContextFactory
private val logger = KotlinLogging.logger {}
abstract class AbstractK8sLoader: K8sResourceLoader {
fun loadK8sResource(kind: String, resourceString: String): KubernetesResource {
return when (kind.replaceFirst(kind[0],kind[0].uppercaseChar())) {
"Deployment" -> loadDeployment(resourceString)
"Service" -> loadService(resourceString)
"ServiceMonitor" -> loadServiceMonitor(resourceString)
"PodMonitor" -> loadPodMonitor(resourceString)
"ConfigMap" -> loadConfigmap(resourceString)
"StatefulSet" -> loadStatefulSet(resourceString)
"Execution" -> loadExecution(resourceString)
"Benchmark" -> loadBenchmark(resourceString)
else -> {
logger.error { "Error during loading of unspecified resource Kind '$kind'." }
throw IllegalArgumentException("error while loading resource with kind: $kind")
}
}
}
fun <T : KubernetesResource> loadGenericResource(resourceString: String, f: (String) -> T): T {
var resource: T? = null
try {
resource = f(resourceString)
} catch (e: Exception) {
logger.warn { e }
}
if (resource == null) {
throw IllegalArgumentException("The Resource: $resourceString could not be loaded")
}
return resource
}
override fun loadServiceMonitor(resource: String): KubernetesResource {
val context = K8sContextFactory().create(
api = "v1",
scope = "Namespaced",
group = "monitoring.coreos.com",
plural = "servicemonitors"
)
return loadCustomResourceWrapper(resource, context)
}
override fun loadPodMonitor(resource: String): KubernetesResource {
val context = K8sContextFactory().create(
api = "v1",
scope = "Namespaced",
group = "monitoring.coreos.com",
plural = "podmonitors"
)
return loadCustomResourceWrapper(resource, context)
}
override fun loadExecution(resource: String): KubernetesResource {
val context = K8sContextFactory().create(
api = "v1",
scope = "Namespaced",
group = "theodolite.com",
plural = "executions"
)
return loadCustomResourceWrapper(resource, context)
}
override fun loadBenchmark(resource: String): KubernetesResource {
val context = K8sContextFactory().create(
api = "v1",
scope = "Namespaced",
group = "theodolite.com",
plural = "benchmarks"
)
return loadCustomResourceWrapper(resource, context)
}
}
\ No newline at end of file
package theodolite.k8s.resourceLoader
import io.fabric8.kubernetes.api.model.KubernetesResource
import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
interface K8sResourceLoader {
fun loadDeployment(resource: String): KubernetesResource
fun loadService(resource: String): KubernetesResource
fun loadStatefulSet(resource: String): KubernetesResource
fun loadExecution(resource: String): KubernetesResource
fun loadBenchmark(resource: String): KubernetesResource
fun loadConfigmap(resource: String): KubernetesResource
fun loadServiceMonitor(resource: String): KubernetesResource
fun loadPodMonitor(resource: String): KubernetesResource
fun loadCustomResourceWrapper(resource: String, context: CustomResourceDefinitionContext): KubernetesResource
}
\ No newline at end of file
package theodolite.k8s.resourceLoader
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.apps.Deployment
import io.fabric8.kubernetes.client.NamespacedKubernetesClient
import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
import theodolite.k8s.CustomResourceWrapper
import theodolite.util.YamlParserFromFile
/**
* Used to load different Kubernetes resources.
* Supports: Deployments, Services, ConfigMaps, and CustomResources.
* @param client KubernetesClient used to deploy or remove.
*/
class K8sResourceLoaderFromFile(private val client: NamespacedKubernetesClient): AbstractK8sLoader(),
K8sResourceLoader {
/**
* Parses a Service from a service yaml
* @param resource of the yaml file
* @return Service from fabric8
*/
override fun loadService(resource: String): Service {
return loadGenericResource(resource) { x: String -> client.services().load(x).get() }
}
/**
* Parses a CustomResource from a yaml
* @param path of the yaml file
* @param context specific crd context for this custom resource
* @return CustomResourceWrapper from fabric8
*/
override fun loadCustomResourceWrapper(resource: String, context: CustomResourceDefinitionContext): CustomResourceWrapper {
return loadGenericResource(resource) {
CustomResourceWrapper(
YamlParserFromFile().parse(
resource,
HashMap<String, String>()::class.java
)!!,
context
)
}
}
/**
* Parses a Deployment from a Deployment yaml
* @param resource of the yaml file
* @return Deployment from fabric8
*/
override fun loadDeployment(resource: String): Deployment {
return loadGenericResource(resource) { x: String -> client.apps().deployments().load(x).get() }
}
/**
* Parses a ConfigMap from a ConfigMap yaml
* @param resource of the yaml file
* @return ConfigMap from fabric8
*/
override fun loadConfigmap(resource: String): ConfigMap {
return loadGenericResource(resource) { x: String -> client.configMaps().load(x).get() }
}
/**
* Parses a StatefulSet from a StatefulSet yaml
* @param resource of the yaml file
* @return StatefulSet from fabric8
*/
override fun loadStatefulSet(resource: String): KubernetesResource {
return loadGenericResource(resource) { x: String -> client.apps().statefulSets().load(x).get() }
}
}
package theodolite.k8s.resourceLoader
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.apps.Deployment
import io.fabric8.kubernetes.api.model.apps.StatefulSet
import io.fabric8.kubernetes.client.NamespacedKubernetesClient
import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
import theodolite.k8s.CustomResourceWrapper
import theodolite.util.YamlParserFromString
import java.io.ByteArrayInputStream
import java.io.InputStream
class K8sResourceLoaderFromString(private val client: NamespacedKubernetesClient): AbstractK8sLoader(),
K8sResourceLoader {
override fun loadService(resource: String): Service {
return loadAnyResource(resource) { stream -> client.services().load(stream).get() }
}
override fun loadDeployment(resource: String): Deployment {
return loadAnyResource(resource) { stream -> client.apps().deployments().load(stream).get() }
}
override fun loadConfigmap(resource: String): ConfigMap {
return loadAnyResource(resource) { stream -> client.configMaps().load(stream).get() }
}
override fun loadStatefulSet(resource: String): StatefulSet {
return loadAnyResource(resource) { stream -> client.apps().statefulSets().load(stream).get() }
}
private fun <T : KubernetesResource> loadAnyResource(resource: String, f: (InputStream) -> T): T {
return loadGenericResource(resource) { f(ByteArrayInputStream(it.encodeToByteArray())) }
}
/**
* Parses a CustomResource from a yaml
* @param resource of the yaml file
* @param context specific crd context for this custom resource
* @return CustomResourceWrapper from fabric8
*/
override fun loadCustomResourceWrapper(resource: String, context: CustomResourceDefinitionContext): CustomResourceWrapper {
return loadGenericResource(resource) {
CustomResourceWrapper(
YamlParserFromString().parse(
resource,
HashMap<String, String>()::class.java
)!!,
context
)
}
}
}
\ No newline at end of file
...@@ -21,5 +21,5 @@ class PatcherDefinition { ...@@ -21,5 +21,5 @@ class PatcherDefinition {
lateinit var resource: String lateinit var resource: String
@JsonSerialize @JsonSerialize
lateinit var properties: MutableMap<String, String> lateinit var properties: Map<String, String>
} }
...@@ -9,6 +9,7 @@ import java.io.InputStream ...@@ -9,6 +9,7 @@ import java.io.InputStream
/** /**
* The YamlParser parses a YAML file * The YamlParser parses a YAML file
*/ */
@Deprecated("Use Jackson ObjectMapper instead")
class YamlParserFromFile : Parser { class YamlParserFromFile : Parser {
override fun <T> parse(path: String, E: Class<T>): T? { override fun <T> parse(path: String, E: Class<T>): T? {
val input: InputStream = FileInputStream(File(path)) val input: InputStream = FileInputStream(File(path))
......
...@@ -6,6 +6,7 @@ import org.yaml.snakeyaml.constructor.Constructor ...@@ -6,6 +6,7 @@ import org.yaml.snakeyaml.constructor.Constructor
/** /**
* The YamlParser parses a YAML string * The YamlParser parses a YAML string
*/ */
@Deprecated("Use Jackson ObjectMapper instead")
class YamlParserFromString : Parser { class YamlParserFromString : Parser {
override fun <T> parse(fileString: String, E: Class<T>): T? { override fun <T> parse(fileString: String, E: Class<T>): T? {
val parser = Yaml(Constructor(E)) val parser = Yaml(Constructor(E))
......
import io.fabric8.kubernetes.api.model.APIResourceListBuilder
import io.fabric8.kubernetes.client.dsl.base.ResourceDefinitionContext
import io.fabric8.kubernetes.client.server.mock.KubernetesServer
fun KubernetesServer.registerResource(context: ResourceDefinitionContext) {
val apiResourceList = APIResourceListBuilder()
.addNewResource()
.withName(context.plural)
.withKind(context.kind)
.withNamespaced(context.isNamespaceScoped)
.endResource()
.build()
this
.expect()
.get()
.withPath("/apis/${context.group}/${context.version}")
.andReturn(200, apiResourceList)
.always()
}
\ No newline at end of file
package theodolite.benchmark package theodolite.benchmark
import com.google.gson.Gson import com.fasterxml.jackson.databind.ObjectMapper
import io.fabric8.kubernetes.api.model.* import io.fabric8.kubernetes.api.model.*
import io.fabric8.kubernetes.api.model.apps.Deployment import io.fabric8.kubernetes.api.model.apps.Deployment
import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder
import io.fabric8.kubernetes.api.model.apps.StatefulSet import io.fabric8.kubernetes.api.model.apps.StatefulSet
import io.fabric8.kubernetes.api.model.apps.StatefulSetBuilder import io.fabric8.kubernetes.api.model.apps.StatefulSetBuilder
import io.fabric8.kubernetes.client.dsl.MixedOperation
import io.fabric8.kubernetes.client.dsl.Resource
import io.fabric8.kubernetes.client.dsl.base.ResourceDefinitionContext
import io.fabric8.kubernetes.client.server.mock.KubernetesServer import io.fabric8.kubernetes.client.server.mock.KubernetesServer
import io.quarkus.test.junit.QuarkusTest import io.quarkus.test.junit.QuarkusTest
import io.quarkus.test.kubernetes.client.KubernetesTestServer
import io.quarkus.test.kubernetes.client.WithKubernetesTestServer
import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.assertThrows
import theodolite.k8s.CustomResourceWrapper import org.mockito.kotlin.mock
import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile import registerResource
import theodolite.TestBenchmark
import theodolite.execution.operator.BenchmarkCRDummy
import theodolite.execution.operator.ExecutionClient
import theodolite.execution.operator.ExecutionEventHandler
import theodolite.execution.operator.ExecutionStateHandler
import theodolite.model.crd.BenchmarkCRD
import theodolite.model.crd.ExecutionCRD
import theodolite.util.DeploymentFailedException import theodolite.util.DeploymentFailedException
import java.io.FileInputStream
private const val testResourcePath = "./src/test/resources/k8s-resource-files/" // TODO move somewhere else
typealias BenchmarkClient = MixedOperation<BenchmarkCRD, KubernetesResourceList<BenchmarkCRD>, Resource<BenchmarkCRD>>
@QuarkusTest @QuarkusTest
class ConfigMapResourceSetTest { @WithKubernetesTestServer
private val server = KubernetesServer(false, true) internal class ConfigMapResourceSetTest {
@KubernetesTestServer
private lateinit var server: KubernetesServer
private val objectMapper: ObjectMapper = ObjectMapper()
private lateinit var executionClient: ExecutionClient
private lateinit var benchmarkClient: BenchmarkClient
@BeforeEach @BeforeEach
fun setUp() { fun setUp() {
server.before() server.before()
this.server.client
.apiextensions().v1()
.customResourceDefinitions()
.load(FileInputStream("crd/crd-execution.yaml"))
.create()
this.server.client
.apiextensions().v1()
.customResourceDefinitions()
.load(FileInputStream("crd/crd-benchmark.yaml"))
.create()
this.executionClient = this.server.client.resources(ExecutionCRD::class.java)
this.benchmarkClient = this.server.client.resources(BenchmarkCRD::class.java)
} }
@AfterEach @AfterEach
...@@ -34,184 +69,196 @@ class ConfigMapResourceSetTest { ...@@ -34,184 +69,196 @@ class ConfigMapResourceSetTest {
server.after() server.after()
} }
fun deployAndGetResource(resource: String): Collection<Pair<String, KubernetesResource>> { private fun deployAndGetResource(vararg resources: HasMetadata): ConfigMapResourceSet {
val configMap1 = ConfigMapBuilder() val configMap = ConfigMapBuilder()
.withNewMetadata().withName("test-configmap").endMetadata() .withNewMetadata().withName("test-configmap").endMetadata()
.addToData("test-resource.yaml",resource) .let {
resources.foldIndexed(it) {
i, b, r -> b.addToData("resource_$i.yaml", objectMapper.writeValueAsString(r))
}
}
.build() .build()
server.client.configMaps().createOrReplace(configMap1) server.client.configMaps().createOrReplace(configMap)
val resourceSet = ConfigMapResourceSet() val resourceSet = ConfigMapResourceSet()
resourceSet.name = "test-configmap" resourceSet.name = "test-configmap"
return resourceSet.getResourceSet(server.client) return resourceSet
} }
@Test @Test
fun testLoadDeployment() { fun testLoadDeployment() {
val resourceBuilder = DeploymentBuilder() val resource = DeploymentBuilder()
resourceBuilder.withNewSpec().endSpec() .withNewSpec()
resourceBuilder.withNewMetadata().endMetadata() .endSpec()
val resource = resourceBuilder.build() .withNewMetadata()
resource.metadata.name = "test-deployment" .withName("test-deployment")
.endMetadata()
.build()
val createdResource = deployAndGetResource(resource = Gson().toJson(resource)) val createdResource = deployAndGetResource(resource).getResourceSet(server.client)
assertEquals(1, createdResource.size) assertEquals(1, createdResource.size)
assertTrue(createdResource.toMutableSet().first().second is Deployment) assertTrue(createdResource.toList().first().second is Deployment)
assertTrue(createdResource.toMutableSet().first().second.toString().contains(other = resource.metadata.name)) assertTrue(createdResource.toList().first().second.toString().contains(other = resource.metadata.name))
} }
@Test @Test
fun testLoadStateFulSet() { fun testLoadStateFulSet() {
val resourceBuilder = StatefulSetBuilder() val resource = StatefulSetBuilder()
resourceBuilder.withNewSpec().endSpec() .withNewSpec()
resourceBuilder.withNewMetadata().endMetadata() .endSpec()
val resource = resourceBuilder.build() .withNewMetadata()
resource.metadata.name = "test-resource" .withName("test-sts")
.endMetadata()
.build()
val createdResource = deployAndGetResource(resource = Gson().toJson(resource)) val createdResource = deployAndGetResource(resource).getResourceSet(server.client)
assertEquals(1, createdResource.size) assertEquals(1, createdResource.size)
assertTrue(createdResource.toMutableSet().first().second is StatefulSet) assertTrue(createdResource.toList().first().second is StatefulSet)
assertTrue(createdResource.toMutableSet().first().second.toString().contains(other = resource.metadata.name)) assertTrue(createdResource.toList().first().second.toString().contains(other = resource.metadata.name))
} }
@Test @Test
fun testLoadService() { fun testLoadService() {
val resourceBuilder = ServiceBuilder() val resource = ServiceBuilder()
resourceBuilder.withNewSpec().endSpec() .withNewSpec()
resourceBuilder.withNewMetadata().endMetadata() .endSpec()
val resource = resourceBuilder.build() .withNewMetadata()
resource.metadata.name = "test-resource" .withName("test-service")
.endMetadata()
.build()
val createdResource = deployAndGetResource(resource = Gson().toJson(resource)) val createdResource = deployAndGetResource(resource).getResourceSet(server.client)
assertEquals(1, createdResource.size) assertEquals(1, createdResource.size)
assertTrue(createdResource.toMutableSet().first().second is Service) assertTrue(createdResource.toList().first().second is Service)
assertTrue(createdResource.toMutableSet().first().second.toString().contains(other = resource.metadata.name)) assertTrue(createdResource.toList().first().second.toString().contains(other = resource.metadata.name))
} }
@Test @Test
fun testLoadConfigMap() { fun testLoadConfigMap() {
val resourceBuilder = ConfigMapBuilder() val resource = ConfigMapBuilder()
resourceBuilder.withNewMetadata().endMetadata() .withNewMetadata()
val resource = resourceBuilder.build() .withName("test-configmap")
resource.metadata.name = "test-resource" .endMetadata()
.build()
val createdResource = deployAndGetResource(resource = Gson().toJson(resource)) val createdResource = deployAndGetResource(resource).getResourceSet(server.client)
assertEquals(1, createdResource.size) assertEquals(1, createdResource.size)
assertTrue(createdResource.toMutableSet().first().second is ConfigMap) assertTrue(createdResource.toList().first().second is ConfigMap)
assertTrue(createdResource.toMutableSet().first().second.toString().contains(other = resource.metadata.name)) assertTrue(createdResource.toList().first().second.toString().contains(other = resource.metadata.name))
} }
@Test @Test
fun testLoadExecution() { fun testLoadExecution() {
val loader = K8sResourceLoaderFromFile(server.client) val stream = javaClass.getResourceAsStream("/k8s-resource-files/test-execution.yaml")
val resource = loader.loadK8sResource("Execution", testResourcePath + "test-execution.yaml") as CustomResourceWrapper val execution = this.executionClient.load(stream).get()
val createdResource = deployAndGetResource(resource = Gson().toJson(resource.crAsMap)) val createdResource = deployAndGetResource(execution).getResourceSet(server.client)
assertEquals(1, createdResource.size) assertEquals(1, createdResource.size)
assertTrue(createdResource.toMutableSet().first().second is CustomResourceWrapper) val loadedResource = createdResource.toList().first().second
assertTrue(loadedResource is ExecutionCRD)
assertEquals("example-execution", loadedResource.metadata.name)
val loadedResource = createdResource.toMutableSet().first().second
if (loadedResource is CustomResourceWrapper){
assertTrue(loadedResource.getName() == "example-execution")
}
} }
@Test @Test
fun testLoadBenchmark() { fun testLoadBenchmark() {
val loader = K8sResourceLoaderFromFile(server.client) val benchmark = BenchmarkCRDummy("example-benchmark").getCR()
val resource = loader.loadK8sResource("Benchmark", testResourcePath + "test-benchmark.yaml") as CustomResourceWrapper val createdResource = deployAndGetResource(benchmark).getResourceSet(server.client)
val createdResource = deployAndGetResource(resource = Gson().toJson(resource.crAsMap))
assertEquals(1, createdResource.size) assertEquals(1, createdResource.size)
assertTrue(createdResource.toMutableSet().first().second is CustomResourceWrapper) val loadedResource = createdResource.toList().first().second
assertTrue(loadedResource is BenchmarkCRD)
val loadedResource = createdResource.toMutableSet().first().second assertEquals("example-benchmark", loadedResource.metadata.name)
if (loadedResource is CustomResourceWrapper){
assertTrue(loadedResource.getName() == "example-benchmark")
}
} }
@Test @Test
fun testLoadServiceMonitor() { fun testLoadServiceMonitor() {
val loader = K8sResourceLoaderFromFile(server.client) val serviceMonitorContext = ResourceDefinitionContext.Builder()
val resource = loader.loadK8sResource("ServiceMonitor", testResourcePath + "test-service-monitor.yaml") as CustomResourceWrapper .withGroup("monitoring.coreos.com")
val createdResource = deployAndGetResource(resource = Gson().toJson(resource.crAsMap)) .withKind("ServiceMonitor")
.withPlural("servicemonitors")
.withNamespaced(true)
.withVersion("v1")
.build()
server.registerResource(serviceMonitorContext)
assertEquals(1, createdResource.size) val stream = javaClass.getResourceAsStream("/k8s-resource-files/test-service-monitor.yaml")
assertTrue(createdResource.toMutableSet().first().second is CustomResourceWrapper) val serviceMonitor = server.client.load(stream).get()[0]
val createdResource = deployAndGetResource(serviceMonitor).getResourceSet(server.client)
val loadedResource = createdResource.toMutableSet().first().second assertEquals(1, createdResource.size)
if (loadedResource is CustomResourceWrapper){ val loadedResource = createdResource.toList().first().second
assertTrue(loadedResource.getName() == "test-service-monitor") assertTrue(loadedResource is GenericKubernetesResource)
} assertEquals("ServiceMonitor", loadedResource.kind)
assertEquals("test-service-monitor", loadedResource.metadata.name)
} }
@Test @Test
fun testMultipleFiles(){ fun testMultipleFiles(){
val resourceBuilder = DeploymentBuilder() val deployment = DeploymentBuilder()
resourceBuilder.withNewSpec().endSpec() .withNewSpec()
resourceBuilder.withNewMetadata().endMetadata() .endSpec()
val resource = resourceBuilder.build() .withNewMetadata()
resource.metadata.name = "test-deployment" .withName("test-deployment")
.endMetadata()
val resourceBuilder1 = ConfigMapBuilder() .build()
resourceBuilder1.withNewMetadata().endMetadata() val configMap = ConfigMapBuilder()
val resource1 = resourceBuilder1.build() .withNewMetadata()
resource1.metadata.name = "test-configmap" .withName("test-configmap")
.endMetadata()
val configMap1 = ConfigMapBuilder()
.withNewMetadata().withName("test-configmap").endMetadata()
.addToData("test-deployment.yaml",Gson().toJson(resource))
.addToData("test-configmap.yaml",Gson().toJson(resource1))
.build() .build()
server.client.configMaps().createOrReplace(configMap1) val createdResourceSet = deployAndGetResource(deployment, configMap).getResourceSet(server.client)
val resourceSet = ConfigMapResourceSet()
resourceSet.name = "test-configmap"
val createdResourcesSet = resourceSet.getResourceSet(server.client)
assertEquals(2,createdResourcesSet.size ) assertEquals(2, createdResourceSet.size )
assert(createdResourcesSet.toMutableList()[0].second is Deployment) assert(createdResourceSet.toList()[0].second is Deployment)
assert(createdResourcesSet.toMutableList()[1].second is ConfigMap) assert(createdResourceSet.toList()[1].second is ConfigMap)
} }
@Test @Test
fun testFileIsSet(){ fun testFilesRestricted() {
val resourceBuilder = DeploymentBuilder() val deployment = DeploymentBuilder()
resourceBuilder.withNewSpec().endSpec() .withNewSpec()
resourceBuilder.withNewMetadata().endMetadata() .endSpec()
val resource = resourceBuilder.build() .withNewMetadata()
resource.metadata.name = "test-deployment" .withName("test-deployment")
.endMetadata()
val resourceBuilder1 = ConfigMapBuilder() .build()
resourceBuilder1.withNewMetadata().endMetadata() val configMap = ConfigMapBuilder()
val resource1 = resourceBuilder1.build() .withNewMetadata()
resource1.metadata.name = "test-configmap" .withName("test-configmap")
.endMetadata()
val configMap1 = ConfigMapBuilder()
.withNewMetadata().withName("test-configmap").endMetadata()
.addToData("test-deployment.yaml",Gson().toJson(resource))
.addToData("test-configmap.yaml",Gson().toJson(resource1))
.build() .build()
server.client.configMaps().createOrReplace(configMap1) val createdResourceSet = deployAndGetResource(deployment, configMap)
val allResources = createdResourceSet.getResourceSet(server.client)
val resourceSet = ConfigMapResourceSet() assertEquals(2, allResources.size)
resourceSet.name = "test-configmap" createdResourceSet.files = listOf(allResources.first().first) // only select first file from ConfigMa
resourceSet.files = listOf("test-deployment.yaml") val resources = createdResourceSet.getResourceSet(server.client)
assertEquals(1, resources.size)
assertTrue(resources.toList().first().second is Deployment)
}
val createdResourcesSet = resourceSet.getResourceSet(server.client) @Test
fun testFileNotExist() {
val resource = DeploymentBuilder()
.withNewSpec()
.endSpec()
.withNewMetadata()
.withName("test-deployment")
.endMetadata()
.build()
assertEquals(1, createdResourcesSet.size ) val resourceSet = deployAndGetResource(resource)
assert(createdResourcesSet.toMutableSet().first().second is Deployment) resourceSet.files = listOf("non-existing-file.yaml")
assertThrows<DeploymentFailedException> {
resourceSet.getResourceSet(server.client)
}
} }
@Test @Test
fun testConfigMapNotExist() { fun testConfigMapNotExist() {
val resourceSet = ConfigMapResourceSet() val resourceSet = ConfigMapResourceSet()
......