Renaming Files having BluePrint to have Blueprint
[ccsdk/cds.git] / ms / blueprintsprocessor / modules / inbounds / designer-api / src / main / kotlin / org / onap / ccsdk / cds / blueprintsprocessor / designer / api / BlueprintManagementGRPCHandler.kt
1 /*
2  * Copyright © 2017-2018 AT&T Intellectual Property.
3  * Modifications Copyright © 2019 Bell Canada.
4  * Modifications Copyright © 2019 IBM.
5  *
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
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19 package org.onap.ccsdk.cds.blueprintsprocessor.designer.api
20
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
51
52 // TODO("Convert to coroutines handler")
53 @Service
54 open class BlueprintManagementGRPCHandler(
55     private val bluePrintModelHandler: BlueprintModelHandler,
56     private val errorCatalogService: ErrorCatalogService
57 ) :
58     BlueprintManagementServiceGrpc.BlueprintManagementServiceImplBase() {
59
60     private val log = LoggerFactory.getLogger(BlueprintManagementGRPCHandler::class.java)
61
62     @PreAuthorize("hasRole('USER')")
63     override fun uploadBlueprint(
64         request: BlueprintUploadInput,
65         responseObserver: StreamObserver<BlueprintManagementOutput>
66     ) {
67
68         runBlocking {
69             // TODO("catch if request id is missing")
70             log.info("request(${request.commonHeader.requestId})")
71             try {
72                 /** Get the file byte array */
73                 val byteArray = request.fileChunk.chunk.toByteArray()
74
75                 /** Get the Upload Action */
76                 val uploadAction = request.actionIdentifiers?.actionName.emptyTONull()
77                     ?: UploadAction.DRAFT.toString()
78
79                 when (uploadAction) {
80                     UploadAction.DRAFT.toString() -> {
81                         val blueprintModel = bluePrintModelHandler.upload(byteArray, false)
82                         responseObserver.onNext(successStatus(request.commonHeader, blueprintModel.asJsonString()))
83                     }
84                     UploadAction.PUBLISH.toString() -> {
85                         val blueprintModel = bluePrintModelHandler.upload(byteArray, true)
86                         responseObserver.onNext(successStatus(request.commonHeader, blueprintModel.asJsonString()))
87                     }
88                     UploadAction.VALIDATE.toString() -> {
89                         // TODO("Not Implemented")
90                         responseObserver.onNext(
91                             failStatus(
92                                 request.commonHeader,
93                                 "Upload action($uploadAction) not implemented",
94                                 BlueprintProcessorException("Not Implemented")
95                             )
96                         )
97                     }
98                     UploadAction.ENRICH.toString() -> {
99                         val enrichedByteArray = bluePrintModelHandler.enrichBlueprintFileSource(byteArray)
100                         responseObserver.onNext(outputWithFileBytes(request.commonHeader, enrichedByteArray))
101                     }
102                     else -> {
103                         responseObserver.onNext(
104                             failStatus(
105                                 request.commonHeader,
106                                 "Upload action($uploadAction) not implemented",
107                                 BlueprintProcessorException("Not implemented")
108                             )
109                         )
110                     }
111                 }
112             } catch (e: Exception) {
113                 responseObserver.onNext(
114                     failStatus(
115                         request.commonHeader,
116                         "request(${request.commonHeader.requestId}): Failed to upload CBA", e
117                     )
118                 )
119             } finally {
120                 responseObserver.onCompleted()
121             }
122         }
123     }
124
125     @PreAuthorize("hasRole('USER')")
126     override fun downloadBlueprint(
127         request: BlueprintDownloadInput,
128         responseObserver: StreamObserver<BlueprintManagementOutput>
129     ) {
130         runBlocking {
131             val blueprintName = request.actionIdentifiers.blueprintName
132             val blueprintVersion = request.actionIdentifiers.blueprintVersion
133             val blueprint = "blueprint $blueprintName:$blueprintVersion"
134
135             /** Get the Search Action */
136             val searchAction = request.actionIdentifiers?.actionName.emptyTONull()
137                 ?: DownloadAction.SEARCH.toString()
138
139             log.info("request(${request.commonHeader.requestId}): Received download $blueprint")
140             try {
141                 when (searchAction) {
142                     DownloadAction.SEARCH.toString() -> {
143                         val downloadByteArray = bluePrintModelHandler.download(blueprintName, blueprintVersion)
144                         responseObserver.onNext(outputWithFileBytes(request.commonHeader, downloadByteArray))
145                     }
146                     else -> {
147                         responseObserver.onNext(
148                             failStatus(
149                                 request.commonHeader,
150                                 "Search action($searchAction) not implemented",
151                                 BlueprintProcessorException("Not implemented")
152                             )
153                         )
154                     }
155                 }
156             } catch (e: Exception) {
157                 responseObserver.onNext(
158                     failStatus(
159                         request.commonHeader,
160                         "request(${request.commonHeader.requestId}): Failed to delete $blueprint", e
161                     )
162                 )
163             } finally {
164                 responseObserver.onCompleted()
165             }
166         }
167     }
168
169     @PreAuthorize("hasRole('USER')")
170     override fun removeBlueprint(
171         request: BlueprintRemoveInput,
172         responseObserver:
173             StreamObserver<BlueprintManagementOutput>
174     ) {
175
176         runBlocking {
177             val blueprintName = request.actionIdentifiers.blueprintName
178             val blueprintVersion = request.actionIdentifiers.blueprintVersion
179             val blueprint = "blueprint $blueprintName:$blueprintVersion"
180
181             log.info("request(${request.commonHeader.requestId}): Received delete $blueprint")
182
183             /** Get the Remove Action */
184             val removeAction = request.actionIdentifiers?.actionName.emptyTONull()
185                 ?: RemoveAction.DEFAULT.toString()
186
187             try {
188                 when (removeAction) {
189                     RemoveAction.DEFAULT.toString() -> {
190                         bluePrintModelHandler.deleteBlueprintModel(blueprintName, blueprintVersion)
191                         responseObserver.onNext(successStatus(request.commonHeader))
192                     }
193                     else -> {
194                         responseObserver.onNext(
195                             failStatus(
196                                 request.commonHeader,
197                                 "Remove action($removeAction) not implemented",
198                                 BlueprintProcessorException("Not implemented")
199                             )
200                         )
201                     }
202                 }
203             } catch (e: Exception) {
204                 responseObserver.onNext(
205                     failStatus(
206                         request.commonHeader,
207                         "request(${request.commonHeader.requestId}): Failed to delete $blueprint", e
208                     )
209                 )
210             } finally {
211                 responseObserver.onCompleted()
212             }
213         }
214     }
215
216     override fun bootstrapBlueprint(
217         request: BlueprintBootstrapInput,
218         responseObserver: StreamObserver<BlueprintManagementOutput>
219     ) {
220         runBlocking {
221             try {
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
227                 }
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(
233                     failStatus(
234                         request.commonHeader,
235                         "request(${request.commonHeader.requestId}): Failed to bootstrap", e
236                     )
237                 )
238             } finally {
239                 responseObserver.onCompleted()
240             }
241         }
242     }
243
244     private fun outputWithFileBytes(header: CommonHeader, byteArray: ByteArray): BlueprintManagementOutput =
245         BlueprintManagementOutput.newBuilder()
246             .setCommonHeader(header)
247             .setFileChunk(FileChunk.newBuilder().setChunk(ByteString.copyFrom(byteArray)))
248             .setStatus(
249                 Status.newBuilder()
250                     .setTimestamp(currentTimestamp())
251                     .setEventType(EventType.EVENT_COMPONENT_EXECUTED)
252                     .setMessage(BlueprintConstants.STATUS_SUCCESS)
253                     .setCode(200)
254                     .build()
255             )
256             .build()
257
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)
263         }
264         return BlueprintManagementOutput.newBuilder()
265             .setCommonHeader(header)
266             .setProperties(propertiesBuilder.build())
267             .setStatus(
268                 Status.newBuilder()
269                     .setTimestamp(currentTimestamp())
270                     .setMessage(BlueprintConstants.STATUS_SUCCESS)
271                     .setEventType(EventType.EVENT_COMPONENT_EXECUTED)
272                     .setCode(200)
273                     .build()
274             )
275             .build()
276     }
277
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)
281     }
282
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)
287             .setStatus(
288                 Status.newBuilder()
289                     .setTimestamp(currentTimestamp())
290                     .setMessage(BlueprintConstants.STATUS_FAILURE)
291                     .setEventType(EventType.EVENT_COMPONENT_FAILURE)
292                     .setErrorMessage("Error : $message \n Details: ${error.errorMessageOrDefault()}")
293                     .setCode(code)
294                     .build()
295             )
296             .build()
297     }
298
299     private fun onErrorCatalog(header: CommonHeader, message: String, error: BlueprintProcessorException):
300         BlueprintManagementOutput {
301             val err = if (error.protocol == "") {
302                 error.grpc(ErrorCatalogCodes.GENERIC_FAILURE)
303             } else {
304                 error.convertToGrpc()
305             }
306             val errorPayload = errorCatalogService.errorPayload(err.addErrorPayloadMessage(message))
307             return BlueprintManagementOutput.newBuilder()
308                 .setCommonHeader(header)
309                 .setStatus(
310                     Status.newBuilder()
311                         .setTimestamp(currentTimestamp())
312                         .setMessage(BlueprintConstants.STATUS_FAILURE)
313                         .setEventType(EventType.EVENT_COMPONENT_FAILURE)
314                         .setErrorMessage("Error : ${errorPayload.message}")
315                         .setCode(errorPayload.code)
316                         .build()
317                 )
318                 .build()
319         }
320 }