Refactor resolution controllers 74/90274/15
authorAlexis de Talhouët <adetalhouet89@gmail.com>
Fri, 21 Jun 2019 02:48:12 +0000 (22:48 -0400)
committerAlexis de Talhouët <adetalhouet89@gmail.com>
Thu, 4 Jul 2019 19:53:42 +0000 (15:53 -0400)
tempalte and resources for get/put API

Change-Id: Ia00bdb08f5f52231481edc6de232f850c66874e9
Issue-ID: CCSDK-1423
Signed-off-by: Alexis de Talhouët <adetalhouet89@gmail.com>
17 files changed:
ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplication.java
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultService.kt [deleted file]
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolution.kt [moved from ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResult.kt with 93% similarity]
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionRepository.kt [moved from ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultRepository.kt with 86% similarity]
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionService.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceController.kt [deleted file]
ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceHandler.kt [deleted file]
ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt [moved from ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceController.kt with 98% similarity]
ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceException.kt [moved from ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceException.kt with 90% similarity]
ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceExceptionHandler.kt [moved from ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceExceptionHandler.kt with 58% similarity]
ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateController.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/java/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceResolutionControllerTest.java [deleted file]
ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceHandlerTest.kt [deleted file]
ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceControllerTest.kt
ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateControllerTest.kt [new file with mode: 0644]
ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/data/BlueprintErrorCode.kt

index 2b6f8bc..a27e079 100644 (file)
@@ -35,7 +35,7 @@ public class BlueprintProcessorApplication {
 
     public static void main(String[] args) {
 
-        // This is required for ResolutionResultsServiceController.getStoredResult to accept a content-type value
+        // This is required for TemplateController.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");
 
index b148293..96c3f64 100644 (file)
@@ -21,7 +21,7 @@ import kotlinx.coroutines.async
 import kotlinx.coroutines.awaitAll
 import kotlinx.coroutines.coroutineScope
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionDBService
-import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionResultService
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.TemplateResolutionService
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.processor.ResourceAssignmentProcessor
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
@@ -58,7 +58,7 @@ interface ResourceResolutionService {
 
 @Service(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION)
 open class ResourceResolutionServiceImpl(private var applicationContext: ApplicationContext,
-                                         private var resolutionResultService: ResourceResolutionResultService,
+                                         private var resolutionResultService: TemplateResolutionService,
                                          private var blueprintTemplateService: BluePrintTemplateService,
                                          private var resourceResolutionDBService: ResourceResolutionDBService) :
     ResourceResolutionService {
@@ -181,7 +181,7 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
                                         blueprintRuntimeService,
                                         artifactPrefix,
                                         resourceAssignment)
-                                    log.info("resolution saved into database successfully : ($resourceAssignment)")
+                                    log.info("Resource resolution saved into database successfully : ($resourceAssignment)")
                                 }
 
                                 // Set errors from RA
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
deleted file mode 100644 (file)
index ebb34ba..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2019 Bell Canada.
- * Modifications Copyright © 2019 IBM.
- *
- * 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.functions.resource.resolution.db
-
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
-import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants
-import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
-import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
-import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
-import org.springframework.dao.DataIntegrityViolationException
-import org.springframework.stereotype.Service
-import java.util.*
-
-@Service
-class ResourceResolutionResultService(private val resourceResolutionRepository: ResourceResolutionResultRepository) {
-
-    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) {
-
-        val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
-
-        val resourceResolutionResult = ResourceResolutionResult()
-        resourceResolutionResult.id = UUID.randomUUID().toString()
-        resourceResolutionResult.artifactName = artifactPrefix
-        resourceResolutionResult.blueprintVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]
-        resourceResolutionResult.blueprintName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]
-        resourceResolutionResult.resolutionKey =
-                properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_KEY].toString()
-        resourceResolutionResult.result = result
-
-        try {
-            resourceResolutionRepository.saveAndFlush(resourceResolutionResult)
-        } catch (ex: DataIntegrityViolationException) {
-            throw BluePrintException("Failed to store resource resolution result.", ex)
-        }
-    }
-
-    suspend fun readByKey(resolutionResultId: String): String = withContext(Dispatchers.IO) {
-
-        resourceResolutionRepository.getOne(resolutionResultId).result!!
-    }
-
-    suspend fun deleteByKey(resolutionResultId: String): Unit = withContext(Dispatchers.IO) {
-
-        val row = resourceResolutionRepository.getOne(resolutionResultId)
-        resourceResolutionRepository.delete(row)
-        resourceResolutionRepository.flush()
-    }
-}
\ No newline at end of file
@@ -33,12 +33,12 @@ import javax.persistence.TemporalType
 
 @EntityListeners(AuditingEntityListener::class)
 @Entity
