Merge "Add k8s-upload-profile node type and logic."
authorKAPIL SINGAL <ks220y@att.com>
Tue, 8 Sep 2020 13:12:06 +0000 (13:12 +0000)
committerGerrit Code Review <gerrit@onap.org>
Tue, 8 Sep 2020 13:12:06 +0000 (13:12 +0000)
14 files changed:
components/model-catalog/definition-type/starter-type/node_type/component-k8s-profile-upload.json [new file with mode: 0644]
ms/blueprintsprocessor/application/pom.xml
ms/blueprintsprocessor/application/src/main/resources/application-dev.properties
ms/blueprintsprocessor/application/src/main/resources/application.properties
ms/blueprintsprocessor/application/src/test/resources/application-test.properties
ms/blueprintsprocessor/functions/k8s-profile-upload/pom.xml [new file with mode: 0644]
ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sPluginApi.kt [new file with mode: 0644]
ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfile.kt [new file with mode: 0644]
ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfileUploadComponent.kt [new file with mode: 0644]
ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfileUploadConfiguration.kt [new file with mode: 0644]
ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sProfileUploadProperties.kt [new file with mode: 0644]
ms/blueprintsprocessor/functions/k8s-profile-upload/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/profile/upload/K8sUploadFileRestClientService.kt [new file with mode: 0644]
ms/blueprintsprocessor/functions/pom.xml
ms/blueprintsprocessor/parent/pom.xml

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 (file)
index 0000000..ac7c95c
--- /dev/null
@@ -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
index 16a2d45..eb45220 100755 (executable)
             <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId>
             <artifactId>config-snapshots</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId>
+            <artifactId>k8s-profile-upload</artifactId>
+        </dependency>
         <dependency>
             <groupId>com.h2database</groupId>
             <artifactId>h2</artifactId>
index fb32d9a..e744343 100755 (executable)
@@ -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/
index 429011a..9b48359 100755 (executable)
@@ -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/
index d2170c7..c436b38 100644 (file)
@@ -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 (file)
index 0000000..674882b
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright © 2017-2018 AT&T Intellectual Property.
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
+        <artifactId>functions</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+    </parent>
+
+    <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId>
+    <artifactId>k8s-profile-upload</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+
+    <name>Blueprints Processor Function - K8s Profile Upload</name>
+    <description>Blueprints Processor Function - K8s Profile Upload</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId>
+            <artifactId>resource-resolution</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
+            <artifactId>ssh-lib</artifactId>
+        </dependency>
+    </dependencies>
+</project>
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 (file)
index 0000000..dab977d
--- /dev/null
@@ -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<String, String>()
+        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<String> = 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<String> = 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<String> = 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<String> = 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 (file)
index 0000000..8783642
--- /dev/null
@@ -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 (file)
index 0000000..aa726a5
--- /dev/null
@@ -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<String, String>()
+        var inputParamsMap = mutableMapOf<String, JsonNode?>()
+
+        inputParameterNames.forEach {
+            inputParamsMap[it] = getOptionalOperationInput(it)?.returnNullIfMissing()
+        }
+
+        log.info("Getting the template prefixes")
+        val prefixList: ArrayList<String> = 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<String> {
+        val result = ArrayList<String>()
+        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 (file)
index 0000000..193fdda
--- /dev/null
@@ -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 (file)
index 0000000..b023a53
--- /dev/null
@@ -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 (file)
index 0000000..2cd87ad
--- /dev/null
@@ -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<String, String> {
+
+        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<String, String>):
+        Array<BasicHeader> {
+            val customHeaders: MutableMap<String, String> = 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<String> {
+        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<String> {
+        val convertedHeaders: Array<BasicHeader> = 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)
+    }
+}
index 4d417f3..4d886de 100755 (executable)
@@ -42,6 +42,7 @@
         <module>cli-executor</module>
         <module>config-snapshots</module>
         <module>message-prioritizaion</module>
+        <module>k8s-profile-upload</module>
     </modules>
 
     <dependencies>
index a71392b..91cc4a0 100755 (executable)
                 <artifactId>message-prioritizaion</artifactId>
                 <version>${ccsdk.cds.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId>
+                <artifactId>k8s-profile-upload</artifactId>
+                <version>${ccsdk.cds.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
                 <artifactId>health-api</artifactId>
                 <artifactId>health-api-common</artifactId>
                 <version>${ccsdk.cds.version}</version>
             </dependency>
-
             <!-- Diff capability providers for config-snapshots -->
             <dependency>
                 <groupId>com.github.fge</groupId>