2 * Copyright © 2019 IBM.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.onap.ccsdk.cds.blueprintsprocessor.services.workflow
19 import kotlinx.coroutines.CompletableDeferred
20 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
21 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceOutput
22 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.Status
23 import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType
24 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
25 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
26 import org.onap.ccsdk.cds.controllerblueprints.core.asGraph
27 import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty
28 import org.onap.ccsdk.cds.controllerblueprints.core.data.EdgeLabel
29 import org.onap.ccsdk.cds.controllerblueprints.core.data.Graph
30 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintWorkflowExecutionService
31 import org.onap.ccsdk.cds.controllerblueprints.core.logger
32 import org.onap.ccsdk.cds.controllerblueprints.core.service.AbstractBluePrintWorkFlowService
33 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
34 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintWorkFlowService
35 import org.onap.ccsdk.cds.controllerblueprints.core.service.NodeExecuteMessage
36 import org.onap.ccsdk.cds.controllerblueprints.core.service.NodeSkipMessage
37 import org.onap.ccsdk.cds.controllerblueprints.core.service.WorkflowExecuteMessage
38 import org.springframework.beans.factory.config.ConfigurableBeanFactory
39 import org.springframework.context.annotation.Scope
40 import org.springframework.stereotype.Service
42 @Service("imperativeWorkflowExecutionService")
43 class ImperativeWorkflowExecutionService(
44 private val imperativeBluePrintWorkflowService: BluePrintWorkFlowService<ExecutionServiceInput, ExecutionServiceOutput>
46 BluePrintWorkflowExecutionService<ExecutionServiceInput, ExecutionServiceOutput> {
48 override suspend fun executeBluePrintWorkflow(
49 bluePrintRuntimeService: BluePrintRuntimeService<*>,
50 executionServiceInput: ExecutionServiceInput,
51 properties: MutableMap<String, Any>
52 ): ExecutionServiceOutput {
54 val bluePrintContext = bluePrintRuntimeService.bluePrintContext()
56 val workflowName = executionServiceInput.actionIdentifiers.actionName
58 val graph = bluePrintContext.workflowByName(workflowName).asGraph()
60 return imperativeBluePrintWorkflowService.executeWorkflow(
61 graph, bluePrintRuntimeService,
68 @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
69 open class ImperativeBluePrintWorkflowService(private val nodeTemplateExecutionService: NodeTemplateExecutionService) :
70 AbstractBluePrintWorkFlowService<ExecutionServiceInput, ExecutionServiceOutput>() {
72 val log = logger(ImperativeBluePrintWorkflowService::class)
74 lateinit var bluePrintRuntimeService: BluePrintRuntimeService<*>
75 lateinit var executionServiceInput: ExecutionServiceInput
76 lateinit var workflowName: String
78 override suspend fun executeWorkflow(
80 bluePrintRuntimeService: BluePrintRuntimeService<*>,
81 input: ExecutionServiceInput
82 ): ExecutionServiceOutput {
84 this.bluePrintRuntimeService = bluePrintRuntimeService
85 this.executionServiceInput = input
86 this.workflowName = this.executionServiceInput.actionIdentifiers.actionName
87 this.workflowId = bluePrintRuntimeService.id()
88 val output = CompletableDeferred<ExecutionServiceOutput>()
89 val startMessage = WorkflowExecuteMessage(input, output)
90 val workflowActor = workflowActor()
91 if (!workflowActor.isClosedForSend) {
92 workflowActor.send(startMessage)
94 throw BluePrintProcessorException("workflow($workflowActor) actor is closed")
99 override suspend fun initializeWorkflow(input: ExecutionServiceInput): EdgeLabel {
100 return EdgeLabel.SUCCESS
103 override suspend fun prepareWorkflowOutput(): ExecutionServiceOutput {
104 val wfStatus = Status().apply {
105 if (exceptions.isNotEmpty()) {
107 val errorMessage = it.message ?: ""
108 bluePrintRuntimeService.getBluePrintError().addError(errorMessage)
109 log.error("workflow($workflowId) exception :", it)
111 message = BluePrintConstants.STATUS_FAILURE
113 message = BluePrintConstants.STATUS_SUCCESS
115 eventType = EventType.EVENT_COMPONENT_EXECUTED.name
117 return ExecutionServiceOutput().apply {
118 commonHeader = executionServiceInput.commonHeader
119 actionIdentifiers = executionServiceInput.actionIdentifiers
124 override suspend fun prepareNodeExecutionMessage(node: Graph.Node):
125 NodeExecuteMessage<ExecutionServiceInput, ExecutionServiceOutput> {
126 val nodeOutput = ExecutionServiceOutput().apply {
127 commonHeader = executionServiceInput.commonHeader
128 actionIdentifiers = executionServiceInput.actionIdentifiers
130 return NodeExecuteMessage(node, executionServiceInput, nodeOutput)
133 override suspend fun prepareNodeSkipMessage(node: Graph.Node):
134 NodeSkipMessage<ExecutionServiceInput, ExecutionServiceOutput> {
135 val nodeOutput = ExecutionServiceOutput().apply {
136 commonHeader = executionServiceInput.commonHeader
137 actionIdentifiers = executionServiceInput.actionIdentifiers
139 return NodeSkipMessage(node, executionServiceInput, nodeOutput)
142 override suspend fun executeNode(
144 nodeInput: ExecutionServiceInput,
145 nodeOutput: ExecutionServiceOutput
147 log.info("Executing workflow($workflowName[${this.workflowId}])'s step($${node.id})")
148 val step = bluePrintRuntimeService.bluePrintContext().workflowStepByName(this.workflowName, node.id)
149 checkNotEmpty(step.target) { "couldn't get step target for workflow(${this.workflowName})'s step(${node.id})" }
150 val nodeTemplateName = step.target!!
151 /** execute node template */
152 val executionServiceOutput = nodeTemplateExecutionService
153 .executeNodeTemplate(bluePrintRuntimeService, nodeTemplateName, nodeInput)
155 return when (executionServiceOutput.status.message) {
156 BluePrintConstants.STATUS_FAILURE -> EdgeLabel.FAILURE
157 else -> EdgeLabel.SUCCESS
161 override suspend fun skipNode(
163 nodeInput: ExecutionServiceInput,
164 nodeOutput: ExecutionServiceOutput
166 return EdgeLabel.SUCCESS
169 override suspend fun cancelNode(
171 nodeInput: ExecutionServiceInput,
172 nodeOutput: ExecutionServiceOutput
174 TODO("not implemented")
177 override suspend fun restartNode(
179 nodeInput: ExecutionServiceInput,
180 nodeOutput: ExecutionServiceOutput
182 TODO("not implemented")