f8024d92e8e6c9ab23c968c750a86e79d85e5b32
[ccsdk/cds.git] /
1 /*
2  * Copyright © 2017-2018 AT&T Intellectual Property.
3  * Modifications Copyright © 2019 IBM.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils
19
20 import com.fasterxml.jackson.databind.JsonNode
21 import com.fasterxml.jackson.databind.ObjectMapper
22 import com.fasterxml.jackson.databind.node.ObjectNode
23 import com.fasterxml.jackson.databind.node.TextNode
24 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceAssignmentRuntimeService
25 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants
26 import org.onap.ccsdk.cds.controllerblueprints.core.*
27 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
28 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonReactorUtils
29 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
30 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDefinition
31 import org.slf4j.LoggerFactory
32 import java.util.*
33
34 class ResourceAssignmentUtils {
35     companion object {
36
37         private val logger = LoggerFactory.getLogger(ResourceAssignmentUtils::class.toString())
38
39         suspend fun resourceDefinitions(blueprintBasePath: String): MutableMap<String, ResourceDefinition> {
40             val dictionaryFile = normalizedFile(blueprintBasePath, BluePrintConstants.TOSCA_DEFINITIONS_DIR,
41                     ResourceResolutionConstants.FILE_NAME_RESOURCE_DEFINITION_TYPES)
42             checkFileExists(dictionaryFile) { "resource definition file(${dictionaryFile.absolutePath}) is missing" }
43             return JacksonReactorUtils.getMapFromFile(dictionaryFile, ResourceDefinition::class.java)
44         }
45
46         @Throws(BluePrintProcessorException::class)
47         fun setResourceDataValue(resourceAssignment: ResourceAssignment,
48                                  raRuntimeService: ResourceAssignmentRuntimeService, value: Any?) {
49             // TODO("See if Validation is needed in future with respect to conversion and Types")
50             return setResourceDataValue(resourceAssignment, raRuntimeService, value.asJsonType())
51         }
52
53         @Throws(BluePrintProcessorException::class)
54         fun setResourceDataValue(resourceAssignment: ResourceAssignment,
55                                  raRuntimeService: ResourceAssignmentRuntimeService, value: JsonNode) {
56             val resourceProp = checkNotNull(resourceAssignment.property) {
57                 "Failed in setting resource value for resource mapping $resourceAssignment"
58             }
59             checkNotEmpty(resourceAssignment.name) {
60                 "Failed in setting resource value for resource mapping $resourceAssignment"
61             }
62
63             if (resourceAssignment.dictionaryName.isNullOrEmpty()) {
64                 resourceAssignment.dictionaryName = resourceAssignment.name
65                 logger.warn("Missing dictionary key, setting with template key (${resourceAssignment.name}) " +
66                         "as dictionary key (${resourceAssignment.dictionaryName})")
67             }
68
69             try {
70                 if (resourceProp.type.isNotEmpty()) {
71                     logger.info("Setting Resource Value ($value) for Resource Name " +
72                             "(${resourceAssignment.name}), definition(${resourceAssignment.dictionaryName}) " +
73                             "of type (${resourceProp.type})")
74                     setResourceValue(resourceAssignment, raRuntimeService, value)
75                     resourceAssignment.updatedDate = Date()
76                     resourceAssignment.updatedBy = BluePrintConstants.USER_SYSTEM
77                     resourceAssignment.status = BluePrintConstants.STATUS_SUCCESS
78                 }
79             } catch (e: Exception) {
80                 throw BluePrintProcessorException("Failed in setting value for template key " +
81                         "(${resourceAssignment.name}) and dictionary key (${resourceAssignment.dictionaryName}) of " +
82                         "type (${resourceProp.type}) with error message (${e.message})", e)
83             }
84         }
85
86         private fun setResourceValue(resourceAssignment: ResourceAssignment,
87                                      raRuntimeService: ResourceAssignmentRuntimeService, value: JsonNode) {
88             // TODO("See if Validation is needed wrt to type before storing")
89             raRuntimeService.putResolutionStore(resourceAssignment.name, value)
90             raRuntimeService.putDictionaryStore(resourceAssignment.dictionaryName!!, value)
91             resourceAssignment.property!!.value = value
92         }
93
94         fun setFailedResourceDataValue(resourceAssignment: ResourceAssignment, message: String?) {
95             if (isNotEmpty(resourceAssignment.name)) {
96                 resourceAssignment.updatedDate = Date()
97                 resourceAssignment.updatedBy = BluePrintConstants.USER_SYSTEM
98                 resourceAssignment.status = BluePrintConstants.STATUS_FAILURE
99                 resourceAssignment.message = message
100             }
101         }
102
103         @Throws(BluePrintProcessorException::class)
104         fun assertTemplateKeyValueNotNull(resourceAssignment: ResourceAssignment) {
105             val resourceProp = checkNotNull(resourceAssignment.property) {
106                 "Failed to populate mandatory resource resource mapping $resourceAssignment"
107             }
108             if (resourceProp.required != null && resourceProp.required!!
109                     && (resourceProp.value == null || resourceProp.value!!.returnNullIfMissing() == null)) {
110                 logger.error("failed to populate mandatory resource mapping ($resourceAssignment)")
111                 throw BluePrintProcessorException("failed to populate mandatory resource mapping ($resourceAssignment)")
112             }
113         }
114
115         @Throws(BluePrintProcessorException::class)
116         fun generateResourceDataForAssignments(assignments: List<ResourceAssignment>): String {
117             val result: String
118             try {
119                 val mapper = ObjectMapper()
120                 val root: ObjectNode = mapper.createObjectNode()
121
122                 assignments.forEach {
123                     if (isNotEmpty(it.name) && it.property != null) {
124                         val rName = it.name
125                         val type = nullToEmpty(it.property?.type).toLowerCase()
126                         val value = useDefaultValueIfNull(it, rName)
127                         logger.info("Generating Resource name ($rName), type ($type), value ($value)")
128                         root.set(rName, value)
129                     }
130                 }
131                 result = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(root)
132                 logger.info("Generated Resource Param Data ($result)")
133             } catch (e: Exception) {
134                 throw BluePrintProcessorException("Resource Assignment is failed with $e.message", e)
135             }
136
137             return result
138         }
139
140         @Throws(BluePrintProcessorException::class)
141         fun generateResourceForAssignments(assignments: List<ResourceAssignment>): MutableMap<String, JsonNode> {
142             val data: MutableMap<String, JsonNode> = hashMapOf()
143             assignments.forEach {
144                 if (isNotEmpty(it.name) && it.property != null) {
145                     val rName = it.name
146                     val type = nullToEmpty(it.property?.type).toLowerCase()
147                     val value = useDefaultValueIfNull(it, rName)
148                     logger.trace("Generating Resource name ($rName), type ($type), value ($value)")
149                     data[rName] = value
150                 }
151             }
152             return data
153         }
154
155         private fun useDefaultValueIfNull(resourceAssignment: ResourceAssignment, resourceAssignmentName: String): JsonNode {
156             if (resourceAssignment.property?.value == null) {
157                 val defaultValue = "\${$resourceAssignmentName}"
158                 return TextNode(defaultValue)
159             } else {
160                 return resourceAssignment.property!!.value!!
161             }
162         }
163
164         fun transformToRARuntimeService(blueprintRuntimeService: BluePrintRuntimeService<*>,
165                                         templateArtifactName: String): ResourceAssignmentRuntimeService {
166
167             val resourceAssignmentRuntimeService = ResourceAssignmentRuntimeService(blueprintRuntimeService.id(),
168                     blueprintRuntimeService.bluePrintContext())
169             resourceAssignmentRuntimeService.createUniqueId(templateArtifactName)
170             resourceAssignmentRuntimeService.setExecutionContext(blueprintRuntimeService.getExecutionContext() as MutableMap<String, JsonNode>)
171
172             return resourceAssignmentRuntimeService
173         }
174
175         @Throws(BluePrintProcessorException::class)
176         fun getPropertyType(raRuntimeService: ResourceAssignmentRuntimeService, dataTypeName: String,
177                             propertyName: String): String {
178             lateinit var type: String
179             try {
180                 val dataTypeProps = checkNotNull(raRuntimeService.bluePrintContext().dataTypeByName(dataTypeName)?.properties)
181
182                 val propertyDefinition = checkNotNull(dataTypeProps[propertyName])
183                 type = checkNotEmpty(propertyDefinition.type) { "Couldn't get data type ($dataTypeName)" }
184                 logger.trace("Data type({})'s property ({}) is ({})", dataTypeName, propertyName, type)
185             } catch (e: Exception) {
186                 logger.error("couldn't get data type($dataTypeName)'s property ($propertyName), error message $e")
187                 throw BluePrintProcessorException("${e.message}", e)
188             }
189             return type
190         }
191     }
192 }