Add Imperative workflow execution service. 88/93588/4
authorBrinda Santh <brindasanth@in.ibm.com>
Wed, 14 Aug 2019 23:10:04 +0000 (19:10 -0400)
committerBrinda Santh Muthuramalingam <brindasanth@in.ibm.com>
Fri, 16 Aug 2019 14:28:50 +0000 (14:28 +0000)
Workflow implementation based on multiple steps in blueprint model.

Change-Id: I21eaf5d08621ae6eac2fa0a5db2aca0291928d52
Issue-ID: CCSDK-1619
Signed-off-by: Brinda Santh <brindasanth@in.ibm.com>
13 files changed:
ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/ImperativeWorkflowExecutionService.kt [new file with mode: 0644]
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/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/BlueprintServiceLogicTest.kt
ms/blueprintsprocessor/modules/services/workflow-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/ImperativeWorkflowExecutionServiceTest.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/services/workflow-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/NodeTemplateExecutionServiceTest.kt
ms/blueprintsprocessor/modules/services/workflow-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/mock/MockComponentFunction.kt
ms/blueprintsprocessor/modules/services/workflow-service/src/test/resources/execution-input/imperative-test-input.json [new file with mode: 0644]
ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/GraphExtensionFunctions.kt
ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintWorkflowService.kt
ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/BluePrintMetadataUtils.kt
ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintRuntimeServiceTest.kt
ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintWorkflowServiceTest.kt

