Merge "Include orig err in CBA upload errmsg"
[ccsdk/cds.git] / ms / blueprintsprocessor / functions / resource-resolution / src / main / kotlin / org / onap / ccsdk / cds / blueprintsprocessor / functions / resource / resolution / ResourceResolutionService.kt
index ce3aa4d..ebff478 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright © 2017-2018 AT&T Intellectual Property.
- *  Modifications Copyright © 2018 IBM.
+ *  Modifications Copyright © 2018-2019 IBM, Bell Canada
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 
 package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution
 
+import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitAll
+import kotlinx.coroutines.coroutineScope
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionResultService
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.processor.ResourceAssignmentProcessor
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils
-import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
-import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmptyOrThrow
+import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintTemplateService
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
@@ -32,28 +34,27 @@ import org.onap.ccsdk.cds.controllerblueprints.resource.dict.utils.BulkResourceS
 import org.slf4j.LoggerFactory
 import org.springframework.context.ApplicationContext
 import org.springframework.stereotype.Service
-import java.io.File
 
 interface ResourceResolutionService {
 
     fun registeredResourceSources(): List<String>
 
-    fun resolveFromDatabase(bluePrintRuntimeService: BluePrintRuntimeService<*>, artifactTemplate: String,
-                            resolutionKey: String): String
+    suspend fun resolveFromDatabase(bluePrintRuntimeService: BluePrintRuntimeService<*>, artifactTemplate: String,
+                                    resolutionKey: String): String
 
-    fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,
-                         artifactNames: List<String>, properties: Map<String, Any>): MutableMap<String, String>
+    suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,
+                                 artifactNames: List<String>, properties: Map<String, Any>): MutableMap<String, String>
 
-    fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,
-                         artifactPrefix: String, properties: Map<String, Any>): String
+    suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,
+                                 artifactPrefix: String, properties: Map<String, Any>): String
 
-    fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,
-                         artifactMapping: String, artifactTemplate: String?): String
+    suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,
+                                 artifactMapping: String, artifactTemplate: String?): String
 
-    fun resolveResourceAssignments(blueprintRuntimeService: BluePrintRuntimeService<*>,
-                                   resourceDictionaries: MutableMap<String, ResourceDefinition>,
-                                   resourceAssignments: MutableList<ResourceAssignment>,
-                                   identifierName: String)
+    suspend fun resolveResourceAssignments(blueprintRuntimeService: BluePrintRuntimeService<*>,
+                                           resourceDefinitions: MutableMap<String, ResourceDefinition>,
+                                           resourceAssignments: MutableList<ResourceAssignment>,
+                                           identifierName: String)
 }
 
 @Service(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION)
@@ -69,45 +70,49 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
                 .map { it.substringAfter(ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR) }
     }
 
-    override fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,
-                                  artifactNames: List<String>,
-                                  properties: Map<String, Any>): MutableMap<String, String> {
+    override suspend fun resolveFromDatabase(bluePrintRuntimeService: BluePrintRuntimeService<*>,
+                                             artifactTemplate: String,
+                                             resolutionKey: String): String {
+        return resolutionResultService.read(bluePrintRuntimeService, artifactTemplate, resolutionKey)
+    }
+
+    override suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,
+                                          artifactNames: List<String>, properties: Map<String, Any>): MutableMap<String, String> {
 
         val resolvedParams: MutableMap<String, String> = hashMapOf()
         artifactNames.forEach { artifactName ->
-            val resolvedContent = resolveResources(bluePrintRuntimeService, nodeTemplateName, artifactName, properties)
+            val resolvedContent = resolveResources(bluePrintRuntimeService, nodeTemplateName,
+                    artifactName, properties)
             resolvedParams[artifactName] = resolvedContent
         }
         return resolvedParams
     }
 
-    override fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,
-                                  artifactPrefix: String, properties: Map<String, Any>): String {
+    override suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,
+                                          artifactPrefix: String, properties: Map<String, Any>): String {
 
         // Velocity Artifact Definition Name
         val artifactTemplate = "$artifactPrefix-template"
         // Resource Assignment Artifact Definition Name
         val artifactMapping = "$artifactPrefix-mapping"
 
-        val result = resolveResources(bluePrintRuntimeService, nodeTemplateName, artifactMapping, artifactTemplate)
+        val result = resolveResources(bluePrintRuntimeService, nodeTemplateName,
+                artifactMapping, artifactTemplate)
 
         if (properties.containsKey(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT)
                 && properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] as Boolean) {
             resolutionResultService.write(properties, result, bluePrintRuntimeService, artifactPrefix)
+            log.info("resolution saved into database successfully : ($properties)")
         }
 
         return result
     }
 
