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()
75 /** Get the Upload Action */
76 val uploadAction = request.actionIdentifiers?.actionName.emptyTONull()
77 ?: UploadAction.DRAFT.toString()
80 UploadAction.DRAFT.toString() -> {
81 val blueprintModel = bluePrintModelHandler.upload(byteArray, false)
82 responseObserver.onNext(successStatus(request.commonHeader, blueprintModel.asJsonString()))
84 UploadAction.PUBLISH.toString() -> {
85 val blueprintModel = bluePrintModelHandler.upload(byteArray, true)
86 responseObserver.onNext(successStatus(request.commonHeader, blueprintModel.asJsonString()))
88 UploadAction.VALIDATE.toString() -> {
89 // TODO("Not Implemented")
90 responseObserver.onNext(
93 "Upload action($uploadAction) not implemented",
94 BluePrintProcessorException("Not Implemented")
98 UploadAction.ENRICH.toString() -> {
99 val enrichedByteArray = bluePrintModelHandler.enrichBlueprintFileSource(byteArray)
100 responseObserver.onNext(outputWithFileBytes(request.commonHeader, enrichedByteArray))
103 responseObserver.onNext(
105 request.commonHeader,
106 "Upload action($uploadAction) not implemented",
107 BluePrintProcessorException("Not implemented")
112 } catch (e: Exception) {
113 responseObserver.onNext(
115 request.commonHeader,
116 "request(${request.commonHeader.requestId}): Failed to upload CBA", e
120 responseObserver.onCompleted()
125 @PreAuthorize("hasRole('USER')")
126 override fun downloadBlueprint(
127 request: BluePrintDownloadInput,
128 responseObserver: StreamObserver<BluePrintManagementOutput>
131 val blueprintName = request.actionIdentifiers.blueprintName
132 val blueprintVersion = request.actionIdentifiers.blueprintVersion
133 val blueprint = "blueprint $blueprintName:$blueprintVersion"
135 /** Get the Search Action */
136 val searchAction = request.actionIdentifiers?.actionName.emptyTONull()
137 ?: DownloadAction.SEARCH.toString()
139 log.info("request(${request.commonHeader.requestId}): Received download $blueprint")
141 when (searchAction) {
142 DownloadAction.SEARCH.toString() -> {
143 val downloadByteArray = bluePrintModelHandler.download(blueprintName, blueprintVersion)
144 responseObserver.onNext(outputWithFileBytes(request.commonHeader, downloadByteArray))
147 responseObserver.onNext(
149 request.commonHeader,
150 "Search action($searchAction) not implemented",
151 BluePrintProcessorException("Not implemented")
156 } catch (e: Exception) {
157 responseObserver.onNext(
159 request.commonHeader,
160 "request(${request.commonHeader.requestId}): Failed to delete $blueprint", e
164 responseObserver.onCompleted()
169 @PreAuthorize("hasRole('USER')")
170 override fun removeBlueprint(
171 request: BluePrintRemoveInput,
173 StreamObserver<BluePrintManagementOutput>
177 val blueprintName = request.actionIdentifiers.blueprintName
178 val blueprintVersion = request.actionIdentifiers.blueprintVersion
179 val blueprint = "blueprint $blueprintName:$blueprintVersion"
181 log.info("request(${request.commonHeader.requestId}): Received delete $blueprint")
183 /** Get the Remove Action */
184 val removeAction = request.actionIdentifiers?.actionName.emptyTONull()
185 ?: RemoveAction.DEFAULT.toString()
188 when (removeAction) {
189 RemoveAction.DEFAULT.toString() -> {
190 bluePrintModelHandler.deleteBlueprintModel(blueprintName, blueprintVersion)
191 responseObserver.onNext(successStatus(request.commonHeader))
194 responseObserver.onNext(
196 request.commonHeader,
197 "Remove action($removeAction) not implemented",
198 BluePrintProcessorException("Not implemented")
203 } catch (e: Exception) {
204 responseObserver.onNext(
206 request.commonHeader,
207 "request(${request.commonHeader.requestId}): Failed to delete $blueprint", e
211 responseObserver.onCompleted()
216 override fun bootstrapBlueprint(
217 request: BluePrintBootstrapInput,
218 responseObserver: StreamObserver<BluePrintManagementOutput>
222 log.info("request(${request.commonHeader.requestId}): Received bootstrap request")
223 val bootstrapRequest = BootstrapRequest().apply {
224 loadModelType = request.loadModelType
225 loadResourceDictionary = request.loadResourceDictionary
226 loadCBA = request.loadCBA
228 /** Perform bootstrap of Model Types, Resource Definitions and CBA */
229 bluePrintModelHandler.bootstrapBlueprint(bootstrapRequest)
230 responseObserver.onNext(successStatus(request.commonHeader))
231 } catch (e: Exception) {
232 responseObserver.onNext(
234 request.commonHeader,
235 "request(${request.commonHeader.requestId}): Failed to bootstrap", e
239 responseObserver.onCompleted()
244 private fun outputWithFileBytes(header: CommonHeader, byteArray: ByteArray): BluePrintManagementOutput =
245 BluePrintManagementOutput.newBuilder()
246 .setCommonHeader(header)
247 .setFileChunk(FileChunk.newBuilder().setChunk(ByteString.copyFrom(byteArray)))
250 .setTimestamp(currentTimestamp())
251 .setEventType(EventType.EVENT_COMPONENT_EXECUTED)
252 .setMessage(BluePrintConstants.STATUS_SUCCESS)
258 private fun successStatus(header: CommonHeader, propertyContent: String? = null): BluePrintManagementOutput {
259 // Populate Response Payload
260 val propertiesBuilder = BluePrintManagementOutput.newBuilder().propertiesBuilder
261 propertyContent?.let {
262 JsonFormat.parser().merge(propertyContent, propertiesBuilder)
264 return BluePrintManagementOutput.newBuilder()
265 .setCommonHeader(header)
266 .setProperties(propertiesBuilder.build())
269 .setTimestamp(currentTimestamp())
270 .setMessage(BluePrintConstants.STATUS_SUCCESS)
271 .setEventType(EventType.EVENT_COMPONENT_EXECUTED)
278 private fun failStatus(header: CommonHeader, message: String, e: Exception): BluePrintManagementOutput {
279 log.error(message, e)
280 return if (e is BluePrintProcessorException) onErrorCatalog(header, message, e) else onError(header, message, e)
283 private fun onError(header: CommonHeader, message: String, error: Exception): BluePrintManagementOutput {
284 val code = GrpcErrorCodes.code(ErrorCatalogCodes.GENERIC_FAILURE)
285 return BluePrintManagementOutput.newBuilder()
286 .setCommonHeader(header)
289 .setTimestamp(currentTimestamp())
290 .setMessage(BluePrintConstants.STATUS_FAILURE)
291 .setEventType(EventType.EVENT_COMPONENT_FAILURE)
292 .setErrorMessage("Error : $message \n Details: ${error.errorMessageOrDefault()}")
299 private fun onErrorCatalog(header: CommonHeader, message: String, error: BluePrintProcessorException):
300 BluePrintManagementOutput {
301 val err = if (error.protocol == "") {
302 error.grpc(ErrorCatalogCodes.GENERIC_FAILURE)
304 error.convertToGrpc()
306 val errorPayload = errorCatalogService.errorPayload(err.addErrorPayloadMessage(message))
307 return BluePrintManagementOutput.newBuilder()
308 .setCommonHeader(header)
311 .setTimestamp(currentTimestamp())
312 .setMessage(BluePrintConstants.STATUS_FAILURE)
313 .setEventType(EventType.EVENT_COMPONENT_FAILURE)
314 .setErrorMessage("Error : ${errorPayload.message}")
315 .setCode(errorPayload.code)