diff --git a/.gitignore b/.gitignore index 2fafe53..3a6ef2a 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ out/ .gradle build test_db.mv.db +.env diff --git a/buildSrc/src/main/kotlin/org/octopusden/octopus/task/ConfigureMockServer.kt b/buildSrc/src/main/kotlin/org/octopusden/octopus/task/ConfigureMockServer.kt index 6674684..7bd6f0d 100644 --- a/buildSrc/src/main/kotlin/org/octopusden/octopus/task/ConfigureMockServer.kt +++ b/buildSrc/src/main/kotlin/org/octopusden/octopus/task/ConfigureMockServer.kt @@ -10,7 +10,6 @@ import org.json.JSONObject import org.mockserver.client.MockServerClient import org.mockserver.model.HttpRequest import org.mockserver.model.HttpResponse -import org.mockserver.model.Parameter.param abstract class ConfigureMockServer : DefaultTask() { @@ -46,10 +45,45 @@ abstract class ConfigureMockServer : DefaultTask() { ).withStatusCode(200) } mockServerClient.`when`( - HttpRequest.request().withMethod("GET").withPath("/rest/release-engineering/3/component/ee-component/version/{version}/status") + HttpRequest.request().withMethod("GET").withPath("/rest/release-engineering/3/components/some-ee-component") + .withQueryStringParameter("build_whitelist", "status,version,release_version") + ).respond { + val versions = it.getFirstQueryStringParameter("versions").split(',') + val versionsField = it.getFirstQueryStringParameter("versions_field") + val versionStatuses = it.getFirstQueryStringParameter("version_statuses").split(',') + val builds = eeComponentBuilds.filter { build -> + build as JSONObject + versionStatuses.contains(build.getString("status")) && when (versionsField) { + "VERSION" -> versions.contains(build.getString("version")) + "RELEASE_VERSION" -> versions.contains(build.getString("release_version")) + else -> false + } + } + HttpResponse.response().withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.mimeType) + .withBody( + JSONObject().put("name", "some-ee-component") + .put("builds", builds) + .toString(2) + ).withStatusCode(200) + } + mockServerClient.`when`( + HttpRequest.request().withMethod("GET").withPath("/rest/release-engineering/3/component/{component-name}") + .withPathParameter("component-name") + ).respond { + val component = it.getFirstPathParameter("component-name") + if ("ee-component".equals(component, ignoreCase = true)) { + HttpResponse.response().withStatusCode(200) + } else { + HttpResponse.response().withStatusCode(404) + } + } + mockServerClient.`when`( + HttpRequest.request().withMethod("GET").withPath("/rest/release-engineering/3/component/{component-name}/version/{version}/status") .withPathParameter("version") + .withPathParameter("component-name") ).respond { val version = it.getFirstPathParameter("version") + val component = it.getFirstPathParameter("component-name") val build = eeComponentBuilds.firstOrNull { build -> build as JSONObject version == build.getString("version") @@ -57,7 +91,7 @@ abstract class ConfigureMockServer : DefaultTask() { if (build != null) { HttpResponse.response().withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.mimeType) .withBody( - JSONObject().put("component", "ee-component") + JSONObject().put("component", component) .put("version", build.getString("version")) .put("buildVersion", build.getString("version")) .put("releaseVersion", build.getString("release_version")) diff --git a/client/client/src/main/kotlin/org/octopusden/octopus/dms/client/DmsServiceFeignClient.kt b/client/client/src/main/kotlin/org/octopusden/octopus/dms/client/DmsServiceFeignClient.kt index c4c9347..d5a72f0 100644 --- a/client/client/src/main/kotlin/org/octopusden/octopus/dms/client/DmsServiceFeignClient.kt +++ b/client/client/src/main/kotlin/org/octopusden/octopus/dms/client/DmsServiceFeignClient.kt @@ -16,6 +16,7 @@ import feign.Headers import feign.Param import feign.RequestLine import feign.Response +import org.octopusden.octopus.dms.client.common.dto.ComponentDTO interface DmsServiceFeignClient { @RequestLine("GET rest/api/3/components") @@ -81,6 +82,13 @@ interface DmsServiceFeignClient { @Param("artifact-id") artifactId: Long ) + @RequestLine("POST /rest/api/3/admin/rename-component/{component-name}/{new-component-name}?dry-run=false") + @Headers("Accept: application/json") + fun renameComponent( + @Param("component-name") componentName: String, + @Param("new-component-name") newComponentName: String + ) + @RequestLine("GET rest/api/3/configuration") fun getConfiguration(): PropertiesDTO diff --git a/client/client/src/main/kotlin/org/octopusden/octopus/dms/client/impl/ClassicDmsServiceClient.kt b/client/client/src/main/kotlin/org/octopusden/octopus/dms/client/impl/ClassicDmsServiceClient.kt index 8b6ee54..817c14b 100644 --- a/client/client/src/main/kotlin/org/octopusden/octopus/dms/client/impl/ClassicDmsServiceClient.kt +++ b/client/client/src/main/kotlin/org/octopusden/octopus/dms/client/impl/ClassicDmsServiceClient.kt @@ -88,6 +88,9 @@ class ClassicDmsServiceClient( componentName: String, version: String, artifactId: Long ) = client.deleteComponentVersionArtifact(componentName, version, artifactId) + override fun renameComponent(componentName: String, newComponentName: String) = + client.renameComponent(componentName, newComponentName) + override fun getConfiguration() = client.getConfiguration() override fun getRepositories( diff --git a/common/src/main/kotlin/org/octopusden/octopus/dms/exception/ServicesExceptions.kt b/common/src/main/kotlin/org/octopusden/octopus/dms/exception/ServicesExceptions.kt index d381a3c..18a466b 100644 --- a/common/src/main/kotlin/org/octopusden/octopus/dms/exception/ServicesExceptions.kt +++ b/common/src/main/kotlin/org/octopusden/octopus/dms/exception/ServicesExceptions.kt @@ -12,7 +12,8 @@ abstract class DMSException(message: String, val code: String) : RuntimeExceptio "DMS-40008" to { message: String -> DownloadResultFailureException(message) }, "DMS-40010" to { message: String -> VersionFormatIsNotValidException(message) }, "DMS-40011" to { message: String -> NotFoundException(message) }, - "DMS-40012" to { message: String -> IllegalVersionStatusException(message) } + "DMS-40012" to { message: String -> IllegalVersionStatusException(message) }, + "DMS-40013" to { message: String -> IllegalComponentRenamingException(message) } ) } } @@ -26,4 +27,5 @@ class PackagingIsNotSpecifiedException(message: String) : DMSException(message, class DownloadResultFailureException(message: String) : DMSException(message, "DMS-40008") class VersionFormatIsNotValidException(message: String) : DMSException(message, "DMS-40010") class NotFoundException(message: String) : DMSException(message, "DMS-40011") -class IllegalVersionStatusException(message: String) : DMSException(message, "DMS-40012") \ No newline at end of file +class IllegalVersionStatusException(message: String) : DMSException(message, "DMS-40012") +class IllegalComponentRenamingException(message: String) : DMSException(message, "DMS-40013") \ No newline at end of file diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/controller/AdminController.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/controller/AdminController.kt index 9fd057d..fcd2ef6 100644 --- a/server/src/main/kotlin/org/octopusden/octopus/dms/controller/AdminController.kt +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/controller/AdminController.kt @@ -3,8 +3,10 @@ package org.octopusden.octopus.dms.controller import org.octopusden.octopus.dms.service.AdminService import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag +import org.springframework.http.MediaType import org.springframework.security.access.prepost.PreAuthorize import org.springframework.web.bind.annotation.DeleteMapping +import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestParam @@ -40,4 +42,13 @@ class AdminController( fun deleteOrphanedArtifacts( @RequestParam("dry-run", defaultValue = "true", required = false) dryRun: Boolean ) = adminService.deleteOrphanedArtifacts(dryRun) + + @Operation(summary = "Rename a component") + @PostMapping("rename-component/{component-name}/{new-component-name}", produces = [MediaType.APPLICATION_JSON_VALUE]) + fun renameComponent( + @PathVariable(name = "component-name") componentName: String, + @PathVariable(name = "new-component-name") newComponentName: String, + @RequestParam("dry-run", defaultValue = "true", required = false) dryRun: Boolean, + ) = adminService.renameComponent(componentName, newComponentName, dryRun) + } \ No newline at end of file diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/controller/advice/ExceptionHandler.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/controller/advice/ExceptionHandler.kt index 2c963a8..3800e63 100644 --- a/server/src/main/kotlin/org/octopusden/octopus/dms/controller/advice/ExceptionHandler.kt +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/controller/advice/ExceptionHandler.kt @@ -14,6 +14,7 @@ import org.octopusden.octopus.dms.exception.UnknownArtifactTypeException import org.octopusden.octopus.dms.exception.VersionFormatIsNotValidException import org.octopusden.octopus.dms.client.common.dto.ApplicationErrorResponse import feign.FeignException +import org.octopusden.octopus.dms.exception.IllegalComponentRenamingException import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpServletResponse import org.slf4j.Logger @@ -41,7 +42,8 @@ class ExceptionHandler(private val objectMapper: ObjectMapper) { PackagingIsNotSpecifiedException::class, DownloadResultFailureException::class, VersionFormatIsNotValidException::class, - IllegalVersionStatusException::class + IllegalVersionStatusException::class, + IllegalComponentRenamingException::class ) @Order(5) fun handle(request: HttpServletRequest, response: HttpServletResponse, e: DMSException) = diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/security/PermissionEvaluator.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/security/PermissionEvaluator.kt index e08812c..bd01fac 100644 --- a/server/src/main/kotlin/org/octopusden/octopus/dms/security/PermissionEvaluator.kt +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/security/PermissionEvaluator.kt @@ -41,7 +41,7 @@ class PermissionEvaluator( securityService.getCurrentUser(), componentName, try { - componentsRegistryService.getComponentReadSecurityGroups(componentName) + componentsRegistryService.getComponent(componentName).securityGroups.read } catch (e: Exception) { log.warn("Unable to get read security groups for component '$componentName'", e) emptyList() diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/service/AdminService.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/service/AdminService.kt index 748250a..b3dc371 100644 --- a/server/src/main/kotlin/org/octopusden/octopus/dms/service/AdminService.kt +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/service/AdminService.kt @@ -5,4 +5,5 @@ interface AdminService { fun deleteInvalidComponentsVersions(dryRun: Boolean) fun recalculateMinorVersions(dryRun: Boolean) fun deleteOrphanedArtifacts(dryRun: Boolean) + fun renameComponent(name: String, newName: String, dryRun: Boolean) } \ No newline at end of file diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/service/ComponentsRegistryService.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/service/ComponentsRegistryService.kt index a0cc41d..7661724 100644 --- a/server/src/main/kotlin/org/octopusden/octopus/dms/service/ComponentsRegistryService.kt +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/service/ComponentsRegistryService.kt @@ -5,8 +5,14 @@ import org.octopusden.octopus.components.registry.core.dto.DetailedComponentVers import org.octopusden.releng.versions.VersionNames interface ComponentsRegistryService { - fun getComponents(): List - fun getComponentReadSecurityGroups(component: String): List + /** + * Get component by name + * @param name component name + * @return component + * @throws NotFoundException if component not found + */ + fun getComponent(name: String): ComponentDTO + fun getExplicitExternalComponents(): List fun checkComponent(component: String) fun getDetailedComponentVersion(component: String, version: String): DetailedComponentVersion fun getVersionNames(): VersionNames diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/service/RelengService.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/service/RelengService.kt index ba121ad..c428dbf 100644 --- a/server/src/main/kotlin/org/octopusden/octopus/dms/service/RelengService.kt +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/service/RelengService.kt @@ -6,6 +6,7 @@ import org.octopusden.octopus.dms.client.common.dto.ArtifactType import org.octopusden.octopus.dms.client.common.dto.BuildStatus interface RelengService { + fun componentExists(component: String): Boolean fun checkVersionStatus(component: String, version: String, type: ArtifactType? = null) fun getComponentBuilds( component: String, diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/AdminServiceImpl.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/AdminServiceImpl.kt index b9f5dc2..b033069 100644 --- a/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/AdminServiceImpl.kt +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/AdminServiceImpl.kt @@ -1,5 +1,8 @@ package org.octopusden.octopus.dms.service.impl +import org.octopusden.octopus.dms.entity.Component +import org.octopusden.octopus.dms.exception.IllegalComponentRenamingException +import org.octopusden.octopus.dms.exception.NotFoundException import org.octopusden.octopus.dms.exception.UnableToFindArtifactException import org.octopusden.octopus.dms.repository.ArtifactRepository import org.octopusden.octopus.dms.repository.ComponentRepository @@ -8,10 +11,12 @@ import org.octopusden.octopus.dms.service.AdminService import org.octopusden.octopus.dms.service.ArtifactService import org.octopusden.octopus.dms.service.ComponentService import org.octopusden.octopus.dms.service.ComponentsRegistryService +import org.octopusden.octopus.dms.service.RelengService import org.octopusden.octopus.dms.service.StorageService import org.slf4j.LoggerFactory import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional +import org.octopusden.octopus.components.registry.core.exceptions.NotFoundException as ComponentsRegistryNotFoundException @Service @Transactional(readOnly = false) @@ -22,7 +27,8 @@ class AdminServiceImpl( //TODO: move functionality to ComponentService and Artif private val storageService: StorageService, private val componentRepository: ComponentRepository, private val componentVersionRepository: ComponentVersionRepository, - private val artifactRepository: ArtifactRepository + private val artifactRepository: ArtifactRepository, + private val relengService: RelengService ) : AdminService { override fun deleteInvalidComponents(dryRun: Boolean) { @@ -68,6 +74,70 @@ class AdminServiceImpl( //TODO: move functionality to ComponentService and Artif } } + /** + * Update component name and return new component name. + * By this point, the component should have already been renamed in 'releng'. + * @param name - old component name + * @param newName - new component name + * @param dryRun - if true, do not update component name + * @throws NotFoundException if component with name [name] not found in releng + */ + @Transactional(readOnly = false) + override fun renameComponent(name: String, newName: String, dryRun: Boolean) { + log.info("Update component name from '$name' to '$newName'") + + if (isComponentPresentInRegistry(name)) { + log.error("Component with name $name exists in components registry") + throw IllegalComponentRenamingException("Component with name $name exists in components registry") + } + if (!isComponentPresentInRegistry(newName)) { + log.error("Component with name $newName not found in components registry") + throw NotFoundException("Component with name $newName not found in components registry") + } + if (!relengService.componentExists(newName)) { + throw NotFoundException("Component with name $newName not found in releng") + } + val component = componentRepository.findByName(newName) + val existedComponent = componentRepository.findByName(name) + + if (existedComponent != null && component != null) { + with("Both component with name $name and name $newName exists in DMS") { + log.error(this) + throw IllegalComponentRenamingException(this) + } + } + + existedComponent?.let { + if (!dryRun) { + componentRepository.save(Component(name = newName, id = it.id)) + log.info("Component with name $name updated to $newName") + } else { + log.info("Component with name $name will be updated to $newName") + } + } ?: run { + log.warn("Component with name $name not found in DMS") + if (component == null) { + throw NotFoundException("None of $name and $newName components were found in DMS") + } + log.info("Component $name already renamed to $newName") + } + } + + /** + * Check if component with name [newName] exists in components registry + * @param name - the component name + * @return true if component with name [newName] exists in components registry + */ + private fun isComponentPresentInRegistry(name: String): Boolean { + return try{ + componentsRegistryService.getComponent(name) + return true + } catch (e: ComponentsRegistryNotFoundException) { + log.info("Component with name $name not found in components registry") + return false + } + } + companion object { private val log = LoggerFactory.getLogger(AdminServiceImpl::class.java) } diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/ComponentServiceImpl.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/ComponentServiceImpl.kt index 1a7693a..b6e231c 100644 --- a/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/ComponentServiceImpl.kt +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/ComponentServiceImpl.kt @@ -39,7 +39,7 @@ class ComponentServiceImpl( ) : ComponentService { override fun getComponents(): List { log.info("Get components") - return componentsRegistryService.getComponents() + return componentsRegistryService.getExplicitExternalComponents() } @Transactional(readOnly = false) diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/ComponentsRegistryServiceImpl.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/ComponentsRegistryServiceImpl.kt index 109df8a..11dae37 100644 --- a/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/ComponentsRegistryServiceImpl.kt +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/ComponentsRegistryServiceImpl.kt @@ -7,6 +7,7 @@ import org.octopusden.octopus.dms.exception.NotFoundException import org.octopusden.octopus.dms.service.ComponentsRegistryService import org.octopusden.octopus.components.registry.client.impl.ClassicComponentsRegistryServiceClient import org.octopusden.octopus.components.registry.client.impl.ClassicComponentsRegistryServiceClientUrlProvider +import org.octopusden.octopus.components.registry.core.dto.Component import org.octopusden.octopus.components.registry.core.dto.DetailedComponentVersion import org.octopusden.octopus.components.registry.core.dto.VersionRequest import org.octopusden.releng.versions.NumericVersionFactory @@ -27,20 +28,23 @@ class ComponentsRegistryServiceImpl( } ) - override fun getComponents() = client.getAllComponents().components + override fun getComponent(name: String): ComponentDTO = client.getById(name).let { + it.toComponentDTO() + } + + override fun getExplicitExternalComponents() = client.getAllComponents().components .filter { it.distribution?.let { d -> d.explicit && d.external } ?: false } .map { - ComponentDTO( - it.id, // Component name - it.name ?: it.id, // Component display name - it.clientCode, - it.parentComponent, - SecurityGroupsDTO(it.distribution?.securityGroups?.read ?: emptyList()) - ) + it.toComponentDTO() } - override fun getComponentReadSecurityGroups(component: String) = - client.getById(component).distribution?.securityGroups?.read ?: emptyList() + private fun Component.toComponentDTO() = ComponentDTO( + id, + name ?: id, + clientCode, + parentComponent, + SecurityGroupsDTO(distribution?.securityGroups?.read ?: emptyList()) + ) override fun checkComponent(component: String) { val distribution = client.getById(component).distribution diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/RelengServiceImpl.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/RelengServiceImpl.kt index e4d5a05..3bd3b74 100644 --- a/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/RelengServiceImpl.kt +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/RelengServiceImpl.kt @@ -11,6 +11,7 @@ import org.octopusden.octopus.dms.exception.NotFoundException import org.octopusden.octopus.dms.service.RelengService import khttp.get import khttp.responses.Response +import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service @@ -33,6 +34,18 @@ class RelengServiceImpl( //TODO: reimplement using RelengClient } } + override fun componentExists(component: String): Boolean = with(get( + url = "$baseURL/component/$component" + )) { + if (this.statusCode == 404) { + false + } else if (this.statusCode / 100 == 2) { + true + } else { + throw RuntimeException(this.text) + } + } + override fun getComponentBuilds( component: String, buildStatuses: Array, @@ -53,10 +66,13 @@ class RelengServiceImpl( //TODO: reimplement using RelengClient } } - private fun getComponentBuilds(component: String, params: Map) = get( - url = "$baseURL/components/$component", - params = params - ).toObject(object : TypeReference() {}).builds + private fun getComponentBuilds(component: String, params: Map): List { + log.debug("GET \"$baseURL/components/$component\" params=$params") + return get( + url = "$baseURL/components/$component", + params = params + ).toObject(object : TypeReference() {}).builds + } private fun Response.toObject(typeReference: TypeReference): T { if (this.statusCode / 100 != 2) { @@ -68,6 +84,10 @@ class RelengServiceImpl( //TODO: reimplement using RelengClient } return objectMapper.readValue(this.text, typeReference) } + + companion object { + private val log = LoggerFactory.getLogger(RelengServiceImpl::class.java) + } } data class VersionStatus( diff --git a/server/src/test/kotlin/org/octopusden/octopus/dms/DmsServiceApplicationUnitTest.kt b/server/src/test/kotlin/org/octopusden/octopus/dms/DmsServiceApplicationUnitTest.kt index 8dcbb62..8e44802 100644 --- a/server/src/test/kotlin/org/octopusden/octopus/dms/DmsServiceApplicationUnitTest.kt +++ b/server/src/test/kotlin/org/octopusden/octopus/dms/DmsServiceApplicationUnitTest.kt @@ -130,6 +130,11 @@ class DmsServiceApplicationUnitTest : DmsServiceApplicationBaseTest() { .with(SecurityMockMvcRequestPostProcessors.csrf()) ).andReturn().response.processError() + override fun renameComponent(componentName: String, newComponentName: String) = mockMvc.perform( + MockMvcRequestBuilders.post("/rest/api/3/admin/rename-component/$componentName/$newComponentName") + .with(SecurityMockMvcRequestPostProcessors.csrf()) + ).andReturn().response.processError() + override fun getConfiguration() = mockMvc.perform( MockMvcRequestBuilders.get("/rest/api/3/configuration") .accept(MediaType.APPLICATION_JSON) diff --git a/test-common/src/main/kotlin/org/octopusden/octopus/dms/DmsServiceApplicationBaseTest.kt b/test-common/src/main/kotlin/org/octopusden/octopus/dms/DmsServiceApplicationBaseTest.kt index ba6c7c3..82414b7 100644 --- a/test-common/src/main/kotlin/org/octopusden/octopus/dms/DmsServiceApplicationBaseTest.kt +++ b/test-common/src/main/kotlin/org/octopusden/octopus/dms/DmsServiceApplicationBaseTest.kt @@ -34,6 +34,7 @@ import org.junit.jupiter.api.TestInstance import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource +import org.octopusden.octopus.dms.exception.IllegalComponentRenamingException @TestInstance(TestInstance.Lifecycle.PER_CLASS) abstract class DmsServiceApplicationBaseTest { @@ -70,6 +71,15 @@ abstract class DmsServiceApplicationBaseTest { " FROM component WHERE name = '$component'") } + /** + * Internal method to update component name in the database + * @param name the old name + * @param newName the new name + */ + private fun updateName(name: String, newName: String) = dmsDbConnection.createStatement().use { + it.executeUpdate("UPDATE component SET name = '$newName' WHERE name = '$name'") + } + fun getResource(path: String) = this.javaClass.classLoader.getResource(path)!! @ParameterizedTest @@ -237,6 +247,40 @@ abstract class DmsServiceApplicationBaseTest { } } + @ParameterizedTest + @MethodSource("releaseArtifacts") + fun testRenameComponent(artifactCoordinates: ArtifactCoordinatesDTO) { + val artifact = client.addArtifact(artifactCoordinates) + client.registerComponentVersionArtifact(eeComponent, eeComponentReleaseVersion0354.buildVersion, artifact.id, RegisterArtifactDTO(ArtifactType.DISTRIBUTION)) + val componentVersionArtifacts = client.getComponentVersionArtifacts(eeComponent, eeComponentReleaseVersion0354.releaseVersion, ArtifactType.DISTRIBUTION) + assertEquals(1, componentVersionArtifacts.artifacts.size) + updateName(eeComponent, "some-$eeComponent") + assertThrows(NotFoundException::class.java) { + client.getComponentVersionArtifact("some-$eeComponent", eeComponentReleaseVersion0354.releaseVersion, artifact.id) + } + client.renameComponent("some-$eeComponent", eeComponent) + client.getComponentVersions(eeComponent, eeComponentReleaseVersion0354.minorVersion) + // Check that the operation(renaming) is idempotent + client.renameComponent("some-$eeComponent", eeComponent) + // Check exception to rename unexisting component + assertThrowsExactly(IllegalComponentRenamingException::class.java) { + client.renameComponent(eeComponent, eeComponent) + } + assertThrowsExactly(NotFoundException::class.java) { + client.renameComponent("some-$eeComponent", "some-$eeComponent") + } + // Check an exception, when both old and new component names exist in the system + val artifact2 = client.addArtifact(artifactCoordinates) + client.registerComponentVersionArtifact(eeClientSpecificComponent, eeComponentReleaseVersion0353.buildVersion, artifact2.id, RegisterArtifactDTO(ArtifactType.NOTES)) + assertThrows(IllegalComponentRenamingException::class.java) { + client.renameComponent(eeComponent, eeClientSpecificComponent) + } + // Check that artifact with new component name is available + client.downloadComponentVersionArtifact(eeComponent, eeComponentReleaseVersion0354.releaseVersion, artifact.id).use { response -> + assertTrue(response.body().asInputStream().readBytes().isNotEmpty()) + } + } + @Test fun testGetPreviousLinesLatestVersions() { assertEquals( @@ -406,6 +450,7 @@ abstract class DmsServiceApplicationBaseTest { companion object { data class Version(val minorVersion: String, val buildVersion: String, val releaseVersion: String) const val eeComponent = "ee-component" + const val eeClientSpecificComponent = "ee-client-specific-component" val eeComponentReleaseVersion0353 = Version("03.53.31", "03.53.30.31-1", "03.53.30.31") val eeComponentBuildVersion0353 = Version("03.53.31", "03.53.30.42-1", "03.53.30.42") val eeComponentRCVersion0353 = Version("03.53.31", "03.53.30.53-1", "03.53.30.53")