-    override fun resolveFromDatabase(bluePrintRuntimeService: BluePrintRuntimeService<*>, artifactTemplate: String,
-                                     resolutionKey: String): String {
-        return resolutionResultService.read(bluePrintRuntimeService, artifactTemplate, resolutionKey)
-    }
 
-    override fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,
-                                  artifactMapping: String, artifactTemplate: String?): String {
+    override suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,
+                                          artifactMapping: String, artifactTemplate: String?): String {
 
-        var resolvedContent = ""
+        val resolvedContent: String
         log.info("Resolving resource for template artifact($artifactTemplate) with resource assignment artifact($artifactMapping)")
 
         val identifierName = artifactTemplate ?: "no-template"
@@ -121,25 +126,21 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
                         ?: throw BluePrintProcessorException("couldn't get Dictionary Definitions")
 
         // Get the Resource Dictionary Name
-        val dictionaryFile = bluePrintRuntimeService.bluePrintContext().rootPath.plus(File.separator)
-                .plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR).plus(File.separator)
-                .plus(ResourceResolutionConstants.FILE_NAME_RESOURCE_DEFINITION_TYPES)
-
-        val resourceDictionaries: MutableMap<String, ResourceDefinition> =
-                JacksonUtils.getMapFromFile(dictionaryFile, ResourceDefinition::class.java)
-                        ?: throw BluePrintProcessorException("couldn't get Dictionary Definitions")
+        val resourceDefinitions: MutableMap<String, ResourceDefinition> = ResourceAssignmentUtils
+                .resourceDefinitions(bluePrintRuntimeService.bluePrintContext().rootPath)
 
         // Resolve resources
-        resolveResourceAssignments(bluePrintRuntimeService, resourceDictionaries, resourceAssignments, identifierName)
+        resolveResourceAssignments(bluePrintRuntimeService, resourceDefinitions, resourceAssignments, identifierName)
 
         val resolvedParamJsonContent =
                 ResourceAssignmentUtils.generateResourceDataForAssignments(resourceAssignments.toList())
 
         // Check Template is there
         if (artifactTemplate != null) {
-            val templateContent =
-                    bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactTemplate)
-            resolvedContent = BluePrintTemplateService.generateContent(templateContent, resolvedParamJsonContent)
+            val blueprintTemplateService = BluePrintTemplateService()
+            resolvedContent = blueprintTemplateService.generateContent(bluePrintRuntimeService, nodeTemplateName,
+                    artifactTemplate, resolvedParamJsonContent)
+
         } else {
             resolvedContent = resolvedParamJsonContent
         }
@@ -152,44 +153,51 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
      * name, then get the type of the Resource Definition, Get the instance for the Resource Type and process the
      * request.
      */
