Add functions/endpoints to fetch all config snapshots for a given resource type or... 28/111128/1
authorSerge Simard <serge@agilitae.com>
Tue, 11 Aug 2020 13:47:23 +0000 (09:47 -0400)
committerSerge Simard <serge@agilitae.com>
Tue, 11 Aug 2020 13:50:04 +0000 (09:50 -0400)
Issue-ID: CCSDK-2641

Signed-off-by: Serge Simard <serge@agilitae.com>
Change-Id: I392fa72bcbe39fd5306d4d2fdf7f49d62ec441b5

ms/blueprintsprocessor/functions/config-snapshots/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/config/snapshots/db/ResourceConfigSnapshotRepository.kt
ms/blueprintsprocessor/functions/config-snapshots/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/config/snapshots/db/ResourceConfigSnapshotService.kt
ms/blueprintsprocessor/modules/inbounds/configs-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotController.kt
ms/blueprintsprocessor/modules/inbounds/configs-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotControllerTest.kt

index e180643..6806ad6 100644 (file)
@@ -40,4 +40,60 @@ interface ResourceConfigSnapshotRepository : JpaRepository<ResourceConfigSnapsho
         resourceType: String,
         status: ResourceConfigSnapshot.Status
     )
+
+    /**
+     * Finds all ResourceConfigSnapshot for a given resourceId and status as search criterias,
+     * ordering the resulting list in reverse chronological order.
+     *
+     * @param resourceId a resource identifier, e.g. CLLI1234555
+     * @param status RUNNING or CANDIDATE
+     *
+     * @return A list of entries are found returns a list of ConfigSnapshot.
+     * If no entries are found, this method returns an empty list.
+     */
+    fun findByResourceIdAndStatusOrderByCreatedDateDesc(
+        resourceId: String,
+        status: ResourceConfigSnapshot.Status
+    ): List<ResourceConfigSnapshot>?
+
+    /**
+     * Finds all ResourceConfigSnapshot for a given resourceId,
+     * ordering the resulting list in reverse chronological order.
+     *
+     * @param resourceId a resource identifier, e.g. CLLI1234555
+     *
+     * @return A list of entries are found returns a list of ConfigSnapshot.
+     * If no entries are found, this method returns an empty list.
+     */
+    fun findByResourceIdOrderByCreatedDateDesc(
+        resourceId: String
+    ): List<ResourceConfigSnapshot>?
+
+    /**
+     * Finds all ResourceConfigSnapshot for a given resourceType and status as search criterias,
+     * ordering the resulting list in reverse chronological order.
+     *
+     * @param resourceType a resource type name, e.g full_config
+     * @param status RUNNING or CANDIDATE
+     *
+     * @return A list of entries are found returns a list of ConfigSnapshot.
+     * If no entries are found, this method returns an empty list.
+     */
+    fun findByResourceTypeAndStatusOrderByCreatedDateDesc(
+        resourceType: String,
+        status: ResourceConfigSnapshot.Status
+    ): List<ResourceConfigSnapshot>?
+
+    /**
+     * Finds all ResourceConfigSnapshot for a given resourceType,
+     * ordering the resulting list in reverse chronological order.
+     *
+     * @param resourceType a resource type name, e.g full_config
+     *
+     * @return A list of entries are found returns a list of ConfigSnapshot.
+     * If no entries are found, this method returns an empty list.
+     */
+    fun findByResourceTypeOrderByCreatedDateDesc(
+        resourceType: String
+    ): List<ResourceConfigSnapshot>?
 }