diff --git a/ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/ImperativeWorkflowExecutionService.kt b/ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/ImperativeWorkflowExecutionService.kt
new file mode 100644 (file)
index 0000000..e7e5fe6
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ *  Copyright © 2019 IBM.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.onap.ccsdk.cds.blueprintsprocessor.services.workflow
+
+import kotlinx.coroutines.CompletableDeferred
+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.controllerblueprints.core.BluePrintConstants
+import org.onap.ccsdk.cds.controllerblueprints.core.asGraph
+import org.onap.ccsdk.cds.controllerblueprints.core.data.EdgeLabel
+import org.onap.ccsdk.cds.controllerblueprints.core.data.Graph
+import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintWorkflowExecutionService
+import org.onap.ccsdk.cds.controllerblueprints.core.logger
+import org.onap.ccsdk.cds.controllerblueprints.core.service.*
+import org.springframework.beans.factory.config.ConfigurableBeanFactory
+import org.springframework.context.annotation.Scope
+import org.springframework.stereotype.Service
+
+@Service("imperativeWorkflowExecutionService")
+class ImperativeWorkflowExecutionService(
+        private val bluePrintWorkFlowService: BluePrintWorkFlowService<ExecutionServiceInput, ExecutionServiceOutput>)
+    : BluePrintWorkflowExecutionService<ExecutionServiceInput, ExecutionServiceOutput> {
+
+    override suspend fun executeBluePrintWorkflow(bluePrintRuntimeService: BluePrintRuntimeService<*>,
+                                                  executionServiceInput: ExecutionServiceInput,
+                                                  properties: MutableMap<String, Any>): ExecutionServiceOutput {
+
+        val bluePrintContext = bluePrintRuntimeService.bluePrintContext()
+
+        val workflowName = executionServiceInput.actionIdentifiers.actionName
+
+        val graph = bluePrintContext.workflowByName(workflowName).asGraph()
+
+        val deferredOutput = CompletableDeferred<ExecutionServiceOutput>()
+        bluePrintWorkFlowService.executeWorkflow(graph, bluePrintRuntimeService, executionServiceInput, deferredOutput)
+        return deferredOutput.await()
+    }
+}
+
+@Service
+@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+open class ImperativeBluePrintWorkflowService(private val nodeTemplateExecutionService: NodeTemplateExecutionService)
+    : AbstractBluePrintWorkFlowService<ExecutionServiceInput, ExecutionServiceOutput>() {
+    val log = logger(ImperativeBluePrintWorkflowService::class)
+
+    lateinit var bluePrintRuntimeService: BluePrintRuntimeService<*>
+    lateinit var executionServiceInput: ExecutionServiceInput
+    lateinit var deferredExecutionServiceOutput: CompletableDeferred<ExecutionServiceOutput>
+
+    override suspend fun executeWorkflow(graph: Graph, bluePrintRuntimeService: BluePrintRuntimeService<*>,
+                                         input: ExecutionServiceInput,
+                                         output: CompletableDeferred<ExecutionServiceOutput>) {
+        this.graph = graph
+        this.bluePrintRuntimeService = bluePrintRuntimeService
+        this.executionServiceInput = input
+        this.deferredExecutionServiceOutput = output
+        this.workflowId = bluePrintRuntimeService.id()
+        val startMessage = WorkflowExecuteMessage(input, output)
+        workflowActor.send(startMessage)
+    }
+
+    override suspend fun initializeWorkflow(input: ExecutionServiceInput): EdgeLabel {
+        return EdgeLabel.SUCCESS
+    }
+
+    override suspend fun prepareWorkflowOutput(): ExecutionServiceOutput {
+        return ExecutionServiceOutput().apply {
+            commonHeader = executionServiceInput.commonHeader
+            actionIdentifiers = executionServiceInput.actionIdentifiers
+        }
+    }
+
+    override suspend fun prepareNodeExecutionMessage(node: Graph.Node)
+            : NodeExecuteMessage<ExecutionServiceInput, ExecutionServiceOutput> {
+        val deferredOutput = CompletableDeferred<ExecutionServiceOutput>()
+        return NodeExecuteMessage(node, executionServiceInput, deferredOutput)
+    }
+
+    override suspend fun prepareNodeSkipMessage(node: Graph.Node)
+            : NodeSkipMessage<ExecutionServiceInput, ExecutionServiceOutput> {
+        val deferredOutput = CompletableDeferred<ExecutionServiceOutput>()
+        return NodeSkipMessage(node, executionServiceInput, deferredOutput)
+    }
+
+    override suspend fun executeNode(node: Graph.Node, nodeInput: ExecutionServiceInput,
+                                     deferredNodeOutput: CompletableDeferred<ExecutionServiceOutput>,
+                                     deferredNodeStatus: CompletableDeferred<EdgeLabel>) {
+        try {
+            val nodeTemplateName = node.id
+            /** execute node template */
+            val executionServiceOutput = nodeTemplateExecutionService
+                    .executeNodeTemplate(bluePrintRuntimeService, nodeTemplateName, nodeInput)
+            val edgeStatus = when (executionServiceOutput.status.message) {
+                BluePrintConstants.STATUS_FAILURE -> EdgeLabel.FAILURE
+                else -> EdgeLabel.SUCCESS
+            }
+            /** set deferred output and status */
+            deferredNodeOutput.complete(executionServiceOutput)
+            deferredNodeStatus.complete(edgeStatus)
+        } catch (e: Exception) {
+            log.error("failed in executeNode($node)", e)
+            deferredNodeOutput.completeExceptionally(e)
+            deferredNodeStatus.complete(EdgeLabel.FAILURE)
+        }
+    }
+
+    override suspend fun skipNode(node: Graph.Node, nodeInput: ExecutionServiceInput,
+                                  deferredNodeOutput: CompletableDeferred<ExecutionServiceOutput>,
+                                  deferredNodeStatus: CompletableDeferred<EdgeLabel>) {
+        val executionServiceOutput = ExecutionServiceOutput().apply {
+            commonHeader = nodeInput.commonHeader
+            actionIdentifiers = nodeInput.actionIdentifiers
+        }
+        deferredNodeOutput.complete(executionServiceOutput)
+        deferredNodeStatus.complete(EdgeLabel.SUCCESS)
+    }
+
+    override suspend fun cancelNode(node: Graph.Node, nodeInput: ExecutionServiceInput,
+                                    deferredNodeOutput: CompletableDeferred<ExecutionServiceOutput>,
+                                    deferredNodeStatus: CompletableDeferred<EdgeLabel>) {
+        TODO("not implemented")
+    }
+
+    override suspend fun restartNode(node: Graph.Node, nodeInput: ExecutionServiceInput,
+                                     deferredNodeOutput: CompletableDeferred<ExecutionServiceOutput>,
+                                     deferredNodeStatus: CompletableDeferred<EdgeLabel>) {
+        TODO("not implemented")
+    }
+}
\ No newline at end of file
index af78463..89732e3 100644 (file)
@@ -23,13 +23,13 @@ import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StepData
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
 import org.onap.ccsdk.cds.controllerblueprints.core.putJsonElement
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
 import org.slf4j.LoggerFactory