-    override fun resolveResourceAssignments(blueprintRuntimeService: BluePrintRuntimeService<*>,
-                                            resourceDictionaries: MutableMap<String, ResourceDefinition>,
-                                            resourceAssignments: MutableList<ResourceAssignment>,
-                                            identifierName: String) {
+    override suspend fun resolveResourceAssignments(blueprintRuntimeService: BluePrintRuntimeService<*>,
+                                                    resourceDefinitions: MutableMap<String, ResourceDefinition>,
+                                                    resourceAssignments: MutableList<ResourceAssignment>,
+                                                    identifierName: String) {
 
         val bulkSequenced = BulkResourceSequencingUtils.process(resourceAssignments)
         val resourceAssignmentRuntimeService =
                 ResourceAssignmentUtils.transformToRARuntimeService(blueprintRuntimeService, identifierName)
 
-        bulkSequenced.map { batchResourceAssignments ->
-            batchResourceAssignments.filter { it.name != "*" && it.name != "start" }
-                    .forEach { resourceAssignment ->
-                        val dictionaryName = resourceAssignment.dictionaryName
-                        val dictionarySource = resourceAssignment.dictionarySource
-                        /**
-                         * Get the Processor name
-                         */
-                        val processorName = processorName(dictionaryName!!, dictionarySource!!, resourceDictionaries)
-
-                        val resourceAssignmentProcessor =
-                                applicationContext.getBean(processorName) as? ResourceAssignmentProcessor
-                                        ?: throw BluePrintProcessorException("failed to get resource processor for name($processorName) " +
-                                                "for resource assignment(${resourceAssignment.name})")
-                        try {
-                            // Set BluePrint Runtime Service
-                            resourceAssignmentProcessor.raRuntimeService = resourceAssignmentRuntimeService
-                            // Set Resource Dictionaries
-                            resourceAssignmentProcessor.resourceDictionaries = resourceDictionaries
-                            // Invoke Apply Method
-                            resourceAssignmentProcessor.apply(resourceAssignment)
-
-                            // Set errors from RA
-                            blueprintRuntimeService.setBluePrintError(resourceAssignmentRuntimeService.getBluePrintError())
-                        } catch (e: RuntimeException) {
-                            throw BluePrintProcessorException(e)
+        coroutineScope {
+            bulkSequenced.forEach { batchResourceAssignments ->
+                // Execute Non Dependent Assignments in parallel ( ie asynchronously )
+                val deferred = batchResourceAssignments.filter { it.name != "*" && it.name != "start" }
+                        .map { resourceAssignment ->
+                            async {
+                                val dictionaryName = resourceAssignment.dictionaryName
+                                val dictionarySource = resourceAssignment.dictionarySource
+                                /**
+                                 * Get the Processor name
+                                 */
+                                val processorName = processorName(dictionaryName!!, dictionarySource!!, resourceDefinitions)
+
+                                val resourceAssignmentProcessor =
+                                        applicationContext.getBean(processorName) as? ResourceAssignmentProcessor
+                                                ?: throw BluePrintProcessorException("failed to get resource processor ($processorName) " +
+                                                        "for resource assignment(${resourceAssignment.name})")
+                                try {
+                                    // Set BluePrint Runtime Service
+                                    resourceAssignmentProcessor.raRuntimeService = resourceAssignmentRuntimeService
+                                    // Set Resource Dictionaries
+                                    resourceAssignmentProcessor.resourceDictionaries = resourceDefinitions
+                                    // Invoke Apply Method
+                                    resourceAssignmentProcessor.applyNB(resourceAssignment)
+                                    // Set errors from RA
+                                    blueprintRuntimeService.setBluePrintError(resourceAssignmentRuntimeService.getBluePrintError())
+                                } catch (e: RuntimeException) {
+                                    throw BluePrintProcessorException(e)
+                                }
+                            }
                         }
-                    }
+                log.debug("Resolving (${deferred.size})resources parallel.")
+                deferred.awaitAll()
+            }
         }
+
     }
 
 
@@ -198,29 +206,27 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
      *  derive the default input processor.
      */
     private fun processorName(dictionaryName: String, dictionarySource: String,
-                              resourceDictionaries: MutableMap<String, ResourceDefinition>): String {
-        var processorName: String? = null
-        when (dictionarySource) {
+                              resourceDefinitions: MutableMap<String, ResourceDefinition>): String {
+        val processorName: String = when (dictionarySource) {
             "input" -> {
-                processorName = "${ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR}source-input"
+                "${ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR}source-input"
             }
             "default" -> {
-                processorName = "${ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR}source-default"
+                "${ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR}source-default"
             }
             else -> {
-                val resourceDefinition = resourceDictionaries[dictionaryName]
+                val resourceDefinition = resourceDefinitions[dictionaryName]
                         ?: throw BluePrintProcessorException("couldn't get resource dictionary definition for $dictionaryName")
 
                 val resourceSource = resourceDefinition.sources[dictionarySource]
                         ?: throw BluePrintProcessorException("couldn't get resource definition $dictionaryName source($dictionarySource)")
 
-                processorName = ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR
-                        .plus(resourceSource.type)
+                ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR.plus(resourceSource.type)
             }
         }
-        checkNotEmptyOrThrow(processorName,
-                "couldn't get processor name for resource dictionary definition($dictionaryName) source" +
-                        "($dictionarySource)")
+        checkNotEmpty(processorName) {
+            "couldn't get processor name for resource dictionary definition($dictionaryName) source($dictionarySource)"
+        }
 
         return processorName