Merge "Wrap day2 api and create configuration-value component"
diff --git a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/template/K8sConfigTemplateComponent.kt b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/template/K8sConfigTemplateComponent.kt
index 4e20dcb..cb759e5 100644
--- a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/template/K8sConfigTemplateComponent.kt
+++ b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/template/K8sConfigTemplateComponent.kt
@@ -75,7 +75,7 @@
     private val log = LoggerFactory.getLogger(K8sConfigTemplateComponent::class.java)!!
 
     override suspend fun processNB(executionRequest: ExecutionServiceInput) {
-        log.info("Triggering K8s Profile Upload component logic.")
+        log.info("Triggering K8s Config Upload component logic.")
 
         val inputParameterNames = arrayOf(
             INPUT_K8S_TEMPLATE_NAME,
@@ -153,7 +153,7 @@
                 api.createTemplate(definitionName, definitionVersion, template)
                 api.uploadTemplate(definitionName, definitionVersion, template, templateFilePath)
 
-                log.info("K8s Profile Upload Completed")
+                log.info("K8s Config Upload Completed")
                 outputPrefixStatuses[prefix] = OUTPUT_UPLOADED
             }
         }
@@ -183,17 +183,17 @@
         return result
     }
 
-    private suspend fun prepareTemplateFile(k8sRbTemplateName: String, ks8ProfileSource: String, ks8ProfileLocation: String): Path {
+    private suspend fun prepareTemplateFile(k8sRbTemplateName: String, ks8ConfigSource: String, k8sConfigLocation: String): Path {
         val bluePrintContext = bluePrintRuntimeService.bluePrintContext()
         val bluePrintBasePath: String = bluePrintContext.rootPath
-        val profileSourceFileFolderPath: Path = Paths.get(
-            bluePrintBasePath.plus(File.separator).plus(ks8ProfileLocation)
+        val configeSourceFileFolderPath: Path = Paths.get(
+            bluePrintBasePath.plus(File.separator).plus(k8sConfigLocation)
         )
 
-        if (profileSourceFileFolderPath.toFile().exists() && !profileSourceFileFolderPath.toFile().isDirectory)
-            return profileSourceFileFolderPath
-        else if (profileSourceFileFolderPath.toFile().exists()) {
-            log.info("Profile building started from source $ks8ProfileSource")
+        if (configeSourceFileFolderPath.toFile().exists() && !configeSourceFileFolderPath.toFile().isDirectory)
+            return configeSourceFileFolderPath
+        else if (configeSourceFileFolderPath.toFile().exists()) {
+            log.info("Config building started from source $ks8ConfigSource")
             val properties: MutableMap<String, Any> = mutableMapOf()
             properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] = false
             properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = ""
@@ -204,28 +204,28 @@
             val resolutionResult: Pair<String, MutableList<ResourceAssignment>> = resourceResolutionService.resolveResources(
                 bluePrintRuntimeService,
                 nodeTemplateName,
-                ks8ProfileSource,
+                ks8ConfigSource,
                 properties
             )
             val tempMainPath: File = createTempDir("k8s-profile-", "")
-            val tempProfilePath: File = createTempDir("content-", "", tempMainPath)
+            val tempPath: File = createTempDir("content-", "", tempMainPath)
 
             val resolvedJsonContent = resolutionResult.second
                 .associateBy({ it.name }, { it.property?.value })
                 .asJsonNode()
 
             try {
-                templateLocation(profileSourceFileFolderPath.toFile(), resolvedJsonContent, tempProfilePath)
-                // Preparation of the final profile content
+                templateLocation(configeSourceFileFolderPath.toFile(), resolvedJsonContent, tempPath)
+                // Preparation of the final config content
                 val finalTemplateFilePath = Paths.get(
                     tempMainPath.toString().plus(File.separator).plus(
                         "$k8sRbTemplateName.tar.gz"
                     )
                 )
-                if (!BlueprintArchiveUtils.compress(tempProfilePath, finalTemplateFilePath.toFile(), ArchiveType.TarGz)) {
-                    throw BlueprintProcessorException("Profile compression has failed")
+                if (!BlueprintArchiveUtils.compress(tempPath, finalTemplateFilePath.toFile(), ArchiveType.TarGz)) {
+                    throw BlueprintProcessorException("Config template compression has failed")
                 }
-                FileUtils.deleteDirectory(tempProfilePath)
+                FileUtils.deleteDirectory(tempPath)
 
                 return finalTemplateFilePath
             } catch (t: Throwable) {
@@ -233,7 +233,7 @@
                 throw t
             }
         } else
-            throw BlueprintProcessorException("Profile source $ks8ProfileLocation is missing in CBA folder")
+            throw BlueprintProcessorException("Config source $k8sConfigLocation is missing in CBA folder")
     }
 
     private fun templateLocation(location: File, params: JsonNode, destinationFolder: File) {
diff --git a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/template/K8sConfigValueComponent.kt b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/template/K8sConfigValueComponent.kt
new file mode 100644
index 0000000..7e9f407
--- /dev/null
+++ b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/template/K8sConfigValueComponent.kt
@@ -0,0 +1,149 @@
+package org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.definition.template
+
+import com.fasterxml.jackson.databind.JsonNode
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.databind.node.ArrayNode
+import com.fasterxml.jackson.databind.node.ObjectNode
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
+import com.fasterxml.jackson.module.kotlin.convertValue
+import org.onap.ccsdk.cds.blueprintsprocessor.core.BlueprintPropertiesService
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.K8sConnectionPluginConfiguration
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.K8sConfigValueRequest
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.K8sPluginInstanceApi
+import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction
+import org.onap.ccsdk.cds.controllerblueprints.core.BlueprintConstants
+import org.onap.ccsdk.cds.controllerblueprints.core.BlueprintProcessorException
+import org.onap.ccsdk.cds.controllerblueprints.core.data.ArtifactDefinition
+import org.onap.ccsdk.cds.controllerblueprints.core.returnNullIfMissing
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+import org.slf4j.LoggerFactory
+import org.springframework.beans.factory.config.ConfigurableBeanFactory
+import org.springframework.context.annotation.Scope
+import org.springframework.stereotype.Component
+import java.io.File
+import java.nio.file.Path
+import java.nio.file.Paths
+
+@Component("component-k8s-config-value")
+@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+open class K8sConfigValueComponent(
+    private var bluePrintPropertiesService: BlueprintPropertiesService
+) : AbstractComponentFunction() {
+
+    private val log = LoggerFactory.getLogger(K8sConfigValueComponent::class.java)!!
+
+    companion object {
+        const val INPUT_RESOURCE_ASSIGNMENT_MAP = "resource-assignment-map"
+        const val INPUT_ARTIFACT_PREFIX_NAMES = "artifact-prefix-names"
+        const val INPUT_K8S_TEMPLATE_NAME = "k8s-template-name"
+        const val INPUT_K8S_CONFIG_NAME = "k8s-config-name"
+        const val INPUT_K8S_INSTANCE_ID = "k8s-instance-id"
+        const val INPUT_K8S_TEMPLATE_VALUE_SOURCE = "k8s-rb-template-value-source"
+
+        const val OUTPUT_STATUSES = "statuses"
+        const val OUTPUT_SKIPPED = "skipped"
+        const val OUTPUT_UPLOADED = "uploaded"
+        const val OUTPUT_ERROR = "error"
+    }
+
+    override suspend fun processNB(executionRequest: ExecutionServiceInput) {
+        log.info("Triggering K8s Config Value component logic.")
+        val inputParameterNames = arrayOf(
+            INPUT_K8S_TEMPLATE_NAME,
+            INPUT_K8S_CONFIG_NAME,
+            INPUT_K8S_INSTANCE_ID,
+            INPUT_K8S_TEMPLATE_VALUE_SOURCE,
+            INPUT_ARTIFACT_PREFIX_NAMES
+        )
+        val outputPrefixStatuses = mutableMapOf<String, String>()
+        val inputParamsMap = mutableMapOf<String, JsonNode?>()
+
+        inputParameterNames.forEach {
+            inputParamsMap[it] = getOptionalOperationInput(it)?.returnNullIfMissing()
+        }
+
+        log.info("Getting the template prefixes")
+        val prefixList: ArrayList<String> = getTemplatePrefixList(inputParamsMap[INPUT_ARTIFACT_PREFIX_NAMES])
+
+        log.info("Iterating over prefixes in resource assignment map.")
+        for (prefix in prefixList) {
+            outputPrefixStatuses[prefix] = OUTPUT_SKIPPED
+            val prefixNode: JsonNode = operationInputs[INPUT_RESOURCE_ASSIGNMENT_MAP]?.get(prefix) ?: continue
+            val assignmentMapPrefix = JacksonUtils.jsonNode(prefixNode.toPrettyString()) as ObjectNode
+            val prefixInputParamsMap = inputParamsMap.toMutableMap()
+            prefixInputParamsMap.forEach { (inputParamName, value) ->
+                if (value == null) {
+                    val mapValue = assignmentMapPrefix.get(inputParamName)
+                    log.debug("$inputParamName value was $value so we fetch $mapValue")
+                    prefixInputParamsMap[inputParamName] = mapValue
+                }
+            }
+
+            val templateName: String? = prefixInputParamsMap[INPUT_K8S_TEMPLATE_NAME]?.returnNullIfMissing()?.asText()
+            val configName: String? = prefixInputParamsMap[INPUT_K8S_CONFIG_NAME]?.returnNullIfMissing()?.asText()
+            val instanceId: String? = prefixInputParamsMap[INPUT_K8S_INSTANCE_ID]?.returnNullIfMissing()?.asText()
+            val valueSource: String? = prefixInputParamsMap[INPUT_K8S_TEMPLATE_VALUE_SOURCE]?.returnNullIfMissing()?.asText()
+            if (templateName == null || instanceId == null || valueSource == null) {
+                log.warn("$INPUT_K8S_TEMPLATE_NAME or $INPUT_K8S_TEMPLATE_NAME or $INPUT_K8S_TEMPLATE_VALUE_SOURCE or $INPUT_K8S_CONFIG_NAME is null")
+            } else if (templateName.isEmpty()) {
+                log.warn("$INPUT_K8S_TEMPLATE_NAME is empty")
+            } else {
+                log.info("Uploading K8s template value..")
+                outputPrefixStatuses[prefix] = OUTPUT_ERROR
+                val bluePrintContext = bluePrintRuntimeService.bluePrintContext()
+                val artifact: ArtifactDefinition = bluePrintContext.nodeTemplateArtifact(nodeTemplateName, valueSource)
+                if (artifact.type != BlueprintConstants.MODEL_TYPE_ARTIFACT_K8S_PROFILE)
+                    throw BlueprintProcessorException(
+                        "Unexpected profile artifact type for profile source $valueSource. Expecting: $artifact.type"
+                    )
+                // Creating API connector
+                val api = K8sPluginInstanceApi(K8sConnectionPluginConfiguration(bluePrintPropertiesService))
+                val configValueRequest = K8sConfigValueRequest()
+                configValueRequest.templateName = templateName
+                configValueRequest.configName = configName
+                configValueRequest.description = valueSource
+                configValueRequest.values = parseResult(valueSource)
+                api.createConfigurationValues(configValueRequest, instanceId)
+            }
+        }
+    }
+
+    private fun parseResult(templateValueSource: String): Any {
+        val ymlSourceFile = getYmlSourceFile(templateValueSource)
+        val yamlReader = ObjectMapper(YAMLFactory())
+        val obj: Any = yamlReader.readValue(ymlSourceFile, Any::class.java)
+
+        val jsonWriter = ObjectMapper()
+        return jsonWriter.convertValue(obj)
+    }
+
+    private fun getYmlSourceFile(templateValueSource: String): File {
+        val bluePrintBasePath: String = bluePrintRuntimeService.bluePrintContext().rootPath
+        val profileSourceFileFolderPath: Path = Paths.get(bluePrintBasePath.plus(File.separator).plus(templateValueSource))
+
+        if (profileSourceFileFolderPath.toFile().exists() && !profileSourceFileFolderPath.toFile().isDirectory)
+            return profileSourceFileFolderPath.toFile()
+        else
+            throw BlueprintProcessorException("Template value $profileSourceFileFolderPath is missing in CBA folder")
+    }
+
+    private fun getTemplatePrefixList(node: JsonNode?): ArrayList<String> {
+        val result = ArrayList<String>()
+        when (node) {
+            is ArrayNode -> {
+                val arrayNode = node.toList()
+                for (prefixNode in arrayNode)
+                    result.add(prefixNode.asText())
+            }
+            is ObjectNode -> {
+                result.add(node.asText())
+            }
+        }
+        return result
+    }
+
+    override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
+        bluePrintRuntimeService.getBlueprintError().addError(runtimeException.message!!)
+    }
+}
diff --git a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sConfigValueRequest.kt b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sConfigValueRequest.kt
new file mode 100644
index 0000000..b6093d6
--- /dev/null
+++ b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sConfigValueRequest.kt
@@ -0,0 +1,32 @@
+package org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance
+
+import com.fasterxml.jackson.annotation.JsonProperty
+
+class K8sConfigValueRequest {
+
+    @get:JsonProperty("template-name")
+    var templateName: String? = null
+
+    @get:JsonProperty("config-name")
+    var configName: String? = null
+
+    @get:JsonProperty("description")
+    var description: String? = null
+
+    @get:JsonProperty("values")
+    var values: Any? = null
+
+    override fun toString(): String {
+        return "$templateName:$configName:$description:$values"
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (javaClass != other?.javaClass) return false
+        return true
+    }
+
+    override fun hashCode(): Int {
+        return javaClass.hashCode()
+    }
+}
diff --git a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sConfigValueResponse.kt b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sConfigValueResponse.kt
new file mode 100644
index 0000000..823009f
--- /dev/null
+++ b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sConfigValueResponse.kt
@@ -0,0 +1,38 @@
+package org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance
+
+import com.fasterxml.jackson.annotation.JsonProperty
+
+class K8sConfigValueResponse {
+
+    @get:JsonProperty("rb-name")
+    var rbName: String? = null
+
+    @get:JsonProperty("rb-version")
+    var rbVersion: String? = null
+
+    @get:JsonProperty("profile-name")
+    var profileName: String? = null
+
+    @get:JsonProperty("template-name")
+    var templateName: String? = null
+
+    @get:JsonProperty("config-name")
+    var configName: String? = null
+
+    @get:JsonProperty("config-name")
+    var configVersion: String? = null
+
+    override fun toString(): String {
+        return "$rbName:$rbVersion:$profileName:$templateName:$configName:$configVersion"
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (javaClass != other?.javaClass) return false
+        return true
+    }
+
+    override fun hashCode(): Int {
+        return javaClass.hashCode()
+    }
+}
diff --git a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sPluginInstanceApi.kt b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sPluginInstanceApi.kt
index e0366f9..b312adc 100644
--- a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sPluginInstanceApi.kt
+++ b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sPluginInstanceApi.kt
@@ -30,6 +30,7 @@
 import org.springframework.http.HttpMethod.DELETE
 import org.springframework.http.HttpMethod.GET
 import org.springframework.http.HttpMethod.POST
+import org.springframework.http.HttpMethod.PUT
 
 class K8sPluginInstanceApi(
     private val k8sConfiguration: K8sConnectionPluginConfiguration
@@ -222,6 +223,134 @@
         }
     }
 
+    fun createConfigurationValues(configValues: K8sConfigValueRequest, instanceId: String): K8sConfigValueResponse? {
+        val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
+        try {
+            val result: BlueprintWebClientService.WebClientResponse<String> = rbInstanceService.exchangeResource(
+                POST.name,
+                "/config",
+                JacksonUtils.getJson(configValues)
+            )
+            log.debug(result.toString())
+            return if (result.status in 200..299) {
+                val parsedObject: K8sConfigValueResponse? = JacksonUtils.readValue(
+                    result.body, K8sConfigValueResponse::class.java
+                )
+                parsedObject
+            } else
+                throw BlueprintProcessorException(result.body)
+        } catch (e: Exception) {
+            log.error("Caught exception trying to get k8s rb instance")
+            throw BlueprintProcessorException("${e.message}")
+        }
+    }
+
+    fun editConfigurationValues(configValues: K8sConfigValueRequest, instanceId: String, configName: String): K8sConfigValueResponse? {
+        val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
+        try {
+            val result: BlueprintWebClientService.WebClientResponse<String> = rbInstanceService.exchangeResource(
+                PUT.name,
+                "/config/$configName",
+                JacksonUtils.getJson(configValues)
+            )
+            log.debug(result.toString())
+            return if (result.status in 200..299) {
+                val parsedObject: K8sConfigValueResponse? = JacksonUtils.readValue(
+                    result.body, K8sConfigValueResponse::class.java
+                )
+                parsedObject
+            } else
+                throw BlueprintProcessorException(result.body)
+        } catch (e: Exception) {
+            log.error("Caught exception trying to get k8s rb instance")
+            throw BlueprintProcessorException("${e.message}")
+        }
+    }
+
+    fun getConfigurationValues(instanceId: String, configName: String): K8sConfigValueResponse? {
+        val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
+        try {
+            val result: BlueprintWebClientService.WebClientResponse<String> = rbInstanceService.exchangeResource(
+                GET.name,
+                "/config/$configName",
+                ""
+            )
+            log.debug(result.toString())
+            return if (result.status in 200..299) {
+                val parsedObject: K8sConfigValueResponse? = JacksonUtils.readValue(
+                    result.body, K8sConfigValueResponse::class.java
+                )
+                parsedObject
+            } else
+                throw BlueprintProcessorException(result.body)
+        } catch (e: Exception) {
+            log.error("Caught exception trying to get k8s rb instance")
+            throw BlueprintProcessorException("${e.message}")
+        }
+    }
+
+    fun deleteConfigurationValues(instanceId: String, configName: String) {
+        val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
+        try {
+            val result: BlueprintWebClientService.WebClientResponse<String> = rbInstanceService.exchangeResource(
+                DELETE.name,
+                "/config/$configName",
+                ""
+            )
+            log.debug(result.toString())
+            if (result.status !in 200..299) {
+                throw BlueprintProcessorException(result.body)
+            }
+        } catch (e: Exception) {
+            log.error("Caught exception trying to get k8s rb instance")
+            throw BlueprintProcessorException("${e.message}")
+        }
+    }
+
+    fun rollbackConfigurationValues(instanceId: String): K8sConfigValueResponse? {
+        val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
+        try {
+            val result: BlueprintWebClientService.WebClientResponse<String> = rbInstanceService.exchangeResource(
+                POST.name,
+                "/rollback",
+                ""
+            )
+            log.debug(result.toString())
+            return if (result.status in 200..299) {
+                val parsedObject: K8sConfigValueResponse? = JacksonUtils.readValue(
+                    result.body, K8sConfigValueResponse::class.java
+                )
+                parsedObject
+            } else
+                throw BlueprintProcessorException(result.body)
+        } catch (e: Exception) {
+            log.error("Caught exception trying to get k8s rb instance")
+            throw BlueprintProcessorException("${e.message}")
+        }
+    }
+
+    fun createConfigurationValues(instanceId: String): K8sConfigValueResponse? {
+        val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
+        try {
+            val result: BlueprintWebClientService.WebClientResponse<String> = rbInstanceService.exchangeResource(
+                POST.name,
+                "/tagit",
+                ""
+            )
+            log.debug(result.toString())
+            return if (result.status in 200..299) {
+                val parsedObject: K8sConfigValueResponse? = JacksonUtils.readValue(
+                    result.body, K8sConfigValueResponse::class.java
+                )
+                parsedObject
+            } else
+                throw BlueprintProcessorException(result.body)
+        } catch (e: Exception) {
+            log.error("Caught exception trying to get k8s rb instance")
+            throw BlueprintProcessorException("${e.message}")
+        }
+    }
+
     fun deleteInstanceHealthCheck(instanceId: String, healthCheckId: String) {
         val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
         try {
diff --git a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sTopic.kt b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sTopic.kt
new file mode 100644
index 0000000..7ff18ad
--- /dev/null
+++ b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sTopic.kt
@@ -0,0 +1,32 @@
+package org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance
+
+import com.fasterxml.jackson.annotation.JsonProperty
+
+class K8sTopic {
+
+    @get:JsonProperty("name")
+    var name: String? = null
+
+    @get:JsonProperty("cluster")
+    var cluster: String? = null
+
+    @get:JsonProperty("partitions")
+    var partitions: Number? = null
+
+    @get:JsonProperty("replicas")
+    var replicas: Number? = null
+
+    override fun toString(): String {
+        return "$name:$cluster:$partitions:$replicas"
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (javaClass != other?.javaClass) return false
+        return true
+    }
+
+    override fun hashCode(): Int {
+        return javaClass.hashCode()
+    }
+}