aboutsummaryrefslogtreecommitdiffstats
path: root/ms/blueprintsprocessor
diff options
context:
space:
mode:
authorSerge Simard <serge@agilitae.com>2019-06-18 10:36:57 -0400
committerSerge Simard <serge@agilitae.com>2019-06-18 10:36:57 -0400
commitd1e26003105404f974f9fa45d542f658706ad3cb (patch)
tree154fbabc9232146e518a25dee845ee16ec4f2405 /ms/blueprintsprocessor
parent39167cccae3271603819aa39c6476e434c759533 (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')
-rw-r--r--ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplication.java5
-rw-r--r--ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultService.kt32
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/resource-api/pom.xml27
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceController.kt104
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceExceptionHandler.kt97
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceHandler.kt71
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceHandlerTest.kt215
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/resources/application-test.properties33
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/resources/logback.xml35
-rw-r--r--ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/resources/test-cba.zipbin0 -> 9554 bytes
10 files changed, 609 insertions, 10 deletions
diff --git a/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplication.java b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplication.java
index 85268c7fa..2b6f8bcf1 100644
--- a/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplication.java
+++ b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplication.java
@@ -34,6 +34,11 @@ import org.springframework.context.annotation.ComponentScan;
public class BlueprintProcessorApplication {
public static void main(String[] args) {
+
+ // This is required for ResolutionResultsServiceController.getStoredResult to accept a content-type value
+ // as a request parameter, e.g. &format=application%2Fxml is accepted
+ System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
+
SpringApplication.run(BlueprintProcessorApplication.class, args);
}
}
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultService.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultService.kt
index cbc68bbc9..3cb9dec63 100644
--- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultService.kt
+++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultService.kt
@@ -29,6 +29,21 @@ import java.util.*
@Service
class ResourceResolutionResultService(private val resourceResolutionRepository: ResourceResolutionRepository) {
+ suspend fun read(bluePrintRuntimeService: BluePrintRuntimeService<*>, artifactPrefix: String,
+ resolutionKey: String): String = withContext(Dispatchers.IO) {
+
+ val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
+
+ val blueprintVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]
+ val blueprintName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]
+
+ resourceResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
+ resolutionKey,
+ blueprintName,
+ blueprintVersion,
+ artifactPrefix).result!!
+ }
+
suspend fun write(properties: Map<String, Any>, result: String, bluePrintRuntimeService: BluePrintRuntimeService<*>,
artifactPrefix: String) = withContext(Dispatchers.IO) {
@@ -50,18 +65,15 @@ class ResourceResolutionResultService(private val resourceResolutionRepository:
}
}
- suspend fun read(bluePrintRuntimeService: BluePrintRuntimeService<*>, artifactPrefix: String,
- resolutionKey: String): String = withContext(Dispatchers.IO) {
+ suspend fun readByKey(resolutionResultId: String): String = withContext(Dispatchers.IO) {
- val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
+ resourceResolutionRepository.getOne(resolutionResultId).result!!
+ }
- val blueprintVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]
- val blueprintName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]
+ suspend fun deleteByKey(resolutionResultId: String): Unit = withContext(Dispatchers.IO) {
- resourceResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
- resolutionKey,
- blueprintName,
- blueprintVersion,
- artifactPrefix).result!!
+ val row = resourceResolutionRepository.getOne(resolutionResultId)
+ resourceResolutionRepository.delete(row)
+ resourceResolutionRepository.flush()
}
} \ No newline at end of file
diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/pom.xml b/ms/blueprintsprocessor/modules/inbounds/resource-api/pom.xml
index d5acf4f93..5dbbc71de 100644
--- a/ms/blueprintsprocessor/modules/inbounds/resource-api/pom.xml
+++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/pom.xml
@@ -27,4 +27,31 @@
<name>Blueprints Processor Resource API</name>
<description>Blueprints Processor Resource API</description>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.controllerblueprints</groupId>
+ <artifactId>blueprint-core</artifactId>
+ </dependency>
+ <!--dependency>
+ <groupId>org.onap.ccsdk.cds.controllerblueprints</groupId>
+ <artifactId>db-resources</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.controllerblueprints</groupId>
+ <artifactId>blueprint-validation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.cds.controllerblueprints</groupId>
+ <artifactId>blueprint-scripts</artifactId>
+ </dependency-->
+ <dependency>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
</project>
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
diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceHandlerTest.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceHandlerTest.kt
new file mode 100644
index 000000000..813c900d7
--- /dev/null
+++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceHandlerTest.kt
@@ -0,0 +1,215 @@
+/*
+ * Copyright © 2019 Bell Canada.
+ *
+ * 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 kotlinx.coroutines.runBlocking
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintCoreConfiguration
+import org.onap.ccsdk.cds.controllerblueprints.core.deleteDir
+import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService
+import org.slf4j.LoggerFactory
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.autoconfigure.security.SecurityProperties
+import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest
+import org.springframework.context.annotation.ComponentScan
+import org.springframework.http.HttpStatus
+import org.springframework.http.MediaType
+import org.springframework.test.context.ContextConfiguration
+import org.springframework.test.context.TestPropertySource
+import org.springframework.test.context.junit4.SpringRunner
+import org.springframework.test.web.reactive.server.WebTestClient
+import org.springframework.web.reactive.function.BodyInserters
+import java.io.File
+import java.nio.file.Paths
+import java.util.*
+import kotlin.test.AfterTest
+import kotlin.test.BeforeTest
+import kotlin.test.assertTrue
+
+@RunWith(SpringRunner::class)
+@WebFluxTest
+@ContextConfiguration(classes = [ResolutionResultsServiceHandler::class, BluePrintCoreConfiguration::class,
+ BluePrintCatalogService::class, SecurityProperties::class])
+@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"])
+@TestPropertySource(locations = ["classpath:application-test.properties"])
+class ResolutionResultsServiceHandlerTest {
+
+ private val log = LoggerFactory.getLogger(ResolutionResultsServiceHandlerTest::class.toString())
+
+ @Autowired
+ lateinit var blueprintCatalog: BluePrintCatalogService
+ @Autowired
+ lateinit var webTestClient: WebTestClient
+
+ var resolutionKey = "7cafa9f3-bbc8-49ec-8f25-fcaa6ac3ff08"
+ val blueprintName = "baseconfiguration"
+ val blueprintVersion = "1.0.0"
+ val templatePrefix = "activate"
+ val payloadDummyTemplateData = "PAYLOAD DATA"
+
+ @BeforeTest
+ fun init() {
+ runBlocking {
+ deleteDir("target", "blueprints")
+ blueprintCatalog.saveToDatabase(UUID.randomUUID().toString(), loadTestCbaFile())
+ }
+ }
+
+ @AfterTest
+ fun cleanDir() {
+ deleteDir("target", "blueprints")
+ }
+
+ @Test
+ fun `ping return Success`() {
+ runBlocking {
+
+ webTestClient.get().uri("/api/v1/resolution-results/ping")
+ .exchange()
+ .expectStatus().isOk
+ .expectBody().equals("Success")
+ }
+ }
+
+ @Test
+ fun `store-retrieve-delete result by path or UUID`() {
+ runBlocking {
+ createRetrieveDelete()
+ }
+ }
+
+ @Test
+ fun `get returns requested JSON content-type`() {
+ runBlocking {
+ createRetrieveDelete("json")
+ }
+ }
+
+ @Test
+ fun `get returns requested XML content-type`() {
+ runBlocking {
+ createRetrieveDelete("xml")
+ }
+ }
+
+ private fun createRetrieveDelete(expectedType : String? = null): WebTestClient.ResponseSpec {
+ var uuid = "MISSING"
+
+ // Store new result for blueprint/artifact/resolutionkey
+ webTestClient
+ .post()
+ .uri("/api/v1/resolution-results/$blueprintName/$blueprintVersion/$templatePrefix/$resolutionKey/")
+ .body(BodyInserters.fromObject(payloadDummyTemplateData))
+ .exchange()
+ .expectStatus().is2xxSuccessful
+ .expectBody()
+ .consumeWith {
+ uuid = String(it.responseBody)
+ log.info("Stored result under UUID $uuid")
+ }
+ // Retrieve same payload
+ var requestArguments = "bpName=$blueprintName&bpVersion=$blueprintVersion" +
+ "&artifactName=$templatePrefix&resolutionKey=$resolutionKey"
+ if (expectedType != null) {
+ requestArguments = "$requestArguments&format=$expectedType"
+ webTestClient
+ .get()
+ .uri("/api/v1/resolution-results/?$requestArguments")
+ .exchange()
+ .expectStatus().is2xxSuccessful
+ .expectHeader().contentType(MediaType.valueOf("application/$expectedType"))
+ .expectBody().equals(payloadDummyTemplateData)
+ } else {
+ webTestClient
+ .get()
+ .uri("/api/v1/resolution-results/?$requestArguments")
+ .exchange()
+ .expectStatus().is2xxSuccessful
+ .expectHeader().contentType(MediaType.TEXT_PLAIN)
+ .expectBody().equals(payloadDummyTemplateData)
+ }
+ // And delete by UUID
+ return webTestClient
+ .delete()
+ .uri("/api/v1/resolution-results/$uuid/")
+ .exchange()
+ .expectStatus().is2xxSuccessful
+ }
+
+ /*
+ * Error cases
+ */
+ @Test
+ fun `get returns 400 error if missing arg`() {
+ runBlocking {
+ val arguments = "bpBADName=$blueprintName" +
+ "&bpBADVersion=$blueprintVersion" +
+ "&artifactName=$templatePrefix" +
+ "&resolutionKey=$resolutionKey"
+
+ webTestClient.get().uri("/api/v1/resolution-results/?$arguments")
+ .exchange()
+ .expectStatus().isBadRequest
+ }
+ }
+
+ @Test
+ fun `get returns 503 error if Blueprint not found`() {
+ runBlocking {
+ val arguments = "bpName=BAD_BP_NAME" +
+ "&bpVersion=BAD_BP_VERSION" +
+ "&artifactName=$templatePrefix" +
+ "&resolutionKey=$resolutionKey"
+
+ webTestClient.get().uri("/api/v1/resolution-results/?$arguments")
+ .exchange()
+ .expectStatus().isEqualTo(HttpStatus.SERVICE_UNAVAILABLE)
+ }
+ }
+
+ @Test
+ fun `get returns 404 if entry not found`() {
+ runBlocking {
+
+ webTestClient
+ .get()
+ .uri("/api/v1/resolution-results/?bpName=$blueprintName&bpVersion=$blueprintVersion" +
+ "&artifactName=$templatePrefix&resolutionKey=$resolutionKey")
+ .exchange()
+ .expectStatus().isNotFound
+ }
+ }
+
+ @Test
+ fun `get returns 404 if UUID not found`() {
+ runBlocking {
+
+ webTestClient
+ .get()
+ .uri("/api/v1/resolution-results/234234234234/")
+ .exchange()
+ .expectStatus().isNotFound
+ }
+ }
+
+ private fun loadTestCbaFile(): File {
+ val testCbaFile = Paths.get("./src/test/resources/test-cba.zip").toFile()
+ assertTrue(testCbaFile.exists(), "couldn't get file ${testCbaFile.absolutePath}")
+ return testCbaFile
+ }
+} \ No newline at end of file
diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/resources/application-test.properties b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/resources/application-test.properties
new file mode 100644
index 000000000..ebd5dc859
--- /dev/null
+++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/resources/application-test.properties
@@ -0,0 +1,33 @@
+#
+# Copyright © 2017-2018 AT&T Intellectual Property.
+#
+# Modifications Copyright © 2019 IBM, Bell Canada.
+#
+# 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.
+#
+blueprintsprocessor.db.primary.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
+blueprintsprocessor.db.primary.username=sa
+blueprintsprocessor.db.primary.password=
+blueprintsprocessor.db.primary.driverClassName=org.h2.Driver
+blueprintsprocessor.db.primary.hibernateHbm2ddlAuto=create-drop
+blueprintsprocessor.db.primary.hibernateDDLAuto=update
+blueprintsprocessor.db.primary.hibernateNamingStrategy=org.hibernate.cfg.ImprovedNamingStrategy
+blueprintsprocessor.db.primary.hibernateDialect=org.hibernate.dialect.H2Dialect
+# Controller Blueprints Core Configuration
+blueprintsprocessor.blueprintDeployPath=./target/blueprints/deploy
+blueprintsprocessor.blueprintWorkingPath=./target/blueprints/work
+blueprintsprocessor.blueprintArchivePath=./target/blueprints/archive
+
+# Python executor
+blueprints.processor.functions.python.executor.executionPath=./../../../../components/scripts/python/ccsdk_blueprints
+blueprints.processor.functions.python.executor.modulePaths=./../../../../components/scripts/python/ccsdk_blueprints
diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/resources/logback.xml b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/resources/logback.xml
new file mode 100644
index 000000000..56b077424
--- /dev/null
+++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/resources/logback.xml
@@ -0,0 +1,35 @@
+<!--
+ ~ Copyright © 2017-2018 AT&T 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.
+ -->
+
+<configuration>
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <!-- encoders are assigned the type
+ ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
+ <encoder>
+ <pattern>%d{HH:mm:ss.SSS} %-5level %logger{100} - %msg%n</pattern>
+ </encoder>
+ </appender>
+
+
+ <logger name="org.springframework" level="warn"/>
+ <logger name="org.hibernate" level="info"/>
+ <logger name="org.onap.ccsdk.cds.blueprintsprocessor" level="info"/>
+
+ <root level="info">
+ <appender-ref ref="STDOUT"/>
+ </root>
+
+</configuration>
diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/resources/test-cba.zip b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/resources/test-cba.zip
new file mode 100644
index 000000000..785ec6c00
--- /dev/null
+++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/resources/test-cba.zip
Binary files differ