Skip to content

Commit

Permalink
[CID-1867] Registering webhooks on boot (Create new, then delete old …
Browse files Browse the repository at this point in the history
…ones) (#7)

* Registering webhooks on boot. (Create new then delete old ones)

* fixing formatting issues

* changing gitlab webhook url from  to /webhook

* addressing PR comments

* deleting unused CreateGitlabWebhookRequest

* reading enableSSLVerification from props

* adding enable-ssl-verification to test application.yaml

* adding enable-ssl-verification to test application.yaml

* moving interfaces to the domain package

* moving interfaces to the domain package

* adding LEANIX_WEBHOOK_PATH assertion to test
  • Loading branch information
ahmed-ali-55 authored Aug 28, 2023
1 parent 503e874 commit 9d75e99
Show file tree
Hide file tree
Showing 15 changed files with 254 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.leanix.vsm.gitlab.broker.connector.applicaiton
package net.leanix.vsm.gitlab.broker.connector.application

import net.leanix.vsm.gitlab.broker.connector.domain.AssignmentProvider
import net.leanix.vsm.gitlab.broker.connector.domain.GitLabAssignment
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package net.leanix.vsm.gitlab.broker.connector.runner

import net.leanix.vsm.gitlab.broker.connector.applicaiton.AssignmentService
import net.leanix.vsm.gitlab.broker.connector.application.AssignmentService
import net.leanix.vsm.gitlab.broker.shared.cache.AssignmentsCache
import net.leanix.vsm.gitlab.broker.webhook.domain.WebhookService
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.boot.ApplicationArguments
Expand All @@ -11,12 +12,18 @@ import org.springframework.stereotype.Component
@Component
class InitialStateRunner(
private val assignmentService: AssignmentService,
private val webhookService: WebhookService
) : ApplicationRunner {

private val logger: Logger = LoggerFactory.getLogger(InitialStateRunner::class.java)

override fun run(args: ApplicationArguments?) {
logger.info("Started to get initial state")
fetchAssignments()
setupWebhook()
}

private fun fetchAssignments() {
runCatching {
assignmentService.getAssignments()?.forEach { assignment ->
logger.info(
Expand All @@ -30,4 +37,14 @@ class InitialStateRunner(
logger.error("Failed to get initial state", e)
}
}

private fun setupWebhook() {
runCatching {
webhookService.registerWebhook()
}.onSuccess {
logger.info("webhook registered successfully")
}.onFailure {
logger.info("webhook registration failed", it)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package net.leanix.vsm.gitlab.broker.connector.scheduler

import net.leanix.vsm.gitlab.broker.connector.adapter.feign.VsmClient
import net.leanix.vsm.gitlab.broker.connector.applicaiton.AssignmentService
import net.leanix.vsm.gitlab.broker.connector.application.AssignmentService
import net.leanix.vsm.gitlab.broker.shared.cache.AssignmentsCache
import org.slf4j.LoggerFactory
import org.springframework.scheduling.annotation.Scheduled
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package net.leanix.vsm.gitlab.broker.webhook.adapter.feign

import net.leanix.vsm.gitlab.broker.webhook.domain.GitlabWebhook
import org.springframework.cloud.openfeign.FeignClient
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestParam

@FeignClient(
name = "gitlabWebhookClient",
url = "\${leanix.gitlab.base-url}",
configuration = [GitlabWebhookFeignClientConfiguration::class]
)
interface GitlabWebhookClient {

@GetMapping("/hooks")
fun getAllWebhooks(): List<GitlabWebhook>

@DeleteMapping("/hooks/{webhookId}")
fun deleteWebhook(@PathVariable("webhookId") webhookId: Int)

@Suppress("LongParameterList")
@PostMapping("/hooks")
fun createWebhook(
@RequestParam("url") url: String,
@RequestParam("token") token: String,
@RequestParam("push_events") receivePushEvents: Boolean,
@RequestParam("tag_push_events") receiveTagPushEvents: Boolean,
@RequestParam("merge_requests_events") receiveMergeRequestEvents: Boolean,
@RequestParam("repository_update_events") receiveRepositoryUpdateEvents: Boolean,
@RequestParam("enable_ssl_verification") enableSSLVerification: Boolean,
): GitlabWebhook
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package net.leanix.vsm.gitlab.broker.webhook.adapter.feign

import feign.RequestInterceptor
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class GitlabWebhookFeignClientConfiguration(

@Value("\${leanix.gitlab.access-token}") private val gitlabAccessToken: String
) {
@Bean
fun requestInterceptor(): RequestInterceptor {
return RequestInterceptor {
it.header("PRIVATE-TOKEN", gitlabAccessToken)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package net.leanix.vsm.gitlab.broker.webhook.adapter.feign

import net.leanix.vsm.gitlab.broker.connector.application.AssignmentService
import net.leanix.vsm.gitlab.broker.webhook.domain.GitlabWebhook
import net.leanix.vsm.gitlab.broker.webhook.domain.WebhookProvider
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component

const val LEANIX_WEBHOOK_PATH = "/leanix-vsm/webhook"

@Component
class GitlabWebhookProvider(
private val webhookClient: GitlabWebhookClient,
@Value("\${leanix.gitlab.webhook-url}") private val gitlabWebhookUrl: String,
@Value("\${leanix.gitlab.leanix-id}") private val leanixId: String,
@Value("\${leanix.gitlab.enable-ssl-verification}") private val enableSSLVerification: Boolean,
) : WebhookProvider {

private val logger = LoggerFactory.getLogger(AssignmentService::class.java)

override fun getAllWebhooks(): List<GitlabWebhook> {
return kotlin.runCatching {
webhookClient.getAllWebhooks()
}.onSuccess {
logger.info("Webhooks fetched. size: ${it.size}")
}.onFailure {
logger.error("Error while fetching webhooks: ${it.message}")
}.getOrThrow()
}

override fun deleteWebhook(webhookId: Int) {
return kotlin.runCatching {
webhookClient.deleteWebhook(webhookId)
}.onSuccess {
logger.info("Webhooks deleted for id: $webhookId")
}.onFailure {
logger.error("Error while deleting webhook with id $webhookId: ${it.message}")
}.getOrThrow()
}

override fun createWebhook(): GitlabWebhook {
return kotlin.runCatching {
webhookClient.createWebhook(
url = "$gitlabWebhookUrl$LEANIX_WEBHOOK_PATH",
token = leanixId,
receivePushEvents = true,
receiveTagPushEvents = false,
receiveMergeRequestEvents = true,
receiveRepositoryUpdateEvents = true,
enableSSLVerification = enableSSLVerification
)
}.onSuccess {
logger.info("Webhook created with id ${it.id}")
}.onFailure {
logger.error("Error creating webhook: ${it.message}")
}.getOrThrow()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package net.leanix.vsm.gitlab.broker.webhook.application

import net.leanix.vsm.gitlab.broker.webhook.adapter.feign.LEANIX_WEBHOOK_PATH
import net.leanix.vsm.gitlab.broker.webhook.domain.GitlabWebhook
import net.leanix.vsm.gitlab.broker.webhook.domain.WebhookProvider
import net.leanix.vsm.gitlab.broker.webhook.domain.WebhookService
import org.springframework.stereotype.Service

@Service
class GitlabWebhookServiceImpl(
private val webhookProvider: WebhookProvider
) : WebhookService {

override fun registerWebhook(): GitlabWebhook {
val webhook = webhookProvider.createWebhook()

webhookProvider.getAllWebhooks()
.filter { it.url.contains(LEANIX_WEBHOOK_PATH) && it.id != webhook.id }
.forEach { webhookProvider.deleteWebhook(it.id) }

return webhook
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package net.leanix.vsm.gitlab.broker.webhook.domain

import com.fasterxml.jackson.annotation.JsonProperty
import java.util.Date

data class GitlabWebhook(
val id: Int,
val url: String,
@JsonProperty("created_at")
val createdAt: Date,
@JsonProperty("push_events")
val pushEvents: Boolean,
@JsonProperty("tag_push_events")
val tagPushEvents: Boolean,
@JsonProperty("merge_requests_events")
val mergeRequestsEvents: Boolean,
@JsonProperty("repository_update_events")
val repositoryUpdateEvents: Boolean,
@JsonProperty("enable_ssl_verification")
val enableSSLVerification: Boolean,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package net.leanix.vsm.gitlab.broker.webhook.domain

interface WebhookProvider {

fun getAllWebhooks(): List<GitlabWebhook>
fun deleteWebhook(webhookId: Int)
fun createWebhook(): GitlabWebhook
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package net.leanix.vsm.gitlab.broker.webhook.domain

interface WebhookService {
fun registerWebhook(): GitlabWebhook
}
2 changes: 2 additions & 0 deletions src/main/resources/application-local.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ leanix:
base-url: http://localhost:8080
auth:
access-token-uri: https://test-app-1.leanix.net/services/mtm/v1
gitlab:
leanix-id: ${LEANIX_ID:dummy}

server:
port: 8082
8 changes: 7 additions & 1 deletion src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ leanix:
base-url: ${leanix.vsm.base-url}/vsm-events-broker
auth:
access-token-uri: ${leanix.base-url}/mtm/v1
gitlab:
base-url: ${GITLAB_URL}
access-token: ${GITLAB_TOKEN}
webhook-url: ${GITLAB_WEBHOOK_URL}
leanix-id: ${LEANIX_ID}
enable-ssl-verification: ${ENABLE_SSL_VERIFICATION:false}

server:
port: 8082
port: 8082
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package net.leanix.vsm.gitlab.broker.connector.scheduler

import net.leanix.vsm.gitlab.broker.connector.adapter.feign.VsmClient
import net.leanix.vsm.gitlab.broker.connector.applicaiton.AssignmentService
import net.leanix.vsm.gitlab.broker.connector.application.AssignmentService
import net.leanix.vsm.gitlab.broker.connector.domain.GitLabAssignment
import net.leanix.vsm.gitlab.broker.connector.domain.GitLabConfiguration
import net.leanix.vsm.gitlab.broker.connector.domain.GitLabHeartbeatResponse
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package net.leanix.vsm.gitlab.broker.webhook.application

import net.leanix.vsm.gitlab.broker.webhook.adapter.feign.LEANIX_WEBHOOK_PATH
import net.leanix.vsm.gitlab.broker.webhook.domain.GitlabWebhook
import net.leanix.vsm.gitlab.broker.webhook.domain.WebhookProvider
import org.junit.jupiter.api.Test
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mockito.mock
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import java.util.Date

class GitlabWebhookServiceImplTest {

private val webhookProvider = mock(WebhookProvider::class.java)
private val subject = GitlabWebhookServiceImpl(webhookProvider)

@Test
fun `given a new one webhook is created successfully when registerWebhook then delete all other leanix webhooks`() {
`when`(webhookProvider.createWebhook()).thenReturn(dummyGitlabWebhookDto(id = 1))
`when`(webhookProvider.getAllWebhooks()).thenReturn(
listOf(
dummyGitlabWebhookDto(id = 1),
dummyGitlabWebhookDto(id = 2),
dummyGitlabWebhookDto(id = 3, url = "https://gitlab.example.com/webhook"),
)
)

subject.registerWebhook()

verify(webhookProvider, times(0)).deleteWebhook(eq(1))
verify(webhookProvider, times(0)).deleteWebhook(eq(3))
verify(webhookProvider).deleteWebhook(eq(2))
}
}

fun dummyGitlabWebhookDto(id: Int, url: String = "https://gitlab.example.com$LEANIX_WEBHOOK_PATH") = GitlabWebhook(
id = id,
url = url,
createdAt = Date(),
pushEvents = true,
tagPushEvents = false,
mergeRequestsEvents = true,
repositoryUpdateEvents = true,
enableSSLVerification = false
)
8 changes: 7 additions & 1 deletion src/test/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,10 @@ leanix:
events-broker:
base-url: http://localhost:${wiremock.server.port:6666}
auth:
access-token-uri: ${leanix.base-url}/mtm/v1
access-token-uri: ${leanix.base-url}/mtm/v1
gitlab:
base-url: dummy
access-token: dummy
webhook-url: dummy
leanix-id: dummy
enable-ssl-verification: false

0 comments on commit 9d75e99

Please sign in to comment.