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.Status
28 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
29 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
30 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonString
31 import org.onap.ccsdk.cds.controllerblueprints.core.emptyTONull
32 import org.onap.ccsdk.cds.controllerblueprints.core.utils.currentTimestamp
33 import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintBootstrapInput
34 import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintDownloadInput
35 import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintManagementOutput
36 import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintManagementServiceGrpc
37 import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintRemoveInput
38 import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintUploadInput
39 import org.onap.ccsdk.cds.controllerblueprints.management.api.DownloadAction
40 import org.onap.ccsdk.cds.controllerblueprints.management.api.FileChunk
41 import org.onap.ccsdk.cds.controllerblueprints.management.api.RemoveAction
42 import org.onap.ccsdk.cds.controllerblueprints.management.api.UploadAction
43 import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogCodes
44 import org.onap.ccsdk.cds.error.catalog.core.GrpcErrorCodes
45 import org.onap.ccsdk.cds.error.catalog.core.utils.errorMessageOrDefault
46 import org.onap.ccsdk.cds.error.catalog.services.ErrorCatalogService
47 import org.slf4j.LoggerFactory
48 import org.springframework.security.access.prepost.PreAuthorize
49 import org.springframework.stereotype.Service
51 // TODO("Convert to coroutines handler")
53 open class BluePrintManagementGRPCHandler(
54 private val bluePrintModelHandler: BluePrintModelHandler,
55 private val errorCatalogService: ErrorCatalogService
57 BluePrintManagementServiceGrpc.BluePrintManagementServiceImplBase() {
59 private val log = LoggerFactory.getLogger(BluePrintManagementGRPCHandler::class.java)
61 @PreAuthorize("hasRole('USER')")
62 override fun uploadBlueprint(
63 request: BluePrintUploadInput,
64 responseObserver: StreamObserver<BluePrintManagementOutput>
68 // TODO("catch if request id is missing")
69 log.info("request(${request.commonHeader.requestId})")
71 /** Get the file byte array */
72 val byteArray = request.fileChunk.chunk.toByteArray()
73 /** Get the Upload Action */
74 val uploadAction = request.actionIdentifiers?.actionName.emptyTONull()
75 ?: UploadAction.DRAFT.toString()
78 UploadAction.DRAFT.toString() -> {
79 val blueprintModel = bluePrintModelHandler.upload(byteArray, false)
80 responseObserver.onNext(successStatus(request.commonHeader, blueprintModel.asJsonString()))
82 UploadAction.PUBLISH.toString() -> {
83 val blueprintModel = bluePrintModelHandler.upload(byteArray, true)
84 responseObserver.onNext(successStatus(request.commonHeader, blueprintModel.asJsonString()))
86 UploadAction.VALIDATE.toString() -> {
87 // TODO("Not Implemented")
88 responseObserver.onNext(
91 "Upload action($uploadAction) not implemented",
92 BluePrintProcessorException("Not Implemented")
96 UploadAction.ENRICH.toString() -> {
97 val enrichedByteArray = bluePrintModelHandler.enrichBlueprintFileSource(byteArray)
98 responseObserver.onNext(outputWithFileBytes(request.commonHeader, enrichedByteArray))
101 responseObserver.onNext(
103 request.commonHeader,
104 "Upload action($uploadAction) not implemented",
105 BluePrintProcessorException("Not implemented")
110 } catch (e: Exception) {
111 responseObserver.onNext(
113 request.commonHeader,
114 "request(${request.commonHeader.requestId}): Failed to upload CBA", e
118 responseObserver.onCompleted()
123 @PreAuthorize("hasRole('USER')")
124 override fun downloadBlueprint(
125 request: BluePrintDownloadInput,
126 responseObserver: StreamObserver<BluePrintManagementOutput>
129 val blueprintName = request.actionIdentifiers.blueprintName
130 val blueprintVersion = request.actionIdentifiers.blueprintVersion
131 val blueprint = "blueprint $blueprintName:$blueprintVersion"
133 /** Get the Search Action */
134 val searchAction = request.actionIdentifiers?.actionName.emptyTONull()
135 ?: DownloadAction.SEARCH.toString()
137 log.info("request(${request.commonHeader.requestId}): Received download $blueprint")
139 when (searchAction) {
140 DownloadAction.SEARCH.toString() -> {
141 val downloadByteArray = bluePrintModelHandler.download(blueprintName, blueprintVersion)
142 responseObserver.onNext(outputWithFileBytes(request.commonHeader, downloadByteArray))
145 responseObserver.onNext(
147 request.commonHeader,
148 "Search action($searchAction) not implemented",
149 BluePrintProcessorException("Not implemented")
154 } catch (e: Exception) {
155 responseObserver.onNext(
157 request.commonHeader,
158 "request(${request.commonHeader.requestId}): Failed to delete $blueprint", e
162 responseObserver.onCompleted()
167 @PreAuthorize("hasRole('USER')")
168 override fun removeBlueprint(
169 request: BluePrintRemoveInput,
171 StreamObserver<BluePrintManagementOutput>
175 val blueprintName = request.actionIdentifiers.blueprintName
176 val blueprintVersion = request.actionIdentifiers.blueprintVersion
177 val blueprint = "blueprint $blueprintName:$blueprintVersion"
179 log.info("request(${request.commonHeader.requestId}): Received delete $blueprint")
181 /** Get the Remove Action */
182 val removeAction = request.actionIdentifiers?.actionName.emptyTONull()
183 ?: RemoveAction.DEFAULT.toString()
186 when (removeAction) {
187 RemoveAction.DEFAULT.toString() -> {
188 bluePrintModelHandler.deleteBlueprintModel(blueprintName, blueprintVersion)
189 responseObserver.onNext(successStatus(request.commonHeader))
192 responseObserver.onNext(
194 request.commonHeader,
195 "Remove action($removeAction) not implemented",
196 BluePrintProcessorException("Not implemented")
201 } catch (e: Exception) {
202 responseObserver.onNext(
204 request.commonHeader,
205 "request(${request.commonHeader.requestId}): Failed to delete $blueprint", e
209 responseObserver.onCompleted()
214 override fun bootstrapBlueprint(
215 request: BluePrintBootstrapInput,
216 responseObserver: StreamObserver<BluePrintManagementOutput>
220 log.info("request(${request.commonHeader.requestId}): Received bootstrap request")
221 val bootstrapRequest = BootstrapRequest().apply {
222 loadModelType = request.loadModelType
223 loadResourceDictionary = request.loadResourceDictionary
224 loadCBA = request.loadCBA
226 /** Perform bootstrap of Model Types, Resource Definitions and CBA */
227 bluePrintModelHandler.bootstrapBlueprint(bootstrapRequest)
228 responseObserver.onNext(successStatus(request.commonHeader))
229 } catch (e: Exception) {
230 responseObserver.onNext(
232 request.commonHeader,
233 "request(${request.commonHeader.requestId}): Failed to bootstrap", e
237 responseObserver.onCompleted()
242 private fun outputWithFileBytes(header: CommonHeader, byteArray: ByteArray): BluePrintManagementOutput =
243 BluePrintManagementOutput.newBuilder()
244 .setCommonHeader(header)
245 .setFileChunk(FileChunk.newBuilder().setChunk(ByteString.copyFrom(byteArray)))
248 .setTimestamp(currentTimestamp())
249 .setMessage(BluePrintConstants.STATUS_SUCCESS)
255 private fun successStatus(header: CommonHeader, propertyContent: String? = null): BluePrintManagementOutput {
256 // Populate Response Payload
257 val propertiesBuilder = BluePrintManagementOutput.newBuilder().propertiesBuilder
258 propertyContent?.let {
259 JsonFormat.parser().merge(propertyContent, propertiesBuilder)
261 return BluePrintManagementOutput.newBuilder()
262 .setCommonHeader(header)
263 .setProperties(propertiesBuilder.build())
266 .setTimestamp(currentTimestamp())
267 .setMessage(BluePrintConstants.STATUS_SUCCESS)
274 private fun failStatus(header: CommonHeader, message: String, e: Exception): BluePrintManagementOutput {
275 log.error(message, e)
276 return if (e is BluePrintProcessorException) onErrorCatalog(header, message, e) else onError(header, message, e)
279 private fun onError(header: CommonHeader, message: String, error: Exception): BluePrintManagementOutput {
280 val code = GrpcErrorCodes.code(ErrorCatalogCodes.GENERIC_FAILURE)
281 return BluePrintManagementOutput.newBuilder()
282 .setCommonHeader(header)
285 .setTimestamp(currentTimestamp())
286 .setMessage(BluePrintConstants.STATUS_FAILURE)
287 .setErrorMessage("Error : $message \n Details: ${error.errorMessageOrDefault()}")
294 private fun onErrorCatalog(header: CommonHeader, message: String, error: BluePrintProcessorException):
295 BluePrintManagementOutput {
296 val err = if (error.protocol == "") {
297 error.grpc(ErrorCatalogCodes.GENERIC_FAILURE)
299 error.convertToGrpc()
301 val errorPayload = errorCatalogService.errorPayload(err.addErrorPayloadMessage(message))
302 return BluePrintManagementOutput.newBuilder()
303 .setCommonHeader(header)
306 .setTimestamp(currentTimestamp())
307 .setMessage(BluePrintConstants.STATUS_FAILURE)
308 .setErrorMessage("Error : ${errorPayload.message}")
309 .setCode(errorPayload.code)