diff options
author | Serge Simard <serge@agilitae.com> | 2019-06-18 10:36:57 -0400 |
---|---|---|
committer | Serge Simard <serge@agilitae.com> | 2019-06-18 10:36:57 -0400 |
commit | d1e26003105404f974f9fa45d542f658706ad3cb (patch) | |
tree | 154fbabc9232146e518a25dee845ee16ec4f2405 /ms/blueprintsprocessor/modules/inbounds/resource-api/src/main | |
parent | 39167cccae3271603819aa39c6476e434c759533 (diff) |
Create REST API layer for resource resolution stored configlet
Issue-ID: CCSDK-1407
Signed-off-by: Serge Simard <serge@agilitae.com>
Change-Id: I18db6b654cbf4f416af54596ee71f56eaa860d32
Diffstat (limited to 'ms/blueprintsprocessor/modules/inbounds/resource-api/src/main')
3 files changed, 272 insertions, 0 deletions
diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceController.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceController.kt new file mode 100644 index 000000000..61a9541d3 --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceController.kt @@ -0,0 +1,104 @@ +/* + * Copyright © 2018-2019 Bell Canada Intellectual Property. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.resolutionresults.api + +import io.swagger.annotations.ApiOperation +import kotlinx.coroutines.runBlocking +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.http.MediaType +import org.springframework.http.ResponseEntity +import org.springframework.security.access.prepost.PreAuthorize +import org.springframework.web.bind.annotation.* + +/** + * Exposes Resolution Results API to store and retrieve resource resolution results from external processes, + * like python or ansible scripts + * + * @author Serge Simard + * @version 1.0 + */ +@RestController +@RequestMapping("/api/v1/resolution-results") +open class ResolutionResultsServiceController { + + @Autowired + lateinit var resolutionResultsServiceHandler: ResolutionResultsServiceHandler + + @RequestMapping(path = ["/ping"], method = [RequestMethod.GET], produces = [MediaType.APPLICATION_JSON_VALUE]) + @ResponseBody + fun ping(): String = runBlocking { + "Success" + } + + @RequestMapping(path = ["/{resolution_result_id}"], method = [RequestMethod.GET], produces = [MediaType.TEXT_PLAIN_VALUE]) + @ApiOperation(value = "Fetch a stored result by ID", + notes = "Loads a stored result using the resolution_result_id primary key") + @ResponseBody + @PreAuthorize("hasRole('USER')") + fun getStoredResultById(@PathVariable(value = "resolution_result_id") resolutionResultId: String) + : String = runBlocking { + resolutionResultsServiceHandler.loadStoredResultById(resolutionResultId) + } + + @RequestMapping(path = ["/"], method = [RequestMethod.GET], produces = [MediaType.TEXT_PLAIN_VALUE]) + @ApiOperation(value = "Fetch a stored result ", + notes = "Loads a stored result using the blueprint metadata, artifact name and resolution-key") + @ResponseBody + @PreAuthorize("hasRole('USER')") + fun getStoredResult(@RequestParam(value = "bpName") bpName: String, + @RequestParam(value = "bpVersion") bpVersion: String, + @RequestParam(value = "artifactName") artifactName: String, + @RequestParam(value = "resolutionKey") resolutionKey: String, + @RequestParam(value = "format", required = false, defaultValue = "text/plain") format: String) + : ResponseEntity<String> = runBlocking { + + val payload = resolutionResultsServiceHandler.loadStoredResult(bpName, bpVersion, artifactName, resolutionKey) + + var expectedContentType = format + if (expectedContentType.indexOf('/') < 0) { + expectedContentType = "application/$expectedContentType" + } + val expectedMediaType : MediaType = MediaType.valueOf(expectedContentType) + + ResponseEntity.ok().contentType(expectedMediaType).body(payload) + } + + + @PostMapping("/{bpName}/{bpVersion}/{artifactName}/{resolutionKey}", produces = [MediaType.TEXT_PLAIN_VALUE]) + @ApiOperation(value = "Store result ", + notes = "Store result under resolution-key for the specified blueprint/version/artifact.") + @ResponseBody + @PreAuthorize("hasRole('USER')") + fun putStoredResult(@PathVariable(value = "bpName") bpName: String, + @PathVariable(value = "bpVersion") bpVersion: String, + @PathVariable(value = "artifactName") artifactName: String, + @PathVariable(value = "resolutionKey") resolutionKey: String, + @RequestBody result : String): String? = runBlocking { + resolutionResultsServiceHandler.saveNewStoredResult(bpName, bpVersion, artifactName, resolutionKey, result).id + } + + + @DeleteMapping(path = ["/{resolution_result_id}"]) + @ApiOperation(value = "Deletes a stored result by ID", + notes = "Removes a stored result, using the resolution_result_id primary key") + @ResponseBody + @PreAuthorize("hasRole('USER')") + fun deleteStoredResult(@PathVariable(value = "resolution_result_id") resolutionResultId: String) = runBlocking { + resolutionResultsServiceHandler.removeStoredResultById(resolutionResultId) + } + +} diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceExceptionHandler.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceExceptionHandler.kt new file mode 100644 index 000000000..69641c628 --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceExceptionHandler.kt @@ -0,0 +1,97 @@ +/* + * Copyright © 2018-2019 Bell Canada Intellectual Property. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.resolutionresults.api + +import com.fasterxml.jackson.annotation.JsonFormat +import com.fasterxml.jackson.annotation.JsonInclude +import com.fasterxml.jackson.annotation.JsonTypeInfo +import com.fasterxml.jackson.annotation.JsonTypeName +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException +import org.onap.ccsdk.cds.controllerblueprints.core.data.ErrorCode +import org.slf4j.LoggerFactory +import org.springframework.http.HttpStatus +import org.springframework.http.ResponseEntity +import org.springframework.orm.jpa.JpaObjectRetrievalFailureException +import org.springframework.dao.EmptyResultDataAccessException +import org.springframework.web.server.ServerWebInputException +import org.springframework.web.bind.annotation.ExceptionHandler +import org.springframework.web.bind.annotation.RestControllerAdvice +import java.io.Serializable +import java.util.* + +/** + * Handle exceptions in Resolution Results API and provide relevant HTTP status codes and messages + * + * @author Serge Simard + * @version 1.0 + */ +@RestControllerAdvice("org.onap.ccsdk.cds.blueprintsprocessor.resolutionresults") +open class ResolutionResultsServiceExceptionHandler { + + private val log = LoggerFactory.getLogger(ResolutionResultsServiceExceptionHandler::class.toString()) + + private val debugMsg = "ResolutionResultsService_Error_Message" + + @ExceptionHandler + fun ResolutionResultsServiceExceptionHandler(e: BluePrintProcessorException): ResponseEntity<ErrorMessage> { + log.error(e.message) + val errorCode = ErrorCode.BLUEPRINT_PATH_MISSING + val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg) + return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode)) + } + + @ExceptionHandler + fun ResolutionResultsServiceExceptionHandler(e: ServerWebInputException): ResponseEntity<ErrorMessage> { + log.error(e.message) + val errorCode = ErrorCode.INVALID_REQUEST_FORMAT + val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg) + return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode)) + } + + @ExceptionHandler + fun ResolutionResultsServiceExceptionHandler(e: EmptyResultDataAccessException): ResponseEntity<ErrorMessage> { + log.error(e.message) + var errorCode = ErrorCode.RESOURCE_NOT_FOUND + val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg) + return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode)) + } + + @ExceptionHandler + fun ResolutionResultsServiceExceptionHandler(e: JpaObjectRetrievalFailureException): ResponseEntity<ErrorMessage> { + log.error(e.message) + + var errorCode = ErrorCode.RESOURCE_NOT_FOUND + val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg) + return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode)) + } + + @ExceptionHandler + fun ResolutionResultsServiceExceptionHandler(e: Exception): ResponseEntity<ErrorMessage> { + log.error(e.message, e) + var errorCode = ErrorCode.GENERIC_FAILURE + val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg) + return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode)) + } +} + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonTypeName("errorMessage") +@JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT, use = JsonTypeInfo.Id.NAME) +class ErrorMessage(var message: String?, var code: Int?, var debugMessage: String?) : Serializable { + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") + var timestamp = Date() +}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceHandler.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceHandler.kt new file mode 100644 index 000000000..1fb34d789 --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceHandler.kt @@ -0,0 +1,71 @@ +/* + * Copyright © 2018-2019 Bell Canada Intellectual Property. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.resolutionresults.api + +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionResult +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionResultService +import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService +import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils +import org.springframework.stereotype.Service +import java.util.* + +/** + * Process Resolution Results API request to store and retrieve resource resolution results using database acess layer + * ResourceResolutionResultService and corresponding entities + * + * @author Serge Simard + * @version 1.0 + */ +@Service +class ResolutionResultsServiceHandler(private val bluePrintCatalogService: BluePrintCatalogService, + private var resolutionResultService: ResourceResolutionResultService) { + + suspend fun loadStoredResultById(resolutionResultId: String): String { + + return resolutionResultService.readByKey(resolutionResultId) + } + + suspend fun loadStoredResult(blueprintName : String, blueprintVersion : String, artifactTemplate: String, + resolutionKey: String): String { + + val basePath = bluePrintCatalogService.getFromDatabase(blueprintName, blueprintVersion) + val blueprintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime(UUID.randomUUID().toString(), + basePath.toString()) + + return resolutionResultService.read(blueprintRuntimeService, artifactTemplate, resolutionKey) + } + + suspend fun saveNewStoredResult(blueprintName : String, blueprintVersion : String, artifactTemplate: String, + resolutionKey: String, result: String): ResourceResolutionResult { + + val basePath = bluePrintCatalogService.getFromDatabase(blueprintName, blueprintVersion) + val blueprintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime(UUID.randomUUID().toString(), + basePath.toString()) + + val properties = mapOf(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_KEY to resolutionKey) + + val resultStored = resolutionResultService.write(properties, result, blueprintRuntimeService, artifactTemplate) + + return resultStored + } + + suspend fun removeStoredResultById(resolutionResultId: String): Unit { + + return resolutionResultService.deleteByKey(resolutionResultId) + } +}
\ No newline at end of file |