7e9f407e1610a5bdaab1290fbede94e28b24769e
[ccsdk/cds.git] /
1 package org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.definition.template
2
3 import com.fasterxml.jackson.databind.JsonNode
4 import com.fasterxml.jackson.databind.ObjectMapper
5 import com.fasterxml.jackson.databind.node.ArrayNode
6 import com.fasterxml.jackson.databind.node.ObjectNode
7 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
8 import com.fasterxml.jackson.module.kotlin.convertValue
9 import org.onap.ccsdk.cds.blueprintsprocessor.core.BlueprintPropertiesService
10 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
11 import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.K8sConnectionPluginConfiguration
12 import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.K8sConfigValueRequest
13 import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.K8sPluginInstanceApi
14 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction
15 import org.onap.ccsdk.cds.controllerblueprints.core.BlueprintConstants
16 import org.onap.ccsdk.cds.controllerblueprints.core.BlueprintProcessorException
17 import org.onap.ccsdk.cds.controllerblueprints.core.data.ArtifactDefinition
18 import org.onap.ccsdk.cds.controllerblueprints.core.returnNullIfMissing
19 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
20 import org.slf4j.LoggerFactory
21 import org.springframework.beans.factory.config.ConfigurableBeanFactory
22 import org.springframework.context.annotation.Scope
23 import org.springframework.stereotype.Component
24 import java.io.File
25 import java.nio.file.Path
26 import java.nio.file.Paths
27
28 @Component("component-k8s-config-value")
29 @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
30 open class K8sConfigValueComponent(
31     private var bluePrintPropertiesService: BlueprintPropertiesService
32 ) : AbstractComponentFunction() {
33
34     private val log = LoggerFactory.getLogger(K8sConfigValueComponent::class.java)!!
35
36     companion object {
37         const val INPUT_RESOURCE_ASSIGNMENT_MAP = "resource-assignment-map"
38         const val INPUT_ARTIFACT_PREFIX_NAMES = "artifact-prefix-names"
39         const val INPUT_K8S_TEMPLATE_NAME = "k8s-template-name"
40         const val INPUT_K8S_CONFIG_NAME = "k8s-config-name"
41         const val INPUT_K8S_INSTANCE_ID = "k8s-instance-id"
42         const val INPUT_K8S_TEMPLATE_VALUE_SOURCE = "k8s-rb-template-value-source"
43
44         const val OUTPUT_STATUSES = "statuses"
45         const val OUTPUT_SKIPPED = "skipped"
46         const val OUTPUT_UPLOADED = "uploaded"
47         const val OUTPUT_ERROR = "error"
48     }
49
50     override suspend fun processNB(executionRequest: ExecutionServiceInput) {
51         log.info("Triggering K8s Config Value component logic.")
52         val inputParameterNames = arrayOf(
53             INPUT_K8S_TEMPLATE_NAME,
54             INPUT_K8S_CONFIG_NAME,
55             INPUT_K8S_INSTANCE_ID,
56             INPUT_K8S_TEMPLATE_VALUE_SOURCE,
57             INPUT_ARTIFACT_PREFIX_NAMES
58         )
59         val outputPrefixStatuses = mutableMapOf<String, String>()
60         val inputParamsMap = mutableMapOf<String, JsonNode?>()
61
62         inputParameterNames.forEach {
63             inputParamsMap[it] = getOptionalOperationInput(it)?.returnNullIfMissing()
64         }
65
66         log.info("Getting the template prefixes")
67         val prefixList: ArrayList<String> = getTemplatePrefixList(inputParamsMap[INPUT_ARTIFACT_PREFIX_NAMES])
68
69         log.info("Iterating over prefixes in resource assignment map.")
70         for (prefix in prefixList) {
71             outputPrefixStatuses[prefix] = OUTPUT_SKIPPED
72             val prefixNode: JsonNode = operationInputs[INPUT_RESOURCE_ASSIGNMENT_MAP]?.get(prefix) ?: continue
73             val assignmentMapPrefix = JacksonUtils.jsonNode(prefixNode.toPrettyString()) as ObjectNode
74             val prefixInputParamsMap = inputParamsMap.toMutableMap()
75             prefixInputParamsMap.forEach { (inputParamName, value) ->
76                 if (value == null) {
77                     val mapValue = assignmentMapPrefix.get(inputParamName)
78                     log.debug("$inputParamName value was $value so we fetch $mapValue")
79                     prefixInputParamsMap[inputParamName] = mapValue
80                 }
81             }
82
83             val templateName: String? = prefixInputParamsMap[INPUT_K8S_TEMPLATE_NAME]?.returnNullIfMissing()?.asText()
84             val configName: String? = prefixInputParamsMap[INPUT_K8S_CONFIG_NAME]?.returnNullIfMissing()?.asText()
85             val instanceId: String? = prefixInputParamsMap[INPUT_K8S_INSTANCE_ID]?.returnNullIfMissing()?.asText()
86             val valueSource: String? = prefixInputParamsMap[INPUT_K8S_TEMPLATE_VALUE_SOURCE]?.returnNullIfMissing()?.asText()
87             if (templateName == null || instanceId == null || valueSource == null) {
88                 log.warn("$INPUT_K8S_TEMPLATE_NAME or $INPUT_K8S_TEMPLATE_NAME or $INPUT_K8S_TEMPLATE_VALUE_SOURCE or $INPUT_K8S_CONFIG_NAME is null")
89             } else if (templateName.isEmpty()) {
90                 log.warn("$INPUT_K8S_TEMPLATE_NAME is empty")
91             } else {
92                 log.info("Uploading K8s template value..")
93                 outputPrefixStatuses[prefix] = OUTPUT_ERROR
94                 val bluePrintContext = bluePrintRuntimeService.bluePrintContext()
95                 val artifact: ArtifactDefinition = bluePrintContext.nodeTemplateArtifact(nodeTemplateName, valueSource)
96                 if (artifact.type != BlueprintConstants.MODEL_TYPE_ARTIFACT_K8S_PROFILE)
97                     throw BlueprintProcessorException(
98                         "Unexpected profile artifact type for profile source $valueSource. Expecting: $artifact.type"
99                     )
100                 // Creating API connector
101                 val api = K8sPluginInstanceApi(K8sConnectionPluginConfiguration(bluePrintPropertiesService))
102                 val configValueRequest = K8sConfigValueRequest()
103                 configValueRequest.templateName = templateName
104                 configValueRequest.configName = configName
105                 configValueRequest.description = valueSource
106                 configValueRequest.values = parseResult(valueSource)
107                 api.createConfigurationValues(configValueRequest, instanceId)
108             }
109         }
110     }
111
112     private fun parseResult(templateValueSource: String): Any {
113         val ymlSourceFile = getYmlSourceFile(templateValueSource)
114         val yamlReader = ObjectMapper(YAMLFactory())
115         val obj: Any = yamlReader.readValue(ymlSourceFile, Any::class.java)
116
117         val jsonWriter = ObjectMapper()
118         return jsonWriter.convertValue(obj)
119     }
120
121     private fun getYmlSourceFile(templateValueSource: String): File {
122         val bluePrintBasePath: String = bluePrintRuntimeService.bluePrintContext().rootPath
123         val profileSourceFileFolderPath: Path = Paths.get(bluePrintBasePath.plus(File.separator).plus(templateValueSource))
124
125         if (profileSourceFileFolderPath.toFile().exists() && !profileSourceFileFolderPath.toFile().isDirectory)
126             return profileSourceFileFolderPath.toFile()
127         else
128             throw BlueprintProcessorException("Template value $profileSourceFileFolderPath is missing in CBA folder")
129     }
130
131     private fun getTemplatePrefixList(node: JsonNode?): ArrayList<String> {
132         val result = ArrayList<String>()
133         when (node) {
134             is ArrayNode -> {
135                 val arrayNode = node.toList()
136                 for (prefixNode in arrayNode)
137                     result.add(prefixNode.asText())
138             }
139             is ObjectNode -> {
140                 result.add(node.asText())
141             }
142         }
143         return result
144     }
145
146     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
147         bluePrintRuntimeService.getBlueprintError().addError(runtimeException.message!!)
148     }
149 }