K8sPlugin integration changes for Istanbul APIs 42/127042/1
authorLukasz Rajewski <lukasz.rajewski@orange.com>
Wed, 9 Feb 2022 16:07:31 +0000 (17:07 +0100)
committerLukasz Rajewski <lukasz.rajewski@orange.com>
Wed, 9 Feb 2022 16:07:31 +0000 (17:07 +0100)
Implementation of the K8sPlugin new APIs or
changes introduced there in the Istanbul
release.

Issue-ID: CCSDK-3537
Signed-off-by: Lukasz Rajewski <lukasz.rajewski@orange.com>
Change-Id: I263dd22bb1d3cbcc9360583cd82a728afbebc09d

ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/K8sPluginDefinitionApi.kt
ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/profile/K8sProfile.kt
ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/profile/K8sProfileUploadComponent.kt
ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/template/K8sConfigValueComponent.kt
ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/template/K8sTemplate.kt
ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sConfigValueResponse.kt
ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sPluginInstanceApi.kt
ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sRbInstance.kt
ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/query/K8sPluginQueryApi.kt [new file with mode: 0644]
ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/query/K8sQueryRestClient.kt [new file with mode: 0644]
ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/query/K8sResourceStatus.kt [new file with mode: 0644]

index 73c0e80..02b2556 100644 (file)
@@ -24,12 +24,15 @@ import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.definition.profile.K
 import com.fasterxml.jackson.module.kotlin.readValue
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.K8sConnectionPluginConfiguration
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.definition.template.K8sTemplate
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.K8sRbInstanceFull
 import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
 import org.slf4j.LoggerFactory
 import org.springframework.http.HttpMethod.DELETE
 import org.springframework.http.HttpMethod.GET
 import org.springframework.http.HttpMethod.POST
+import org.springframework.http.HttpMethod.PUT
 import java.nio.file.Path
 
 class K8sPluginDefinitionApi(
@@ -78,6 +81,32 @@ class K8sPluginDefinitionApi(
         }
     }
 
