2 * Copyright © 2017-2018 AT&T Intellectual Property.
3 * Modifications Copyright © 2018 IBM.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 package org.onap.ccsdk.apps.controllerblueprints.core.service
21 import com.att.eelf.configuration.EELFLogger
22 import com.att.eelf.configuration.EELFManager
23 import com.fasterxml.jackson.databind.JsonNode
24 import com.fasterxml.jackson.databind.node.NullNode
25 import com.fasterxml.jackson.databind.node.ObjectNode
26 import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
27 import org.onap.ccsdk.apps.controllerblueprints.core.*
28 import org.onap.ccsdk.apps.controllerblueprints.core.data.ArtifactDefinition
29 import org.onap.ccsdk.apps.controllerblueprints.core.data.NodeTemplate
30 import org.onap.ccsdk.apps.controllerblueprints.core.data.PropertyDefinition
31 import org.onap.ccsdk.apps.controllerblueprints.core.utils.BluePrintMetadataUtils
32 import org.onap.ccsdk.apps.controllerblueprints.core.utils.JacksonUtils
35 interface BluePrintRuntimeService<T> {
39 fun bluePrintContext(): BluePrintContext
41 fun getExecutionContext(): T
43 fun setExecutionContext(executionContext: T)
45 fun put(key: String, value: JsonNode)
47 fun get(key: String): JsonNode?
49 fun check(key: String): Boolean
53 fun getAsString(key: String): String?
55 fun getAsBoolean(key: String): Boolean?
57 fun getAsInt(key: String): Int?
59 fun getAsDouble(key: String): Double?
61 fun getBluePrintError(): BluePrintError
63 fun setBluePrintError(bluePrintError: BluePrintError)
65 fun loadEnvironments(type: String, fileName: String)
67 fun resolveNodeTemplatePropertyAssignments(nodeTemplateName: String,
68 propertyDefinitions: MutableMap<String, PropertyDefinition>,
69 propertyAssignments: MutableMap<String, JsonNode>): MutableMap<String, JsonNode>
71 fun resolveNodeTemplateProperties(nodeTemplateName: String): MutableMap<String, JsonNode>
73 fun resolveNodeTemplateCapabilityProperties(nodeTemplateName: String, capabilityName: String): MutableMap<String,
76 fun resolveNodeTemplateInterfaceOperationInputs(nodeTemplateName: String, interfaceName: String,
77 operationName: String): MutableMap<String, JsonNode>
79 fun resolveNodeTemplateInterfaceOperationOutputs(nodeTemplateName: String, interfaceName: String,
80 operationName: String): MutableMap<String, JsonNode>
82 fun resolveNodeTemplateArtifact(nodeTemplateName: String, artifactName: String): String
84 fun resolveNodeTemplateArtifactDefinition(nodeTemplateName: String, artifactName: String): ArtifactDefinition
86 fun resolveDSLExpression(dslPropertyName: String): JsonNode
88 fun setInputValue(propertyName: String, propertyDefinition: PropertyDefinition, value: JsonNode)
90 fun setWorkflowInputValue(workflowName: String, propertyName: String, propertyDefinition: PropertyDefinition, value: JsonNode)
92 fun setNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String, value: JsonNode)
94 fun setNodeTemplateAttributeValue(nodeTemplateName: String, attributeName: String, value: JsonNode)
96 fun setNodeTemplateOperationPropertyValue(nodeTemplateName: String, interfaceName: String,
97 operationName: String, propertyName: String, value: JsonNode)
99 fun setNodeTemplateOperationInputValue(nodeTemplateName: String, interfaceName: String,
100 operationName: String, propertyName: String, value: JsonNode)
102 fun setNodeTemplateOperationOutputValue(nodeTemplateName: String, interfaceName: String,
103 operationName: String, propertyName: String, value: JsonNode)
105 fun getInputValue(propertyName: String): JsonNode
107 fun getNodeTemplateOperationOutputValue(nodeTemplateName: String, interfaceName: String,
108 operationName: String, propertyName: String): JsonNode
110 fun getNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String): JsonNode?
112 fun getNodeTemplateAttributeValue(nodeTemplateName: String, attributeName: String): JsonNode?
114 fun assignInputs(jsonNode: JsonNode)
116 fun assignWorkflowInputs(workflowName: String, jsonNode: JsonNode)
118 fun getJsonForNodeTemplateAttributeProperties(nodeTemplateName: String, keys: List<String>): JsonNode
124 * @author Brinda Santh
126 open class DefaultBluePrintRuntimeService(private var id: String, private var bluePrintContext: BluePrintContext)
127 : BluePrintRuntimeService<MutableMap<String, JsonNode>> {
130 private val log: EELFLogger = EELFManager.getInstance().getLogger(BluePrintRuntimeService::class.toString())
132 private var store: MutableMap<String, JsonNode> = hashMapOf()
134 private var bluePrintError = BluePrintError()
138 * Load Blueprint Environments Properties
140 val absoluteEnvFilePath = bluePrintContext.rootPath.plus(File.separator)
141 .plus(BluePrintConstants.TOSCA_ENVIRONMENTS_DIR)
142 loadEnvironments(BluePrintConstants.PROPERTY_BPP, absoluteEnvFilePath)
146 override fun id(): String {
150 override fun bluePrintContext(): BluePrintContext {
151 return bluePrintContext
154 override fun getExecutionContext(): MutableMap<String, JsonNode> {
158 @Suppress("UNCHECKED_CAST")
159 override fun setExecutionContext(executionContext: MutableMap<String, JsonNode>) {
160 this.store = executionContext
163 override fun put(key: String, value: JsonNode) {
167 override fun get(key: String): JsonNode {
168 return store[key] ?: throw BluePrintProcessorException("failed to get execution property($key)")
171 override fun check(key: String): Boolean {
172 return store.containsKey(key)
175 override fun cleanRuntime() {
179 private fun getJsonNode(key: String): JsonNode {
183 override fun getAsString(key: String): String? {
184 return get(key).asText()
187 override fun getAsBoolean(key: String): Boolean? {
188 return get(key).asBoolean()
191 override fun getAsInt(key: String): Int? {
192 return get(key).asInt()
195 override fun getAsDouble(key: String): Double? {
196 return get(key).asDouble()
199 override fun getBluePrintError(): BluePrintError {
200 return this.bluePrintError
203 override fun setBluePrintError(bluePrintError: BluePrintError) {
204 this.bluePrintError = bluePrintError
207 override fun loadEnvironments(type: String, fileName: String) {
208 BluePrintMetadataUtils.environmentFileProperties(fileName).forEach { key, value ->
209 setNodeTemplateAttributeValue(type, key.toString(), value.toString()
215 * Resolve any property assignments for the node
217 override fun resolveNodeTemplatePropertyAssignments(nodeTemplateName: String,
218 propertyDefinitions: MutableMap<String, PropertyDefinition>,
219 propertyAssignments: MutableMap<String, JsonNode>)
220 : MutableMap<String, JsonNode> {
222 val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf()
224 propertyDefinitions.forEach { nodeTypePropertyName, nodeTypeProperty ->
225 // Get the Express or Value for the Node Template
226 val propertyAssignment: JsonNode? = propertyAssignments[nodeTypePropertyName]
228 var resolvedValue: JsonNode = NullNode.getInstance()
229 if (propertyAssignment != null) {
230 // Resolve the Expressing
231 val propertyAssignmentExpression = PropertyAssignmentService(this)
232 resolvedValue = propertyAssignmentExpression.resolveAssignmentExpression(nodeTemplateName,
233 nodeTypePropertyName, propertyAssignment)
235 // Assign default value to the Operation
236 nodeTypeProperty.defaultValue?.let {
237 resolvedValue = JacksonUtils.jsonNodeFromObject(nodeTypeProperty.defaultValue!!)
240 // Set for Return of method
241 propertyAssignmentValue[nodeTypePropertyName] = resolvedValue
243 return propertyAssignmentValue
246 override fun resolveNodeTemplateProperties(nodeTemplateName: String): MutableMap<String, JsonNode> {
247 log.info("resolveNodeTemplatePropertyValues for node template ({})", nodeTemplateName)
249 val nodeTemplate: NodeTemplate = bluePrintContext.nodeTemplateByName(nodeTemplateName)
251 val propertyAssignments: MutableMap<String, JsonNode> = nodeTemplate.properties!!
253 // Get the Node Type Definitions
254 val nodeTypePropertieDefinitions: MutableMap<String, PropertyDefinition> = bluePrintContext
255 .nodeTypeChainedProperties(nodeTemplate.type)!!
258 * Resolve the NodeTemplate Property Assignment Values.
260 return resolveNodeTemplatePropertyAssignments(nodeTemplateName, nodeTypePropertieDefinitions,
264 override fun resolveNodeTemplateCapabilityProperties(nodeTemplateName: String, capabilityName: String):
265 MutableMap<String, JsonNode> {
266 log.info("resolveNodeTemplateCapabilityProperties for node template($nodeTemplateName) capability " +
268 val nodeTemplate: NodeTemplate = bluePrintContext.nodeTemplateByName(nodeTemplateName)
270 val propertyAssignments = nodeTemplate.capabilities?.get(capabilityName)?.properties ?: hashMapOf()
272 val propertyDefinitions = bluePrintContext.nodeTemplateNodeType(nodeTemplateName)
273 .capabilities?.get(capabilityName)?.properties ?: hashMapOf()
276 * Resolve the Capability Property Assignment Values.
278 return resolveNodeTemplatePropertyAssignments(nodeTemplateName, propertyDefinitions,
282 override fun resolveNodeTemplateInterfaceOperationInputs(nodeTemplateName: String,
283 interfaceName: String,
284 operationName: String): MutableMap<String, JsonNode> {
285 log.info("resolveNodeTemplateInterfaceOperationInputs for node template ($nodeTemplateName),interface name " +
286 "($interfaceName), operationName($operationName)")
288 val propertyAssignments: MutableMap<String, JsonNode> =
289 bluePrintContext.nodeTemplateInterfaceOperationInputs(nodeTemplateName, interfaceName, operationName)
292 val nodeTypeName = bluePrintContext.nodeTemplateByName(nodeTemplateName).type
294 val nodeTypeInterfaceOperationInputs: MutableMap<String, PropertyDefinition> =
295 bluePrintContext.nodeTypeInterfaceOperationInputs(nodeTypeName, interfaceName, operationName)
298 log.info("input definition for node template ($nodeTemplateName), values ($propertyAssignments)")
301 * Resolve the Property Input Assignment Values.
303 return resolveNodeTemplatePropertyAssignments(nodeTemplateName, nodeTypeInterfaceOperationInputs,
309 override fun resolveNodeTemplateInterfaceOperationOutputs(nodeTemplateName: String,
310 interfaceName: String,
311 operationName: String): MutableMap<String, JsonNode> {
312 log.info("resolveNodeTemplateInterfaceOperationOutputs for node template ($nodeTemplateName),interface name " +
313 "($interfaceName), operationName($operationName)")
315 val propertyAssignments: MutableMap<String, JsonNode> =
316 bluePrintContext.nodeTemplateInterfaceOperationOutputs(nodeTemplateName, interfaceName, operationName)
319 val nodeTypeName = bluePrintContext.nodeTemplateByName(nodeTemplateName).type
321 val nodeTypeInterfaceOperationOutputs: MutableMap<String, PropertyDefinition> =
322 bluePrintContext.nodeTypeInterfaceOperationOutputs(nodeTypeName, interfaceName, operationName)
325 * Resolve the Property Output Assignment Values.
327 val propertyAssignmentValue = resolveNodeTemplatePropertyAssignments(nodeTemplateName,
328 nodeTypeInterfaceOperationOutputs, propertyAssignments)
330 // Store operation output values into context
331 propertyAssignmentValue.forEach { key, value ->
332 setNodeTemplateOperationOutputValue(nodeTemplateName, interfaceName, operationName, key, value)
334 return propertyAssignmentValue
337 override fun resolveNodeTemplateArtifact(nodeTemplateName: String, artifactName: String): String {
338 val artifactDefinition: ArtifactDefinition = resolveNodeTemplateArtifactDefinition(nodeTemplateName, artifactName)
339 val propertyAssignmentExpression = PropertyAssignmentService(this)
340 return propertyAssignmentExpression.artifactContent(artifactDefinition)
343 override fun resolveNodeTemplateArtifactDefinition(nodeTemplateName: String, artifactName: String): ArtifactDefinition {
344 val nodeTemplate = bluePrintContext.nodeTemplateByName(nodeTemplateName)
346 return nodeTemplate.artifacts?.get(artifactName)
347 ?: throw BluePrintProcessorException("failed to get artifat definition($artifactName) from the node " +
353 * Read the DSL Property reference, If there is any expression, then resolve those expression and return as Json
356 override fun resolveDSLExpression(dslPropertyName: String): JsonNode {
357 val propertyAssignments = bluePrintContext.dslPropertiesByName(dslPropertyName)
358 return if (BluePrintExpressionService.checkContainsExpression(propertyAssignments)
359 && propertyAssignments is ObjectNode) {
361 val rootKeyMap = propertyAssignments.rootFieldsToMap()
362 val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf()
363 rootKeyMap.forEach { propertyName, propertyValue ->
364 val propertyAssignmentExpression = PropertyAssignmentService(this)
365 propertyAssignmentValue[propertyName] = propertyAssignmentExpression
366 .resolveAssignmentExpression("DSL", propertyName, propertyValue)
368 propertyAssignmentValue.asJsonNode()
374 override fun setInputValue(propertyName: String, propertyDefinition: PropertyDefinition, value: JsonNode) {
375 val path = StringBuilder(BluePrintConstants.PATH_INPUTS)
376 .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
377 log.trace("setting input path ({}), values ({})", path, value)
381 override fun setWorkflowInputValue(workflowName: String, propertyName: String,
382 propertyDefinition: PropertyDefinition, value: JsonNode) {
383 val path: String = StringBuilder(BluePrintConstants.PATH_NODE_WORKFLOWS)
384 .append(BluePrintConstants.PATH_DIVIDER).append(workflowName)
385 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INPUTS)
386 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
387 .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
391 override fun setNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String, value: JsonNode) {
393 val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
394 .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
395 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
396 .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
400 override fun setNodeTemplateAttributeValue(nodeTemplateName: String, attributeName: String, value: JsonNode) {
402 val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
403 .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
404 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES)
405 .append(BluePrintConstants.PATH_DIVIDER).append(attributeName).toString()
409 override fun setNodeTemplateOperationPropertyValue(nodeTemplateName: String, interfaceName: String, operationName: String, propertyName: String,
411 val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
412 .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
413 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
414 .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
415 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
416 .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
417 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
418 .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
419 log.trace("setting operation property path ({}), values ({})", path, value)
423 override fun setNodeTemplateOperationInputValue(nodeTemplateName: String, interfaceName: String,
424 operationName: String, propertyName: String,
426 val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
427 .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
428 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
429 .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
430 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
431 .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
432 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INPUTS)
433 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
434 .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
438 override fun setNodeTemplateOperationOutputValue(nodeTemplateName: String, interfaceName: String,
439 operationName: String, propertyName: String,
441 val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
442 .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
443 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
444 .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
445 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
446 .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
447 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OUTPUTS)
448 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
449 .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
454 override fun getInputValue(propertyName: String): JsonNode {
455 val path = StringBuilder(BluePrintConstants.PATH_INPUTS)
456 .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
457 return getJsonNode(path)
460 override fun getNodeTemplateOperationOutputValue(nodeTemplateName: String, interfaceName: String,
461 operationName: String, propertyName: String): JsonNode {
462 val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
463 .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
464 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES)
465 .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName)
466 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS)
467 .append(BluePrintConstants.PATH_DIVIDER).append(operationName)
468 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OUTPUTS)
469 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
470 .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
471 return getJsonNode(path)
474 override fun getNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String): JsonNode {
475 val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
476 .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
477 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES)
478 .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString()
479 return getJsonNode(path)
482 override fun getNodeTemplateAttributeValue(nodeTemplateName: String, attributeName: String): JsonNode {
483 val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
484 .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
485 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES)
486 .append(BluePrintConstants.PATH_DIVIDER).append(attributeName).toString()
487 return getJsonNode(path)
490 override fun assignInputs(jsonNode: JsonNode) {
491 log.info("assignInputs from input JSON ({})", jsonNode.toString())
492 bluePrintContext.inputs?.forEach { propertyName, property ->
493 val valueNode: JsonNode = jsonNode.at(BluePrintConstants.PATH_DIVIDER + propertyName)
494 ?: NullNode.getInstance()
495 setInputValue(propertyName, property, valueNode)
499 override fun assignWorkflowInputs(workflowName: String, jsonNode: JsonNode) {
500 log.info("assign workflow {} input value ({})", workflowName, jsonNode.toString())
502 val dynamicInputPropertiesName = "$workflowName-properties"
504 bluePrintContext.workflowByName(workflowName).inputs?.forEach { propertyName, property ->
505 if (propertyName != dynamicInputPropertiesName) {
506 val valueNode: JsonNode = jsonNode.at(BluePrintConstants.PATH_DIVIDER + propertyName)
507 ?: NullNode.getInstance()
508 setInputValue(propertyName, property, valueNode)
511 // Load Dynamic data Types
512 val workflowDynamicInputs: JsonNode? = jsonNode.get(dynamicInputPropertiesName)
514 workflowDynamicInputs?.let {
515 bluePrintContext.dataTypeByName("dt-$dynamicInputPropertiesName")?.properties?.forEach { propertyName, property ->
516 val valueNode: JsonNode = workflowDynamicInputs.at(BluePrintConstants.PATH_DIVIDER + propertyName)
517 ?: NullNode.getInstance()
518 setInputValue(propertyName, property, valueNode)
524 override fun getJsonForNodeTemplateAttributeProperties(nodeTemplateName: String, keys: List<String>): JsonNode {
526 val jsonNode: ObjectNode = jacksonObjectMapper().createObjectNode()
527 val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES)
528 .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName)
529 .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES)
530 .append(BluePrintConstants.PATH_DIVIDER).toString()
534 val key = it.replace(path, "")
535 if (keys.contains(key)) {
536 val value = store[it] as JsonNode
537 jsonNode.set(key, value)