index 9260b79..2383f2c 100644 (file)
@@ -36,6 +36,36 @@ open class ResourceConfigSnapshotService(private val resourceConfigSnapshotRepos
 
     private val log = LoggerFactory.getLogger(ResourceConfigSnapshotService::class.toString())
 
+    suspend fun findAllByResourceIdForStatus(
+        resourceId: String,
+        status: ResourceConfigSnapshot.Status
+    ): List<ResourceConfigSnapshot>? =
+        withContext(Dispatchers.IO) {
+            resourceConfigSnapshotRepository.findByResourceIdAndStatusOrderByCreatedDateDesc(resourceId, status)
+        }
+
+    suspend fun findAllByResourceId(
+        resourceId: String
+    ): List<ResourceConfigSnapshot>? =
+        withContext(Dispatchers.IO) {
+            resourceConfigSnapshotRepository.findByResourceIdOrderByCreatedDateDesc(resourceId)
+        }
+
+    suspend fun findAllByResourceTypeForStatus(
+        resourceType: String,
+        status: ResourceConfigSnapshot.Status
+    ): List<ResourceConfigSnapshot>? =
+        withContext(Dispatchers.IO) {
+            resourceConfigSnapshotRepository.findByResourceTypeAndStatusOrderByCreatedDateDesc(resourceType, status)
+        }
+
+    suspend fun findAllByResourceType(
+        resourceType: String
+    ): List<ResourceConfigSnapshot>? =
+        withContext(Dispatchers.IO) {
+            resourceConfigSnapshotRepository.findByResourceTypeOrderByCreatedDateDesc(resourceType)
+        }
+
     suspend fun findByResourceIdAndResourceTypeAndStatus(
         resourceId: String,
         resourceType: String,
index 2a5f4c3..05f43c1 100644 (file)
@@ -53,6 +53,8 @@ import org.springframework.web.bind.annotation.RestController
 )
 open class ResourceConfigSnapshotController(private val resourceConfigSnapshotService: ResourceConfigSnapshotService) {
 
+    private val JSON_MIME_TYPE = "application/json"
+
     @RequestMapping(
         path = ["/health-check"],
         method = [RequestMethod.GET],
@@ -157,4 +159,84 @@ open class ResourceConfigSnapshotController(private val resourceConfigSnapshotSe
 
         ResponseEntity.ok().body(resultStored)
     }
+
+    @RequestMapping(
+            path = ["/allByID"],
+            method = [RequestMethod.GET],
+            produces = [MediaType.APPLICATION_JSON_VALUE]
+    )
+    @ApiOperation(
+            value = "Retrieve all resource configuration snapshots identified by a given resource_id",
+            notes = "Retrieve all config snapshots, identified by its Resource Id, ordered by most recently created/modified date. "
+    )
+    @ResponseBody
+    @PreAuthorize("hasRole('USER')")
+    fun getAllByID(
+        @ApiParam(value = "Resource Id associated of the resource configuration snapshots.", required = false)
+        @RequestParam(value = "resourceId", required = true) resourceId: String,
+        @ApiParam(value = "Status of the snapshot being retrieved.", defaultValue = "ANY", required = false)
+        @RequestParam(value = "status", required = false, defaultValue = "ANY") status: String
+    ): ResponseEntity<List<ResourceConfigSnapshot>?> = runBlocking {
+        var configSnapshots: List<ResourceConfigSnapshot>?
+
+        try {
+            if (status == "ANY") {
+                configSnapshots = resourceConfigSnapshotService.findAllByResourceId(resourceId)
+            } else {
+                configSnapshots = resourceConfigSnapshotService.findAllByResourceIdForStatus(
+                        resourceId, ResourceConfigSnapshot.Status.valueOf(status.toUpperCase()))
+            }
+        } catch (ex: NoSuchElementException) {
+            throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, ConfigsApiDomains.CONFIGS_API,
+                    "Could not find configuration snapshot entry for ID $resourceId",
+                    ex.errorCauseOrDefault())
+        } catch (ex: Exception) {
+            throw httpProcessorException(ErrorCatalogCodes.INVALID_REQUEST_FORMAT, ConfigsApiDomains.CONFIGS_API,
+                    "Unexpected error while finding configuration snapshot entries for ID $resourceId",
+                    ex.errorCauseOrDefault())
+        }
+
+        val expectedMediaType: MediaType = MediaType.valueOf(JSON_MIME_TYPE)
+        ResponseEntity.ok().contentType(expectedMediaType).body(configSnapshots)
+    }
+
+    @RequestMapping(
+            path = ["allByType"],
+            method = [RequestMethod.GET],
+            produces = [MediaType.APPLICATION_JSON_VALUE]
+    )
+    @ApiOperation(
+            value = "Retrieve all resource configuration snapshots for a given resource type.",
+            notes = "Retrieve all config snapshots matching a specified Resource Type, ordered by most recently created/modified date. "
+    )
+    @ResponseBody
+    @PreAuthorize("hasRole('USER')")
+    fun getAllByType(
+        @ApiParam(value = "Resource Type associated of the resource configuration snapshot.", required = false)
+        @RequestParam(value = "resourceType", required = true) resourceType: String,
+        @ApiParam(value = "Status of the snapshot being retrieved.", defaultValue = "ANY", required = false)
+        @RequestParam(value = "status", required = false, defaultValue = "ANY") status: String
+    ): ResponseEntity<List<ResourceConfigSnapshot>?> = runBlocking {
+        var configSnapshots: List<ResourceConfigSnapshot>?
+
+        try {
+            if (status == "ANY") {
+                configSnapshots = resourceConfigSnapshotService.findAllByResourceType(resourceType)
+            } else {
+                configSnapshots = resourceConfigSnapshotService.findAllByResourceTypeForStatus(
+                        resourceType, ResourceConfigSnapshot.Status.valueOf(status.toUpperCase()))
+            }
+        } catch (ex: NoSuchElementException) {
+            throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, ConfigsApiDomains.CONFIGS_API,
+                    "Could not find configuration snapshot entry for ID $resourceType",
+                    ex.errorCauseOrDefault())
+        } catch (ex: Exception) {
+            throw httpProcessorException(ErrorCatalogCodes.INVALID_REQUEST_FORMAT, ConfigsApiDomains.CONFIGS_API,
+                    "Unexpected error while finding configuration snapshot entries for type $resourceType",
+                    ex.errorCauseOrDefault())
+        }
+
+        val expectedMediaType: MediaType = MediaType.valueOf(JSON_MIME_TYPE)
+        ResponseEntity.ok().contentType(expectedMediaType).body(configSnapshots)
+    }
 }
