2a14be216fb3a014cc875bc3047ea5625ecb03a5
[ccsdk/cds.git] /
1 /*
2  *  Copyright © 2019 IBM.
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package org.onap.ccsdk.cds.blueprintsprocessor.services.workflow
18
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.core.*
24 import org.onap.ccsdk.cds.controllerblueprints.core.data.EdgeLabel
25 import org.onap.ccsdk.cds.controllerblueprints.core.data.Graph
26 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintWorkflowExecutionService
27 import org.onap.ccsdk.cds.controllerblueprints.core.service.*
28 import org.springframework.beans.factory.config.ConfigurableBeanFactory
29 import org.springframework.context.annotation.Scope
30 import org.springframework.stereotype.Service
31
32 @Service("imperativeWorkflowExecutionService")
33 class ImperativeWorkflowExecutionService(
34         private val imperativeBluePrintWorkflowService: BluePrintWorkFlowService<ExecutionServiceInput, ExecutionServiceOutput>)
35     : BluePrintWorkflowExecutionService<ExecutionServiceInput, ExecutionServiceOutput> {
36
37     override suspend fun executeBluePrintWorkflow(bluePrintRuntimeService: BluePrintRuntimeService<*>,
38                                                   executionServiceInput: ExecutionServiceInput,
39                                                   properties: MutableMap<String, Any>): ExecutionServiceOutput {
40
41         val bluePrintContext = bluePrintRuntimeService.bluePrintContext()
42
43         val workflowName = executionServiceInput.actionIdentifiers.actionName
44
45         val graph = bluePrintContext.workflowByName(workflowName).asGraph()
46
47         val deferredOutput = CompletableDeferred<ExecutionServiceOutput>()
48         imperativeBluePrintWorkflowService.executeWorkflow(graph, bluePrintRuntimeService,
49                 executionServiceInput, deferredOutput)
50         return deferredOutput.await()
51     }
52 }
53
54 @Service
55 @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
56 open class ImperativeBluePrintWorkflowService(private val nodeTemplateExecutionService: NodeTemplateExecutionService)
57     : AbstractBluePrintWorkFlowService<ExecutionServiceInput, ExecutionServiceOutput>() {
58     val log = logger(ImperativeBluePrintWorkflowService::class)
59
60     lateinit var bluePrintRuntimeService: BluePrintRuntimeService<*>
61     lateinit var executionServiceInput: ExecutionServiceInput
62     lateinit var workflowName: String
63     lateinit var deferredExecutionServiceOutput: CompletableDeferred<ExecutionServiceOutput>
64
65     override suspend fun executeWorkflow(graph: Graph, bluePrintRuntimeService: BluePrintRuntimeService<*>,
66                                          input: ExecutionServiceInput,
67                                          output: CompletableDeferred<ExecutionServiceOutput>) {
68         this.graph = graph
69         this.bluePrintRuntimeService = bluePrintRuntimeService
70         this.executionServiceInput = input
71         this.workflowName = this.executionServiceInput.actionIdentifiers.actionName
72         this.deferredExecutionServiceOutput = output
73         this.workflowId = bluePrintRuntimeService.id()
74         val startMessage = WorkflowExecuteMessage(input, output)
75         workflowActor().send(startMessage)
76     }
77
78     override suspend fun initializeWorkflow(input: ExecutionServiceInput): EdgeLabel {
79         return EdgeLabel.SUCCESS
80     }
81
82     override suspend fun prepareWorkflowOutput(exception: BluePrintProcessorException?): ExecutionServiceOutput {
83         val wfStatus = if (exception != null) {
84             val status = Status()
85             status.message = BluePrintConstants.STATUS_FAILURE
86             status.errorMessage = exception.message
87             status
88         } else {
89             val status = Status()
90             status.message = BluePrintConstants.STATUS_SUCCESS
91             status
92         }
93         return ExecutionServiceOutput().apply {
94             commonHeader = executionServiceInput.commonHeader
95             actionIdentifiers = executionServiceInput.actionIdentifiers
96             status = wfStatus
97         }
98     }
99
100     override suspend fun prepareNodeExecutionMessage(node: Graph.Node)
101             : NodeExecuteMessage<ExecutionServiceInput, ExecutionServiceOutput> {
102         val nodeOutput = ExecutionServiceOutput().apply {
103             commonHeader = executionServiceInput.commonHeader
104             actionIdentifiers = executionServiceInput.actionIdentifiers
105         }
106         return NodeExecuteMessage(node, executionServiceInput, nodeOutput)
107     }
108
109     override suspend fun prepareNodeSkipMessage(node: Graph.Node)
110             : NodeSkipMessage<ExecutionServiceInput, ExecutionServiceOutput> {
111         val nodeOutput = ExecutionServiceOutput().apply {
112             commonHeader = executionServiceInput.commonHeader
113             actionIdentifiers = executionServiceInput.actionIdentifiers
114         }
115         return NodeSkipMessage(node, executionServiceInput, nodeOutput)
116     }
117
118     override suspend fun executeNode(node: Graph.Node, nodeInput: ExecutionServiceInput,
119                                      nodeOutput: ExecutionServiceOutput): EdgeLabel {
120         log.info("Executing workflow($workflowName[${this.workflowId}])'s step($${node.id})")
121         val step = bluePrintRuntimeService.bluePrintContext().workflowStepByName(this.workflowName, node.id)
122         checkNotEmpty(step.target) { "couldn't get step target for workflow(${this.workflowName})'s step(${node.id})" }
123         val nodeTemplateName = step.target!!
124         /** execute node template */
125         val executionServiceOutput = nodeTemplateExecutionService
126                 .executeNodeTemplate(bluePrintRuntimeService, nodeTemplateName, nodeInput)
127
128         return when (executionServiceOutput.status.message) {
129             BluePrintConstants.STATUS_FAILURE -> EdgeLabel.FAILURE
130             else -> EdgeLabel.SUCCESS
131         }
132     }
133
134     override suspend fun skipNode(node: Graph.Node, nodeInput: ExecutionServiceInput,
135                                   nodeOutput: ExecutionServiceOutput): EdgeLabel {
136         return EdgeLabel.SUCCESS
137     }
138
139     override suspend fun cancelNode(node: Graph.Node, nodeInput: ExecutionServiceInput,
140                                     nodeOutput: ExecutionServiceOutput): EdgeLabel {
141         TODO("not implemented")
142     }
143
144     override suspend fun restartNode(node: Graph.Node, nodeInput: ExecutionServiceInput,
145                                      nodeOutput: ExecutionServiceOutput): EdgeLabel {
146         TODO("not implemented")
147     }
148 }