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 7bd6f0d..68548c8 100644 --- a/buildSrc/src/main/kotlin/org/octopusden/octopus/task/ConfigureMockServer.kt +++ b/buildSrc/src/main/kotlin/org/octopusden/octopus/task/ConfigureMockServer.kt @@ -102,5 +102,14 @@ abstract class ConfigureMockServer : DefaultTask() { HttpResponse.response().withStatusCode(404) } } + mockServerClient.`when`( + HttpRequest.request().withMethod("POST").withPath("/webhook") + ).respond { + if (it.bodyAsString?.contains("ee-component") == true) { + HttpResponse.response().withStatusCode(200) + } else { + HttpResponse.response().withStatusCode(500) + } + } } } diff --git a/ft/src/ft/docker/dms-service.yaml b/ft/src/ft/docker/dms-service.yaml index c9d0104..70488a6 100644 --- a/ft/src/ft/docker/dms-service.yaml +++ b/ft/src/ft/docker/dms-service.yaml @@ -21,6 +21,10 @@ auth-server: server: forward-headers-strategy: framework +dms-service: + webhook: + url: http://mockserver:1080/webhook + storage: maven-group-prefix: corp.domain.dms artifactory: diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/DmsServiceApplication.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/DmsServiceApplication.kt index d639834..a924858 100644 --- a/server/src/main/kotlin/org/octopusden/octopus/dms/DmsServiceApplication.kt +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/DmsServiceApplication.kt @@ -3,9 +3,11 @@ package org.octopusden.octopus.dms import org.springframework.boot.SpringApplication import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.context.properties.ConfigurationPropertiesScan +import org.springframework.cloud.openfeign.EnableFeignClients @SpringBootApplication @ConfigurationPropertiesScan +@EnableFeignClients class DmsServiceApplication fun main(args: Array) { diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/controller/ArtifactControllerV2.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/controller/ArtifactControllerV2.kt index e711e5c..27ea6af 100644 --- a/server/src/main/kotlin/org/octopusden/octopus/dms/controller/ArtifactControllerV2.kt +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/controller/ArtifactControllerV2.kt @@ -1,6 +1,9 @@ package org.octopusden.octopus.dms.controller import com.fasterxml.jackson.databind.ObjectMapper +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.Parameter +import io.swagger.v3.oas.annotations.tags.Tag import org.octopusden.octopus.dms.client.common.dto.ArtifactType import org.octopusden.octopus.dms.client.common.dto.BuildStatus import org.octopusden.octopus.dms.client.common.dto.ComponentVersionsStatusesDTO @@ -8,6 +11,7 @@ import org.octopusden.octopus.dms.client.common.dto.MavenArtifactFullDTO import org.octopusden.octopus.dms.client.common.dto.RepositoryType import org.octopusden.octopus.dms.client.common.dto.legacy.LegacyArtifactDTO import org.octopusden.octopus.dms.client.common.dto.legacy.LegacyArtifactsDTO +import org.octopusden.octopus.dms.dto.ComponentVersionStatusWithInfoDTO import org.octopusden.octopus.dms.exception.NotFoundException import org.octopusden.octopus.dms.exception.VersionFormatIsNotValidException import org.octopusden.octopus.dms.repository.ComponentVersionArtifactRepository @@ -17,10 +21,6 @@ import org.octopusden.octopus.dms.service.ComponentsRegistryService import org.octopusden.octopus.dms.service.RelengService import org.octopusden.octopus.dms.service.StorageService import org.octopusden.octopus.dms.service.impl.VersionField -import org.octopusden.octopus.dms.service.impl.dto.ComponentVersionStatusWithInfoDTO -import io.swagger.v3.oas.annotations.Operation -import io.swagger.v3.oas.annotations.Parameter -import io.swagger.v3.oas.annotations.tags.Tag import org.octopusden.releng.versions.NumericVersionFactory import org.slf4j.Logger import org.slf4j.LoggerFactory diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/dto/ComponentVersionStatusWithInfoDTO.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/dto/ComponentVersionStatusWithInfoDTO.kt similarity index 88% rename from server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/dto/ComponentVersionStatusWithInfoDTO.kt rename to server/src/main/kotlin/org/octopusden/octopus/dms/dto/ComponentVersionStatusWithInfoDTO.kt index d4ef5f6..acaa160 100644 --- a/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/dto/ComponentVersionStatusWithInfoDTO.kt +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/dto/ComponentVersionStatusWithInfoDTO.kt @@ -1,4 +1,4 @@ -package org.octopusden.octopus.dms.service.impl.dto +package org.octopusden.octopus.dms.dto import org.octopusden.octopus.dms.client.common.dto.BuildStatus import org.octopusden.octopus.dms.client.common.dto.ComponentVersionStatusDTO diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/dto/DownloadArtifactDTO.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/dto/DownloadArtifactDTO.kt similarity index 67% rename from server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/dto/DownloadArtifactDTO.kt rename to server/src/main/kotlin/org/octopusden/octopus/dms/dto/DownloadArtifactDTO.kt index 2ced5ed..1a7a00c 100644 --- a/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/dto/DownloadArtifactDTO.kt +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/dto/DownloadArtifactDTO.kt @@ -1,4 +1,4 @@ -package org.octopusden.octopus.dms.service.impl.dto +package org.octopusden.octopus.dms.dto import java.io.InputStream diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/event/DeleteComponentVersionArtifactEvent.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/event/DeleteComponentVersionArtifactEvent.kt new file mode 100644 index 0000000..1e27996 --- /dev/null +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/event/DeleteComponentVersionArtifactEvent.kt @@ -0,0 +1,9 @@ +package org.octopusden.octopus.dms.event + +import org.octopusden.octopus.dms.client.common.dto.ArtifactFullDTO + +data class DeleteComponentVersionArtifactEvent( + val component: String, + val version: String, + val artifact: ArtifactFullDTO +) : Event(EventType.DELETE_COMPONENT_VERSION_ARTIFACT) diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/event/Event.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/event/Event.kt new file mode 100644 index 0000000..6278e34 --- /dev/null +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/event/Event.kt @@ -0,0 +1,18 @@ +package org.octopusden.octopus.dms.event + +import com.fasterxml.jackson.annotation.JsonSubTypes +import com.fasterxml.jackson.annotation.JsonTypeInfo + +@JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + include = JsonTypeInfo.As.EXISTING_PROPERTY, + property = "type", + visible = true +) +@JsonSubTypes( + JsonSubTypes.Type(RegisterComponentVersionArtifactEvent::class, name = "REGISTER_COMPONENT_VERSION_ARTIFACT"), + JsonSubTypes.Type(DeleteComponentVersionArtifactEvent::class, name = "DELETE_COMPONENT_VERSION_ARTIFACT") +) +abstract class Event( + val type: EventType +) \ No newline at end of file diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/event/EventType.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/event/EventType.kt new file mode 100644 index 0000000..ee3c299 --- /dev/null +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/event/EventType.kt @@ -0,0 +1,5 @@ +package org.octopusden.octopus.dms.event + +enum class EventType { + REGISTER_COMPONENT_VERSION_ARTIFACT, DELETE_COMPONENT_VERSION_ARTIFACT +} \ No newline at end of file diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/event/RegisterComponentVersionArtifactEvent.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/event/RegisterComponentVersionArtifactEvent.kt new file mode 100644 index 0000000..913de19 --- /dev/null +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/event/RegisterComponentVersionArtifactEvent.kt @@ -0,0 +1,9 @@ +package org.octopusden.octopus.dms.event + +import org.octopusden.octopus.dms.client.common.dto.ArtifactFullDTO + +data class RegisterComponentVersionArtifactEvent( + val component: String, + val version: String, + val artifact: ArtifactFullDTO +) : Event(EventType.REGISTER_COMPONENT_VERSION_ARTIFACT) \ No newline at end of file diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/repository/ComponentVersionArtifactRepository.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/repository/ComponentVersionArtifactRepository.kt index 4763e19..993f372 100644 --- a/server/src/main/kotlin/org/octopusden/octopus/dms/repository/ComponentVersionArtifactRepository.kt +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/repository/ComponentVersionArtifactRepository.kt @@ -7,6 +7,8 @@ import org.octopusden.octopus.dms.entity.ComponentVersionArtifact import org.springframework.data.jpa.repository.JpaRepository interface ComponentVersionArtifactRepository : JpaRepository { + fun findByComponentVersion(componentVersion: ComponentVersion): List + fun findByComponentVersionComponentNameAndComponentVersionVersion( componentVersionComponentName: String, componentVersionVersion: String diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/repository/ComponentVersionRepository.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/repository/ComponentVersionRepository.kt index 5a247de..a58cc33 100644 --- a/server/src/main/kotlin/org/octopusden/octopus/dms/repository/ComponentVersionRepository.kt +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/repository/ComponentVersionRepository.kt @@ -16,6 +16,8 @@ interface ComponentVersionRepository : JpaRepository { @Param("minorVersions") minorVersions: List ): List + fun findByComponent(component: Component): List + fun findByComponentName(componentName: String): List fun findByComponentAndVersion(component: Component, version: String): ComponentVersion? diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/service/ArtifactService.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/service/ArtifactService.kt index be61452..07fd010 100644 --- a/server/src/main/kotlin/org/octopusden/octopus/dms/service/ArtifactService.kt +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/service/ArtifactService.kt @@ -3,7 +3,7 @@ package org.octopusden.octopus.dms.service import org.octopusden.octopus.dms.client.common.dto.ArtifactCoordinatesDTO import org.octopusden.octopus.dms.client.common.dto.ArtifactDTO import org.octopusden.octopus.dms.client.common.dto.RepositoryType -import org.octopusden.octopus.dms.service.impl.dto.DownloadArtifactDTO +import org.octopusden.octopus.dms.dto.DownloadArtifactDTO import org.springframework.web.multipart.MultipartFile interface ArtifactService { diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/service/ComponentService.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/service/ComponentService.kt index 511a1be..30e1960 100644 --- a/server/src/main/kotlin/org/octopusden/octopus/dms/service/ComponentService.kt +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/service/ComponentService.kt @@ -1,12 +1,12 @@ package org.octopusden.octopus.dms.service -import org.octopusden.octopus.dms.service.impl.dto.ComponentVersionStatusWithInfoDTO -import org.octopusden.octopus.dms.service.impl.dto.DownloadArtifactDTO import org.octopusden.octopus.dms.client.common.dto.ArtifactFullDTO import org.octopusden.octopus.dms.client.common.dto.ArtifactType import org.octopusden.octopus.dms.client.common.dto.ArtifactsDTO import org.octopusden.octopus.dms.client.common.dto.ComponentDTO import org.octopusden.octopus.dms.client.common.dto.RegisterArtifactDTO +import org.octopusden.octopus.dms.dto.ComponentVersionStatusWithInfoDTO +import org.octopusden.octopus.dms.dto.DownloadArtifactDTO interface ComponentService { fun getComponents(): List diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/ArtifactServiceImpl.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/ArtifactServiceImpl.kt index bdaa5f7..94abc11 100644 --- a/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/ArtifactServiceImpl.kt +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/service/impl/ArtifactServiceImpl.kt @@ -6,6 +6,7 @@ import org.octopusden.octopus.dms.client.common.dto.DebianArtifactCoordinatesDTO import org.octopusden.octopus.dms.client.common.dto.MavenArtifactCoordinatesDTO import org.octopusden.octopus.dms.client.common.dto.RepositoryType import org.octopusden.octopus.dms.client.common.dto.RpmArtifactCoordinatesDTO +import org.octopusden.octopus.dms.dto.DownloadArtifactDTO import org.octopusden.octopus.dms.entity.DebianArtifact import org.octopusden.octopus.dms.entity.MavenArtifact import org.octopusden.octopus.dms.entity.RpmArtifact @@ -14,7 +15,6 @@ import org.octopusden.octopus.dms.exception.NotFoundException import org.octopusden.octopus.dms.repository.ArtifactRepository import org.octopusden.octopus.dms.service.ArtifactService import org.octopusden.octopus.dms.service.StorageService -import org.octopusden.octopus.dms.service.impl.dto.DownloadArtifactDTO import org.slf4j.LoggerFactory import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional 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 b6e231c..5b1f9e9 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 @@ -6,9 +6,13 @@ import org.octopusden.octopus.dms.client.common.dto.ArtifactsDTO import org.octopusden.octopus.dms.client.common.dto.BuildStatus import org.octopusden.octopus.dms.client.common.dto.ComponentDTO import org.octopusden.octopus.dms.client.common.dto.RegisterArtifactDTO +import org.octopusden.octopus.dms.dto.ComponentVersionStatusWithInfoDTO +import org.octopusden.octopus.dms.dto.DownloadArtifactDTO import org.octopusden.octopus.dms.entity.Component import org.octopusden.octopus.dms.entity.ComponentVersion import org.octopusden.octopus.dms.entity.ComponentVersionArtifact +import org.octopusden.octopus.dms.event.DeleteComponentVersionArtifactEvent +import org.octopusden.octopus.dms.event.RegisterComponentVersionArtifactEvent import org.octopusden.octopus.dms.exception.ArtifactAlreadyExistsException import org.octopusden.octopus.dms.exception.NotFoundException import org.octopusden.octopus.dms.exception.VersionFormatIsNotValidException @@ -20,10 +24,9 @@ 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.octopusden.octopus.dms.service.impl.dto.ComponentVersionStatusWithInfoDTO -import org.octopusden.octopus.dms.service.impl.dto.DownloadArtifactDTO import org.octopusden.releng.versions.NumericVersionFactory import org.slf4j.LoggerFactory +import org.springframework.context.ApplicationEventPublisher import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -35,7 +38,8 @@ class ComponentServiceImpl( private val componentRepository: ComponentRepository, private val componentVersionRepository: ComponentVersionRepository, private val componentVersionArtifactRepository: ComponentVersionArtifactRepository, - private val artifactRepository: ArtifactRepository + private val artifactRepository: ArtifactRepository, + private val applicationEventPublisher: ApplicationEventPublisher ) : ComponentService { override fun getComponents(): List { log.info("Get components") @@ -45,9 +49,20 @@ class ComponentServiceImpl( @Transactional(readOnly = false) override fun deleteComponent(componentName: String, dryRun: Boolean) { log.info("Delete component '$componentName'") - componentRepository.findByName(componentName)?.let { - if (!dryRun) componentRepository.delete(it) - log.info("$it deleted") + componentRepository.findByName(componentName)?.let { component -> + if (!dryRun) { + componentVersionRepository.findByComponent(component).forEach { componentVersion -> + componentVersionArtifactRepository.findByComponentVersion(componentVersion).forEach { + applicationEventPublisher.publishEvent( + DeleteComponentVersionArtifactEvent( + componentName, componentVersion.version, it.toFullDTO() + ) + ) + } + } + componentRepository.delete(component) + } + log.info("$component deleted") } } @@ -101,14 +116,22 @@ class ComponentServiceImpl( @Transactional(readOnly = false) override fun deleteComponentVersion(componentName: String, version: String, dryRun: Boolean) { log.info("Delete version '$version' of component '$componentName'") - componentVersionRepository.findByComponentNameAndVersion(componentName, version)?.let { - if (!dryRun) componentVersionRepository.delete(it) - log.info("$it deleted") - } ?: with(normalizeComponentVersion(componentName, version)) { - componentVersionRepository.findByComponentNameAndVersion(componentName, this.second)?.let { - if (!dryRun) componentVersionRepository.delete(it) - log.info("$it deleted") + val componentVersion = componentVersionRepository.findByComponentNameAndVersion(componentName, version) + ?: with(normalizeComponentVersion(componentName, version)) { + componentVersionRepository.findByComponentNameAndVersion(componentName, this.second) + } + componentVersion?.let { + if (!dryRun) { + componentVersionArtifactRepository.findByComponentVersion(it).forEach { componentVersionArtifact -> + applicationEventPublisher.publishEvent( + DeleteComponentVersionArtifactEvent( + componentName, it.version, componentVersionArtifact.toFullDTO() + ) + ) + } + componentVersionRepository.delete(it) } + log.info("$it deleted") } } @@ -141,8 +164,7 @@ class ComponentServiceImpl( version: String, type: ArtifactType? ): ArtifactsDTO { - log.info("Get artifacts" + (type?.let { " with type '$it'" } - ?: "") + " for version '$version' of component '$componentName'") + log.info("Get artifacts" + (type?.let { " with type '$it'" } ?: "") + " for version '$version' of component '$componentName'") componentsRegistryService.checkComponent(componentName) val (_, buildVersion) = normalizeComponentVersion(componentName, version) relengService.checkVersionStatus(componentName, buildVersion, type) @@ -236,7 +258,11 @@ class ComponentServiceImpl( type = registerArtifactDTO.type ) ) - return componentVersionArtifact.toFullDTO() + return componentVersionArtifact.toFullDTO().also { + applicationEventPublisher.publishEvent( + RegisterComponentVersionArtifactEvent(componentName, buildVersion, it) + ) + } } @Transactional(readOnly = false) @@ -251,7 +277,12 @@ class ComponentServiceImpl( componentVersionArtifactRepository.findByComponentVersionComponentNameAndComponentVersionVersionAndArtifactId( componentName, buildVersion, artifactId )?.let { - if (!dryRun) componentVersionArtifactRepository.delete(it) + if (!dryRun) { + applicationEventPublisher.publishEvent( + DeleteComponentVersionArtifactEvent(componentName, buildVersion, it.toFullDTO()) + ) + componentVersionArtifactRepository.delete(it) + } log.info("$it deleted") } } diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/webhook/WebhookEventListener.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/webhook/WebhookEventListener.kt new file mode 100644 index 0000000..75774ec --- /dev/null +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/webhook/WebhookEventListener.kt @@ -0,0 +1,29 @@ +package org.octopusden.octopus.dms.webhook + +import org.octopusden.octopus.dms.event.Event +import org.slf4j.LoggerFactory +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.scheduling.annotation.Async +import org.springframework.stereotype.Component +import org.springframework.transaction.event.TransactionalEventListener + +@ConditionalOnProperty(prefix = "dms-service.webhook", name = ["enabled"], havingValue = "true", matchIfMissing = true) +@Component +class WebhookEventListener( + val webhookFeignClient: WebhookFeignClient +) { + @Async + @TransactionalEventListener + fun onEvent(event: Event) { + log.info("Sending ${event.type} webhook") + try { + webhookFeignClient.post(event) + } catch (e: Exception) { + log.warn("Unable to send webhook", e) + } + } + + companion object { + private val log = LoggerFactory.getLogger(WebhookEventListener::class.java) + } +} \ No newline at end of file diff --git a/server/src/main/kotlin/org/octopusden/octopus/dms/webhook/WebhookFeignClient.kt b/server/src/main/kotlin/org/octopusden/octopus/dms/webhook/WebhookFeignClient.kt new file mode 100644 index 0000000..b994924 --- /dev/null +++ b/server/src/main/kotlin/org/octopusden/octopus/dms/webhook/WebhookFeignClient.kt @@ -0,0 +1,13 @@ +package org.octopusden.octopus.dms.webhook + +import org.octopusden.octopus.dms.event.Event +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.cloud.openfeign.FeignClient +import org.springframework.web.bind.annotation.PostMapping + +@ConditionalOnProperty(prefix = "dms-service.webhook", name = ["enabled"], havingValue = "true", matchIfMissing = true) +@FeignClient("webhook", url = "\${dms-service.webhook.url}") +interface WebhookFeignClient { + @PostMapping + fun post(event: Event) +} \ No newline at end of file diff --git a/server/src/test/resources/application-ut.yaml b/server/src/test/resources/application-ut.yaml index cd76aaf..25de014 100644 --- a/server/src/test/resources/application-ut.yaml +++ b/server/src/test/resources/application-ut.yaml @@ -17,6 +17,10 @@ auth-server: url: # set via env realm: # set via env +dms-service: + webhook: + enabled: false + storage: maven-group-prefix: corp.domain.dms artifactory: