Add rollback and update functionality for config-value component.

Issue-ID: CCSDK-2922
Signed-off-by: Grzegorz Wielgosinski <g.wielgosins@samsung.com>
Change-Id: I7384aa3d99fe273454e3acf2f933add0fb07a66c
diff --git a/components/model-catalog/definition-type/starter-type/node_type/component-k8s-config-value.json b/components/model-catalog/definition-type/starter-type/node_type/component-k8s-config-value.json
index c47a856..901f322 100644
--- a/components/model-catalog/definition-type/starter-type/node_type/component-k8s-config-value.json
+++ b/components/model-catalog/definition-type/starter-type/node_type/component-k8s-config-value.json
@@ -37,13 +37,21 @@
                 "required": false,
                 "type": "string"
             },
+            "k8s-operation-type" : {
+                "required" : false,
+                "type" : "string",
+                "constraints" : [{
+                   "valid_values" : [ "create", "update", "rollback" ]
+                }],
+                "default" : "create"
+            },
             "artifact-prefix-names": {
-              "description": "Resource Assignment Artifact Prefix names",
-              "required": false,
-              "type": "list",
-              "entry_schema": {
-                "type": "string"
-              }
+                "description": "Resource Assignment Artifact Prefix names",
+                "required": false,
+                "type": "list",
+                "entry_schema": {
+                  "type": "string"
+                }
             },
             "resource-assignment-map": {
                 "description": "Holds resolved values for each artifact prefix eg. { vdns: { vnf-id: 123 } }",
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
index 7e9f407..2e7b34e 100644
--- 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
@@ -40,6 +40,7 @@
         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 INPUT_K8S_OPERATION_TYPE = "k8s-operation-type"
 
         const val OUTPUT_STATUSES = "statuses"
         const val OUTPUT_SKIPPED = "skipped"
@@ -53,6 +54,7 @@
             INPUT_K8S_TEMPLATE_NAME,
             INPUT_K8S_CONFIG_NAME,
             INPUT_K8S_INSTANCE_ID,
+            INPUT_K8S_OPERATION_TYPE,
             INPUT_K8S_TEMPLATE_VALUE_SOURCE,
             INPUT_ARTIFACT_PREFIX_NAMES
         )
@@ -84,31 +86,86 @@
             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 operationType = prefixInputParamsMap[INPUT_K8S_TEMPLATE_VALUE_SOURCE]?.returnNullIfMissing()?.asText()?.toUpperCase()
+
+            if (operationType == null || operationType == OperationType.CREATE.toString())
+                createOperation(templateName, instanceId, valueSource, outputPrefixStatuses, prefix, configName)
+            else if (operationType == OperationType.UPDATE.toString())
+                updateOperation(templateName, instanceId, valueSource, outputPrefixStatuses, prefix, configName)
+            else if (operationType == OperationType.ROLLBACK.toString())
+                rollbackOperation(instanceId)
+            else
+                throw BlueprintProcessorException("Unknown operation type: $operationType")
+        }
+    }
+
+    private fun createOperation(templateName: String?, instanceId: String?, valueSource: String?, outputPrefixStatuses: MutableMap<String, String>, prefix: String, configName: String?) {
+        if (templateName == null || configName == null || instanceId == null || valueSource == null) {
+            log.warn("$INPUT_K8S_TEMPLATE_NAME or $INPUT_K8S_INSTANCE_ID 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 if (configName.isEmpty()) {
+            log.warn("$INPUT_K8S_CONFIG_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 updateOperation(templateName: String?, instanceId: String?, valueSource: String?, outputPrefixStatuses: MutableMap<String, String>, prefix: String, configName: String?) {
+        if (templateName == null || configName == null || instanceId == null || valueSource == null) {
+            log.warn("$INPUT_K8S_TEMPLATE_NAME or $INPUT_K8S_INSTANCE_ID 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 if (configName.isEmpty()) {
+            log.warn("$INPUT_K8S_CONFIG_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))
+            if (api.hasConfigurationValues(instanceId, configName)) {
                 val configValueRequest = K8sConfigValueRequest()
                 configValueRequest.templateName = templateName
                 configValueRequest.configName = configName
                 configValueRequest.description = valueSource
                 configValueRequest.values = parseResult(valueSource)
-                api.createConfigurationValues(configValueRequest, instanceId)
+                api.editConfigurationValues(configValueRequest, instanceId, configName)
+            } else {
+                throw BlueprintProcessorException("Error while getting configuration value")
             }
         }
     }
 
+    private fun rollbackOperation(instanceId: String?) {
+        if (instanceId != null) {
+            val api = K8sPluginInstanceApi(K8sConnectionPluginConfiguration(bluePrintPropertiesService))
+            api.rollbackConfigurationValues(instanceId)
+        } else {
+            throw BlueprintProcessorException("$INPUT_K8S_INSTANCE_ID is null")
+        }
+    }
+
     private fun parseResult(templateValueSource: String): Any {
         val ymlSourceFile = getYmlSourceFile(templateValueSource)
         val yamlReader = ObjectMapper(YAMLFactory())
@@ -146,4 +203,8 @@
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
         bluePrintRuntimeService.getBlueprintError().addError(runtimeException.message!!)
     }
+
+    private enum class OperationType {
+        CREATE, UPDATE, ROLLBACK
+    }
 }
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 b312adc..7663699 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
@@ -267,7 +267,7 @@
         }
     }
 
-    fun getConfigurationValues(instanceId: String, configName: String): K8sConfigValueResponse? {
+    fun hasConfigurationValues(instanceId: String, configName: String): Boolean {
         val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
         try {
             val result: BlueprintWebClientService.WebClientResponse<String> = rbInstanceService.exchangeResource(
@@ -276,31 +276,7 @@
                 ""
             )
             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)
-            }
+            return result.status in 200..299
         } catch (e: Exception) {
             log.error("Caught exception trying to get k8s rb instance")
             throw BlueprintProcessorException("${e.message}")