Refactoring to enable on_failure for imperative workflow 36/119636/2
authorJozsef Csongvai <jozsef.csongvai@bell.ca>
Thu, 10 Dec 2020 00:49:48 +0000 (19:49 -0500)
committerKAPIL SINGAL <ks220y@att.com>
Wed, 24 Mar 2021 01:58:57 +0000 (01:58 +0000)
BlueprintError needs to associate errors with the steps in which they occurred
in order for imperative workflow to handle on_failure properly.

Made stepName more accessible and corrected places where stepName was assigned to nodeTemplateName.

Issue-ID: CCSDK-3219
Change-Id: I7e5805745c63558cff6be533e1b99c32ad06c3db
Signed-off-by: Jozsef Csongvai <jozsef.csongvai@bell.ca>
(cherry picked from commit b96b44d6d7ca11dbbc3ad4bd2194df31fba5efb6)

49 files changed:
components/model-catalog/blueprint-model/service-blueprint/5GC_Simulator_CNF_CDS/Scripts/kotlin/KotlinDayOneConfig.kt
components/model-catalog/blueprint-model/service-blueprint/5GC_Simulator_CNF_CDS/Scripts/kotlin/KotlinK8sProfileUpload.kt
components/model-catalog/blueprint-model/service-blueprint/vLB/Scripts/kotlin/ConfigDeploy.kt
components/model-catalog/blueprint-model/service-blueprint/vLB/Scripts/kotlin/HealthCheck.kt
components/model-catalog/blueprint-model/service-blueprint/vLB_CDS_RESTCONF/Scripts/kotlin/KotlinRestCall.kt
ms/blueprintsprocessor/functions/ansible-awx-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/ansible/executor/ComponentRemoteAnsibleExecutorTest.kt
ms/blueprintsprocessor/functions/config-snapshots/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/config/snapshots/ComponentConfigSnapshotsExecutorTest.kt
ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/profile/K8sProfileUploadComponent.kt
ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/template/K8sConfigTemplateComponent.kt
ms/blueprintsprocessor/functions/k8s-connection-plugin/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/k8s/definition/template/K8sConfigValueComponent.kt
ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ComponentNetconfExecutor.kt
ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentJythonExecutor.kt
ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponent.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/capabilities/IpAssignResolutionCapability.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/capabilities/NamingResolutionCapability.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/CapabilityResourceResolutionProcessor.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DefaultResourceResolutionProcessor.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/InputResourceResolutionProcessor.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/ResourceAssignmentProcessor.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt
ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentTest.kt
ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionServiceTest.kt
ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/mock/MockRestResourceResolutionProcessor.kt
ms/blueprintsprocessor/functions/restful-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restful/executor/ComponentRestfulExecutor.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BlueprintError.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BlueprintContext.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BlueprintErrorTest.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-validation/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/validation/BlueprintDesignTimeValidatorService.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-validation/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/validation/BlueprintServiceTemplateValidatorImpl.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-validation/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/validation/BlueprintWorkflowValidatorImpl.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-validation/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/validation/BlueprintDesignTimeValidatorServiceTest.kt
ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/enhancer/BlueprintEnhancerServiceImpl.kt
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandler.kt
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/KafkaPublishAuditService.kt
ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt
ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentRemoteScriptExecutor.kt
ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentScriptExecutor.kt
ms/blueprintsprocessor/modules/services/execution-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/scripts/AbstractComponentFunctionTest.kt
ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/BlueprintWorkflowExecutionServiceImpl.kt
ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/ComponentWorkflowExecutionService.kt
ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/DGWorkflowExecutionService.kt
ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/ImperativeWorkflowExecutionService.kt
ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/NodeTemplateExecutionService.kt
ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/executor/ComponentExecuteNodeExecutor.kt
ms/blueprintsprocessor/modules/services/workflow-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/BlueprintWorkflowExecutionServiceImplTest.kt
ms/blueprintsprocessor/modules/services/workflow-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/NodeTemplateExecutionServiceTest.kt

index 38d843a..1080418 100644 (file)
@@ -221,7 +221,7 @@ open class DayOneConfig : AbstractScriptComponentFunction() {
     }
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
         log.info("Executing Recovery")
