package org.onap.ccsdk.cds.blueprintsprocessor.designer.api
-import io.grpc.StatusException
+import com.google.protobuf.ByteString
+import com.google.protobuf.util.JsonFormat
import io.grpc.stub.StreamObserver
import kotlinx.coroutines.runBlocking
+import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.handler.BluePrintModelHandler
import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader
import org.onap.ccsdk.cds.controllerblueprints.common.api.Status
-import org.onap.ccsdk.cds.controllerblueprints.core.*
-import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfiguration
-import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService
-import org.onap.ccsdk.cds.controllerblueprints.core.scripts.BluePrintCompileCache
-import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintFileUtils
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonString
+import org.onap.ccsdk.cds.controllerblueprints.core.emptyTONull
import org.onap.ccsdk.cds.controllerblueprints.core.utils.currentTimestamp
-import org.onap.ccsdk.cds.controllerblueprints.management.api.*
+import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintBootstrapInput
+import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintDownloadInput
+import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintManagementOutput
+import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintManagementServiceGrpc
+import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintRemoveInput
+import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintUploadInput
+import org.onap.ccsdk.cds.controllerblueprints.management.api.DownloadAction
+import org.onap.ccsdk.cds.controllerblueprints.management.api.FileChunk
+import org.onap.ccsdk.cds.controllerblueprints.management.api.RemoveAction
+import org.onap.ccsdk.cds.controllerblueprints.management.api.UploadAction
+import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogCodes
+import org.onap.ccsdk.cds.error.catalog.core.GrpcErrorCodes
+import org.onap.ccsdk.cds.error.catalog.core.utils.errorMessageOrDefault
+import org.onap.ccsdk.cds.error.catalog.services.ErrorCatalogService
import org.slf4j.LoggerFactory
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.stereotype.Service
-import java.io.File
-import java.util.*
+// TODO("Convert to coroutines handler")
@Service
-open class BluePrintManagementGRPCHandler(private val bluePrintLoadConfiguration: BluePrintLoadConfiguration,
- private val blueprintsProcessorCatalogService: BluePrintCatalogService)
- : BluePrintManagementServiceGrpc.BluePrintManagementServiceImplBase() {
+open class BluePrintManagementGRPCHandler(
+ private val bluePrintModelHandler: BluePrintModelHandler,
+ private val errorCatalogService: ErrorCatalogService
+) :
+ BluePrintManagementServiceGrpc.BluePrintManagementServiceImplBase() {
private val log = LoggerFactory.getLogger(BluePrintManagementGRPCHandler::class.java)
@PreAuthorize("hasRole('USER')")
- override fun uploadBlueprint(request: BluePrintUploadInput, responseObserver:
- StreamObserver<BluePrintManagementOutput>) {
- runBlocking {
+ override fun uploadBlueprint(
+ request: BluePrintUploadInput,
+ responseObserver: StreamObserver<BluePrintManagementOutput>
+ ) {
+ runBlocking {
+ // TODO("catch if request id is missing")
log.info("request(${request.commonHeader.requestId})")
- val uploadId = UUID.randomUUID().toString()
- val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, uploadId)
- val blueprintWorking = normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, uploadId)
try {
- val cbaFile = normalizedFile(blueprintArchive, "cba.zip")
-
- saveToDisk(request, cbaFile)
-
+ /** Get the file byte array */
+ val byteArray = request.fileChunk.chunk.toByteArray()
+ /** Get the Upload Action */
val uploadAction = request.actionIdentifiers?.actionName.emptyTONull()
- ?: UploadAction.DRAFT.toString()
+ ?: UploadAction.DRAFT.toString()
when (uploadAction) {
UploadAction.DRAFT.toString() -> {
- val blueprintId = blueprintsProcessorCatalogService.saveToDatabase(uploadId, cbaFile, false)
- responseObserver.onNext(successStatus("Successfully uploaded CBA($blueprintId)...",
- request.commonHeader))
+ val blueprintModel = bluePrintModelHandler.upload(byteArray, false)
+ responseObserver.onNext(successStatus(request.commonHeader, blueprintModel.asJsonString()))
}
UploadAction.PUBLISH.toString() -> {
- val blueprintId = blueprintsProcessorCatalogService.saveToDatabase(uploadId, cbaFile, true)
- responseObserver.onNext(successStatus("Successfully uploaded CBA($blueprintId)...",
- request.commonHeader))
+ val blueprintModel = bluePrintModelHandler.upload(byteArray, true)
+ responseObserver.onNext(successStatus(request.commonHeader, blueprintModel.asJsonString()))
}
UploadAction.VALIDATE.toString() -> {
- //TODO("Not Implemented")
- responseObserver.onError(failStatus("Not Implemented",
- BluePrintProcessorException("Not Implemented")))
+ // TODO("Not Implemented")
+ responseObserver.onNext(
+ failStatus(
+ request.commonHeader,
+ "Upload action($uploadAction) not implemented",
+ BluePrintProcessorException("Not Implemented")
+ )
+ )
}
UploadAction.ENRICH.toString() -> {
- //TODO("Not Implemented")
- responseObserver.onError(failStatus("Not Implemented",
- BluePrintProcessorException("Not Implemented")))
+ val enrichedByteArray = bluePrintModelHandler.enrichBlueprintFileSource(byteArray)
+ responseObserver.onNext(outputWithFileBytes(request.commonHeader, enrichedByteArray))
+ }
+ else -> {
+ responseObserver.onNext(
+ failStatus(
+ request.commonHeader,
+ "Upload action($uploadAction) not implemented",
+ BluePrintProcessorException("Not implemented")
+ )
+ )
}
}
+ } catch (e: Exception) {
+ responseObserver.onNext(
+ failStatus(
+ request.commonHeader,
+ "request(${request.commonHeader.requestId}): Failed to upload CBA", e
+ )
+ )
+ } finally {
responseObserver.onCompleted()
+ }
+ }
+ }
+
+ @PreAuthorize("hasRole('USER')")
+ override fun downloadBlueprint(
+ request: BluePrintDownloadInput,
+ responseObserver: StreamObserver<BluePrintManagementOutput>
+ ) {
+ runBlocking {
+ val blueprintName = request.actionIdentifiers.blueprintName
+ val blueprintVersion = request.actionIdentifiers.blueprintVersion
+ val blueprint = "blueprint $blueprintName:$blueprintVersion"
+
+ /** Get the Search Action */
+ val searchAction = request.actionIdentifiers?.actionName.emptyTONull()
+ ?: DownloadAction.SEARCH.toString()
+
+ log.info("request(${request.commonHeader.requestId}): Received download $blueprint")
+ try {
+ when (searchAction) {
+ DownloadAction.SEARCH.toString() -> {
+ val downloadByteArray = bluePrintModelHandler.download(blueprintName, blueprintVersion)
+ responseObserver.onNext(outputWithFileBytes(request.commonHeader, downloadByteArray))
+ }
+ else -> {
+ responseObserver.onNext(
+ failStatus(
+ request.commonHeader,
+ "Search action($searchAction) not implemented",
+ BluePrintProcessorException("Not implemented")
+ )
+ )
+ }
+ }
} catch (e: Exception) {
- responseObserver.onError(failStatus("request(${request.commonHeader.requestId}): Failed to upload CBA", e))
+ responseObserver.onNext(
+ failStatus(
+ request.commonHeader,
+ "request(${request.commonHeader.requestId}): Failed to delete $blueprint", e
+ )
+ )
} finally {
- // Clean blueprint script cache
- val cacheKey = BluePrintFileUtils
- .compileCacheKey(normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, uploadId))
- BluePrintCompileCache.cleanClassLoader(cacheKey)
- deleteNBDir(blueprintArchive)
- deleteNBDir(blueprintWorking)
+ responseObserver.onCompleted()
}
}
}
@PreAuthorize("hasRole('USER')")
- override fun removeBlueprint(request: BluePrintRemoveInput, responseObserver:
- StreamObserver<BluePrintManagementOutput>) {
+ override fun removeBlueprint(
+ request: BluePrintRemoveInput,
+ responseObserver:
+ StreamObserver<BluePrintManagementOutput>
+ ) {
runBlocking {
- val blueprintName = request.blueprintName
- val blueprintVersion = request.blueprintVersion
+ val blueprintName = request.actionIdentifiers.blueprintName
+ val blueprintVersion = request.actionIdentifiers.blueprintVersion
val blueprint = "blueprint $blueprintName:$blueprintVersion"
log.info("request(${request.commonHeader.requestId}): Received delete $blueprint")
+ /** Get the Remove Action */
+ val removeAction = request.actionIdentifiers?.actionName.emptyTONull()
+ ?: RemoveAction.DEFAULT.toString()
try {
- blueprintsProcessorCatalogService.deleteFromDatabase(blueprintName, blueprintVersion)
- responseObserver.onNext(successStatus("Successfully deleted $blueprint", request.commonHeader))
- responseObserver.onCompleted()
+ when (removeAction) {
+ RemoveAction.DEFAULT.toString() -> {
+ bluePrintModelHandler.deleteBlueprintModel(blueprintName, blueprintVersion)
+ responseObserver.onNext(successStatus(request.commonHeader))
+ }
+ else -> {
+ responseObserver.onNext(
+ failStatus(
+ request.commonHeader,
+ "Remove action($removeAction) not implemented",
+ BluePrintProcessorException("Not implemented")
+ )
+ )
+ }
+ }
} catch (e: Exception) {
- responseObserver.onError(failStatus("request(${request.commonHeader.requestId}): Failed to delete $blueprint", e))
+ responseObserver.onNext(
+ failStatus(
+ request.commonHeader,
+ "request(${request.commonHeader.requestId}): Failed to delete $blueprint", e
+ )
+ )
+ } finally {
+ responseObserver.onCompleted()
}
}
}
- private fun saveToDisk(request: BluePrintUploadInput, cbaFile: File) {
- log.info("request(${request.commonHeader.requestId}): Writing CBA File under :${cbaFile.absolutePath}")
+ override fun bootstrapBlueprint(
+ request: BluePrintBootstrapInput,
+ responseObserver: StreamObserver<BluePrintManagementOutput>
+ ) {
+ runBlocking {
+ try {
+ log.info("request(${request.commonHeader.requestId}): Received bootstrap request")
+ val bootstrapRequest = BootstrapRequest().apply {
+ loadModelType = request.loadModelType
+ loadResourceDictionary = request.loadResourceDictionary
+ loadCBA = request.loadCBA
+ }
+ /** Perform bootstrap of Model Types, Resource Definitions and CBA */
+ bluePrintModelHandler.bootstrapBlueprint(bootstrapRequest)
+ responseObserver.onNext(successStatus(request.commonHeader))
+ } catch (e: Exception) {
+ responseObserver.onNext(
+ failStatus(
+ request.commonHeader,
+ "request(${request.commonHeader.requestId}): Failed to bootstrap", e
+ )
+ )
+ } finally {
+ responseObserver.onCompleted()
+ }
+ }
+ }
- // Recreate Folder
- cbaFile.parentFile.reCreateDirs()
+ private fun outputWithFileBytes(header: CommonHeader, byteArray: ByteArray): BluePrintManagementOutput =
+ BluePrintManagementOutput.newBuilder()
+ .setCommonHeader(header)
+ .setFileChunk(FileChunk.newBuilder().setChunk(ByteString.copyFrom(byteArray)))
+ .setStatus(
+ Status.newBuilder()
+ .setTimestamp(currentTimestamp())
+ .setMessage(BluePrintConstants.STATUS_SUCCESS)
+ .setCode(200)
+ .build()
+ )
+ .build()
- // Write the File
- cbaFile.writeBytes(request.fileChunk.chunk.toByteArray()).apply {
- log.info("request(${request.commonHeader.requestId}): CBA file(${cbaFile.absolutePath} written successfully")
+ private fun successStatus(header: CommonHeader, propertyContent: String? = null): BluePrintManagementOutput {
+ // Populate Response Payload
+ val propertiesBuilder = BluePrintManagementOutput.newBuilder().propertiesBuilder
+ propertyContent?.let {
+ JsonFormat.parser().merge(propertyContent, propertiesBuilder)
}
+ return BluePrintManagementOutput.newBuilder()
+ .setCommonHeader(header)
+ .setProperties(propertiesBuilder.build())
+ .setStatus(
+ Status.newBuilder()
+ .setTimestamp(currentTimestamp())
+ .setMessage(BluePrintConstants.STATUS_SUCCESS)
+ .setCode(200)
+ .build()
+ )
+ .build()
+ }
+ private fun failStatus(header: CommonHeader, message: String, e: Exception): BluePrintManagementOutput {
+ log.error(message, e)
+ return if (e is BluePrintProcessorException) onErrorCatalog(header, message, e) else onError(header, message, e)
}
- private fun successStatus(message: String, header: CommonHeader): BluePrintManagementOutput =
- BluePrintManagementOutput.newBuilder()
- .setCommonHeader(header)
- .setStatus(Status.newBuilder()
- .setTimestamp(currentTimestamp())
- .setMessage(message)
- .setCode(200)
- .build())
- .build()
+ private fun onError(header: CommonHeader, message: String, error: Exception): BluePrintManagementOutput {
+ val code = GrpcErrorCodes.code(ErrorCatalogCodes.GENERIC_FAILURE)
+ return BluePrintManagementOutput.newBuilder()
+ .setCommonHeader(header)
+ .setStatus(
+ Status.newBuilder()
+ .setTimestamp(currentTimestamp())
+ .setMessage(BluePrintConstants.STATUS_FAILURE)
+ .setErrorMessage("Error : $message \n Details: ${error.errorMessageOrDefault()}")
+ .setCode(code)
+ .build()
+ )
+ .build()
+ }
- private fun failStatus(message: String, e: Exception): StatusException {
- log.error(message, e)
- return io.grpc.Status.INTERNAL
- .withDescription(message)
- .withCause(e)
- .asException()
+ private fun onErrorCatalog(header: CommonHeader, message: String, error: BluePrintProcessorException):
+ BluePrintManagementOutput {
+ val err = if (error.protocol == "") {
+ error.grpc(ErrorCatalogCodes.GENERIC_FAILURE)
+ } else {
+ error.convertToGrpc()
+ }
+ val errorPayload = errorCatalogService.errorPayload(err.addErrorPayloadMessage(message))
+ return BluePrintManagementOutput.newBuilder()
+ .setCommonHeader(header)
+ .setStatus(
+ Status.newBuilder()
+ .setTimestamp(currentTimestamp())
+ .setMessage(BluePrintConstants.STATUS_FAILURE)
+ .setErrorMessage("Error : ${errorPayload.message}")
+ .setCode(errorPayload.code)
+ .build()
+ )
+ .build()
}
}