2 * Copyright © 2017-2018 AT&T Intellectual Property.
3 * Modifications Copyright © 2019 Bell Canada.
4 * Modifications Copyright © 2019 IBM.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 package org.onap.ccsdk.cds.blueprintsprocessor.designer.api
21 import com.google.protobuf.ByteString
22 import com.google.protobuf.util.JsonFormat
23 import io.grpc.stub.StreamObserver
24 import kotlinx.coroutines.runBlocking
25 import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.handler.BluePrintModelHandler
26 import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader
27 import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType
28 import org.onap.ccsdk.cds.controllerblueprints.common.api.Status
29 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
30 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
31 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonString
32 import org.onap.ccsdk.cds.controllerblueprints.core.emptyTONull
33 import org.onap.ccsdk.cds.controllerblueprints.core.utils.currentTimestamp
34 import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintBootstrapInput
35 import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintDownloadInput
36 import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintManagementOutput
37 import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintManagementServiceGrpc
38 import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintRemoveInput
39 import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintUploadInput
40 import org.onap.ccsdk.cds.controllerblueprints.management.api.DownloadAction
41 import org.onap.ccsdk.cds.controllerblueprints.management.api.FileChunk
42 import org.onap.ccsdk.cds.controllerblueprints.management.api.RemoveAction
43 import org.onap.ccsdk.cds.controllerblueprints.management.api.UploadAction
44 import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogCodes
45 import org.onap.ccsdk.cds.error.catalog.core.GrpcErrorCodes
46 import org.onap.ccsdk.cds.error.catalog.core.utils.errorMessageOrDefault
47 import org.onap.ccsdk.cds.error.catalog.services.ErrorCatalogService
48 import org.slf4j.LoggerFactory
49 import org.springframework.security.access.prepost.PreAuthorize
50 import org.springframework.stereotype.Service
52 // TODO("Convert to coroutines handler")
54 open class BluePrintManagementGRPCHandler(
55 private val bluePrintModelHandler: BluePrintModelHandler,
56 private val errorCatalogService: ErrorCatalogService
58 BluePrintManagementServiceGrpc.BluePrintManagementServiceImplBase() {
60 private val log = LoggerFactory.getLogger(BluePrintManagementGRPCHandler::class.java)
62 @PreAuthorize("hasRole('USER')")
63 override fun uploadBlueprint(
64 request: BluePrintUploadInput,
65 responseObserver: StreamObserver<BluePrintManagementOutput>
69 // TODO("catch if request id is missing")
70 log.info("request(${request.commonHeader.requestId})")
72 /** Get the file byte array */
73 val byteArray = request.fileChunk.chunk.toByteArray()
74 /** Get the Upload Action */
75 val uploadAction = request.actionIdentifiers?.actionName.emptyTONull()
76 ?: UploadAction.DRAFT.toString()
79 UploadAction.DRAFT.toString() -> {
80 val blueprintModel = bluePrintModelHandler.upload(byteArray, false)
81 responseObserver.onNext(successStatus(request.commonHeader, blueprintModel.asJsonString()))
83 UploadAction.PUBLISH.toString() -> {
84 val blueprintModel = bluePrintModelHandler.upload(byteArray, true)
85 responseObserver.onNext(successStatus(request.commonHeader, blueprintModel.asJsonString()))
87 UploadAction.VALIDATE.toString() -> {
88 // TODO("Not Implemented")
89 responseObserver.onNext(
92 "Upload action($uploadAction) not implemented",
93 BluePrintProcessorException("Not Implemented")
97 UploadAction.ENRICH.toString() -> {
98 val enrichedByteArray = bluePrintModelHandler.enrichBlueprintFileSource(byteArray)
99 responseObserver.onNext(outputWithFileBytes(request.commonHeader, enrichedByteArray))
102 responseObserver.onNext(
104 request.commonHeader,
105 "Upload action($uploadAction) not implemented",
106 BluePrintProcessorException("Not implemented")
111 } catch (e: Exception) {
112 responseObserver.onNext(
114 request.commonHeader,
115 "request(${request.commonHeader.requestId}): Failed to upload CBA", e
119 responseObserver.onCompleted()
124 @PreAuthorize("hasRole('USER')")
125 override fun downloadBlueprint(
126 request: BluePrintDownloadInput,
127 responseObserver: StreamObserver<BluePrintManagementOutput>
130 val blueprintName = request.actionIdentifiers.blueprintName
131 val blueprintVersion = request.actionIdentifiers.blueprintVersion
132 val blueprint = "blueprint $blueprintName:$blueprintVersion"
134 /** Get the Search Action */
135 val searchAction = request.actionIdentifiers?.actionName.emptyTONull()
136 ?: DownloadAction.SEARCH.toString()
138 log.info("request(${request.commonHeader.requestId}): Received download $blueprint")
140 when (searchAction) {
141 DownloadAction.SEARCH.toString() -> {
142 val downloadByteArray = bluePrintModelHandler.download(blueprintName, blueprintVersion)
143 responseObserver.onNext(outputWithFileBytes(request.commonHeader, downloadByteArray))
146 responseObserver.onNext(
148 request.commonHeader,
149 "Search action($searchAction) not implemented",
150 BluePrintProcessorException("Not implemented")
155 } catch (e: Exception) {
156 responseObserver.onNext(
158 request.commonHeader,
159 "request(${request.commonHeader.requestId}): Failed to delete $blueprint", e
163 responseObserver.onCompleted()
168 @PreAuthorize("hasRole('USER')")
169 override fun removeBlueprint(
170 request: BluePrintRemoveInput,
172 StreamObserver<BluePrintManagementOutput>
176 val blueprintName = request.actionIdentifiers.blueprintName
177 val blueprintVersion = request.actionIdentifiers.blueprintVersion
178 val blueprint = "blueprint $blueprintName:$blueprintVersion"
180 log.info("request(${request.commonHeader.requestId}): Received delete $blueprint")
182 /** Get the Remove Action */
183 val removeAction = request.actionIdentifiers?.actionName.emptyTONull()
184 ?: RemoveAction.DEFAULT.toString()
187 when (removeAction) {
188 RemoveAction.DEFAULT.toString() -> {
189 bluePrintModelHandler.deleteBlueprintModel(blueprintName, blueprintVersion)
190 responseObserver.onNext(successStatus(request.commonHeader))
193 responseObserver.onNext(
195 request.commonHeader,
196 "Remove action($removeAction) not implemented",
197 BluePrintProcessorException("Not implemented")
202 } catch (e: Exception) {
203 responseObserver.onNext(
205 request.commonHeader,
206 "request(${request.commonHeader.requestId}): Failed to delete $blueprint", e
210 responseObserver.onCompleted()
215 override fun bootstrapBlueprint(
216 request: BluePrintBootstrapInput,
217 responseObserver: StreamObserver<BluePrintManagementOutput>
221 log.info("request(${request.commonHeader.requestId}): Received bootstrap request")
222 val bootstrapRequest = BootstrapRequest().apply {
223 loadModelType = request.loadModelType
224 loadResourceDictionary = request.loadResourceDictionary
225 loadCBA = request.loadCBA
227 /** Perform bootstrap of Model Types, Resource Definitions and CBA */
228 bluePrintModelHandler.bootstrapBlueprint(bootstrapRequest)
229 responseObserver.onNext(successStatus(request.commonHeader))
230 } catch (e: Exception) {
231 responseObserver.onNext(
233 request.commonHeader,
234 "request(${request.commonHeader.requestId}): Failed to bootstrap", e
238 responseObserver.onCompleted()
243 private fun outputWithFileBytes(header: CommonHeader, byteArray: ByteArray): BluePrintManagementOutput =
244 BluePrintManagementOutput.newBuilder()
245 .setCommonHeader(header)
246 .setFileChunk(FileChunk.newBuilder().setChunk(ByteString.copyFrom(byteArray)))
249 .setTimestamp(currentTimestamp())
250 .setEventType(EventType.EVENT_COMPONENT_EXECUTED)
251 .setMessage(BluePrintConstants.STATUS_SUCCESS)
257 private fun successStatus(header: CommonHeader, propertyContent: String? = null): BluePrintManagementOutput {
258 // Populate Response Payload
259 val propertiesBuilder = BluePrintManagementOutput.newBuilder().propertiesBuilder
260 propertyContent?.let {
261 JsonFormat.parser().merge(propertyContent, propertiesBuilder)
263 return BluePrintManagementOutput.newBuilder()
264 .setCommonHeader(header)
265 .setProperties(propertiesBuilder.build())
268 .setTimestamp(currentTimestamp())
269 .setMessage(BluePrintConstants.STATUS_SUCCESS)
270 .setEventType(EventType.EVENT_COMPONENT_EXECUTED)
277 private fun failStatus(header: CommonHeader, message: String, e: Exception): BluePrintManagementOutput {
278 log.error(message, e)
279 return if (e is BluePrintProcessorException) onErrorCatalog(header, message, e) else onError(header, message, e)
282 private fun onError(header: CommonHeader, message: String, error: Exception): BluePrintManagementOutput {
283 val code = GrpcErrorCodes.code(ErrorCatalogCodes.GENERIC_FAILURE)
284 return BluePrintManagementOutput.newBuilder()
285 .setCommonHeader(header)
288 .setTimestamp(currentTimestamp())
289 .setMessage(BluePrintConstants.STATUS_FAILURE)
290 .setEventType(EventType.EVENT_COMPONENT_FAILURE)
291 .setErrorMessage("Error : $message \n Details: ${error.errorMessageOrDefault()}")
298 private fun onErrorCatalog(header: CommonHeader, message: String, error: BluePrintProcessorException):
299 BluePrintManagementOutput {
300 val err = if (error.protocol == "") {
301 error.grpc(ErrorCatalogCodes.GENERIC_FAILURE)
303 error.convertToGrpc()
305 val errorPayload = errorCatalogService.errorPayload(err.addErrorPayloadMessage(message))
306 return BluePrintManagementOutput.newBuilder()
307 .setCommonHeader(header)
310 .setTimestamp(currentTimestamp())
311 .setMessage(BluePrintConstants.STATUS_FAILURE)
312 .setEventType(EventType.EVENT_COMPONENT_FAILURE)
313 .setErrorMessage("Error : ${errorPayload.message}")
314 .setCode(errorPayload.code)