-        bluePrintRuntimeService.getBlueprintError().addError("${runtimeException.message}")
+        addError("${runtimeException.message}")
     }
 
     fun modifyTemplate(configmapName: String, typOfVfmodule: String): String {
index 2673b3c..e69bdbe 100644 (file)
@@ -275,7 +275,7 @@ open class K8sProfileUpload : AbstractScriptComponentFunction() {
 
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
         log.info("Executing Recovery")
-        bluePrintRuntimeService.getBlueprintError().addError("${runtimeException.message}")
+        addError("${runtimeException.message}")
     }
 
     inner class K8sApi(
index e53b73e..bcbb471 100644 (file)
@@ -87,7 +87,7 @@ open class ConfigDeploy : AbstractScriptComponentFunction() {
 \r
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {\r
         log.info("Executing Recovery")\r
-        bluePrintRuntimeService.getBlueprintError().addError("${runtimeException.message}")\r
+        addError("${runtimeException.message}")\r
     }\r
 }\r
 \r
index 606e76e..c34decc 100644 (file)
@@ -89,7 +89,7 @@ open class HealthCheck : AbstractScriptComponentFunction() {
 \r
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {\r
         log.info("Executing Recovery")\r
-        bluePrintRuntimeService.getBlueprintError().addError("${runtimeException.message}")\r
+        addError("${runtimeException.message}")\r
     }\r
 }\r
 \r
index 07168ce..c7f4c93 100644 (file)
@@ -87,7 +87,7 @@ open class ConfigDeploy : AbstractScriptComponentFunction() {
 \r
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {\r
         log.info("Executing Recovery")\r
-        bluePrintRuntimeService.getBlueprintError().addError("${runtimeException.message}")\r
+        addError("${runtimeException.message}")\r
     }\r
 }\r
 \r
index 27ce7a2..88cf099 100644 (file)
@@ -112,7 +112,7 @@ class ComponentRemoteAnsibleExecutorTest {
         }
 
         // then
-        assertTrue(bluePrintRuntimeService.getBlueprintError().errors.isEmpty())
+        assertTrue(bluePrintRuntimeService.getBlueprintError().allErrors().isEmpty())
     }
 
     @Test
@@ -146,7 +146,7 @@ class ComponentRemoteAnsibleExecutorTest {
         }
 
         // then
-        val errors = bluePrintRuntimeService.getBlueprintError().errors
+        val errors = bluePrintRuntimeService.getBlueprintError().allErrors()
         assertEquals(1, errors.size)
     }
 
@@ -187,7 +187,7 @@ class ComponentRemoteAnsibleExecutorTest {
         }
 
         // then
-        val errors = bluePrintRuntimeService.getBlueprintError().errors
+        val errors = bluePrintRuntimeService.getBlueprintError().allErrors()
         assertEquals(1, errors.size)
     }
 
index acdbe07..99de664 100644 (file)
@@ -247,7 +247,7 @@ class ComponentConfigSnapshotsExecutorTest {
             }
 
             // then; we should get error in our output properties
-            assertTrue(bluePrintRuntimeService.getBlueprintError().errors.size == 1)
+            assertTrue(bluePrintRuntimeService.getBlueprintError().allErrors().size == 1)
             assertEquals(
                 ComponentConfigSnapshotsExecutor.OUTPUT_STATUS_ERROR.asJsonPrimitive(),
                 bluePrintRuntimeService.getNodeTemplateAttributeValue(
@@ -328,7 +328,7 @@ class ComponentConfigSnapshotsExecutorTest {
             }
 
             // then; we should get success
-            assertTrue(bluePrintRuntimeService.getBlueprintError().errors.size == 0)
+            assertTrue(bluePrintRuntimeService.getBlueprintError().allErrors().size == 0)
             assertEquals(
                 ComponentConfigSnapshotsExecutor.OUTPUT_STATUS_SUCCESS.asJsonPrimitive(),
                 bluePrintRuntimeService.getNodeTemplateAttributeValue(
@@ -377,7 +377,7 @@ class ComponentConfigSnapshotsExecutorTest {
             }
 
             // then; we should get success
-            assertTrue(bluePrintRuntimeService.getBlueprintError().errors.size == 0)
+            assertTrue(bluePrintRuntimeService.getBlueprintError().allErrors().size == 0)
             assertEquals(
                 ComponentConfigSnapshotsExecutor.OUTPUT_STATUS_SUCCESS.asJsonPrimitive(),
                 bluePrintRuntimeService.getNodeTemplateAttributeValue(
index db549f3..201895c 100644 (file)
@@ -174,7 +174,7 @@ open class K8sProfileUploadComponent(
     }
 
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
-        bluePrintRuntimeService.getBlueprintError().addError(runtimeException.message!!)
+        addError(runtimeException.message!!)
     }
 
     private fun getTemplatePrefixList(node: JsonNode?): ArrayList<String> {
index 0944c23..87a4d4e 100644 (file)
@@ -165,7 +165,7 @@ open class K8sConfigTemplateComponent(
     }
 
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
-        bluePrintRuntimeService.getBlueprintError().addError(runtimeException.message!!)
+        addError(runtimeException.message!!)
     }
 
     private fun getTemplatePrefixList(node: JsonNode?): ArrayList<String> {
index de6eb6b..aa13fa0 100644 (file)
@@ -69,7 +69,6 @@ open class ComponentNetconfExecutor(private var componentFunctionScriptingServic
     }
 
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
-        bluePrintRuntimeService.getBlueprintError()
-            .addError("Failed in ComponentNetconfExecutor : ${runtimeException.message}")
+        addError("Failed in ComponentNetconfExecutor : ${runtimeException.message}")
     }
 }
index 7911559..b32ccea 100644 (file)
@@ -56,8 +56,7 @@ open class ComponentJythonExecutor(
     }
 
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
-        bluePrintRuntimeService.getBlueprintError()
-            .addError("Failed in ComponentJythonExecutor : ${runtimeException.message}")
+        addError("Failed in ComponentJythonExecutor : ${runtimeException.message}")
     }
 
     private suspend fun populateJythonComponentInstance() {
index 22154e5..539e03d 100644 (file)
@@ -313,11 +313,11 @@ open class ComponentRemotePythonExecutor(
         }
     }
 
-    private fun noBlueprintErrors() = bluePrintRuntimeService.getBlueprintError().errors.isEmpty()
+    private fun noBlueprintErrors() =
+        bluePrintRuntimeService.getBlueprintError().stepErrors(stepName).isNullOrEmpty()
 
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
-        bluePrintRuntimeService.getBlueprintError()
-            .addError("Failed in ComponentRemotePythonExecutor : ${runtimeException.message}")
+        addError("Failed in ComponentRemotePythonExecutor : ${runtimeException.message}")
     }
 
     private fun formatNestedJsonNode(node: JsonNode): String {
index 6a2e128..ada1a72 100644 (file)
@@ -115,7 +115,8 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re
                 bluePrintRuntimeService,
                 nodeTemplateName,
                 artifactPrefixNames,
-                properties
+                properties,
+                stepName
             )
 
             // provide indexed result in output if we have multiple resolution
@@ -140,6 +141,6 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re
     }
 
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
-        bluePrintRuntimeService.getBlueprintError().addError(runtimeException.message!!)
+        addError(runtimeException.message!!)
     }
 }
