From 836be777835eb05be1a62b98a9e1f5860623d7b2 Mon Sep 17 00:00:00 2001 From: Marek Szwałkiewicz Date: Wed, 2 Sep 2020 12:48:47 +0000 Subject: Add k8s-upload-profile node type and logic. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue-ID: CCSDK-2630 Change-Id: Icd50ab98503a2c2259c56ced20976579afefd7fc Signed-off-by: Marek Szwałkiewicz --- .../node_type/component-k8s-profile-upload.json | 62 ++++++++ ms/blueprintsprocessor/application/pom.xml | 4 + .../src/main/resources/application-dev.properties | 5 + .../src/main/resources/application.properties | 5 + .../src/test/resources/application-test.properties | 5 + .../functions/k8s-profile-upload/pom.xml | 46 ++++++ .../functions/k8s/profile/upload/K8sPluginApi.kt | 113 ++++++++++++++ .../functions/k8s/profile/upload/K8sProfile.kt | 47 ++++++ .../profile/upload/K8sProfileUploadComponent.kt | 171 +++++++++++++++++++++ .../upload/K8sProfileUploadConfiguration.kt | 50 ++++++ .../profile/upload/K8sProfileUploadProperties.kt | 25 +++ .../upload/K8sUploadFileRestClientService.kt | 104 +++++++++++++ ms/blueprintsprocessor/functions/pom.xml | 1 + ms/blueprintsprocessor/parent/pom.xml | 6 +- 14 files changed, 643 insertions(+), 1 deletion(-) create mode 100644 components/model-catalog/definition-type/starter-type/node_type/component-k8s-profile-upload.json create mode 100644 ms/blueprintsprocessor/functions/k8s-profile-upload/pom.xml create mode 100644 ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sPluginApi.kt create mode 100644 ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfile.kt create mode 100644 ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfileUploadComponent.kt create mode 100644 ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfileUploadConfiguration.kt create mode 100644 ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfileUploadProperties.kt create mode 100644 ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sUploadFileRestClientService.kt diff --git a/components/model-catalog/definition-type/starter-type/node_type/component-k8s-profile-upload.json b/components/model-catalog/definition-type/starter-type/node_type/component-k8s-profile-upload.json new file mode 100644 index 000000000..ac7c95cd8 --- /dev/null +++ b/components/model-catalog/definition-type/starter-type/node_type/component-k8s-profile-upload.json @@ -0,0 +1,62 @@ +{ + "description": "This component is rendering and sending the k8s profile to the multicloud plugin.", + "version": "1.0.0", + "attributes": { + "statuses": { + "required": true, + "type": "json" + } + }, + "capabilities": { + "component-node": { + "type": "tosca.capabilities.Node" + } + }, + "interfaces": { + "K8sProfileUploadComponent": { + "operations": { + "process": { + "inputs": { + "k8s-rb-profile-name": { + "description": "K8s profile name", + "required": false, + "type": "string" + }, + "k8s-rb-definition-name": { + "description": "K8s definition name", + "required": false, + "type": "string" + }, + "k8s-rb-definition-version": { + "description": "Version of the definition", + "required": false, + "type": "string" + }, + "k8s-rb-profile-namespace": { + "description": "a K8s namespace for the profile", + "required": false, + "type": "string" + }, + "k8s-rb-profile-source": { + "description": "Source (tgz/folder) for the template in CBA", + "required": false, + "type": "string" + }, + "resource-assignment-map": { + "description": "Holds resolved values for each artifact prefix eg. { vdns: { vnf-id: 123 } }", + "required": false, + "type": "json" + } + }, + "outputs": { + "statuses": { + "required": true, + "type": "string" + } + } + } + } + } + }, + "derived_from": "tosca.nodes.Component" +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/application/pom.xml b/ms/blueprintsprocessor/application/pom.xml index 16a2d456e..eb4522040 100755 --- a/ms/blueprintsprocessor/application/pom.xml +++ b/ms/blueprintsprocessor/application/pom.xml @@ -128,6 +128,10 @@ org.onap.ccsdk.cds.blueprintsprocessor.functions config-snapshots + + org.onap.ccsdk.cds.blueprintsprocessor.functions + k8s-profile-upload + com.h2database h2 diff --git a/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties b/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties index fb32d9afc..e7443434a 100755 --- a/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties +++ b/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties @@ -170,3 +170,8 @@ blueprintsprocessor.messageproducer.self-service-api.audit.response.topic=audit- #blueprintsprocessor.messageconsumer.prioritize-input.bootstrapServers=127.0.0.1:9092 #blueprintsprocessor.messageconsumer.prioritize-input.applicationId=cds-controller #blueprintsprocessor.messageconsumer.prioritize-input.topic=prioritize-input-topic + +#K8s Plugin properties +blueprintprocessor.k8s.plugin.username=test +blueprintprocessor.k8s.plugin.password=pass +blueprintprocessor.k8s.plugin.url=http://multicloud-k8s:9015/ diff --git a/ms/blueprintsprocessor/application/src/main/resources/application.properties b/ms/blueprintsprocessor/application/src/main/resources/application.properties index 429011aff..9b48359a1 100755 --- a/ms/blueprintsprocessor/application/src/main/resources/application.properties +++ b/ms/blueprintsprocessor/application/src/main/resources/application.properties @@ -163,3 +163,8 @@ cdslistener.healthcheck.mapping-service-name-with-service-link=[SDC Listener ser management.endpoints.web.exposure.include=* management.endpoint.health.show-details=always management.info.git.mode=full + +#K8s Plugin properties +blueprintprocessor.k8s.plugin.username=test +blueprintprocessor.k8s.plugin.password=pass +blueprintprocessor.k8s.plugin.url=http://multicloud-k8s:9015/ diff --git a/ms/blueprintsprocessor/application/src/test/resources/application-test.properties b/ms/blueprintsprocessor/application/src/test/resources/application-test.properties index d2170c7c1..c436b3876 100644 --- a/ms/blueprintsprocessor/application/src/test/resources/application-test.properties +++ b/ms/blueprintsprocessor/application/src/test/resources/application-test.properties @@ -66,3 +66,8 @@ blueprintprocessor.healthcheck.mapping-service-name-with-service-link=[Execution #BaseUrls for health check Cds Listener services cdslistener.healthcheck.baseUrl=http://cds-sdc-listener:8080/ cdslistener.healthcheck.mapping-service-name-with-service-link=[SDC Listener service,/api/v1/sdclistener/healthcheck] + +#K8s Plugin properties +blueprintprocessor.k8s.plugin.username=test +blueprintprocessor.k8s.plugin.password=pass +blueprintprocessor.k8s.plugin.url=http://multicloud-k8s:9015/ diff --git a/ms/blueprintsprocessor/functions/k8s-profile-upload/pom.xml b/ms/blueprintsprocessor/functions/k8s-profile-upload/pom.xml new file mode 100644 index 000000000..674882bd2 --- /dev/null +++ b/ms/blueprintsprocessor/functions/k8s-profile-upload/pom.xml @@ -0,0 +1,46 @@ + + + + + 4.0.0 + + + org.onap.ccsdk.cds.blueprintsprocessor + functions + 1.0.0-SNAPSHOT + + + org.onap.ccsdk.cds.blueprintsprocessor.functions + k8s-profile-upload + 1.0.0-SNAPSHOT + + Blueprints Processor Function - K8s Profile Upload + Blueprints Processor Function - K8s Profile Upload + + + + org.onap.ccsdk.cds.blueprintsprocessor.functions + resource-resolution + + + org.onap.ccsdk.cds.blueprintsprocessor + ssh-lib + + + diff --git a/ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sPluginApi.kt b/ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sPluginApi.kt new file mode 100644 index 000000000..dab977db0 --- /dev/null +++ b/ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sPluginApi.kt @@ -0,0 +1,113 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * Modifications Copyright © 2019 IBM. + * Modifications Copyright © 2020 Orange. + * Modifications Copyright © 2020 Deutsche Telekom AG. + * + * 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.profile.upload + +import org.springframework.http.HttpMethod +import com.fasterxml.jackson.databind.ObjectMapper +import org.onap.ccsdk.cds.blueprintsprocessor.rest.BasicAuthRestClientProperties +import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService +import java.nio.file.Path +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException +import org.slf4j.LoggerFactory + +class K8sPluginApi( + val username: String, + val password: String, + val baseUrl: String, + val definition: String?, + val definitionVersion: String? +) { + private val service: K8sUploadFileRestClientService // BasicAuthRestClientService + private val log = LoggerFactory.getLogger(K8sPluginApi::class.java)!! + + init { + var mapOfHeaders = hashMapOf() + mapOfHeaders.put("Accept", "application/json") + mapOfHeaders.put("Content-Type", "application/json") + mapOfHeaders.put("cache-control", " no-cache") + mapOfHeaders.put("Accept", "application/json") + var basicAuthRestClientProperties: BasicAuthRestClientProperties = BasicAuthRestClientProperties() + basicAuthRestClientProperties.username = username + basicAuthRestClientProperties.password = password + basicAuthRestClientProperties.url = "$baseUrl/v1/rb/definition/$definition/$definitionVersion" + basicAuthRestClientProperties.additionalHeaders = mapOfHeaders + + this.service = K8sUploadFileRestClientService(basicAuthRestClientProperties) + } + + fun hasDefinition(): Boolean { + try { + val result: BlueprintWebClientService.WebClientResponse = service.exchangeResource(HttpMethod.GET.name, "", "") + log.debug(result.toString()) + return result.status in 200..299 + } catch (e: Exception) { + log.error("Caught exception trying to get k8s rb definition") + throw BluePrintProcessorException("${e.message}") + } + } + + fun hasProfile(profileName: String): Boolean { + try { + val result: BlueprintWebClientService.WebClientResponse = service.exchangeResource( + HttpMethod.GET.name, + "/profile/$profileName", + "" + ) + log.debug(result.toString()) + return result.status in 200..299 + } catch (e: Exception) { + log.error("Caught exception trying to get k8s rb profile") + throw BluePrintProcessorException("${e.message}") + } + } + + fun createProfile(profile: K8sProfile) { + val objectMapper = ObjectMapper() + val profileJsonString: String = objectMapper.writeValueAsString(profile) + try { + val result: BlueprintWebClientService.WebClientResponse = service.exchangeResource( + HttpMethod.POST.name, + "/profile", + 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 uploadProfileContent(profile: K8sProfile, filePath: Path) { + try { + val result: BlueprintWebClientService.WebClientResponse = service.uploadBinaryFile( + "/profile/${profile.profileName}/content", + filePath + ) + if (result.status !in 200..299) { + throw Exception(result.body) + } + } catch (e: Exception) { + log.error("Caught exception trying to upload k8s rb profile ${profile.profileName}") + throw BluePrintProcessorException("${e.message}") + } + } +} diff --git a/ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfile.kt b/ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfile.kt new file mode 100644 index 000000000..87836428e --- /dev/null +++ b/ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfile.kt @@ -0,0 +1,47 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * Modifications Copyright © 2019 IBM. + * Modifications Copyright © 2020 Orange. + * Modifications Copyright © 2020 Deutsche Telekom AG. + * + * 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.profile.upload + +import com.fasterxml.jackson.annotation.JsonProperty + +class K8sProfile { + @get:JsonProperty("rb-name") + var rbName: String? = null + @get:JsonProperty("rb-version") + var rbVersion: String? = null + @get:JsonProperty("profile-name") + var profileName: String? = null + @get:JsonProperty("namespace") + var namespace: String? = "default" + + override fun toString(): String { + return "$rbName:$rbVersion:$profileName" + } + + 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-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfileUploadComponent.kt b/ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfileUploadComponent.kt new file mode 100644 index 000000000..aa726a5e9 --- /dev/null +++ b/ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfileUploadComponent.kt @@ -0,0 +1,171 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * Modifications Copyright © 2019 IBM. + * Modifications Copyright © 2020 Orange. + * Modifications Copyright © 2020 Deutsche Telekom AG. + * + * 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.profile.upload + +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction +import org.springframework.beans.factory.config.ConfigurableBeanFactory +import org.springframework.context.annotation.Scope +import org.springframework.stereotype.Component +import java.util.ArrayList +import java.nio.file.Paths +import java.io.File +import com.fasterxml.jackson.databind.JsonNode +import org.onap.ccsdk.cds.controllerblueprints.core.asJsonNode +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintPropertiesService +import org.slf4j.LoggerFactory +import java.nio.file.Path +import org.onap.ccsdk.cds.controllerblueprints.core.returnNullIfMissing +import com.fasterxml.jackson.databind.node.ObjectNode +import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils + +@Component("component-k8s-profile-upload") +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +open class K8sProfileUploadComponent(private var bluePrintPropertiesService: BluePrintPropertiesService) : + + AbstractComponentFunction() { + + companion object { + const val INPUT_K8S_PROFILE_NAME = "k8s-rb-profile-name" + 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_SOURCE = "k8s-rb-profile-source" + const val INPUT_RESOURCE_ASSIGNMENT_MAP = "resource-assignment-map" + + const val OUTPUT_STATUSES = "statuses" + const val OUTPUT_SKIPPED = "skipped" + const val OUTPUT_UPLOADED = "uploaded" + const val OUTPUT_ERROR = "error" + } + + private val log = LoggerFactory.getLogger(K8sProfileUploadComponent::class.java)!! + + override suspend fun processNB(executionRequest: ExecutionServiceInput) { + log.info("Triggering K8s Profile Upload component logic.") + + val inputParameterNames = arrayOf( + INPUT_K8S_PROFILE_NAME, + INPUT_K8S_DEFINITION_NAME, + INPUT_K8S_DEFINITION_VERSION, + INPUT_K8S_PROFILE_NAMESPACE, + INPUT_K8S_PROFILE_SOURCE + ) + var outputPrefixStatuses = mutableMapOf() + var inputParamsMap = mutableMapOf() + + inputParameterNames.forEach { + inputParamsMap[it] = getOptionalOperationInput(it)?.returnNullIfMissing() + } + + log.info("Getting the template prefixes") + val prefixList: ArrayList = getTemplatePrefixList(executionRequest) + + log.info("Iterating over prefixes in resource assignment map.") + for (prefix in prefixList) { + // Prefilling prefix sucess status + outputPrefixStatuses.put(prefix, OUTPUT_SKIPPED) + // Resource assignment map is organized by prefixes, in each iteraton we work only + // on one section of resource assignment map + val prefixNode: JsonNode = operationInputs[INPUT_RESOURCE_ASSIGNMENT_MAP]?.get(prefix) ?: continue + val assignmentMapPrefix = JacksonUtils.jsonNode(prefixNode.toPrettyString()) as ObjectNode + + // We are copying the map because for each prefix it might be completed with a different data + var prefixInputParamsMap = inputParamsMap.toMutableMap() + prefixInputParamsMap.forEach { (inputParamName, value) -> + if (value == null) { + val mapValue = assignmentMapPrefix?.get(inputParamName) + log.debug("$inputParamName value was $value so we fetch $mapValue") + prefixInputParamsMap[inputParamName] = mapValue + } + } + + // For clarity we pull out the required fields + val profileName = prefixInputParamsMap[INPUT_K8S_PROFILE_NAME]?.returnNullIfMissing()?.textValue() + val definitionName = prefixInputParamsMap[INPUT_K8S_DEFINITION_NAME]?.returnNullIfMissing()?.textValue() + val definitionVersion = prefixInputParamsMap[INPUT_K8S_DEFINITION_VERSION]?.returnNullIfMissing()?.textValue() + + val k8sProfileUploadConfiguration = K8sProfileUploadConfiguration(bluePrintPropertiesService) + + // Creating API connector + var api = K8sPluginApi( + k8sProfileUploadConfiguration.getProperties().username, + k8sProfileUploadConfiguration.getProperties().password, + k8sProfileUploadConfiguration.getProperties().url, + definitionName, + definitionVersion + ) + + if ((profileName == null) || (definitionName == null) || (definitionVersion == null)) { + log.warn("Prefix $prefix does not have required data for us to continue.") + } else if (!api.hasDefinition()) { + log.warn("K8s RB Definition ($definitionName/$definitionVersion) not found ") + } else if (profileName == "") { + log.warn("K8s rb profile name is empty! Either define profile name to use or choose default") + } else if (api.hasProfile(profileName)) { + log.info("Profile Already Existing - skipping upload") + } else { + log.info("Uploading K8s Profile..") + outputPrefixStatuses.put(prefix, OUTPUT_ERROR) + + var profile = K8sProfile() + profile.profileName = profileName + profile.rbName = definitionName + profile.rbVersion = definitionVersion + profile.namespace = prefixInputParamsMap[INPUT_K8S_PROFILE_NAMESPACE]?.textValue() + api.createProfile(profile) + val profileFilePath: Path = prepareProfileFile(profileName) + api.uploadProfileContent(profile, profileFilePath) + + log.info("K8s Profile Upload Completed") + outputPrefixStatuses.put(prefix, OUTPUT_UPLOADED) + } + } + bluePrintRuntimeService.setNodeTemplateAttributeValue( + nodeTemplateName, + OUTPUT_STATUSES, + outputPrefixStatuses.asJsonNode() + ) + } + + override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) { + bluePrintRuntimeService.getBluePrintError().addError(runtimeException.message!!) + } + + fun getTemplatePrefixList(executionRequest: ExecutionServiceInput): ArrayList { + val result = ArrayList() + for (prefix in executionRequest.payload.get("resource-assignment-request").get("template-prefix").elements()) + result.add(prefix.asText()) + return result + } + + fun prepareProfileFile(k8sRbProfileName: String): Path { + val bluePrintContext = bluePrintRuntimeService.bluePrintContext() + val bluePrintBasePath: String = bluePrintContext.rootPath + return Paths.get( + bluePrintBasePath.plus(File.separator) + .plus("Templates") + .plus(File.separator) + .plus("k8s-profiles") + .plus(File.separator) + .plus("$k8sRbProfileName.tar.gz") + ) + } +} diff --git a/ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfileUploadConfiguration.kt b/ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfileUploadConfiguration.kt new file mode 100644 index 000000000..193fdda6d --- /dev/null +++ b/ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfileUploadConfiguration.kt @@ -0,0 +1,50 @@ +/* + * Copyright © 2020 Deutsche Telekom AG. + * Modifications Copyright © 2020 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.profile.upload + +import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintCoreConfiguration +import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintPropertiesService +import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintPropertyConfiguration +import org.springframework.boot.context.properties.EnableConfigurationProperties +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Import + +@Configuration +@Import( + BluePrintPropertyConfiguration::class, + BluePrintPropertiesService::class, + BluePrintCoreConfiguration::class +) +@EnableConfigurationProperties +open class K8sProfileUploadConfiguration(private var bluePrintPropertiesService: BluePrintPropertiesService) { + + @Bean("k8s-plugin-properties") + open fun getProperties(): K8sProfileUploadProperties { + return bluePrintPropertiesService.propertyBeanType( + K8sProfileUploadConstants.PREFIX_K8S_PLUGIN, + K8sProfileUploadProperties::class.java + ) + } +} + +class K8sProfileUploadConstants { + companion object { + const val PREFIX_K8S_PLUGIN: String = "blueprintprocessor.k8s.plugin" + } +} diff --git a/ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfileUploadProperties.kt b/ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfileUploadProperties.kt new file mode 100644 index 000000000..b023a5355 --- /dev/null +++ b/ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfileUploadProperties.kt @@ -0,0 +1,25 @@ +/* + * Copyright © 2020 Deutsche Telekom AG. + * Modifications Copyright © 2020 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.profile.upload + +open class K8sProfileUploadProperties { + var type: String = K8sProfileUploadConstants.PREFIX_K8S_PLUGIN + lateinit var url: String + lateinit var username: String + lateinit var password: String +} diff --git a/ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sUploadFileRestClientService.kt b/ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sUploadFileRestClientService.kt new file mode 100644 index 000000000..2cd87ad20 --- /dev/null +++ b/ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sUploadFileRestClientService.kt @@ -0,0 +1,104 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * Modifications Copyright © 2019 IBM. + * Modifications Copyright © 2020 Orange. + * Modifications Copyright © 2020 Deutsche Telekom AG. + * + * 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.profile.upload + +import org.onap.ccsdk.cds.blueprintsprocessor.rest.BasicAuthRestClientProperties +import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService +import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.RestLoggerService +import org.apache.commons.io.IOUtils +import org.apache.http.client.entity.EntityBuilder +import org.apache.http.message.BasicHeader +import org.apache.http.client.methods.HttpPost +import org.apache.http.client.methods.HttpUriRequest +import org.apache.http.client.ClientProtocolException +import java.io.IOException +import java.nio.file.Files +import java.nio.file.Path +import org.springframework.http.HttpHeaders +import org.springframework.http.MediaType +import java.nio.charset.Charset +import java.util.Base64 + +class K8sUploadFileRestClientService( + private val restClientProperties: + BasicAuthRestClientProperties +) : BlueprintWebClientService { + + override fun defaultHeaders(): Map { + + val encodedCredentials = setBasicAuth( + restClientProperties.username, + restClientProperties.password + ) + return mapOf( + HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE, + HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE, + HttpHeaders.AUTHORIZATION to "Basic $encodedCredentials" + ) + } + + override fun host(uri: String): String { + return restClientProperties.url + uri + } + + override fun convertToBasicHeaders(headers: Map): + Array { + val customHeaders: MutableMap = headers.toMutableMap() + // inject additionalHeaders + customHeaders.putAll(verifyAdditionalHeaders(restClientProperties)) + + if (!headers.containsKey(HttpHeaders.AUTHORIZATION)) { + val encodedCredentials = setBasicAuth( + restClientProperties.username, + restClientProperties.password + ) + customHeaders[HttpHeaders.AUTHORIZATION] = + "Basic $encodedCredentials" + } + return super.convertToBasicHeaders(customHeaders) + } + + private fun setBasicAuth(username: String, password: String): String { + val credentialsString = "$username:$password" + return Base64.getEncoder().encodeToString( + credentialsString.toByteArray(Charset.defaultCharset()) + ) + } + + @Throws(IOException::class, ClientProtocolException::class) + private fun performHttpCall(httpUriRequest: HttpUriRequest): BlueprintWebClientService.WebClientResponse { + val httpResponse = httpClient().execute(httpUriRequest) + val statusCode = httpResponse.statusLine.statusCode + httpResponse.entity.content.use { + val body = IOUtils.toString(it, Charset.defaultCharset()) + return BlueprintWebClientService.WebClientResponse(statusCode, body) + } + } + + fun uploadBinaryFile(path: String, filePath: Path): BlueprintWebClientService.WebClientResponse { + val convertedHeaders: Array = convertToBasicHeaders(defaultHeaders()) + val httpPost = HttpPost(host(path)) + val entity = EntityBuilder.create().setBinary(Files.readAllBytes(filePath)).build() + httpPost.setEntity(entity) + RestLoggerService.httpInvoking(convertedHeaders) + httpPost.setHeaders(convertedHeaders) + return performHttpCall(httpPost) + } +} diff --git a/ms/blueprintsprocessor/functions/pom.xml b/ms/blueprintsprocessor/functions/pom.xml index 4d417f38b..4d886de39 100755 --- a/ms/blueprintsprocessor/functions/pom.xml +++ b/ms/blueprintsprocessor/functions/pom.xml @@ -42,6 +42,7 @@ cli-executor config-snapshots message-prioritizaion + k8s-profile-upload diff --git a/ms/blueprintsprocessor/parent/pom.xml b/ms/blueprintsprocessor/parent/pom.xml index a71392b00..91cc4a01c 100755 --- a/ms/blueprintsprocessor/parent/pom.xml +++ b/ms/blueprintsprocessor/parent/pom.xml @@ -489,6 +489,11 @@ message-prioritizaion ${ccsdk.cds.version} + + org.onap.ccsdk.cds.blueprintsprocessor.functions + k8s-profile-upload + ${ccsdk.cds.version} + org.onap.ccsdk.cds.blueprintsprocessor health-api @@ -499,7 +504,6 @@ health-api-common ${ccsdk.cds.version} - com.github.fge -- cgit 1.2.3-korg