-import org.springframework.context.ApplicationContext
 import org.springframework.stereotype.Service
 
 @Service
-open class NodeTemplateExecutionService(private val applicationContext: ApplicationContext) {
+open class NodeTemplateExecutionService {
 
     private val log = LoggerFactory.getLogger(NodeTemplateExecutionService::class.java)!!
 
@@ -48,7 +48,7 @@ open class NodeTemplateExecutionService(private val applicationContext: Applicat
                 "interface($interfaceName) operation($operationName)")
 
         // Get the Component Instance
-        val plugin = applicationContext.getBean(componentName, AbstractComponentFunction::class.java)
+        val plugin = BluePrintDependencyService.instance<AbstractComponentFunction>(componentName)
         // Set the Blueprint Service
         plugin.bluePrintRuntimeService = bluePrintRuntimeService
         plugin.stepName = nodeTemplateName
index c15c054..3c74072 100644 (file)
@@ -17,6 +17,7 @@
 package org.onap.ccsdk.cds.blueprintsprocessor.services.workflow
 
 import kotlinx.coroutines.runBlocking
+import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
@@ -24,9 +25,11 @@ import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceOutp
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintWorkflowExecutionService
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
 import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.context.ApplicationContext
 import org.springframework.test.context.ContextConfiguration
 import org.springframework.test.context.junit4.SpringRunner
 import kotlin.test.assertEquals
@@ -38,9 +41,17 @@ import kotlin.test.assertNotNull
 @ContextConfiguration(classes = [WorkflowServiceConfiguration::class])
 class BluePrintWorkflowExecutionServiceImplTest {
 
+    @Autowired
+    lateinit var applicationContext: ApplicationContext
+
     @Autowired
     lateinit var bluePrintWorkflowExecutionService: BluePrintWorkflowExecutionService<ExecutionServiceInput, ExecutionServiceOutput>
 
+    @Before
+    fun init() {
+        BluePrintDependencyService.inject(applicationContext)
+    }
+
     @Test
     fun testBluePrintWorkflowExecutionService() {
         runBlocking {
index 4352277..12fd9c7 100644 (file)
@@ -18,6 +18,7 @@
 package org.onap.ccsdk.cds.blueprintsprocessor.services.workflow
 
 import kotlinx.coroutines.runBlocking
+import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
@@ -25,6 +26,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.services.workflow.executor.Compone
 import org.onap.ccsdk.cds.blueprintsprocessor.services.workflow.mock.PrototypeComponentFunction
 import org.onap.ccsdk.cds.blueprintsprocessor.services.workflow.mock.SingletonComponentFunction
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonReactorUtils
 import org.springframework.beans.factory.annotation.Autowired
@@ -44,6 +46,11 @@ class BlueprintServiceLogicTest {
     @Autowired
     lateinit var dgWorkflowExecutionService: DGWorkflowExecutionService
 
+    @Before
+    fun init() {
+        BluePrintDependencyService.inject(applicationContext)
+    }
+
     @Test
     fun testExecuteGraphWithSingleComponent() {
         runBlocking {
diff --git a/ms/blueprintsprocessor/modules/services/workflow-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/ImperativeWorkflowExecutionServiceTest.kt b/ms/blueprintsprocessor/modules/services/workflow-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/ImperativeWorkflowExecutionServiceTest.kt
new file mode 100644 (file)
index 0000000..301fc34
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ *  Copyright © 2019 IBM.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.onap.ccsdk.cds.blueprintsprocessor.services.workflow
+
+import io.mockk.every
+import io.mockk.mockkObject
+import io.mockk.unmockkAll
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Before
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
+import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.nodeTypeComponentScriptExecutor
+import org.onap.ccsdk.cds.blueprintsprocessor.services.workflow.mock.MockComponentFunction
+import org.onap.ccsdk.cds.blueprintsprocessor.services.workflow.mock.mockNodeTemplateComponentScriptExecutor
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes
+import org.onap.ccsdk.cds.controllerblueprints.core.dsl.serviceTemplate
+import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+import kotlin.test.Test
+import kotlin.test.assertNotNull
+
+class ImperativeWorkflowExecutionServiceTest {
+
+    @Before
+    fun init() {
+        mockkObject(BluePrintDependencyService)
+        every { BluePrintDependencyService.applicationContext.getBean(any()) } returns MockComponentFunction()
+    }
+
+    @After
+    fun afterTests() {
+        unmockkAll()
+    }
+
+    @Test
+    fun testImperativeExecutionService() {
+        runBlocking {
+            val serviceTemplate = serviceTemplate("imperative-test", "1.0.0",
+                    "brindasanth@onap.com", "tosca") {
+
+                topologyTemplate {
+                    nodeTemplate(mockNodeTemplateComponentScriptExecutor("resolve-config",
+                            "cba.wt.imperative.test.ResolveConfig"))
+                    nodeTemplate(mockNodeTemplateComponentScriptExecutor("activate-config",
+                            "cba.wt.imperative.test.ActivateConfig"))
+                    nodeTemplate(mockNodeTemplateComponentScriptExecutor("activate-config-rollback",
+                            "cba.wt.imperative.test.ActivateConfigRollback"))
+                    nodeTemplate(mockNodeTemplateComponentScriptExecutor("activate-licence",
+                            "cba.wt.imperative.test.ActivateLicence"))
+
+                    workflow("test-wf", "Test Imperative flow") {
+                        step("resolve-config", "resolve-config", "") {
+                            success("activate-config")
+                        }
+                        step("activate-config", "activate-config", "") {
+                            success("activate-licence")
+                            failure("activate-config-rollback")
+                        }
+                        step("activate-config-rollback", "activate-config-rollback", "")
+                        step("activate-licence", "activate-licence", "")
+                    }
+                }
+                nodeType(BluePrintTypes.nodeTypeComponentScriptExecutor())
+            }
+
+            val bluePrintContext = BluePrintContext(serviceTemplate)
+            bluePrintContext.rootPath = normalizedPathName(".")
+            bluePrintContext.entryDefinition = "cba.imperative.test.ImperativeTestDefinitions.kt"
+            val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime("12345", bluePrintContext)
+
+            val executionServiceInput = JacksonUtils
+                    .readValueFromClassPathFile("execution-input/imperative-test-input.json",
+                            ExecutionServiceInput::class.java)!!
+
+            val bluePrintWorkFlowService = ImperativeBluePrintWorkflowService(NodeTemplateExecutionService())
+            val imperativeWorkflowExecutionService = ImperativeWorkflowExecutionService(bluePrintWorkFlowService)
+            val output = imperativeWorkflowExecutionService
+                    .executeBluePrintWorkflow(bluePrintRuntimeService, executionServiceInput, hashMapOf())
+            assertNotNull(output)
+        }
+    }
+}
\ No newline at end of file
index 05cd997..24d9662 100644 (file)
  */
 package org.onap.ccsdk.cds.blueprintsprocessor.services.workflow
 
+import io.mockk.every
+import io.mockk.mockkObject
+import io.mockk.unmockkAll
 import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
+import org.onap.ccsdk.cds.blueprintsprocessor.services.workflow.mock.MockComponentFunction
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
-import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.test.context.ContextConfiguration
 import org.springframework.test.context.junit4.SpringRunner
 import kotlin.test.assertEquals
@@ -32,8 +38,16 @@ import kotlin.test.assertNotNull
 @ContextConfiguration(classes = [WorkflowServiceConfiguration::class])
 
 class NodeTemplateExecutionServiceTest {
-    @Autowired
-    lateinit var nodeTemplateExecutionService: NodeTemplateExecutionService
+    @Before
+    fun init() {
+        mockkObject(BluePrintDependencyService)
+        every { BluePrintDependencyService.applicationContext.getBean(any()) } returns MockComponentFunction()
+    }
+
+    @After
+    fun afterTests() {
+        unmockkAll()
+    }
 
     @Test
     fun testExecuteNodeTemplate() {
@@ -49,7 +63,7 @@ class NodeTemplateExecutionServiceTest {
             bluePrintRuntimeService.assignWorkflowInputs("resource-assignment", input)
 
             val nodeTemplate = "resource-assignment"
-
+            val nodeTemplateExecutionService = NodeTemplateExecutionService()
             val executionServiceOutput = nodeTemplateExecutionService
                     .executeNodeTemplate(bluePrintRuntimeService, nodeTemplate, executionServiceInput)
 
index 5dc5b9d..44751b5 100644 (file)
@@ -19,6 +19,8 @@ package org.onap.ccsdk.cds.blueprintsprocessor.services.workflow.mock
 
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction
+import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.nodeTemplateComponentScriptExecutor
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes
 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
 import org.slf4j.LoggerFactory
 import org.springframework.beans.factory.config.ConfigurableBeanFactory
@@ -27,6 +29,16 @@ import org.springframework.context.annotation.Configuration
 import org.springframework.context.annotation.Scope
 import org.springframework.stereotype.Component
 
+fun mockNodeTemplateComponentScriptExecutor(id: String, script: String) = BluePrintTypes.nodeTemplateComponentScriptExecutor(id,
+        "mock($id) component function") {
+    definedOperation("") {
+        inputs {
+            type("kotlin")
+            scriptClassReference(script)
+        }
+    }
+}
+
 @Configuration
 open class MockComponentConfiguration {
 
diff --git a/ms/blueprintsprocessor/modules/services/workflow-service/src/test/resources/execution-input/imperative-test-input.json b/ms/blueprintsprocessor/modules/services/workflow-service/src/test/resources/execution-input/imperative-test-input.json
new file mode 100644 (file)
index 0000000..188e840
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "commonHeader": {
+    "originatorId": "System",
+    "requestId": "1234",
+    "subRequestId": "1234-12234"
+  },
+  "actionIdentifiers": {
+    "blueprintName": "imperative-test",
+    "blueprintVersion": "1.0.0",
+    "actionName": "test-wf",
+    "mode": "sync"
+  },
+  "payload": {
+    "test-wf-request": {
+      "hostname": "localhost"
+    }
+  }
+}
\ No newline at end of file
index 235c48b..793bdc4 100644 (file)
@@ -18,10 +18,17 @@ package org.onap.ccsdk.cds.controllerblueprints.core
 
 import org.onap.ccsdk.cds.controllerblueprints.core.data.EdgeLabel
 import org.onap.ccsdk.cds.controllerblueprints.core.data.Graph
+import org.onap.ccsdk.cds.controllerblueprints.core.data.Workflow
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.WorkflowGraphUtils
 import java.util.regex.Pattern
 
 private val graphTokenSeparators = Pattern.compile("[->/]")
 
+/** Convert Blueprint workflow to graph data structure */
+fun Workflow.asGraph(): Graph {
+    return WorkflowGraphUtils.workFlowToGraph(this)
+}
+
 fun String.toGraph(): Graph {
     if (!startsWith('[') || !endsWith(']')) {
         throw IllegalArgumentException("Expected string starting '[' and ending with ']' but it was '$")
index 019f318..91c2bcb 100644 (file)
@@ -29,9 +29,9 @@ import kotlin.coroutines.CoroutineContext
 
 interface BluePrintWorkFlowService<In, Out> {
 
-    /** Executes imperative workflow for the bluePrintRuntimeService [bluePrintRuntimeService] and workflow
-     * input [input], response will be retrieve from output [output]*/
-    suspend fun executeWorkflow(bluePrintRuntimeService: BluePrintRuntimeService<*>,
+    /** Executes imperative workflow graph [graph] for the bluePrintRuntimeService [bluePrintRuntimeService]
+     * and workflow input [input], response will be retrieve from output [output]*/
+    suspend fun executeWorkflow(graph: Graph, bluePrintRuntimeService: BluePrintRuntimeService<*>,
                                 input: In, output: CompletableDeferred<Out>)
 
     suspend fun initializeWorkflow(input: In): EdgeLabel
@@ -89,8 +89,9 @@ enum class EdgeAction(val id: String) {
 }
 
 /** Abstract workflow service implementation */
-abstract class AbstractBluePrintWorkFlowService<In, Out>(private val graph: Graph)
-    : CoroutineScope, BluePrintWorkFlowService<In, Out> {
+abstract class AbstractBluePrintWorkFlowService<In, Out> : CoroutineScope, BluePrintWorkFlowService<In, Out> {
+
+    lateinit var graph: Graph
 
     private val log = logger(AbstractBluePrintWorkFlowService::class)
 
@@ -101,8 +102,6 @@ abstract class AbstractBluePrintWorkFlowService<In, Out>(private val graph: Grap
     final override val coroutineContext: CoroutineContext
         get() = job + CoroutineName("Wf")
 
-    val root = graph.startNodes()
-
     fun cancel() {
         log.info("Received workflow($workflowId) cancel request")
         job.cancel()
@@ -121,7 +120,7 @@ abstract class AbstractBluePrintWorkFlowService<In, Out>(private val graph: Grap
             // Prepare Workflow and Populate the Initial store
             initializeWorkflow(workflowExecuteMessage.input)
 
-            val startNode = root.first()
+            val startNode = graph.startNodes().first()
             // Prepare first node message and Send NodeExecuteMessage
             // Start node doesn't wait for any nodes, so we can pass Execute message directly
             val nodeExecuteMessage = prepareNodeExecutionMessage(startNode)
@@ -325,16 +324,12 @@ abstract class AbstractBluePrintWorkFlowService<In, Out>(private val graph: Grap
         }
     }
 
-
-    override suspend fun executeWorkflow(bluePrintRuntimeService: BluePrintRuntimeService<*>, input: In, output: CompletableDeferred<Out>) {
+    override suspend fun executeWorkflow(graph: Graph, bluePrintRuntimeService: BluePrintRuntimeService<*>,
+                                         input: In, output: CompletableDeferred<Out>) {
         log.info("Executing Graph : $graph")
+        this.graph = graph
         this.workflowId = bluePrintRuntimeService.id()
-        validateWorkflow()
         val startMessage = WorkflowExecuteMessage(input, output)
         workflowActor.send(startMessage)
     }
-
-    open fun validateWorkflow() {
-        //check(!graph.findCycles().isNotEmpty()) { "Graph is cyclic, Cycle is not supported" }
-    }
 }
\ No newline at end of file
index 669ab3f..55424ad 100644 (file)
@@ -61,7 +61,7 @@ class BluePrintMetadataUtils {
             // Verify if the environment directory exists
             if (envDir.exists() && envDir.isDirectory) {
                 //Find all available environment files
-                envDir.listFiles()
+                envDir.listFiles()!!
                         .filter { it.name.endsWith(".properties") }
                         .forEach {
                             val istream = it.inputStream()
@@ -96,14 +96,20 @@ class BluePrintMetadataUtils {
             return toscaMetaData
         }
 
-        fun getBluePrintRuntime(id: String, blueprintBasePath: String): BluePrintRuntimeService<MutableMap<String, JsonNode>> {
-
+        fun getBluePrintRuntime(id: String, blueprintBasePath: String)
+                : BluePrintRuntimeService<MutableMap<String, JsonNode>> {
             val bluePrintContext: BluePrintContext = getBluePrintContext(blueprintBasePath)
+            return getBluePrintRuntime(id, bluePrintContext)
+        }
 
+        fun getBluePrintRuntime(id: String, bluePrintContext: BluePrintContext)
+                : BluePrintRuntimeService<MutableMap<String, JsonNode>> {
+            checkNotEmpty(bluePrintContext.rootPath) { "blueprint context root path is missing." }
+            checkNotEmpty(bluePrintContext.entryDefinition) { "blueprint context entry definition is missing." }
+            val blueprintBasePath = bluePrintContext.rootPath
             val bluePrintRuntimeService = DefaultBluePrintRuntimeService(id, bluePrintContext)
             bluePrintRuntimeService.put(BluePrintConstants.PROPERTY_BLUEPRINT_BASE_PATH, blueprintBasePath.asJsonPrimitive())
             bluePrintRuntimeService.put(BluePrintConstants.PROPERTY_BLUEPRINT_PROCESS_ID, id.asJsonPrimitive())
-
             return bluePrintRuntimeService
         }
 
index 4c207fb..9103af3 100644 (file)
 
 package org.onap.ccsdk.cds.controllerblueprints.core.service
 
-import org.slf4j.LoggerFactory
 import com.fasterxml.jackson.databind.JsonNode
 import com.fasterxml.jackson.databind.node.NullNode
 import org.junit.Test
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
 import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition
+import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintRuntimeUtils
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+import org.slf4j.LoggerFactory
 import kotlin.test.assertEquals
 import kotlin.test.assertNotNull
 
@@ -36,7 +37,7 @@ import kotlin.test.assertNotNull
  * @author Brinda Santh
  */
 class BluePrintRuntimeServiceTest {
-    private val log= LoggerFactory.getLogger(this::class.toString())
+    private val log = LoggerFactory.getLogger(this::class.toString())
 
     @Test
     fun `test Resolve NodeTemplate Properties`() {
@@ -167,11 +168,15 @@ class BluePrintRuntimeServiceTest {
     }
 
     private fun getBluePrintRuntimeService(): BluePrintRuntimeService<MutableMap<String, JsonNode>> {
-        val blueprintBasePath: String = ("./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration")
+        val blueprintBasePath = normalizedPathName("./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration")
         val blueprintRuntime = BluePrintMetadataUtils.getBluePrintRuntime("1234", blueprintBasePath)
+        val checkProcessId = blueprintRuntime.get(BluePrintConstants.PROPERTY_BLUEPRINT_PROCESS_ID)
         val checkBasePath = blueprintRuntime.get(BluePrintConstants.PROPERTY_BLUEPRINT_BASE_PATH)
 
-        assertEquals(blueprintBasePath.asJsonPrimitive(), checkBasePath, "Failed to get base path after runtime creation")
+        assertEquals("1234".asJsonPrimitive(),
+                checkProcessId, "Failed to get process id after runtime creation")
+        assertEquals(blueprintBasePath.asJsonPrimitive(),
+                checkBasePath, "Failed to get base path after runtime creation")
 
         return blueprintRuntime
     }
index 7cb6492..62cb108 100644 (file)
@@ -33,11 +33,11 @@ class BluePrintWorkflowServiceTest {
         runBlocking {
             val graph = "[START>A/SUCCESS, A>B/SUCCESS, B>C/SUCCESS, C>D/SUCCESS, D>E/SUCCESS, E>END/SUCCESS]"
                     .toGraph()
-            val simpleWorkflow = TestBluePrintWorkFlowService(graph)
+            val simpleWorkflow = TestBluePrintWorkFlowService()
             simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "B", "C", "D", "E"), null)
             val deferredOutput = CompletableDeferred<String>()
             val input = "123456"
-            simpleWorkflow.executeWorkflow(mockBluePrintRuntimeService(), input, deferredOutput)
+            simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(), input, deferredOutput)
             val response = deferredOutput.await()
             assertNotNull(response, "failed to get response")
         }
@@ -48,11 +48,11 @@ class BluePrintWorkflowServiceTest {
         runBlocking {
             val graph = "[START>A/SUCCESS, A>B/SUCCESS, A>C/FAILURE, B>D/SUCCESS, C>D/SUCCESS, D>END/SUCCESS]"
                     .toGraph()
-            val simpleWorkflow = TestBluePrintWorkFlowService(graph)
+            val simpleWorkflow = TestBluePrintWorkFlowService()
             simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "B", "C", "D", "E"), null)
             val deferredOutput = CompletableDeferred<String>()
             val input = "123456"
-            simpleWorkflow.executeWorkflow(mockBluePrintRuntimeService(), input, deferredOutput)
+            simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(), input, deferredOutput)
             val response = deferredOutput.await()
             assertNotNull(response, "failed to get response")
         }
@@ -64,12 +64,12 @@ class BluePrintWorkflowServiceTest {
             // Failure Flow
             val failurePatGraph = "[START>A/SUCCESS, A>B/SUCCESS, A>C/FAILURE, B>D/SUCCESS, C>D/SUCCESS, D>END/SUCCESS]"
                     .toGraph()
-            val failurePathWorkflow = TestBluePrintWorkFlowService(failurePatGraph)
+            val failurePathWorkflow = TestBluePrintWorkFlowService()
             failurePathWorkflow.simulatedState = prepareSimulation(arrayListOf("B", "C", "D", "E"),
                     arrayListOf("A"))
             val failurePathWorkflowDeferredOutput = CompletableDeferred<String>()
             val failurePathWorkflowInput = "123456"
-            failurePathWorkflow.executeWorkflow(mockBluePrintRuntimeService(), failurePathWorkflowInput, failurePathWorkflowDeferredOutput)
+            failurePathWorkflow.executeWorkflow(failurePatGraph, mockBluePrintRuntimeService(), failurePathWorkflowInput, failurePathWorkflowDeferredOutput)
             val failurePathResponse = failurePathWorkflowDeferredOutput.await()
             assertNotNull(failurePathResponse, "failed to get response")
         }
@@ -80,11 +80,11 @@ class BluePrintWorkflowServiceTest {
         runBlocking {
             val graph = "[START>A/SUCCESS, A>B/SUCCESS, A>C/FAILURE, C>D/SUCCESS, D>E/SUCCESS, B>E/SUCCESS, E>END/SUCCESS]"
                     .toGraph()
-            val simpleWorkflow = TestBluePrintWorkFlowService(graph)
+            val simpleWorkflow = TestBluePrintWorkFlowService()
             simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "B", "C", "D", "E"), null)
             val deferredOutput = CompletableDeferred<String>()
             val input = "123456"
-            simpleWorkflow.executeWorkflow(mockBluePrintRuntimeService(), input, deferredOutput)
+            simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(), input, deferredOutput)
             val response = deferredOutput.await()
             assertNotNull(response, "failed to get response")
         }
@@ -95,11 +95,11 @@ class BluePrintWorkflowServiceTest {
         runBlocking {
             val graph = "[START>A/SUCCESS, A>B/SUCCESS, A>C/SUCCESS, B>D/SUCCESS, C>D/SUCCESS, D>END/SUCCESS]"
                     .toGraph()
-            val simpleWorkflow = TestBluePrintWorkFlowService(graph)
+            val simpleWorkflow = TestBluePrintWorkFlowService()
             simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "B", "C", "D"), null)
             val deferredOutput = CompletableDeferred<String>()
             val input = "123456"
-            simpleWorkflow.executeWorkflow(mockBluePrintRuntimeService(), input, deferredOutput)
+            simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(), input, deferredOutput)
             val response = deferredOutput.await()
             assertNotNull(response, "failed to get response")
         }
@@ -123,8 +123,8 @@ class BluePrintWorkflowServiceTest {
     }
 }
 
-class TestBluePrintWorkFlowService(graph: Graph)
-    : AbstractBluePrintWorkFlowService<String, String>(graph) {
+class TestBluePrintWorkFlowService
+    : AbstractBluePrintWorkFlowService<String, String>() {
 
     lateinit var simulatedState: MutableMap<String, EdgeLabel>