Bootstrap Rest and GRPC API
[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.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.*
34 import org.slf4j.LoggerFactory
35 import org.springframework.security.access.prepost.PreAuthorize
36 import org.springframework.stereotype.Service
37
38 //TODO("Convert to coroutines handler")
39 @Service
40 open class BluePrintManagementGRPCHandler(private val bluePrintModelHandler: BluePrintModelHandler)
41     : BluePrintManagementServiceGrpc.BluePrintManagementServiceImplBase() {
42
43     private val log = LoggerFactory.getLogger(BluePrintManagementGRPCHandler::class.java)
44
45     @PreAuthorize("hasRole('USER')")
46     override fun uploadBlueprint(request: BluePrintUploadInput, responseObserver:
47     StreamObserver<BluePrintManagementOutput>) {
48
49         runBlocking {
50             //TODO("catch if request id is missing")
51             log.info("request(${request.commonHeader.requestId})")
52             try {
53                 /** Get the file byte array */
54                 val byteArray = request.fileChunk.chunk.toByteArray()
55                 /** Get the Upload Action */
56                 val uploadAction = request.actionIdentifiers?.actionName.emptyTONull()
57                         ?: UploadAction.DRAFT.toString()
58
59                 when (uploadAction) {
60                     UploadAction.DRAFT.toString() -> {
61                         val blueprintModel = bluePrintModelHandler.upload(byteArray, false)
62                         responseObserver.onNext(successStatus(request.commonHeader, blueprintModel.asJsonString()))
63                     }
64                     UploadAction.PUBLISH.toString() -> {
65                         val blueprintModel = bluePrintModelHandler.upload(byteArray, true)
66                         responseObserver.onNext(successStatus(request.commonHeader, blueprintModel.asJsonString()))
67                     }
68                     UploadAction.VALIDATE.toString() -> {
69                         //TODO("Not Implemented")
70                         responseObserver.onNext(failStatus(request.commonHeader,
71                                 "Upload action($uploadAction) not implemented",
72                                 BluePrintProcessorException("Not Implemented")))
73                     }
74                     UploadAction.ENRICH.toString() -> {
75                         val enrichedByteArray = bluePrintModelHandler.enrichBlueprintFileSource(byteArray)
76                         responseObserver.onNext(outputWithFileBytes(request.commonHeader, enrichedByteArray))
77                     }
78                     else -> {
79                         responseObserver.onNext(failStatus(request.commonHeader,
80                                 "Upload action($uploadAction) not implemented",
81                                 BluePrintProcessorException("Not implemented")))
82                     }
83                 }
84             } catch (e: Exception) {
85                 responseObserver.onNext(failStatus(request.commonHeader,
86                         "request(${request.commonHeader.requestId}): Failed to upload CBA", e))
87             } finally {
88                 responseObserver.onCompleted()
89             }
90         }
91     }
92
93     @PreAuthorize("hasRole('USER')")
94     override fun downloadBlueprint(request: BluePrintDownloadInput,
95                                    responseObserver: StreamObserver<BluePrintManagementOutput>) {
96         runBlocking {
97             val blueprintName = request.actionIdentifiers.blueprintName
98             val blueprintVersion = request.actionIdentifiers.blueprintVersion
99             val blueprint = "blueprint $blueprintName:$blueprintVersion"
100
101             /** Get the Search Action */
102             val searchAction = request.actionIdentifiers?.actionName.emptyTONull()
103                     ?: DownloadAction.SEARCH.toString()
104
105             log.info("request(${request.commonHeader.requestId}): Received download $blueprint")
106             try {
107                 when (searchAction) {
108                     DownloadAction.SEARCH.toString() -> {
109                         val downloadByteArray = bluePrintModelHandler.download(blueprintName, blueprintVersion)
110                         responseObserver.onNext(outputWithFileBytes(request.commonHeader, downloadByteArray))
111                     }
112                     else -> {
113                         responseObserver.onNext(failStatus(request.commonHeader,
114                                 "Search action($searchAction) not implemented",
115                                 BluePrintProcessorException("Not implemented")))
116                     }
117                 }
118             } catch (e: Exception) {
119                 responseObserver.onNext(failStatus(request.commonHeader,
120                         "request(${request.commonHeader.requestId}): Failed to delete $blueprint", e))
121             } finally {
122                 responseObserver.onCompleted()
123             }
124         }
125     }
126
127     @PreAuthorize("hasRole('USER')")
128     override fun removeBlueprint(request: BluePrintRemoveInput, responseObserver:
129     StreamObserver<BluePrintManagementOutput>) {
130
131         runBlocking {
132             val blueprintName = request.actionIdentifiers.blueprintName
133             val blueprintVersion = request.actionIdentifiers.blueprintVersion
134             val blueprint = "blueprint $blueprintName:$blueprintVersion"
135
136             log.info("request(${request.commonHeader.requestId}): Received delete $blueprint")
137
138             /** Get the Remove Action */
139             val removeAction = request.actionIdentifiers?.actionName.emptyTONull()
140                     ?: RemoveAction.DEFAULT.toString()
141
142             try {
143                 when (removeAction) {
144                     RemoveAction.DEFAULT.toString() -> {
145                         bluePrintModelHandler.deleteBlueprintModel(blueprintName, blueprintVersion)
146                         responseObserver.onNext(successStatus(request.commonHeader))
147                     }
148                     else -> {
149                         responseObserver.onNext(failStatus(request.commonHeader,
150                                 "Remove action($removeAction) not implemented",
151                                 BluePrintProcessorException("Not implemented")))
152                     }
153                 }
154             } catch (e: Exception) {
155                 responseObserver.onNext(failStatus(request.commonHeader,
156                         "request(${request.commonHeader.requestId}): Failed to delete $blueprint", e))
157             } finally {
158                 responseObserver.onCompleted()
159             }
160         }
161     }
162
163     override fun bootstrapBlueprint(request: BluePrintBootstrapInput,
164                                     responseObserver: StreamObserver<BluePrintManagementOutput>) {
165         runBlocking {
166             try {
167                 log.info("request(${request.commonHeader.requestId}): Received bootstrap request")
168                 val bootstrapRequest = BootstrapRequest().apply {
169                     loadModelType = request.loadModelType
170                     loadResourceDictionary = request.loadResourceDictionary
171                     loadCBA = request.loadCBA
172                 }
173                 /** Perform bootstrap of Model Types, Resource Definitions and CBA */
174                 bluePrintModelHandler.bootstrapBlueprint(bootstrapRequest)
175                 responseObserver.onNext(successStatus(request.commonHeader))
176
177             } catch (e: Exception) {
178                 responseObserver.onNext(failStatus(request.commonHeader,
179                         "request(${request.commonHeader.requestId}): Failed to bootstrap", e))
180             } finally {
181                 responseObserver.onCompleted()
182             }
183         }
184     }
185
186     private fun outputWithFileBytes(header: CommonHeader, byteArray: ByteArray): BluePrintManagementOutput =
187             BluePrintManagementOutput.newBuilder()
188                     .setCommonHeader(header)
189                     .setFileChunk(FileChunk.newBuilder().setChunk(ByteString.copyFrom(byteArray)))
190                     .setStatus(Status.newBuilder()
191                             .setTimestamp(currentTimestamp())
192                             .setMessage(BluePrintConstants.STATUS_SUCCESS)
193                             .setCode(200)
194                             .build())
195                     .build()
196
197     private fun successStatus(header: CommonHeader, propertyContent: String? = null): BluePrintManagementOutput {
198         // Populate Response Payload
199         val propertiesBuilder = BluePrintManagementOutput.newBuilder().propertiesBuilder
200         propertyContent?.let {
201             JsonFormat.parser().merge(propertyContent, propertiesBuilder)
202         }
203         return BluePrintManagementOutput.newBuilder()
204                 .setCommonHeader(header)
205                 .setProperties(propertiesBuilder.build())
206                 .setStatus(Status.newBuilder()
207                         .setTimestamp(currentTimestamp())
208                         .setMessage(BluePrintConstants.STATUS_SUCCESS)
209                         .setCode(200)
210                         .build())
211                 .build()
212     }
213
214     private fun failStatus(header: CommonHeader, message: String, e: Exception): BluePrintManagementOutput {
215         log.error(message, e)
216         return BluePrintManagementOutput.newBuilder()
217                 .setCommonHeader(header)
218                 .setStatus(Status.newBuilder()
219                         .setTimestamp(currentTimestamp())
220                         .setMessage(BluePrintConstants.STATUS_FAILURE)
221                         .setErrorMessage(message)
222                         .setCode(500)
223                         .build())
224                 .build()
225 //        return io.grpc.Status.INTERNAL
226 //                .withDescription(message)
227 //                .withCause(e)
228 //                .asException()
229     }
230 }