From: Jozsef Csongvai Date: Mon, 16 May 2022 15:09:06 +0000 (-0400) Subject: Enable deleting resources by lastN occurrences X-Git-Tag: 1.4.0~21 X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=fa536ca8bd901dc51833cfe906f7b22846674d2f;p=ccsdk%2Fcds.git Enable deleting resources by lastN occurrences Also enable deletion using resource-type and resource-id. Issue-ID: CCSDK-3735 Signed-off-by: Jozsef Csongvai Signed-off-by: kuldipr Change-Id: Id1b487fce97f582bd3781dfd5bcff61a8df08c5c --- diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt index ed9e6d1d6..3041fa773 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt @@ -26,6 +26,7 @@ import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment import org.slf4j.LoggerFactory import org.springframework.dao.EmptyResultDataAccessException import org.springframework.stereotype.Service +import java.lang.IllegalArgumentException import java.util.UUID @Service @@ -281,27 +282,80 @@ class ResourceResolutionDBService(private val resourceResolutionRepository: Reso } /** - * This is a deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey method to delete resources - * associated to a specific resolution-key + * This method to deletes resources associated to a specific resolution-key * * @param blueprintName name of the CBA * @param blueprintVersion version of the CBA * @param artifactName name of the artifact * @param resolutionKey value of the resolution-key + * @param lastNOccurrences number of occurrences to delete starting from the last, + * all occurrences will be deleted when null + * + * @return number of deleted rows */ - suspend fun deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey( + fun deleteResources( blueprintName: String, blueprintVersion: String, artifactName: String, - resolutionKey: String - ) { - resourceResolutionRepository.deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey( + resolutionKey: String, + lastNOccurrences: Int? + ): Int = lastNOccurrences?.let { + if (lastNOccurrences < 0) { + throw IllegalArgumentException("last N occurrences must be a positive integer") + } + resourceResolutionRepository.deleteLastNOccurences( blueprintName, blueprintVersion, artifactName, - resolutionKey + resolutionKey, + it ) - } + } ?: resourceResolutionRepository.deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey( + blueprintName, + blueprintVersion, + artifactName, + resolutionKey + ) + + /** + * This method to deletes resources associated to a specific resourceType and resourceId + * + * @param blueprintName name of the CBA + * @param blueprintVersion version of the CBA + * @param artifactName name of the artifact + * @param resourceType value of the resourceType + * @param resourceId value of the resourceId + * @param lastNOccurrences number of occurrences to delete starting from the last, + * all occurrences will be deleted when null + * + * @return number of deleted rows + */ + fun deleteResources( + blueprintName: String, + blueprintVersion: String, + artifactName: String, + resourceType: String, + resourceId: String, + lastNOccurrences: Int? + ): Int = lastNOccurrences?.let { + if (lastNOccurrences < 0) { + throw IllegalArgumentException("last N occurrences must be a positive integer") + } + resourceResolutionRepository.deleteLastNOccurences( + blueprintName, + blueprintVersion, + artifactName, + resourceType, + resourceId, + it + ) + } ?: resourceResolutionRepository.deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResourceTypeAndResourceId( + blueprintName, + blueprintVersion, + artifactName, + resourceType, + resourceId + ) suspend fun deleteResourceResolutionList(listResourceResolution: List) = withContext(Dispatchers.IO) { try { diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt index 4b707b04e..30969f1f6 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt @@ -16,6 +16,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Modifying import org.springframework.data.jpa.repository.Query import org.springframework.data.repository.query.Param import org.springframework.stereotype.Repository @@ -155,9 +156,65 @@ interface ResourceResolutionRepository : JpaRepository ( + SELECT max(occurrence) - :lastN FROM RESOURCE_RESOLUTION + WHERE resolution_key = :resolutionKey AND blueprint_name = :blueprintName + AND blueprint_version = :blueprintVersion AND artifact_name = :artifactName) + """, + nativeQuery = true + ) + fun deleteLastNOccurences( + @Param("blueprintName") blueprintName: String, + @Param("blueprintVersion") blueprintVersion: String, + @Param("artifactName") artifactName: String, + @Param("resolutionKey") resolutionKey: String, + @Param("lastN") lastN: Int + ): Int + + @Transactional + @Modifying + @Query( + value = """ + DELETE FROM RESOURCE_RESOLUTION + WHERE resource_type = :resourceType AND resource_id = :resourceId + AND blueprint_name = :blueprintName + AND blueprint_version = :blueprintVersion AND artifact_name = :artifactName + AND occurrence > ( + SELECT max(occurrence) - :lastN FROM RESOURCE_RESOLUTION + WHERE resource_type = :resourceType AND resource_id = :resourceId + AND blueprint_name = :blueprintName + AND blueprint_version = :blueprintVersion AND artifact_name = :artifactName) + """, + nativeQuery = true ) + fun deleteLastNOccurences( + @Param("blueprintName") blueprintName: String, + @Param("blueprintVersion") blueprintVersion: String, + @Param("artifactName") artifactName: String, + @Param("resourceType") resourceType: String, + @Param("resourceId") resourceId: String, + @Param("lastN") lastN: Int + ): Int } diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt index 8d4109fcf..69e7a646a 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt @@ -321,15 +321,54 @@ open class ResourceResolutionDBServiceTest { } @Test - fun deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKeyTest() { + fun deleteResourcesResolutionKeyAll() { every { - resourceResolutionRepository.deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey(any(), any(), any(), any()) - } returns Unit + resourceResolutionRepository.deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey(blueprintName, blueprintVersion, artifactPrefix, resolutionKey) + } returns 3 runBlocking { - val res = resourceResolutionDBService.deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey( - blueprintName, blueprintVersion, artifactPrefix, resolutionKey + val res = resourceResolutionDBService.deleteResources( + blueprintName, blueprintVersion, artifactPrefix, resolutionKey, null ) - assertEquals(Unit, res) + assertEquals(3, res) + } + } + + @Test + fun deleteResourcesResolutionKeyLastN() { + every { + resourceResolutionRepository.deleteLastNOccurences(blueprintName, blueprintVersion, artifactPrefix, resolutionKey, 1) + } returns 4 + runBlocking { + val res = resourceResolutionDBService.deleteResources( + blueprintName, blueprintVersion, artifactPrefix, resolutionKey, 1 + ) + assertEquals(4, res) + } + } + + @Test + fun deleteResourcesResourceIdAndTypeAll() { + every { + resourceResolutionRepository.deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResourceTypeAndResourceId(blueprintName, blueprintVersion, artifactPrefix, resourceType, resourceId) + } returns 3 + runBlocking { + val res = resourceResolutionDBService.deleteResources( + blueprintName, blueprintVersion, artifactPrefix, resourceType, resourceId, null + ) + assertEquals(3, res) + } + } + + @Test + fun deleteResourcesResourceIdAndTypeLastN() { + every { + resourceResolutionRepository.deleteLastNOccurences(blueprintName, blueprintVersion, artifactPrefix, resourceType, resourceId, 2) + } returns 6 + runBlocking { + val res = resourceResolutionDBService.deleteResources( + blueprintName, blueprintVersion, artifactPrefix, resourceType, resourceId, 2 + ) + assertEquals(6, res) } } } diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/DeleteResponse.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/DeleteResponse.kt new file mode 100644 index 000000000..0ad5b5e17 --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/DeleteResponse.kt @@ -0,0 +1,19 @@ +/* + * Copyright © 2022 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 + +data class DeleteResponse(val deletedEntries: Int) diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt index d2b7ac368..dbfc69738 100644 --- a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt @@ -173,25 +173,45 @@ open class ResourceController(private var resourceResolutionDBService: ResourceR notes = "Delete all the resources associated to a resolution-key using blueprint metadata, artifact name and the resolution-key." ) @PreAuthorize("hasRole('USER')") - fun deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey( + suspend fun deleteResolutions( @ApiParam(value = "Name of the CBA", required = true) @RequestParam(value = "bpName", required = true) bpName: String, @ApiParam(value = "Version of the CBA", required = true) @RequestParam(value = "bpVersion", required = true) bpVersion: String, @ApiParam(value = "Artifact name for which to retrieve a resolved resource", required = true) - @RequestParam(value = "artifactName", required = false, defaultValue = "") artifactName: String, - @ApiParam(value = "Resolution Key associated with the resolution", required = true) - @RequestParam(value = "resolutionKey", required = true) resolutionKey: String + @RequestParam(value = "artifactName", required = true, defaultValue = "") artifactName: String, + @ApiParam(value = "Resolution Key associated with the resolution", required = false) + @RequestParam(value = "resolutionKey", required = false) resolutionKey: String?, + @ApiParam(value = "resourceType associated with the resolution, must be used with resourceId", required = false) + @RequestParam(value = "resourceType", required = false) resourceType: String?, + @ApiParam(value = "Resolution Key associated with the resolution, must be used with resourceType", required = false) + @RequestParam(value = "resourceId", required = false) resourceId: String?, + @ApiParam(value = "Only delete last N occurrences", required = false) + @RequestParam(value = "lastN", required = false) lastN: Int? ) = runBlocking { - ResponseEntity.ok() - .body( - resourceResolutionDBService.deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey( + when { + resolutionKey?.isNotEmpty() == true -> resourceResolutionDBService.deleteResources( + bpName, + bpVersion, + artifactName, + resolutionKey, + lastN + ) + resourceId?.isNotEmpty() == true && resourceType?.isNotEmpty() == true -> + resourceResolutionDBService.deleteResources( bpName, bpVersion, artifactName, - resolutionKey + resourceType, + resourceId, + lastN ) + else -> throw httpProcessorException( + ErrorCatalogCodes.REQUEST_NOT_FOUND, + ResourceApiDomains.RESOURCE_API, + "Either use resolutionKey or resourceType + resourceId. Values cannot be blank" ) + }.let { ResponseEntity.ok().body(DeleteResponse(it)) } } @RequestMapping(