+    fun getProfile(definition: String, definitionVersion: String, profileName: String): K8sProfile? {
+        val rbDefinitionService = K8sDefinitionRestClient(
+            k8sConfiguration,
+            definition,
+            definitionVersion
+        )
+        try {
+            val result: BlueprintWebClientService.WebClientResponse<String> = rbDefinitionService.exchangeResource(
+                GET.name,
+                "/profile/$profileName",
+                ""
+            )
+            log.debug(result.toString())
+            return if (result.status in 200..299) {
+                val parsedObject: K8sProfile? = JacksonUtils.readValue(result.body, K8sProfile::class.java)
+                parsedObject
+            } else if (result.status == 500 && result.body.contains("Error finding master table"))
+                null
+            else
+                throw BluePrintProcessorException(result.body)
+        } catch (e: Exception) {
+            log.error("Caught exception trying to get k8s rb profile")
+            throw BluePrintProcessorException("${e.message}")
+        }
+    }
+
     fun createProfile(definition: String, definitionVersion: String, profile: K8sProfile) {
         val rbDefinitionService = K8sDefinitionRestClient(
             k8sConfiguration,
@@ -100,6 +129,46 @@ class K8sPluginDefinitionApi(
         }
     }
 
+    fun updateProfile(profile: K8sProfile) {
+        val rbDefinitionService = K8sDefinitionRestClient(
+            k8sConfiguration,
+            profile.rbName!!,
+            profile.rbVersion!!
+        )
+        val profileJsonString: String = objectMapper.writeValueAsString(profile)
+        try {
+            val result: BlueprintWebClientService.WebClientResponse<String> = rbDefinitionService.exchangeResource(
+                PUT.name,
+                "/profile/${profile.profileName}",
+                profileJsonString
+            )
+            if (result.status !in 200..299) {
+                throw Exception(result.body)
+            }
+        } catch (e: Exception) {
+            log.error("Caught exception trying to create k8s rb profile ${profile.profileName}")
+            throw BluePrintProcessorException("${e.message}")
+        }
+    }
+
+    fun deleteProfile(definition: String, definitionVersion: String, profileName: String) {
+        val rbDefinitionService = K8sDefinitionRestClient(k8sConfiguration, definition, definitionVersion)
+        try {
+            val result: BlueprintWebClientService.WebClientResponse<String> = rbDefinitionService.exchangeResource(
+                DELETE.name,
+                "/profile/${profileName}",
+                ""
+            )
+            log.debug(result.toString())
+            if (result.status !in 200..299) {
+                throw Exception(result.body)
+            }
+        } catch (e: Exception) {
+            log.error("Caught exception during get template")
+            throw BluePrintProcessorException("${e.message}")
+        }
+    }
+
     fun uploadProfileContent(definition: String, definitionVersion: String, profile: K8sProfile, filePath: Path) {
         val fileUploadService = K8sUploadFileRestClientService(
             k8sConfiguration,
index 8caa1d1..ef0d6b9 100644 (file)
@@ -21,6 +21,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.definition.profile
 
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties
 import com.fasterxml.jackson.annotation.JsonProperty
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.K8sRbInstanceGvk
 
 @JsonIgnoreProperties(ignoreUnknown = true)
 class K8sProfile {
@@ -40,6 +41,12 @@ class K8sProfile {
     @get:JsonProperty("namespace")
     var namespace: String? = "default"
 
+    @get:JsonProperty("labels")
+    var labels: Map<String, String>? = null
+
+    @get:JsonProperty("extra-resource-types")
+    var extraResourceTypes: List<K8sRbInstanceGvk>? = null
+
     override fun toString(): String {
         return "$rbName:$rbVersion:$profileName"
     }
index 067c75b..80e1cb4 100644 (file)
@@ -22,11 +22,15 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.definition.profile
 import com.fasterxml.jackson.databind.JsonNode
 import com.fasterxml.jackson.databind.node.ArrayNode
 import com.fasterxml.jackson.databind.node.ObjectNode
+import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
+import com.fasterxml.jackson.module.kotlin.readValue
 import org.apache.commons.io.FileUtils
 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.definition.K8sPluginDefinitionApi
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.K8sRbInstance
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.K8sRbInstanceGvk
 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionService
@@ -65,6 +69,8 @@ open class K8sProfileUploadComponent(
         const val INPUT_K8S_DEFINITION_NAME = "k8s-rb-definition-name"
         const val INPUT_K8S_DEFINITION_VERSION = "k8s-rb-definition-version"
         const val INPUT_K8S_PROFILE_NAMESPACE = "k8s-rb-profile-namespace"
+        const val INPUT_K8S_PROFILE_LABELS = "k8s-rb-profile-labels"
+        const val INPUT_K8S_PROFILE_EXTRA_TYPES = "k8s-rb-profile-extra-types"
         const val INPUT_K8S_PROFILE_K8S_VERSION = "k8s-rb-profile-k8s-version"
         const val INPUT_K8S_PROFILE_SOURCE = "k8s-rb-profile-source"
         const val INPUT_RESOURCE_ASSIGNMENT_MAP = "resource-assignment-map"
@@ -86,6 +92,8 @@ open class K8sProfileUploadComponent(
             INPUT_K8S_DEFINITION_NAME,
             INPUT_K8S_DEFINITION_VERSION,
             INPUT_K8S_PROFILE_NAMESPACE,
+            INPUT_K8S_PROFILE_LABELS,
+            INPUT_K8S_PROFILE_EXTRA_TYPES,
             INPUT_K8S_PROFILE_K8S_VERSION,
             INPUT_K8S_PROFILE_SOURCE,
             INPUT_ARTIFACT_PREFIX_NAMES
@@ -143,6 +151,8 @@ open class K8sProfileUploadComponent(
                 val profileNamespace: String? = prefixInputParamsMap[INPUT_K8S_PROFILE_NAMESPACE]?.returnNullIfMissing()?.asText()
                 val profileK8sVersion: String? = prefixInputParamsMap[INPUT_K8S_PROFILE_K8S_VERSION]?.returnNullIfMissing()?.asText()
                 var profileSource: String? = prefixInputParamsMap[INPUT_K8S_PROFILE_SOURCE]?.returnNullIfMissing()?.asText()
+                var profileLabels: JsonNode? = prefixInputParamsMap[INPUT_K8S_PROFILE_LABELS]?.returnNullIfMissing()
+                var profileExtraTypes: JsonNode? = prefixInputParamsMap[INPUT_K8S_PROFILE_EXTRA_TYPES]?.returnNullIfMissing()
                 if (profileNamespace == null)
                     throw BluePrintProcessorException("Profile $profileName namespace is missing")
                 if (profileSource == null) {
@@ -163,6 +173,16 @@ open class K8sProfileUploadComponent(
                 profile.namespace = profileNamespace
                 if (profileK8sVersion != null)
                     profile.kubernetesVersion = profileK8sVersion
+                if (profileLabels != null) {
+                    val objectMapper = jacksonObjectMapper()
+                    val labelList: HashMap<String, String> = objectMapper.readValue(profileLabels.toPrettyString())
+                    profile.labels = labelList
+                }
+                if (profileExtraTypes != null) {
+                    val objectMapper = jacksonObjectMapper()
+                    val extraTypeList: ArrayList<K8sRbInstanceGvk> = objectMapper.readValue(profileExtraTypes.toPrettyString())
+                    profile.extraResourceTypes = extraTypeList
+                }
                 val profileFilePath: Path = prepareProfileFile(profileName, profileSource, artifact.file)
                 api.createProfile(definitionName, definitionVersion, profile)
                 api.uploadProfileContent(definitionName, definitionVersion, profile, profileFilePath)
index f1affac..0b62949 100644 (file)
@@ -44,6 +44,7 @@ open class K8sConfigValueComponent(
         const val INPUT_ARTIFACT_PREFIX_NAMES = "artifact-prefix-names"
         const val INPUT_K8S_RB_CONFIG_TEMPLATE_NAME = "k8s-rb-config-template-name"
         const val INPUT_K8S_RB_CONFIG_NAME = "k8s-rb-config-name"
+        const val INPUT_K8S_RB_CONFIG_VERSION = "k8s-rb-config-version"
         const val INPUT_K8S_INSTANCE_ID = "k8s-instance-id"
         const val INPUT_K8S_CONFIG_VALUE_SOURCE = "k8s-rb-config-value-source"
         const val INPUT_K8S_CONFIG_OPERATION_TYPE = "k8s-config-operation-type"
@@ -59,6 +60,7 @@ open class K8sConfigValueComponent(
         val inputParameterNames = arrayOf(
             INPUT_K8S_RB_CONFIG_TEMPLATE_NAME,
             INPUT_K8S_RB_CONFIG_NAME,
+            INPUT_K8S_RB_CONFIG_VERSION,
             INPUT_K8S_INSTANCE_ID,
             INPUT_K8S_CONFIG_OPERATION_TYPE,
             INPUT_K8S_CONFIG_VALUE_SOURCE,
@@ -92,20 +94,21 @@ open class K8sConfigValueComponent(
             val configName: String? = prefixInputParamsMap[INPUT_K8S_RB_CONFIG_NAME]?.returnNullIfMissing()?.asText()
             val instanceId: String? = prefixInputParamsMap[INPUT_K8S_INSTANCE_ID]?.returnNullIfMissing()?.asText()
             var valueSource: String? = prefixInputParamsMap[INPUT_K8S_CONFIG_VALUE_SOURCE]?.returnNullIfMissing()?.asText()
+            var configVersion: String? = prefixInputParamsMap[INPUT_K8S_RB_CONFIG_VERSION]?.returnNullIfMissing()?.asText()
             val operationType = prefixInputParamsMap[INPUT_K8S_CONFIG_OPERATION_TYPE]?.returnNullIfMissing()?.asText()?.toUpperCase()
 
             if (valueSource == null) {
                 valueSource = configName
                 log.info("Config name used instead of value source")
             }
-            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.DELETE.toString())
-                deleteOperation(instanceId, configName)
-            else
-                throw BluePrintProcessorException("Unknown operation type: $operationType")
+            when (operationType) {
+                null, OperationType.CREATE.toString() -> createOperation(templateName, instanceId, valueSource, outputPrefixStatuses, prefix, configName)
+                OperationType.UPDATE.toString() -> updateOperation(templateName, instanceId, valueSource, outputPrefixStatuses, prefix, configName)
+                OperationType.DELETE.toString() -> deleteOperation(instanceId, configName, false)
+                OperationType.DELETE_CONFIG.toString() -> deleteOperation(instanceId, configName, true)
+                OperationType.ROLLBACK.toString() -> rollbackOperation(instanceId, configName, configVersion)
+                else -> throw BluePrintProcessorException("Unknown operation type: $operationType")
+            }
         }
     }
 
@@ -170,14 +173,39 @@ open class K8sConfigValueComponent(
         }
     }
 
-    private fun deleteOperation(instanceId: String?, configName: String?) {
+    private fun rollbackOperation(instanceId: String?, configName: String?, configVersion: String?) {
+        val api = K8sPluginInstanceApi(K8sConnectionPluginConfiguration(bluePrintPropertiesService))
+        if (instanceId == null || configName == null || configVersion == null) {
+            log.warn("$INPUT_K8S_INSTANCE_ID or $INPUT_K8S_RB_CONFIG_NAME or $INPUT_K8S_RB_CONFIG_VERSION is null - skipping delete")
+        } else {
+            if (api.hasConfigurationValues(instanceId, configName))
+                api.rollbackConfigurationValues(instanceId, configName, configVersion, null)
+            else {
+                throw BluePrintProcessorException(
+                    "Configuration $configName does not exist. Cannot perform delete operation"
+                )
+            }
+        }
+    }
+
+    private fun deleteOperation(instanceId: String?, configName: String?, onlyDeleteConfig: Boolean) {
         val api = K8sPluginInstanceApi(K8sConnectionPluginConfiguration(bluePrintPropertiesService))
         if (instanceId == null || configName == null) {
             log.warn("$INPUT_K8S_INSTANCE_ID or $INPUT_K8S_RB_CONFIG_NAME is null - skipping delete")
-        } else if (api.hasConfigurationValues(instanceId, configName)) {
-            log.info("Configuration does not exists - skipping delete")
         } else {
-            api.deleteConfigurationValues(instanceId, configName)
+            if (api.hasConfigurationValues(instanceId, configName)) {
+                if (onlyDeleteConfig)
+                    api.deleteConfigurationValues(instanceId, configName, true)
+                else
+                    api.editConfigurationValuesByDelete(instanceId, configName)
+            } else {
+                if (onlyDeleteConfig)
+                    log.info("Configuration does not exists - skipping delete")
+                else
+                    throw BluePrintProcessorException(
+                        "Configuration $configName does not exist. Cannot perform delete operation"
+                    )
+            }
         }
     }
 
@@ -261,6 +289,6 @@ open class K8sConfigValueComponent(
     }
 
     private enum class OperationType {
-        CREATE, UPDATE, DELETE
+        CREATE, UPDATE, DELETE, ROLLBACK, DELETE_CONFIG
     }
 }
index e135d21..26c8346 100644 (file)
@@ -12,8 +12,14 @@ class K8sTemplate {
     @get:JsonProperty("description")
     var description: String? = null
 
+    @get:JsonProperty("chart-name")
+    var chartName: String? = null
+
+    @get:JsonProperty("has-content")
+    var hasContent: Boolean? = null
+
     override fun toString(): String {
-        return "$templateName:$description"
+        return "$templateName:$description:$chartName:$hasContent"
     }
 
     override fun equals(other: Any?): Boolean {
index cefe3e6..c1eaed8 100644 (file)
@@ -29,7 +29,10 @@ class K8sConfigValueResponse {
 
     @get:JsonProperty("config-version")
     @get:JsonAlias("config-verion")
-    var configVersion: Integer? = null
+    var configVersion: Int? = null
+
+    @get:JsonProperty("config-tag")
+    var configTag: String? = null
 
     @get:JsonProperty("values")
     var values: Map<String, Object>? = null
@@ -48,3 +51,26 @@ class K8sConfigValueResponse {
         return javaClass.hashCode()
     }
 }
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+class K8sConfigValueTag {
+    @get:JsonProperty("config-version")
+    var configVersion: Int? = null
+
+    @get:JsonProperty("config-tag")
+    var configTag: String? = null
+
+    override fun toString(): String {
+        return "$configVersion:$configTag"
+    }
+
+    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()
+    }
+}
index dbcc133..1be45e8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright © 2017-2018 AT&T Intellectual Property.
  * Modifications Copyright © 2019 IBM.
- * Modifications Copyright © 2021 Orange.
+ * Modifications Copyright © 2022 Orange.
  * Modifications Copyright © 2020 Deutsche Telekom AG.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -84,6 +84,28 @@ class K8sPluginInstanceApi(
         }
     }
 
+    fun getFullInstanceById(instanceId: String): K8sRbInstanceFull? {
+        val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
+        try {
+            val result: BlueprintWebClientService.WebClientResponse<String> = rbInstanceService.exchangeResource(
+                GET.name,
+                "?full=true",
+                ""
+            )
+            log.debug(result.toString())
+            return if (result.status in 200..299) {
+                val parsedObject: K8sRbInstanceFull? = JacksonUtils.readValue(result.body, K8sRbInstanceFull::class.java)
+                parsedObject
+            } else if (result.status == 500 && result.body.contains("Error finding master table"))
+                null
+            else
+                throw BluePrintProcessorException(result.body)
+        } catch (e: Exception) {
+            log.error("Caught exception trying to get k8s rb instance")
+            throw BluePrintProcessorException("${e.message}")
+        }
+    }
+
     fun getInstanceByRequestProperties(
         rbDefinitionName: String,
         rbDefinitionVersion: String,
@@ -281,6 +303,28 @@ class K8sPluginInstanceApi(
         }
     }
 
+    fun editConfigurationValuesByDelete(instanceId: String, configName: String): K8sConfigValueResponse?  {
+        val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
+        try {
+            val result: BlueprintWebClientService.WebClientResponse<String> = rbInstanceService.exchangeResource(
+                POST.name,
+                "/config/$configName/delete",
+                ""
+            )
+            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 delete config instance")
+            throw BluePrintProcessorException("${e.message}")
+        }
+    }
+
     fun hasConfigurationValues(instanceId: String, configName: String): Boolean {
         val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
         try {
@@ -297,6 +341,22 @@ class K8sPluginInstanceApi(
         }
     }
 
+    fun hasConfigurationValuesVersion(instanceId: String, configName: String, version: String): Boolean {
+        val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
+        try {
+            val result: BlueprintWebClientService.WebClientResponse<String> = rbInstanceService.exchangeResource(
+                GET.name,
+                "/config/$configName/version/$version",
+                ""
+            )
+            log.debug(result.toString())
+            return result.status in 200..299
+        } 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 {
@@ -319,29 +379,34 @@ class K8sPluginInstanceApi(
         }
     }
 
-    fun deleteConfigurationValues(instanceId: String, configName: String) {
+    fun getConfigurationValuesVersion(instanceId: String, configName: String, version: String): K8sConfigValueResponse? {
         val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
         try {
             val result: BlueprintWebClientService.WebClientResponse<String> = rbInstanceService.exchangeResource(
-                DELETE.name,
-                "/config/$configName",
+                GET.name,
+                "/config/$configName/version/$version",
                 ""
             )
             log.debug(result.toString())
-            if (result.status !in 200..299)
+            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 delete config instance")
+            log.error("Caught exception trying to get config instance")
             throw BluePrintProcessorException("${e.message}")
         }
     }
 
-    fun rollbackConfigurationValues(instanceId: String): K8sConfigValueResponse? {
+    fun getConfigurationValuesVersionByTag(instanceId: String, configName: String, tag: String): K8sConfigValueResponse? {
         val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
         try {
             val result: BlueprintWebClientService.WebClientResponse<String> = rbInstanceService.exchangeResource(
-                POST.name,
-                "/rollback",
+                GET.name,
+                "/config/$configName/tag/$tag",
                 ""
             )
             log.debug(result.toString())
@@ -353,29 +418,137 @@ class K8sPluginInstanceApi(
             } else
                 throw BluePrintProcessorException(result.body)
         } catch (e: Exception) {
-            log.error("Caught exception trying to get k8s rb instance")
+            log.error("Caught exception trying to get config instance")
             throw BluePrintProcessorException("${e.message}")
         }
     }
 
-    fun tagConfigurationValues(instanceId: String): K8sConfigValueResponse? {
+    fun getConfigurationValuesList(instanceId: String): List<K8sConfigValueResponse>? {
         val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
         try {
             val result: BlueprintWebClientService.WebClientResponse<String> = rbInstanceService.exchangeResource(
-                POST.name,
-                "/tagit",
+                GET.name,
+                "/config",
                 ""
             )
             log.debug(result.toString())
             return if (result.status in 200..299) {
-                val parsedObject: K8sConfigValueResponse? = JacksonUtils.readValue(
-                    result.body, K8sConfigValueResponse::class.java
-                )
+                val objectMapper = jacksonObjectMapper()
+                val parsedObject: ArrayList<K8sConfigValueResponse>? = objectMapper.readValue(result.body)
                 parsedObject
-            } else
+            } else if (result.status == 500 && result.body.contains("Did not find any objects with tag"))
+                null
+            else
                 throw BluePrintProcessorException(result.body)
         } catch (e: Exception) {
-            log.error("Caught exception trying to get k8s rb instance")
+            log.error("Caught exception trying to get k8s config instance list")
+            throw BluePrintProcessorException("${e.message}")
+        }
+    }
+
+    fun getConfigurationValuesVersionList(instanceId: String, configName: String): List<K8sConfigValueResponse>? {
+        val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
+        try {
+            val result: BlueprintWebClientService.WebClientResponse<String> = rbInstanceService.exchangeResource(
+                    GET.name,
+                    "/config/$configName/version",
+                    ""
+            )
+            log.debug(result.toString())
+            return if (result.status in 200..299) {
+                val objectMapper = jacksonObjectMapper()
+                val parsedObject: ArrayList<K8sConfigValueResponse>? = objectMapper.readValue(result.body)
+                parsedObject
+            } else if (result.status == 500 && result.body.contains("Did not find any objects with tag"))
+                null
+            else
+                throw BluePrintProcessorException(result.body)
+        } catch (e: Exception) {
+            log.error("Caught exception trying to get k8s config instance version list")
+            throw BluePrintProcessorException("${e.message}")
+        }
+    }
+
+    fun getConfigurationValuesTagList(instanceId: String, configName: String): List<K8sConfigValueTag>? {
+        val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
+        try {
+            val result: BlueprintWebClientService.WebClientResponse<String> = rbInstanceService.exchangeResource(
+                GET.name,
+                "/config/$configName/tag",
+                ""
+            )
+            log.debug(result.toString())
+            return if (result.status in 200..299) {
+                val objectMapper = jacksonObjectMapper()
+                val parsedObject: ArrayList<K8sConfigValueTag>? = objectMapper.readValue(result.body)
+                parsedObject
+            } else if (result.status == 500 && result.body.contains("Did not find any objects with tag"))
+                null
+            else
+                throw BluePrintProcessorException(result.body)
+        } catch (e: Exception) {
+            log.error("Caught exception trying to get k8s config instance tag list")
+            throw BluePrintProcessorException("${e.message}")
+        }
+    }
+
+    fun deleteConfigurationValues(instanceId: String, configName: String, deleteConfigOnly: Boolean) {
+        val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
+        try {
+            var path: String = "/config/$configName"
+            if (deleteConfigOnly)
+                path = path.plus("?deleteConfigOnly=true")
+            val result: BlueprintWebClientService.WebClientResponse<String> = rbInstanceService.exchangeResource(
+                DELETE.name,
+                path,
+                ""
+            )
+            log.debug(result.toString())
+            if (result.status !in 200..299)
+                throw BluePrintProcessorException(result.body)
+        } catch (e: Exception) {
+            log.error("Caught exception trying to delete config instance")
+            throw BluePrintProcessorException("${e.message}")
+        }
+    }
+
+    fun rollbackConfigurationValues(instanceId: String, configName: String, configVersion: String?, configTag: String?) {
+        val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
+        try {
+            val configValues = hashMapOf<String, String>()
+            if (configVersion != null)
+                configValues["config-version"] = configVersion
+            if (configTag != null)
+                configValues["config-tag"] = configTag
+            val result: BlueprintWebClientService.WebClientResponse<String> = rbInstanceService.exchangeResource(
+                POST.name,
+                "/config/$configName/rollback",
+                JacksonUtils.getJson(configValues)
+            )
+            log.debug(result.toString())
+            if (result.status !in 200..299)
+                throw BluePrintProcessorException(result.body)
+        } catch (e: Exception) {
+            log.error("Caught exception trying to rollback config instance")
+            throw BluePrintProcessorException("${e.message}")
+        }
+    }
+
+    fun tagConfigurationValues(instanceId: String, configName: String, tagName: String) {
+        val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId)
+        try {
+            val configValues = hashMapOf<String, String>()
+            configValues["tag-name"] = tagName
+            val result: BlueprintWebClientService.WebClientResponse<String> = rbInstanceService.exchangeResource(
+                POST.name,
+                "/config/$configName/tagit",
+                JacksonUtils.getJson(configValues)
+            )
+            log.debug(result.toString())
+            if (result.status !in 200..299)
+                throw BluePrintProcessorException(result.body)
+        } catch (e: Exception) {
+            log.error("Caught exception trying to tag config instance")
             throw BluePrintProcessorException("${e.message}")
         }
     }
index 2b40d35..97175e2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright © 2017-2018 AT&T Intellectual Property.
  * Modifications Copyright © 2019 IBM.
- * Modifications Copyright © 2021 Orange.
+ * Modifications Copyright © 2022 Orange.
  * Modifications Copyright © 2020 Deutsche Telekom AG.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -55,6 +55,49 @@ class K8sRbInstance {
     }
 }
 
+@JsonIgnoreProperties(ignoreUnknown = true)
+class K8sRbInstanceFull {
+
+    @get:JsonProperty("id")
+    var id: String? = null
+
+    @get:JsonProperty("namespace")
+    var namespace: String? = "default"
+
+    @get:JsonProperty("status")
+    var status: String? = null
+
+    @get:JsonProperty("hook-progress")
+    var hookProgress: String? = null
+
+    @get:JsonProperty("request")
+    var request: K8sRbInstanceRequest? = null
+
+    @get:JsonProperty("release-name")
+    var releaseName: String? = null
+
+    @get:JsonProperty("resources")
+    var resources: List<K8sRbInstanceResource>? = null
+
+    @get:JsonProperty("hooks")
+    var hooks: List<K8sRbInstanceHookDefinition>? = null
+
+    override fun toString(): String {
+        return "$id:$releaseName:$namespace"
+    }
+
+    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()
+    }
+}
+
+@JsonIgnoreProperties(ignoreUnknown = true)
 class K8sRbInstanceResource {
 
     @get:JsonProperty("Name")
@@ -77,3 +120,112 @@ class K8sRbInstanceResource {
         return javaClass.hashCode()
     }
 }
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+class K8sRbInstanceHookDefinition {
+
+    @get:JsonProperty("Hook")
+    var hook: K8sRbInstanceHook? = null
+
+    @get:JsonProperty("KRT")
+    var krt: K8sRbInstanceKrt? = null
+
+    override fun toString(): String {
+        return "$hook"
+    }
+
+    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()
+    }
+}
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+class K8sRbInstanceHook {
+
+    @get:JsonProperty("name")
+    var name: String? = null
+
+    @get:JsonProperty("kind")
+    var kind: String? = null
+
+    @get:JsonProperty("path")
+    var path: String? = null
+
+    @get:JsonProperty("manifest")
+    var manifest: String? = null
+
+    @get:JsonProperty("weight")
+    var weight: Int? = 0
+
+    @get:JsonProperty("last_run")
+    var lastRun: K8sRbInstanceHookExecution? = null
+
+    @get:JsonProperty("events")
+    var events: List<String>? = null
+
+    @get:JsonProperty("delete_policies")
+    var deletePolicies: List<String>? = null
+
+    override fun toString(): String {
+        return "$name"
+    }
+
+    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()
+    }
+}
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+class K8sRbInstanceHookExecution {
+
+    @get:JsonProperty("started_at")
+    var startedAt: String? = null
+
+    @get:JsonProperty("completed_at")
+    var completedAt: String? = null
+
+    @get:JsonProperty("phase")
+    var phase: String? = null
+
+    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()
+    }
+}
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+class K8sRbInstanceKrt {
+
+    @get:JsonProperty("FilePath")
+    var filePath: String? = null
+
+    @get:JsonProperty("GVK")
+    var gvk: K8sRbInstanceGvk? = null
+
+    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/query/K8sPluginQueryApi.kt b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/query/K8sPluginQueryApi.kt
new file mode 100644 (file)
index 0000000..170f295
--- /dev/null
@@ -0,0 +1,56 @@
+package org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.query;
+
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.K8sConnectionPluginConfiguration
+import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+import org.slf4j.LoggerFactory
+import org.springframework.http.HttpMethod.GET
+
+public class K8sPluginQueryApi(
+        private val k8sConfiguration: K8sConnectionPluginConfiguration
+) {
+    private val log = LoggerFactory.getLogger(K8sPluginQueryApi::class.java)!!
+
+    fun queryK8sResources(
+            cloudRegion: String,
+            kind: String,
+            apiVersion: String,
+            name: String? = null,
+            namespace: String? = null,
+            labels: Map<String, String>? = null
+    ): K8sResourceStatus? {
+        val rbQueryService = K8sQueryRestClient(k8sConfiguration)
+        try {
+            var path: String = "?CloudRegion=$cloudRegion&ApiVersion=$apiVersion&Kind=$kind"
+            if (name != null)
+                path = path.plus("&Name=$name")
+            if (namespace != null)
+                path = path.plus("&Namespace=$name")
+            if (labels != null && labels.isNotEmpty()) {
+                path = path.plus("&Labels=")
+                for ((name, value) in labels)
+                    path = path.plus("$name%3D$value,")
+                path = path.trimEnd(',')
+            }
+            val result: BlueprintWebClientService.WebClientResponse<String> = rbQueryService.exchangeResource(
+                    GET.name,
+                    path,
+                    ""
+            )
+            log.debug(result.toString())
+            return if (result.status in 200..299) {
+                val parsedObject: K8sResourceStatus? = JacksonUtils.readValue(
+                        result.body, K8sResourceStatus::class.java
+                )
+                parsedObject
+            } else if (result.status == 500 && result.body.contains("Error finding master table"))
+                null
+            else
+                throw BluePrintProcessorException(result.body)
+        } catch (e: Exception) {
+            log.error("Caught exception trying to get k8s rb instance")
+            throw BluePrintProcessorException("${e.message}")
+        }
+    }
+}
diff --git a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/query/K8sQueryRestClient.kt b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/query/K8sQueryRestClient.kt
new file mode 100644 (file)
index 0000000..dda5a6e
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright © 2017-2018 AT&T Intellectual Property.
+ * Modifications Copyright © 2019 IBM.
+ * Modifications Copyright © 2022 Orange.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.query
+
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.K8sAbstractRestClientService
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.K8sConnectionPluginConfiguration
+
+open class K8sQueryRestClient(
+        k8sConfiguration: K8sConnectionPluginConfiguration
+) : K8sAbstractRestClientService(k8sConfiguration) {
+
+    override fun apiUrl(): String {
+        return "$baseUrl/v1/query"
+    }
+}
diff --git a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/query/K8sResourceStatus.kt b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/query/K8sResourceStatus.kt
new file mode 100644 (file)
index 0000000..d0e84ae
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2017-2018 AT&T Intellectual Property.
+ * Modifications Copyright © 2019 IBM.
+ * Modifications Copyright © 2022 Orange.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.query
+
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.K8sRbInstanceResourceStatus
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties
+import com.fasterxml.jackson.annotation.JsonProperty
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+class K8sResourceStatus {
+
+    @get:JsonProperty("resourceCount")
+    var resourceCount: Int = 0
+
+    @get:JsonProperty("resourcesStatus")
+    var resourcesStatus: List<K8sRbInstanceResourceStatus>? = null
+
+    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()
+    }
+}
\ No newline at end of file