index b54d92b..e2fa5ca 100644 (file)
@@ -140,6 +140,112 @@ class ResourceConfigSnapshotControllerTest {
         }
     }
 
+    @Test
+    fun `getAllByID returns 200 if entries found`() {
+        runBlocking {
+            post(resourceType, "3", "RUNNING")
+            post(resourceType, "2", "RUNNING")
+            post(resourceType, resourceId, "RUNNING")
+
+            webTestClient
+                    .get()
+                    .uri("/api/v1/configs/allByID?resourceId=$resourceId")
+                    .exchange()
+                    .expectStatus().is2xxSuccessful
+                    .expectBody()
+                    .jsonPath("$.length()")
+                    .isEqualTo(1)
+        }
+    }
+
+    @Test
+    fun `getAllByID with CANDIDATE status returns 200 if entries found`() {
+        runBlocking {
+            post(resourceType, "3", "RUNNING")
+            post(resourceType, "2", "RUNNING")
+            post(resourceType, resourceId, "CANDIDATE")
+
+            webTestClient
+                    .get()
+                    .uri("/api/v1/configs/allByID?resourceId=$resourceId&status=CANDIDATE")
+                    .exchange()
+                    .expectStatus().is2xxSuccessful
+                    .expectBody()
+                    .jsonPath("$.length()")
+                    .isEqualTo(1)
+        }
+    }
+
+    @Test
+    fun `getAllByID returns 400 error if missing parameter`() {
+        runBlocking {
+
+            webTestClient
+                    .get()
+                    .uri("/api/v1/configs/allByID")
+                    .exchange()
+                    .expectStatus().is4xxClientError
+                    .expectBody()
+        }
+    }
+
+    @Test
+    fun `getAllByID returns 400 error if wrong status parameter`() {
+        runBlocking {
+
+            webTestClient
+                    .get()
+                    .uri("/api/v1/configs/allByID?resourceId=$resourceId&status=NOTGOOD")
+                    .exchange()
+                    .expectStatus().is4xxClientError
+                    .expectBody()
+        }
+    }
+
+    @Test
+    fun `getAllByType returns 200 if entries found`() {
+        runBlocking {
+            post(resourceType, "3", "RUNNING")
+            post(resourceType + "DIFF", "2", "RUNNING")
+            post(resourceType, "1", "RUNNING")
+
+            webTestClient
+                    .get()
+                    .uri("/api/v1/configs/allByType?resourceType=$resourceType")
+                    .exchange()
+                    .expectStatus().is2xxSuccessful
+                    .expectBody()
+                    .jsonPath("$.length()")
+                    .isEqualTo(3)
+        }
+    }
+
+    @Test
+    fun `getAllByType returns 400 error if missing parameter`() {
+        runBlocking {
+
+            webTestClient
+                    .get()
+                    .uri("/api/v1/configs/allByType")
+                    .exchange()
+                    .expectStatus().is4xxClientError
+                    .expectBody()
+        }
+    }
+
+    @Test
+    fun `getAllByType returns 400 error if wrong status parameter`() {
+        runBlocking {
+
+            webTestClient
+                    .get()
+                    .uri("/api/v1/configs/allByType?resourceType=$resourceType&status=NOTGOOD")
+                    .exchange()
+                    .expectStatus().is4xxClientError
+                    .expectBody()
+        }
+    }
+
     private fun post(resourceType: String, resourceId: String, status: String) {
         webTestClient
             .post()