2 * Copyright © 2017-2018 AT&T Intellectual Property.
3 * Modifications Copyright © 2019 IBM.
4 * Modifications Copyright © 2020 Orange.
5 * Modifications Copyright © 2020 Deutsche Telekom AG.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 package org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.profile.upload
22 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction
23 import org.springframework.beans.factory.config.ConfigurableBeanFactory
24 import org.springframework.context.annotation.Scope
25 import org.springframework.stereotype.Component
26 import java.util.ArrayList
27 import java.nio.file.Paths
29 import com.fasterxml.jackson.databind.JsonNode
30 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonNode
31 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
32 import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintPropertiesService
33 import org.slf4j.LoggerFactory
34 import java.nio.file.Path
35 import org.onap.ccsdk.cds.controllerblueprints.core.returnNullIfMissing
36 import com.fasterxml.jackson.databind.node.ObjectNode
37 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
39 @Component("component-k8s-profile-upload")
40 @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
41 open class K8sProfileUploadComponent(private var bluePrintPropertiesService: BluePrintPropertiesService) :
43 AbstractComponentFunction() {
46 const val INPUT_K8S_PROFILE_NAME = "k8s-rb-profile-name"
47 const val INPUT_K8S_DEFINITION_NAME = "k8s-rb-definition-name"
48 const val INPUT_K8S_DEFINITION_VERSION = "k8s-rb-definition-version"
49 const val INPUT_K8S_PROFILE_NAMESPACE = "k8s-rb-profile-namespace"
50 const val INPUT_K8S_PROFILE_SOURCE = "k8s-rb-profile-source"
51 const val INPUT_RESOURCE_ASSIGNMENT_MAP = "resource-assignment-map"
53 const val OUTPUT_STATUSES = "statuses"
54 const val OUTPUT_SKIPPED = "skipped"
55 const val OUTPUT_UPLOADED = "uploaded"
56 const val OUTPUT_ERROR = "error"
59 private val log = LoggerFactory.getLogger(K8sProfileUploadComponent::class.java)!!
61 override suspend fun processNB(executionRequest: ExecutionServiceInput) {
62 log.info("Triggering K8s Profile Upload component logic.")
64 val inputParameterNames = arrayOf(
65 INPUT_K8S_PROFILE_NAME,
66 INPUT_K8S_DEFINITION_NAME,
67 INPUT_K8S_DEFINITION_VERSION,
68 INPUT_K8S_PROFILE_NAMESPACE,
69 INPUT_K8S_PROFILE_SOURCE
71 var outputPrefixStatuses = mutableMapOf<String, String>()
72 var inputParamsMap = mutableMapOf<String, JsonNode?>()
74 inputParameterNames.forEach {
75 inputParamsMap[it] = getOptionalOperationInput(it)?.returnNullIfMissing()
78 log.info("Getting the template prefixes")
79 val prefixList: ArrayList<String> = getTemplatePrefixList(executionRequest)
81 log.info("Iterating over prefixes in resource assignment map.")
82 for (prefix in prefixList) {
83 // Prefilling prefix sucess status
84 outputPrefixStatuses.put(prefix, OUTPUT_SKIPPED)
85 // Resource assignment map is organized by prefixes, in each iteraton we work only
86 // on one section of resource assignment map
87 val prefixNode: JsonNode = operationInputs[INPUT_RESOURCE_ASSIGNMENT_MAP]?.get(prefix) ?: continue
88 val assignmentMapPrefix = JacksonUtils.jsonNode(prefixNode.toPrettyString()) as ObjectNode
90 // We are copying the map because for each prefix it might be completed with a different data
91 var prefixInputParamsMap = inputParamsMap.toMutableMap()
92 prefixInputParamsMap.forEach { (inputParamName, value) ->
94 val mapValue = assignmentMapPrefix?.get(inputParamName)
95 log.debug("$inputParamName value was $value so we fetch $mapValue")
96 prefixInputParamsMap[inputParamName] = mapValue
100 // For clarity we pull out the required fields
101 val profileName = prefixInputParamsMap[INPUT_K8S_PROFILE_NAME]?.returnNullIfMissing()?.textValue()
102 val definitionName = prefixInputParamsMap[INPUT_K8S_DEFINITION_NAME]?.returnNullIfMissing()?.textValue()
103 val definitionVersion = prefixInputParamsMap[INPUT_K8S_DEFINITION_VERSION]?.returnNullIfMissing()?.textValue()
105 val k8sProfileUploadConfiguration = K8sProfileUploadConfiguration(bluePrintPropertiesService)
107 // Creating API connector
108 var api = K8sPluginApi(
109 k8sProfileUploadConfiguration.getProperties().username,
110 k8sProfileUploadConfiguration.getProperties().password,
111 k8sProfileUploadConfiguration.getProperties().url,
116 if ((profileName == null) || (definitionName == null) || (definitionVersion == null)) {
117 log.warn("Prefix $prefix does not have required data for us to continue.")
118 } else if (!api.hasDefinition()) {
119 log.warn("K8s RB Definition ($definitionName/$definitionVersion) not found ")
120 } else if (profileName == "") {
121 log.warn("K8s rb profile name is empty! Either define profile name to use or choose default")
122 } else if (api.hasProfile(profileName)) {
123 log.info("Profile Already Existing - skipping upload")
125 log.info("Uploading K8s Profile..")
126 outputPrefixStatuses.put(prefix, OUTPUT_ERROR)
128 var profile = K8sProfile()
129 profile.profileName = profileName
130 profile.rbName = definitionName
131 profile.rbVersion = definitionVersion
132 profile.namespace = prefixInputParamsMap[INPUT_K8S_PROFILE_NAMESPACE]?.textValue()
133 api.createProfile(profile)
134 val profileFilePath: Path = prepareProfileFile(profileName)
135 api.uploadProfileContent(profile, profileFilePath)
137 log.info("K8s Profile Upload Completed")
138 outputPrefixStatuses.put(prefix, OUTPUT_UPLOADED)
141 bluePrintRuntimeService.setNodeTemplateAttributeValue(
144 outputPrefixStatuses.asJsonNode()
148 override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
149 bluePrintRuntimeService.getBluePrintError().addError(runtimeException.message!!)
152 fun getTemplatePrefixList(executionRequest: ExecutionServiceInput): ArrayList<String> {
153 val result = ArrayList<String>()
154 for (prefix in executionRequest.payload.get("resource-assignment-request").get("template-prefix").elements())
155 result.add(prefix.asText())
159 fun prepareProfileFile(k8sRbProfileName: String): Path {
160 val bluePrintContext = bluePrintRuntimeService.bluePrintContext()
161 val bluePrintBasePath: String = bluePrintContext.rootPath
163 bluePrintBasePath.plus(File.separator)
165 .plus(File.separator)
166 .plus("k8s-profiles")
167 .plus(File.separator)
168 .plus("$k8sRbProfileName.tar.gz")