index 46410a8..ea420dc 100644 (file)
@@ -65,7 +65,8 @@ interface ResourceResolutionService {
         bluePrintRuntimeService: BlueprintRuntimeService<*>,
         nodeTemplateName: String,
         artifactNames: List<String>,
-        properties: Map<String, Any>
+        properties: Map<String, Any>,
+        stepName: String
     ): ResourceResolutionResult
 
     suspend fun resolveResources(
@@ -128,7 +129,8 @@ open class ResourceResolutionServiceImpl(
         bluePrintRuntimeService: BlueprintRuntimeService<*>,
         nodeTemplateName: String,
         artifactNames: List<String>,
-        properties: Map<String, Any>
+        properties: Map<String, Any>,
+        stepName: String
     ): ResourceResolutionResult {
 
         val resourceAssignmentRuntimeService =
@@ -150,11 +152,10 @@ open class ResourceResolutionServiceImpl(
 
             val failedResolution = resourceAssignmentList.filter { it.status != "success" && it.property?.required == true }.map { it.name }
             if (failedResolution.isNotEmpty()) {
-                // The following error message is returned by default to handle a scenario when
-                // error message comes empty even when resolution has actually failed.
-                // Example: input-source type resolution seems to fail with no error code.
-                bluePrintRuntimeService.getBlueprintError().errors.add("Failed to resolve required resources($failedResolution)")
-                bluePrintRuntimeService.getBlueprintError().errors.addAll(resourceAssignmentRuntimeService.getBlueprintError().errors)
+                val errorMessages = mutableListOf("Failed to resolve required values: $failedResolution").apply {
+                    this.addAll(resourceAssignmentRuntimeService.getBlueprintError().allErrors())
+                }
+                bluePrintRuntimeService.getBlueprintError().addErrors(stepName, errorMessages)
             }
         }
         return ResourceResolutionResult(templateMap, assignmentMap)
index d9a5ba0..a1f3249 100644 (file)
@@ -116,7 +116,7 @@ open class IpAssignResolutionCapability : ResourceAssignmentProcessor() {
     }
 
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ResourceAssignment) {
-        raRuntimeService.getBlueprintError().addError(runtimeException.message!!)
+        addError(runtimeException.message!!)
     }
 
     /** Generates aggregated request payload for Ip Assign mS. Parses the resourceassignments of
index 903c1b3..4f656a8 100644 (file)
@@ -118,7 +118,7 @@ open class NamingResolutionCapability : ResourceAssignmentProcessor() {
     }
 
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ResourceAssignment) {
-        raRuntimeService.getBlueprintError().addError(runtimeException.message!!)
+        addError(runtimeException.message!!)
     }
 
     /** Generates aggregated request payload for Naming mS. Parses the resourceassignments of
index 4f33c82..5e834d7 100644 (file)
@@ -87,8 +87,7 @@ open class CapabilityResourceResolutionProcessor(private var componentFunctionSc
     }
 
     override suspend fun recoverNB(runtimeException: RuntimeException, resourceAssignment: ResourceAssignment) {
-        raRuntimeService.getBlueprintError()
-            .addError("Failed in CapabilityResourceResolutionProcessor : ${runtimeException.message}")
+        addError("Failed in CapabilityResourceResolutionProcessor : ${runtimeException.message}")
         ResourceAssignmentUtils.setFailedResourceDataValue(resourceAssignment, runtimeException.message)
     }
 
index b5bafad..ce00ac1 100644 (file)
@@ -191,11 +191,11 @@ abstract class ResourceAssignmentProcessor : BlueprintFunctionNode<ResourceAssig
     }
 
     fun addError(type: String, name: String, error: String) {
-        raRuntimeService.getBlueprintError().addError(type, name, error)
+        raRuntimeService.getBlueprintError().addError(type, name, error, getName())
     }
 
     fun addError(error: String) {
-        raRuntimeService.getBlueprintError().addError(error)
+        raRuntimeService.getBlueprintError().addError(error, getName())
     }
 
     fun isTemplateKeyValueNull(resourceAssignment: ResourceAssignment): Boolean {
index 80ba831..74a88b4 100644 (file)
@@ -145,7 +145,8 @@ class ResourceResolutionComponentTest {
                 any(),
                 any(),
                 any<List<String>>(),
-                any<MutableMap<String, Any>>()
+                any<MutableMap<String, Any>>(),
+                "step"
             )
         } returns ResourceResolutionResult(mutableMapOf(), mutableMapOf())
 
@@ -168,7 +169,7 @@ class ResourceResolutionComponentTest {
             every { bluePrintRuntimeService.getBlueprintError() } returns blueprintError
             resourceResolutionComponent.recoverNB(exception, executionRequest)
 
-            assertEquals(1, blueprintError.errors.size)
+            assertEquals(1, blueprintError.allErrors().size)
         }
     }
 }
index 00fb395..a1de557 100644 (file)
@@ -182,7 +182,8 @@ class ResourceResolutionServiceTest {
                 bluePrintRuntimeService,
                 "resource-assignment",
                 artifactNames,
-                props
+                props,
+                "mockStep"
             )
         }.let {
             assertEquals(artifactNames.toSet(), it.templateMap.keys)
index de46fe6..77c90ba 100644 (file)
@@ -110,7 +110,7 @@ class MockRestResourceResolutionProcessor(
     }
 
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ResourceAssignment) {
-        raRuntimeService.getBlueprintError().addError(runtimeException.message!!)
+        addError(runtimeException.message!!)
     }
 
     private fun blueprintWebClientService(resourceAssignment: ResourceAssignment): MockBlueprintWebClientService {
index 59c010e..cb44364 100644 (file)
@@ -66,7 +66,6 @@ open class ComponentRestfulExecutor(private var componentFunctionScriptingServic
     }
 
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
-        bluePrintRuntimeService.getBlueprintError()
-            .addError("Failed in ComponentRestfulExecutor : ${runtimeException.message}")
+        addError("Failed in ComponentRestfulExecutor : ${runtimeException.message}")
     }
 }
index b4d95ca..2ecdce7 100644 (file)
@@ -18,13 +18,21 @@ package org.onap.ccsdk.cds.controllerblueprints.core
 
 class BlueprintError {
 
-    var errors: MutableList<String> = arrayListOf()
+    private val errors: MutableMap<String, MutableList<String>> = mutableMapOf()
 
-    fun addError(type: String, name: String, error: String) {
-        this.errors.add("$type : $name : $error")
+    fun addError(type: String, name: String, error: String, stepName: String) {
+        addError("$type : $name : $error", stepName)
     }
 
-    fun addError(error: String) {
-        this.errors.add(error)
+    fun addError(error: String, stepName: String) {
+        errors.getOrPut(stepName, { mutableListOf() }).add(error)
     }
+
+    fun addErrors(stepName: String, errorList: List<String>) {
+        errors.getOrPut(stepName, { mutableListOf() }).addAll(errorList)
+    }
+
+    fun allErrors(): List<String> = errors.values.flatten()
+
+    fun stepErrors(stepName: String): MutableList<String>? = errors[stepName]
 }
index b79b867..62026be 100644 (file)
@@ -103,8 +103,11 @@ class BlueprintContext(val serviceTemplate: ServiceTemplate) {
 
     fun workflowInputs(workFlowName: String) = workflowByName(workFlowName).inputs
 
+    fun workflowSteps(workFlowName: String) =
+        workflowByName(workFlowName).steps ?: throw BlueprintException("could't get steps for workflow($workFlowName)")
+
     fun workflowStepByName(workFlowName: String, stepName: String): Step {
-        return workflowByName(workFlowName).steps?.get(stepName)
+        return workflowSteps(workFlowName)[stepName]
             ?: throw BlueprintException("could't get step($stepName) for workflow($workFlowName)")
     }
 
@@ -114,8 +117,9 @@ class BlueprintContext(val serviceTemplate: ServiceTemplate) {
     }
 
     fun workflowFirstStepNodeTemplate(workFlowName: String): String {
-        val firstStepName = workflowByName(workFlowName).steps?.keys?.first()
-            ?: throw BlueprintException("could't get first step for workflow($workFlowName)")
+        val firstStepName = workflowSteps(workFlowName).keys.ifEmpty {
+            throw BlueprintException("could't get first step for workflow($workFlowName)")
+        }.first()
         return workflowStepNodeTemplate(workFlowName, firstStepName)
     }
 
index 482d21a..94ba986 100644 (file)
@@ -10,24 +10,24 @@ class BlueprintErrorTest {
     fun testBlueprintErrorIsCreatedWithemptyList() {
         val bluePrintError = BlueprintError()
 
-        assertTrue(bluePrintError.errors.isEmpty())
+        assertTrue(bluePrintError.allErrors().isEmpty())
     }
 
     @Test
     fun testAddErrorWith3Params() {
         val bluePrintError = BlueprintError()
 
-        bluePrintError.addError("type", "name", "error")
+        bluePrintError.addError("type", "name", "error", "step")
 
-        assertEquals("type : name : error", bluePrintError.errors[0])
+        assertEquals("type : name : error", bluePrintError.stepErrors("step")!![0])
     }
 
     @Test
-    fun testAddErrorWith1Params() {
+    fun testAddErrorWith2Params() {
         val bluePrintError = BlueprintError()
 
-        bluePrintError.addError("error")
+        bluePrintError.addError("error", "step")
 
-        assertEquals("error", bluePrintError.errors[0])
+        assertEquals("error", bluePrintError.stepErrors("step")!![0])
     }
 }
index fe3aeb1..aac1c2e 100644 (file)
@@ -17,6 +17,7 @@
 
 package org.onap.ccsdk.cds.controllerblueprints.validation
 
+import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
 import org.onap.ccsdk.cds.controllerblueprints.core.BlueprintConstants
 import org.onap.ccsdk.cds.controllerblueprints.core.BlueprintException
 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BlueprintTypeValidatorService
@@ -57,9 +58,10 @@ open class BlueprintDesignTimeValidatorService(
         // Validate Resource Definitions
         validateResourceDefinitions(bluePrintRuntimeService)
 
-        if (bluePrintRuntimeService.getBlueprintError().errors.size > 0) {
-            throw BlueprintException("failed in blueprint validation : ${bluePrintRuntimeService.getBlueprintError().errors.joinToString("\n")}")
+        bluePrintRuntimeService.getBlueprintError().allErrors().ifNotEmpty {
+            throw BlueprintException("failed in blueprint validation : ${this.joinToString("\n")}")
         }
+
         return true
     }
 
index b9450e6..137e6e6 100644 (file)
@@ -58,7 +58,7 @@ open class BlueprintServiceTemplateValidatorImpl(private val bluePrintTypeValida
             serviceTemplate.topologyTemplate?.let { validateTopologyTemplate(serviceTemplate.topologyTemplate!!) }
         } catch (e: Exception) {
             log.error("failed in blueprint service template validation", e)
-            error.addError(BlueprintConstants.PATH_SERVICE_TEMPLATE, paths.joinToString(BlueprintConstants.PATH_DIVIDER), e.message!!)
+            error.addError(BlueprintConstants.PATH_SERVICE_TEMPLATE, paths.joinToString(BlueprintConstants.PATH_DIVIDER), e.message!!, "BlueprintServiceTemplateValidator")
         }
     }
 
index 8f9cb01..bff09fc 100644 (file)
@@ -76,7 +76,8 @@ open class BlueprintWorkflowValidatorImpl(private val bluePrintTypeValidatorServ
                         .addError(
                             "Failed to validate Workflow($workflowName)'s step($stepName)'s " +
                                 "definition",
-                            paths.joinToString(BlueprintConstants.PATH_DIVIDER), e.message!!
+                            paths.joinToString(BlueprintConstants.PATH_DIVIDER), e.message!!,
+                            "BlueprintWorkflowValidatorImpl"
                         )
                 }
             }
index 49c12b9..dd82ec5 100644 (file)
@@ -63,10 +63,10 @@ class BlueprintDesignTimeValidatorServiceTest {
         workflow.steps = mutableMapOf("test" to step)
         workflowValidator.validate(bluePrintRuntime, workflowName, workflow)
 
-        assertEquals(1, bluePrintRuntime.getBlueprintError().errors.size)
+        assertEquals(1, bluePrintRuntime.getBlueprintError().allErrors().size)
         assertEquals(
             "Failed to validate Workflow(resource-assignment)'s step(test)'s definition : resource-assignment/steps/test : could't get node template for the name(TestCaseFailNoNodeTemplate)",
-            bluePrintRuntime.getBlueprintError().errors[0]
+            bluePrintRuntime.getBlueprintError().allErrors()[0]
         )
     }
 
@@ -96,12 +96,12 @@ class BlueprintDesignTimeValidatorServiceTest {
         workflow.steps = mutableMapOf("test" to step)
         workflowValidator.validate(bluePrintRuntime, workflowName, workflow)
 
-        assertEquals(1, bluePrintRuntime.getBlueprintError().errors.size)
+        assertEquals(1, bluePrintRuntime.getBlueprintError().allErrors().size)
         assertEquals(
             "Failed to validate Workflow(resource-assignment)'s step(test)'s definition : " +
                 "resource-assignment/steps/test : NodeType(TestNodeType) derived from is 'tosca.nodes.TEST', " +
                 "Expected 'tosca.nodes.Workflow' or 'tosca.nodes.Component'",
-            bluePrintRuntime.getBlueprintError().errors[0]
+            bluePrintRuntime.getBlueprintError().allErrors()[0]
         )
     }
 
index aa8b77a..7603963 100644 (file)
@@ -78,8 +78,8 @@ open class BlueprintEnhancerServiceImpl(
             // Write the Enhanced Blueprint Resource Definitions
             ResourceDictionaryUtils.writeResourceDefinitionTypes(basePath, resourceDefinitions)
 
-            if (blueprintRuntimeService.getBlueprintError().errors.isNotEmpty()) {
-                throw BlueprintException(blueprintRuntimeService.getBlueprintError().errors.toString())
+            if (blueprintRuntimeService.getBlueprintError().allErrors().isNotEmpty()) {
+                throw BlueprintException(blueprintRuntimeService.getBlueprintError().allErrors().toString())
             }
         } catch (e: BlueprintProcessorException) {
             val errorMsg = "Error while enriching the CBA package."
index 3d8cc04..8c958c4 100644 (file)
@@ -42,7 +42,6 @@ import org.onap.ccsdk.cds.controllerblueprints.core.service.BlueprintDependencyS
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BlueprintMetadataUtils
 import org.slf4j.LoggerFactory
 import org.springframework.stereotype.Service
-import java.util.stream.Collectors
 
 @Service
 class ExecutionServiceHandler(
@@ -119,10 +118,9 @@ class ExecutionServiceHandler(
                     executionServiceInput, hashMapOf()
                 )
 
-                val errors = blueprintRuntimeService.getBlueprintError().errors
+                val errors = blueprintRuntimeService.getBlueprintError().allErrors()
                 if (errors.isNotEmpty()) {
-                    val errorMessage = errors.stream().map { it.toString() }.collect(Collectors.joining(", "))
-                    setErrorStatus(errorMessage, executionServiceOutput.status)
+                    setErrorStatus(errors.joinToString(", "), executionServiceOutput.status)
                 }
             }
         } catch (e: Exception) {
index 8be43cc..46befee 100644 (file)
@@ -169,9 +169,7 @@ class KafkaPublishAuditService(
                 val blueprintRuntimeService = BlueprintMetadataUtils.getBlueprintRuntime(requestId, basePath.toString())
                 val blueprintContext = blueprintRuntimeService.bluePrintContext()
 
-                val workflowSteps = blueprintContext.workflowByName(workflowName).steps
-                checkNotNull(workflowSteps) { "Failed to get step(s) for workflow($workflowName)" }
-                workflowSteps.forEach { step ->
+                blueprintContext.workflowSteps(workflowName).forEach { step ->
                     val nodeTemplateName = step.value.target
                     checkNotNull(nodeTemplateName) { "Failed to get node template target for workflow($workflowName), step($step)" }
                     val nodeTemplate = blueprintContext.nodeTemplateByName(nodeTemplateName)
index c1a8985..f85b642 100644 (file)
@@ -65,7 +65,7 @@ abstract class AbstractComponentFunction : BlueprintFunctionNode<ExecutionServic
     var operationInputs: MutableMap<String, JsonNode> = hashMapOf()
 
     override fun getName(): String {
-        return stepName
+        return "$stepName - $nodeTemplateName"
     }
 
     override suspend fun prepareRequestNB(executionRequest: ExecutionServiceInput): ExecutionServiceInput {
@@ -143,8 +143,12 @@ abstract class AbstractComponentFunction : BlueprintFunctionNode<ExecutionServic
                 properties = stepOutputs
             }
             executionServiceOutput.stepData = stepOutputData
-            // Set the Default Step Status
+
             status.eventType = EventType.EVENT_COMPONENT_EXECUTED.name
+
+            bluePrintRuntimeService.getBlueprintError().stepErrors(stepName)?.let {
+                status.message = BlueprintConstants.STATUS_FAILURE
+            }
         } catch (e: Exception) {
             status.message = BlueprintConstants.STATUS_FAILURE
             status.eventType = EventType.EVENT_COMPONENT_FAILURE.name
@@ -192,11 +196,11 @@ abstract class AbstractComponentFunction : BlueprintFunctionNode<ExecutionServic
     }
 
     fun addError(type: String, name: String, error: String) {
-        bluePrintRuntimeService.getBlueprintError().addError(type, name, error)
+        bluePrintRuntimeService.getBlueprintError().addError(type, name, error, stepName)
     }
 
     fun addError(error: String) {
-        bluePrintRuntimeService.getBlueprintError().addError(error)
+        bluePrintRuntimeService.getBlueprintError().addError(error, stepName)
     }
 
     /**
index 815b190..5a552e3 100644 (file)
@@ -101,7 +101,6 @@ open class ComponentRemoteScriptExecutor(
     }
 
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
-        bluePrintRuntimeService.getBlueprintError()
-            .addError("Failed in ComponentRemoteScriptExecutor : ${runtimeException.message}")
+        addError("Failed in ComponentRemoteScriptExecutor : ${runtimeException.message}")
     }
 }
index 213d21e..d2c81a6 100644 (file)
@@ -67,8 +67,7 @@ open class ComponentScriptExecutor(private var componentFunctionScriptingService
     }
 
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
-        bluePrintRuntimeService.getBlueprintError()
-            .addError("Failed in ComponentScriptExecutor : ${runtimeException.message}")
+        addError("Failed in ComponentScriptExecutor : ${runtimeException.message}")
     }
 
     open fun populateScriptDependencies(scriptDependencies: MutableList<String>) {
index 8440e5f..3438821 100644 (file)
@@ -41,6 +41,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractCompone
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentFunctionScriptingService
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.nodeTypeComponentScriptExecutor
 import org.onap.ccsdk.cds.controllerblueprints.core.BlueprintConstants
+import org.onap.ccsdk.cds.controllerblueprints.core.BlueprintError
 import org.onap.ccsdk.cds.controllerblueprints.core.BlueprintTypes
 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
@@ -90,6 +91,8 @@ class AbstractComponentFunctionTest {
                 any(), any(), any()
             )
         } returns Implementation()
+
+        every { bluePrintRuntimeService.getBlueprintError() } returns BlueprintError()
     }
 
     @Test
index d690235..5a175b0 100644 (file)
@@ -97,7 +97,7 @@ open class BlueprintWorkflowExecutionServiceImpl(
             workflowOutputs = bluePrintRuntimeService.resolveWorkflowOutputs(workflowName)
         } catch (e: RuntimeException) {
             log.error("Failed to resolve outputs for workflow: $workflowName", e)
-            e.message?.let { bluePrintRuntimeService.getBlueprintError().errors.add(it) }
+            e.message?.let { bluePrintRuntimeService.getBlueprintError().addError(it, "workflow") }
         }
 
         // Set the Response Payload
index 330d297..3221808 100644 (file)
@@ -38,10 +38,10 @@ open class ComponentWorkflowExecutionService(private val nodeTemplateExecutionSe
 
         // Get the DG Node Template
         val nodeTemplateName = bluePrintContext.workflowFirstStepNodeTemplate(workflowName)
+        val stepName = bluePrintContext.workflowSteps(workflowName).keys.first()
 
         return nodeTemplateExecutionService.executeNodeTemplate(
-            bluePrintRuntimeService,
-            nodeTemplateName, executionServiceInput
+            bluePrintRuntimeService, stepName, nodeTemplateName, executionServiceInput
         )
     }
 }
index c8d72a1..efcae4a 100644 (file)
@@ -19,6 +19,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.services.workflow
 
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceOutput
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StepData
 import org.onap.ccsdk.cds.blueprintsprocessor.services.workflow.utils.SvcGraphUtils
 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BlueprintWorkflowExecutionService
 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName
@@ -45,6 +46,11 @@ open class DGWorkflowExecutionService(private val blueprintSvcLogicService: Blue
         // Get the DG Node Template
         val nodeTemplateName = bluePrintContext.workflowFirstStepNodeTemplate(workflowName)
 
+        val stepName = bluePrintContext.workflowSteps(workflowName).keys.first()
+        executionServiceInput.stepData = StepData().apply {
+            name = stepName
+        }
+
         log.info("Executing workflow($workflowName) directed graph NodeTemplate($nodeTemplateName)")
 
         // Get the DG file info
index 561136a..29019b7 100644 (file)
@@ -114,7 +114,7 @@ open class ImperativeBlueprintWorkflowService(private val nodeTemplateExecutionS
             if (exceptions.isNotEmpty()) {
                 exceptions.forEach {
                     val errorMessage = it.message ?: ""
-                    bluePrintRuntimeService.getBlueprintError().addError(errorMessage)
+                    bluePrintRuntimeService.getBlueprintError().addError(errorMessage, "workflow")
                     log.error("workflow($workflowId) exception :", it)
                 }
                 message = BlueprintConstants.STATUS_FAILURE
@@ -160,12 +160,15 @@ open class ImperativeBlueprintWorkflowService(private val nodeTemplateExecutionS
 
         /** execute node template */
         val executionServiceOutput = nodeTemplateExecutionService
-            .executeNodeTemplate(bluePrintRuntimeService, nodeTemplateName, nodeInput)
+            .executeNodeTemplate(bluePrintRuntimeService, node.id, nodeTemplateName, nodeInput)
 
-        return when (executionServiceOutput.status.message) {
-            BlueprintConstants.STATUS_FAILURE -> EdgeLabel.FAILURE
-            else -> EdgeLabel.SUCCESS
+        if (executionServiceOutput.status.message == BlueprintConstants.STATUS_FAILURE) {
+            // Clear step errors so that the workflow does not fail
+            bluePrintRuntimeService.getBlueprintError().stepErrors(node.id)?.clear()
+            return EdgeLabel.FAILURE
         }
+
+        return EdgeLabel.SUCCESS
     }
 
     override suspend fun skipNode(
index 1d179a1..ff8f5b8 100644 (file)
@@ -37,6 +37,7 @@ open class NodeTemplateExecutionService(private val bluePrintClusterService: Blu
 
     suspend fun executeNodeTemplate(
         bluePrintRuntimeService: BlueprintRuntimeService<*>,
+        stepName: String,
         nodeTemplateName: String,
         executionServiceInput: ExecutionServiceInput
     ): ExecutionServiceOutput {
@@ -66,7 +67,8 @@ open class NodeTemplateExecutionService(private val bluePrintClusterService: Blu
         // Set the Blueprint Services
         plugin.bluePrintRuntimeService = bluePrintRuntimeService
         plugin.bluePrintClusterService = bluePrintClusterService
-        plugin.stepName = nodeTemplateName
+        plugin.stepName = stepName
+        plugin.nodeTemplateName = nodeTemplateName
 
         // Parent request shouldn't tamper, so need to clone the request and send to the actual component.
         val clonedExecutionServiceInput = ExecutionServiceInput().apply {
@@ -81,7 +83,7 @@ open class NodeTemplateExecutionService(private val bluePrintClusterService: Blu
         stepInputs[BlueprintConstants.PROPERTY_CURRENT_INTERFACE] = interfaceName.asJsonPrimitive()
         stepInputs[BlueprintConstants.PROPERTY_CURRENT_OPERATION] = operationName.asJsonPrimitive()
         val stepInputData = StepData().apply {
-            name = nodeTemplateName
+            name = stepName
             properties = stepInputs
         }
         clonedExecutionServiceInput.stepData = stepInputData
index cf5955e..2e3f78a 100644 (file)
@@ -48,10 +48,11 @@ open class ComponentExecuteNodeExecutor(private val nodeTemplateExecutionService
 
             val executionInput = ctx.getRequest() as ExecutionServiceInput
 
+            val stepName = executionInput.stepData?.name ?: nodeTemplateName
+
             try { // Get the Request from the Context and Set to the Function Input and Invoke the function
                 val executionOutput = nodeTemplateExecutionService.executeNodeTemplate(
-                    ctx.getBlueprintService(),
-                    nodeTemplateName, executionInput
+                    ctx.getBlueprintService(), stepName, nodeTemplateName, executionInput
                 )
 
                 ctx.setResponse(executionOutput)
index 0bd1c33..b7087b3 100644 (file)
@@ -178,7 +178,7 @@ class BlueprintWorkflowExecutionServiceImplTest {
             val output = bluePrintWorkflowExecutionServiceImpl.executeBlueprintWorkflow(
                 bluePrintRuntimeService, executionServiceInput, mutableMapOf()
             )
-            assertEquals("failed to resolve property...", blueprintError.errors[0])
+            assertEquals("failed to resolve property...", blueprintError.allErrors()[0])
             assertEquals("""{"config-assign-response":{}}""".asJsonType(), output.payload)
         }
     }
index 70b52d0..b113987 100644 (file)
@@ -72,10 +72,12 @@ class NodeTemplateExecutionServiceTest {
             val input = executionServiceInput.payload.get("resource-assignment-request")
             bluePrintRuntimeService.assignWorkflowInputs("resource-assignment", input)
 
+            val stepName = bluePrintRuntimeService.bluePrintContext()
+                .workflowSteps("resource-assignment").keys.first()
             val nodeTemplate = "resource-assignment"
             val nodeTemplateExecutionService = NodeTemplateExecutionService(bluePrintClusterService)
             val executionServiceOutput = nodeTemplateExecutionService
-                .executeNodeTemplate(bluePrintRuntimeService, nodeTemplate, executionServiceInput)
+                .executeNodeTemplate(bluePrintRuntimeService, stepName, nodeTemplate, executionServiceInput)
 
             assertNotNull(executionServiceOutput, "failed to get response")
             assertEquals(