-@Table(name = "RESOURCE_RESOLUTION_RESULT")
+@Table(name = "TEMPLATE_RESOLUTION")
 @Proxy(lazy = false)
-class ResourceResolutionResult : Serializable {
+class TemplateResolution : Serializable {
 
     @Id
-    @Column(name = "resource_resolution_result_id")
+    @Column(name = "template_resolution_id")
     var id: String? = null
 
     @Column(name = "resolution_key", nullable = false)
@@ -17,9 +17,9 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db
 
 import org.springframework.data.jpa.repository.JpaRepository
 
-interface ResourceResolutionResultRepository : JpaRepository<ResourceResolutionResult, String> {
+interface TemplateResolutionRepository : JpaRepository<TemplateResolution, String> {
 
     fun findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(key: String, blueprintName: String?,
                                                                               blueprintVersion: String?,
-                                                                              artifactName: String): ResourceResolutionResult
+                                                                              artifactName: String): TemplateResolution
 }
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionService.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionService.kt
new file mode 100644 (file)
index 0000000..c4e3640
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 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.functions.resource.resolution.db
+
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
+import org.springframework.dao.DataIntegrityViolationException
+import org.springframework.stereotype.Service
+import java.util.*
+
+@Service
+class TemplateResolutionService(private val templateResolutionRepository: TemplateResolutionRepository) {
+
+    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]!!
+
+        read(blueprintName, blueprintVersion, artifactPrefix, resolutionKey)
+    }
+
+    suspend fun read(blueprintName: String,
+                     blueprintVersion: String,
+                     artifactPrefix: String,
+                     resolutionKey: String): String = withContext(Dispatchers.IO) {
+
+        templateResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
+            resolutionKey,
+            blueprintName,
+            blueprintVersion,
+            artifactPrefix).result!!
+    }
+
+    suspend fun write(properties: Map<String, Any>,
+                      result: String, bluePrintRuntimeService: BluePrintRuntimeService<*>,
+                      artifactPrefix: String): TemplateResolution = withContext(Dispatchers.IO) {
+
+        val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
+
+        val blueprintVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]!!
+        val blueprintName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]!!
+        val resolutionKey =
+            properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_KEY].toString()
+
+        write(blueprintName, blueprintVersion, resolutionKey, artifactPrefix, result)
+    }
+
+    suspend fun write(blueprintName: String,
+                      blueprintVersion: String,
+                      resolutionKey: String,
+                      artifactPrefix: String,
+                      template: String): TemplateResolution = withContext(Dispatchers.IO) {
+
+        val resourceResolutionResult = TemplateResolution()
+        resourceResolutionResult.id = UUID.randomUUID().toString()
+        resourceResolutionResult.artifactName = artifactPrefix
+        resourceResolutionResult.blueprintVersion = blueprintVersion
+        resourceResolutionResult.blueprintName = blueprintName
+        resourceResolutionResult.resolutionKey = resolutionKey
+        resourceResolutionResult.result = template
+
+        try {
+            templateResolutionRepository.saveAndFlush(resourceResolutionResult)
+        } catch (ex: DataIntegrityViolationException) {
+            throw BluePrintException("Failed to store resource api result.", ex)
+        }
+    }
+}
\ 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/ResolutionResultsServiceController.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceController.kt
deleted file mode 100644 (file)
index 61a9541..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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/ResolutionResultsServiceHandler.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceHandler.kt
deleted file mode 100644 (file)
index 1fb34d7..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2018-2019 Bell Canada Intellectual Property.
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.onap.ccsdk.cds.blueprintsprocessor.resolutionresults.api
+package org.onap.ccsdk.cds.blueprintsprocessor.resource.api
 
 import com.fasterxml.jackson.annotation.JsonFormat
 import com.fasterxml.jackson.annotation.JsonInclude
