From 4954e82b2af21c684ce827959f7949e71d8530a7 Mon Sep 17 00:00:00 2001 From: Lukasz Rajewski Date: Wed, 9 Feb 2022 17:07:31 +0100 Subject: K8sPlugin integration changes for Istanbul APIs Implementation of the K8sPlugin new APIs or changes introduced there in the Istanbul release. Issue-ID: CCSDK-3537 Signed-off-by: Lukasz Rajewski Change-Id: I263dd22bb1d3cbcc9360583cd82a728afbebc09d --- .../k8s/definition/K8sPluginDefinitionApi.kt | 69 +++++++ .../functions/k8s/definition/profile/K8sProfile.kt | 7 + .../profile/K8sProfileUploadComponent.kt | 20 ++ .../definition/template/K8sConfigValueComponent.kt | 54 ++++-- .../k8s/definition/template/K8sTemplate.kt | 8 +- .../k8s/instance/K8sConfigValueResponse.kt | 28 ++- .../functions/k8s/instance/K8sPluginInstanceApi.kt | 209 +++++++++++++++++++-- .../functions/k8s/instance/K8sRbInstance.kt | 154 ++++++++++++++- .../functions/k8s/query/K8sPluginQueryApi.kt | 56 ++++++ .../functions/k8s/query/K8sQueryRestClient.kt | 31 +++ .../functions/k8s/query/K8sResourceStatus.kt | 44 +++++ 11 files changed, 646 insertions(+), 34 deletions(-) create mode 100644 ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/query/K8sPluginQueryApi.kt create mode 100644 ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/query/K8sQueryRestClient.kt create mode 100644 ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/query/K8sResourceStatus.kt diff --git a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/K8sPluginDefinitionApi.kt b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/K8sPluginDefinitionApi.kt index 73c0e8029..02b255673 100644 --- a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/K8sPluginDefinitionApi.kt +++ b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/K8sPluginDefinitionApi.kt @@ -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 = 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 = 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 = 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, diff --git a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/profile/K8sProfile.kt b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/profile/K8sProfile.kt index 8caa1d1a5..ef0d6b9bf 100644 --- a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/profile/K8sProfile.kt +++ b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/profile/K8sProfile.kt @@ -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? = null + + @get:JsonProperty("extra-resource-types") + var extraResourceTypes: List? = null + override fun toString(): String { return "$rbName:$rbVersion:$profileName" } diff --git a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/profile/K8sProfileUploadComponent.kt b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/profile/K8sProfileUploadComponent.kt index 067c75b3e..80e1cb4f1 100644 --- a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/profile/K8sProfileUploadComponent.kt +++ b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/profile/K8sProfileUploadComponent.kt @@ -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 = objectMapper.readValue(profileLabels.toPrettyString()) + profile.labels = labelList + } + if (profileExtraTypes != null) { + val objectMapper = jacksonObjectMapper() + val extraTypeList: ArrayList = 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) 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 f1affacf4..0b6294936 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 @@ -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 } } diff --git a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/template/K8sTemplate.kt b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/template/K8sTemplate.kt index e135d21ce..26c834650 100644 --- a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/template/K8sTemplate.kt +++ b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/template/K8sTemplate.kt @@ -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 { 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 index cefe3e605..c1eaed8bd 100644 --- 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 @@ -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? = 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() + } +} 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 dbcc13395..1be45e892 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 @@ -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 = 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 = 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 = 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 = 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 = 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? { val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId) try { val result: BlueprintWebClientService.WebClientResponse = 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? = 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? { + val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId) + try { + val result: BlueprintWebClientService.WebClientResponse = rbInstanceService.exchangeResource( + GET.name, + "/config/$configName/version", + "" + ) + log.debug(result.toString()) + return if (result.status in 200..299) { + val objectMapper = jacksonObjectMapper() + val parsedObject: ArrayList? = 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? { + val rbInstanceService = K8sRbInstanceRestClient(k8sConfiguration, instanceId) + try { + val result: BlueprintWebClientService.WebClientResponse = rbInstanceService.exchangeResource( + GET.name, + "/config/$configName/tag", + "" + ) + log.debug(result.toString()) + return if (result.status in 200..299) { + val objectMapper = jacksonObjectMapper() + val parsedObject: ArrayList? = 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 = 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() + if (configVersion != null) + configValues["config-version"] = configVersion + if (configTag != null) + configValues["config-tag"] = configTag + val result: BlueprintWebClientService.WebClientResponse = 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() + configValues["tag-name"] = tagName + val result: BlueprintWebClientService.WebClientResponse = 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}") } } diff --git a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sRbInstance.kt b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sRbInstance.kt index 2b40d3517..97175e26f 100644 --- a/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sRbInstance.kt +++ b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/instance/K8sRbInstance.kt @@ -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? = null + + @get:JsonProperty("hooks") + var hooks: List? = 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? = null + + @get:JsonProperty("delete_policies") + var deletePolicies: List? = 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 index 000000000..170f29566 --- /dev/null +++ b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/query/K8sPluginQueryApi.kt @@ -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? = 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 = 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 index 000000000..dda5a6eea --- /dev/null +++ b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/query/K8sQueryRestClient.kt @@ -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 index 000000000..d0e84ae8c --- /dev/null +++ b/ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/query/K8sResourceStatus.kt @@ -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? = 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 -- cgit 1.2.3-korg