2 * Copyright © 2017-2018 AT&T Intellectual Property.
3 * Modifications Copyright © 2019 IBM.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api
20 import io.grpc.stub.StreamObserver
21 import kotlinx.coroutines.Dispatchers
22 import kotlinx.coroutines.GlobalScope
23 import kotlinx.coroutines.launch
24 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.*
25 import org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.utils.toProto
26 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractServiceFunction
27 import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType
28 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
29 import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfiguration
30 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService
31 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintWorkflowExecutionService
32 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService
33 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
34 import org.slf4j.LoggerFactory
35 import org.springframework.stereotype.Service
36 import java.util.stream.Collectors
39 class ExecutionServiceHandler(private val bluePrintLoadConfiguration: BluePrintLoadConfiguration,
40 private val blueprintsProcessorCatalogService: BluePrintCatalogService,
41 private val bluePrintWorkflowExecutionService
42 : BluePrintWorkflowExecutionService<ExecutionServiceInput, ExecutionServiceOutput>) {
44 private val log = LoggerFactory.getLogger(ExecutionServiceHandler::class.toString())
46 suspend fun process(executionServiceInput: ExecutionServiceInput,
47 responseObserver: StreamObserver<org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput>) {
49 executionServiceInput.actionIdentifiers.mode == ACTION_MODE_ASYNC -> {
50 GlobalScope.launch(Dispatchers.Default) {
51 val executionServiceOutput = doProcess(executionServiceInput)
52 responseObserver.onNext(executionServiceOutput.toProto())
53 responseObserver.onCompleted()
55 responseObserver.onNext(response(executionServiceInput).toProto())
57 executionServiceInput.actionIdentifiers.mode == ACTION_MODE_SYNC -> {
58 val executionServiceOutput = doProcess(executionServiceInput)
59 responseObserver.onNext(executionServiceOutput.toProto())
60 responseObserver.onCompleted()
62 else -> responseObserver.onNext(response(executionServiceInput,
63 "Failed to process request, 'actionIdentifiers.mode' not specified. Valid value are: 'sync' or 'async'.",
68 suspend fun doProcess(executionServiceInput: ExecutionServiceInput): ExecutionServiceOutput {
69 val requestId = executionServiceInput.commonHeader.requestId
70 log.info("processing request id $requestId")
71 val actionIdentifiers = executionServiceInput.actionIdentifiers
72 val blueprintName = actionIdentifiers.blueprintName
73 val blueprintVersion = actionIdentifiers.blueprintVersion
75 /** Check Blueprint is needed for this request */
76 if (checkServiceFunction(executionServiceInput)) {
77 return executeServiceFunction(executionServiceInput)
79 val basePath = blueprintsProcessorCatalogService.getFromDatabase(blueprintName, blueprintVersion)
80 log.info("blueprint base path $basePath")
82 val blueprintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime(requestId, basePath.toString())
84 val output = bluePrintWorkflowExecutionService.executeBluePrintWorkflow(blueprintRuntimeService,
85 executionServiceInput, hashMapOf())
87 val errors = blueprintRuntimeService.getBluePrintError().errors
88 if (errors.isNotEmpty()) {
89 val errorMessage = errors.stream().map { it.toString() }.collect(Collectors.joining(", "))
90 setErrorStatus(errorMessage, output.status)
94 } catch (e: Exception) {
95 log.error("fail processing request id $requestId", e)
96 return response(executionServiceInput, e.localizedMessage ?: e.message ?: e.toString(), true)
100 /** If the blueprint name is default, It means no blueprint is needed for the execution */
101 fun checkServiceFunction(executionServiceInput: ExecutionServiceInput): Boolean {
102 return executionServiceInput.actionIdentifiers.blueprintName == "default"
105 /** If no blueprint is needed, then get the Service function instance mapping to the action name and execute it */
106 suspend fun executeServiceFunction(executionServiceInput: ExecutionServiceInput): ExecutionServiceOutput {
107 val actionName = executionServiceInput.actionIdentifiers.actionName
108 val instance = BluePrintDependencyService.instance<AbstractServiceFunction>(actionName)
109 checkNotNull(instance) { "failed to initialize service function($actionName)" }
110 instance.actionName = actionName
111 return instance.applyNB(executionServiceInput)
114 private fun setErrorStatus(errorMessage: String, status: Status) {
115 status.errorMessage = errorMessage
116 status.eventType = EventType.EVENT_COMPONENT_FAILURE.name
118 status.message = BluePrintConstants.STATUS_FAILURE
121 private fun response(executionServiceInput: ExecutionServiceInput, errorMessage: String = "",
122 failure: Boolean = false): ExecutionServiceOutput {
123 val executionServiceOutput = ExecutionServiceOutput()
124 executionServiceOutput.commonHeader = executionServiceInput.commonHeader
125 executionServiceOutput.actionIdentifiers = executionServiceInput.actionIdentifiers
126 executionServiceOutput.payload = executionServiceInput.payload
128 val status = Status()
130 setErrorStatus(errorMessage, status)
132 status.eventType = EventType.EVENT_COMPONENT_PROCESSING.name
134 status.message = BluePrintConstants.STATUS_PROCESSING
137 executionServiceOutput.status = status
139 return executionServiceOutput