@@ -27,6 +27,7 @@ import org.springframework.http.HttpStatus
 import org.springframework.http.ResponseEntity
 import org.springframework.orm.jpa.JpaObjectRetrievalFailureException
 import org.springframework.dao.EmptyResultDataAccessException
+import org.springframework.dao.IncorrectResultSizeDataAccessException
 import org.springframework.web.server.ServerWebInputException
 import org.springframework.web.bind.annotation.ExceptionHandler
 import org.springframework.web.bind.annotation.RestControllerAdvice
@@ -34,57 +35,61 @@ import java.io.Serializable
 import java.util.*
 
 /**
- * Handle exceptions in Resolution Results API and provide relevant HTTP status codes and messages
+ * Handle exceptions in Resolution 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 {
+@RestControllerAdvice("org.onap.ccsdk.cds.blueprintsprocessor.resource.api")
+open class ResourceExceptionHandler {
 
-    private val log = LoggerFactory.getLogger(ResolutionResultsServiceExceptionHandler::class.toString())
+    private val log = LoggerFactory.getLogger(ExceptionHandler::class.toString())
 
-    private val debugMsg = "ResolutionResultsService_Error_Message"
+    private val debugMsg = "Resolution_Service_Error_Message"
 
     @ExceptionHandler
-    fun ResolutionResultsServiceExceptionHandler(e: BluePrintProcessorException): ResponseEntity<ErrorMessage> {
-        log.error(e.message, e)
+    fun resolutionResultsServiceExceptionHandler(e: BluePrintProcessorException): ResponseEntity<ErrorMessage> {
         val errorCode = ErrorCode.BLUEPRINT_PATH_MISSING
-        val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg)
-        return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode))
+        return returnError(e, errorCode)
     }
 
     @ExceptionHandler
-    fun ResolutionResultsServiceExceptionHandler(e: ServerWebInputException): ResponseEntity<ErrorMessage> {
-        log.error(e.message, e)
+    fun resolutionResultsServiceExceptionHandler(e: ServerWebInputException): ResponseEntity<ErrorMessage> {
         val errorCode = ErrorCode.INVALID_REQUEST_FORMAT
-        val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg)
-        return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode))
+        return returnError(e, errorCode)
     }
 
     @ExceptionHandler
-    fun ResolutionResultsServiceExceptionHandler(e: EmptyResultDataAccessException): ResponseEntity<ErrorMessage> {
-        log.error(e.message, e)
-        var errorCode = ErrorCode.RESOURCE_NOT_FOUND
-        val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg)
-        return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode))
+    fun resolutionResultsServiceExceptionHandler(e: IncorrectResultSizeDataAccessException): ResponseEntity<ErrorMessage> {
+        val errorCode = ErrorCode.DUPLICATE_DATA
+        return returnError(e, errorCode)
     }
 
     @ExceptionHandler
-    fun ResolutionResultsServiceExceptionHandler(e: JpaObjectRetrievalFailureException): ResponseEntity<ErrorMessage> {
-        log.error(e.message, e)
+    fun resolutionResultsServiceExceptionHandler(e: EmptyResultDataAccessException): ResponseEntity<ErrorMessage> {
+        val errorCode = ErrorCode.RESOURCE_NOT_FOUND
+        return returnError(e, errorCode)
+    }
 
-        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> {
+        val errorCode = ErrorCode.RESOURCE_NOT_FOUND
+        return returnError(e, errorCode)
     }
 
     @ExceptionHandler
-    fun ResolutionResultsServiceExceptionHandler(e: Exception): ResponseEntity<ErrorMessage> {
+    fun resolutionResultsServiceExceptionHandler(e: Exception): ResponseEntity<ErrorMessage> {
+        val errorCode = ErrorCode.GENERIC_FAILURE
+        return returnError(e, errorCode)
+    }
+
+    fun returnError(e: Exception, errorCode: ErrorCode): 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))
+        val errorMessage =
+            ErrorMessage(errorCode.message(e.message!!),
+                errorCode.value,
+                debugMsg)
+        return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode)!!)
     }
 
     @ExceptionHandler
diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateController.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateController.kt
new file mode 100644 (file)
index 0000000..d3ebd5c
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * 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.resource.api
+
+import io.swagger.annotations.ApiOperation
+import kotlinx.coroutines.runBlocking
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.TemplateResolution
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.TemplateResolutionService
+import org.springframework.http.MediaType
+import org.springframework.http.ResponseEntity
+import org.springframework.security.access.prepost.PreAuthorize
+import org.springframework.web.bind.annotation.*
+
+/**
+ * Exposes Template Resolution API to store and retrieve rendered template results.
+ *
+ * @author Serge Simard
+ * @version 1.0
+ */
+@RestController
+@RequestMapping("/api/v1/template")
+open class TemplateController(private val templateResolutionService: TemplateResolutionService) {
+
+    @RequestMapping(path = ["/ping"], method = [RequestMethod.GET], produces = [MediaType.APPLICATION_JSON_VALUE])
+    @ResponseBody
+    fun ping(): String = runBlocking {
+        "Success"
+    }
+
+    @RequestMapping(path = [""], method = [RequestMethod.GET], produces = [MediaType.TEXT_PLAIN_VALUE])
+    @ApiOperation(value = "Retrieve a meshed template.",
+        notes = "Retrieve a meshed template for a given CBA's action, identified by its blueprint name, blueprint version, " +
+                "artifact name and resolution key. And extra 'format' parameter can be passed to tell what content-type" +
+                " to expect in return")
+    @ResponseBody
+    @PreAuthorize("hasRole('USER')")
+    fun get(@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 result = templateResolutionService.read(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(result)
+    }
+
+
+    @PostMapping("/{bpName}/{bpVersion}/{artifactName}/{resolutionKey}", produces = [MediaType.APPLICATION_JSON_VALUE])
+    @ApiOperation(value = "Store a meshed template",
+        notes = "Store a meshed template for a given CBA's action, identified by its blueprint name, blueprint version, " +
+                "artifact name and resolution key.")
+    @ResponseBody
+    @PreAuthorize("hasRole('USER')")
+    fun post(@PathVariable(value = "bpName") bpName: String,
+             @PathVariable(value = "bpVersion") bpVersion: String,
+             @PathVariable(value = "artifactName") artifactName: String,
+             @PathVariable(value = "resolutionKey") resolutionKey: String,
+             @RequestBody result: String): ResponseEntity<TemplateResolution> = runBlocking {
+
+        val resultStored =
+            templateResolutionService.write(bpName, bpVersion, resolutionKey, artifactName, result)
+
+        ResponseEntity.ok().body(resultStored)
+    }
+}
diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/java/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceResolutionControllerTest.java b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/java/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceResolutionControllerTest.java
deleted file mode 100644 (file)
index f8c37f8..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- *  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.resource.api;
-
-// TODO
-public class ResourceResolutionControllerTest {
-
-}
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
deleted file mode 100644 (file)
index 813c900..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * 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/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateControllerTest.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateControllerTest.kt
new file mode 100644 (file)
index 0000000..d12d058
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * 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.resource.api
+
+import kotlinx.coroutines.runBlocking
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintCoreConfiguration
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.TemplateResolutionService
+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 kotlin.test.AfterTest
+import kotlin.test.BeforeTest
+import kotlin.test.assertTrue
+
+@RunWith(SpringRunner::class)
+@WebFluxTest
+@ContextConfiguration(classes = [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 TemplateControllerTest {
+
+    private val log = LoggerFactory.getLogger(TemplateControllerTest::class.toString())
+
+    @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"
+
+    var requestArguments = "bpName=$blueprintName&bpVersion=$blueprintVersion" +
+            "&artifactName=$templatePrefix&resolutionKey=$resolutionKey"
+
+    @AfterTest
+    fun cleanDir() {
+        deleteDir("target", "blueprints")
+    }
+
+    @Test
+    fun `ping return Success`() {
+        runBlocking {
+            webTestClient.get().uri("/api/v1/template/ping")
+                .exchange()
+                .expectStatus().isOk
+                .expectBody()
+                .equals("Success")
+        }
+    }
+
+    @Test
+    fun `store same value and tries to retrieve - duplicate entry execption`() {
+        runBlocking {
+
+            resolutionKey = "1"
+
+            post(resolutionKey)
+            post(resolutionKey)
+
+            webTestClient
+                .get()
+                .uri("/api/v1/template?$requestArguments")
+                .exchange()
+                .expectStatus().is4xxClientError
+                .expectBody().equals(payloadDummyTemplateData)
+        }
+    }
+
+    @Test
+    fun `get returns requested JSON content-type`() {
+        runBlocking {
+            resolutionKey = "2"
+            post(resolutionKey)
+            get("json", resolutionKey)
+        }
+    }
+
+    @Test
+    fun `get returns requested XML content-type`() {
+        runBlocking {
+            resolutionKey = "3"
+            post(resolutionKey)
+            get("xml", resolutionKey)
+        }
+    }
+
+    @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/template?$arguments")
+                .exchange()
+                .expectStatus().isBadRequest
+        }
+    }
+
+    @Test
+    fun `get returns 404 if entry not found`() {
+        runBlocking {
+
+            webTestClient
+                .get()
+                .uri("/api/v1/template?bpName=$blueprintName&bpVersion=$blueprintVersion" +
+                        "&artifactName=$templatePrefix&resolutionKey=bob")
+                .exchange()
+                .expectStatus().isNotFound
+        }
+    }
+
+    private fun post(resKey: String) {
+        webTestClient
+            .post()
+            .uri("/api/v1/template/$blueprintName/$blueprintVersion/$templatePrefix/$resKey")
+            .body(BodyInserters.fromObject(payloadDummyTemplateData))
+            .exchange()
+            .expectStatus().is2xxSuccessful
+            .expectBody()
+            .consumeWith {
+                log.info("Stored result under UUID ${it.responseBody}")
+            }
+    }
+
+    private fun get(expectedType: String, resKey: String) {
+        var requestArguments = "bpName=$blueprintName&bpVersion=$blueprintVersion" +
+                "&artifactName=$templatePrefix&resolutionKey=$resKey"
+
+        if (expectedType.isNotEmpty()) {
+            requestArguments = "$requestArguments&format=$expectedType"
+            webTestClient
+                .get()
+                .uri("/api/v1/template?$requestArguments")
+                .exchange()
+                .expectStatus().is2xxSuccessful
+                .expectHeader().contentType(MediaType.valueOf("application/$expectedType"))
+                .expectBody().equals(payloadDummyTemplateData)
+        } else {
+            webTestClient
+                .get()
+                .uri("/api/v1/template?$requestArguments")
+                .exchange()
+                .expectStatus().is2xxSuccessful
+                .expectHeader().contentType(MediaType.TEXT_PLAIN)
+                .expectBody().equals(payloadDummyTemplateData)
+        }
+    }
+}
\ No newline at end of file
index 79ef395..51d088e 100644 (file)
@@ -76,6 +76,11 @@ enum class ErrorCode (val value: Int, val httpCode: Int) {
         override fun message(detailMsg: String): String {
             return "Duplicated entry while saving Blueprint. Details : {$detailMsg}"
         }
+    },
+    DUPLICATE_DATA(11, 409) {
+        override fun message(detailMsg: String): String {
+            return "Duplicated data - was expecting one result, got more than one. Details : {$detailMsg}"
+        }
     };
 
     abstract fun message(detailMsg: String): String