From f74b8faf62df7d701a0462f661889082cd95ce2f Mon Sep 17 00:00:00 2001
From: HyunSu1768 <azxcv1768@gmail.com>
Date: Mon, 8 Jul 2024 12:20:22 +0900
Subject: [PATCH] =?UTF-8?q?feat=20::=20=ED=81=B0=EC=9D=BC=EB=82=AC?=
 =?UTF-8?q?=EB=8B=A4~~?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../domain/auth/adapter/AuthWebAdapter.kt     |  2 +-
 .../adapter/V2ContainerWebAdapter.kt          | 20 +++++
 .../dto/request/SetContainerConfigRequest.kt  | 12 +++
 .../port/in/SetContainerConfigUseCase.kt      | 12 +++
 .../service/SetContainerConfigService.kt      | 80 +++++++++++++++++++
 .../domain/container/domain/Container.kt      | 18 ++++-
 .../feign/client/github/GithubClient.kt       | 19 +++++
 .../dto/request/DispatchEventRequest.kt       |  6 ++
 .../global/env/github/GithubProperties.kt     | 10 +++
 .../security/config/RequestPermitConfig.kt    | 10 +--
 src/main/resources/application.yaml           |  3 +
 11 files changed, 185 insertions(+), 7 deletions(-)
 create mode 100644 src/main/kotlin/xquare/app/xquareinfra/domain/container/adapter/V2ContainerWebAdapter.kt
 create mode 100644 src/main/kotlin/xquare/app/xquareinfra/domain/container/adapter/dto/request/SetContainerConfigRequest.kt
 create mode 100644 src/main/kotlin/xquare/app/xquareinfra/domain/container/application/port/in/SetContainerConfigUseCase.kt
 create mode 100644 src/main/kotlin/xquare/app/xquareinfra/domain/container/application/service/SetContainerConfigService.kt
 create mode 100644 src/main/kotlin/xquare/app/xquareinfra/infrastructure/feign/client/github/GithubClient.kt
 create mode 100644 src/main/kotlin/xquare/app/xquareinfra/infrastructure/feign/client/github/dto/request/DispatchEventRequest.kt
 create mode 100644 src/main/kotlin/xquare/app/xquareinfra/infrastructure/global/env/github/GithubProperties.kt

diff --git a/src/main/kotlin/xquare/app/xquareinfra/domain/auth/adapter/AuthWebAdapter.kt b/src/main/kotlin/xquare/app/xquareinfra/domain/auth/adapter/AuthWebAdapter.kt
index 2605ab9..3bfedce 100644
--- a/src/main/kotlin/xquare/app/xquareinfra/domain/auth/adapter/AuthWebAdapter.kt
+++ b/src/main/kotlin/xquare/app/xquareinfra/domain/auth/adapter/AuthWebAdapter.kt
@@ -9,7 +9,7 @@ import xquare.app.xquareinfra.domain.auth.adapter.dto.request.SignupRequest
 import xquare.app.xquareinfra.domain.auth.application.port.`in`.LoginUseCase
 import xquare.app.xquareinfra.domain.auth.application.port.`in`.SignupUseCase
 
-@RequestMapping("/auth")
+@RequestMapping("/v1/auth")
 @RestController
 class AuthWebAdapter(
     private val loginUseCase: LoginUseCase,
diff --git a/src/main/kotlin/xquare/app/xquareinfra/domain/container/adapter/V2ContainerWebAdapter.kt b/src/main/kotlin/xquare/app/xquareinfra/domain/container/adapter/V2ContainerWebAdapter.kt
new file mode 100644
index 0000000..9c5aca1
--- /dev/null
+++ b/src/main/kotlin/xquare/app/xquareinfra/domain/container/adapter/V2ContainerWebAdapter.kt
@@ -0,0 +1,20 @@
+package xquare.app.xquareinfra.domain.container.adapter
+
+import org.springframework.web.bind.annotation.*
+import xquare.app.xquareinfra.domain.container.adapter.dto.request.SetContainerConfigRequest
+import xquare.app.xquareinfra.domain.container.application.port.`in`.SetContainerConfigUseCase
+import java.util.*
+
+@RequestMapping("/v2/container")
+@RestController
+class V2ContainerWebAdapter(
+    private val setContainerConfigUseCase: SetContainerConfigUseCase
+) {
+    @PutMapping("/config")
+    fun setContainerConfig(
+        @RequestParam(name = "deployId", required = true)
+        deployId: UUID,
+        @RequestBody
+        setContainerConfigRequest: SetContainerConfigRequest
+    ) = setContainerConfigUseCase.setContainerConfig(deployId, setContainerConfigRequest)
+}
\ No newline at end of file
diff --git a/src/main/kotlin/xquare/app/xquareinfra/domain/container/adapter/dto/request/SetContainerConfigRequest.kt b/src/main/kotlin/xquare/app/xquareinfra/domain/container/adapter/dto/request/SetContainerConfigRequest.kt
new file mode 100644
index 0000000..050135e
--- /dev/null
+++ b/src/main/kotlin/xquare/app/xquareinfra/domain/container/adapter/dto/request/SetContainerConfigRequest.kt
@@ -0,0 +1,12 @@
+package xquare.app.xquareinfra.domain.container.adapter.dto.request
+
+data class SetContainerConfigRequest(
+    val stag: ContainerConfigDetails?,
+    val prod: ContainerConfigDetails?
+)
+
+data class ContainerConfigDetails(
+    val branch: String,
+    val containerPort: Int
+)
+
diff --git a/src/main/kotlin/xquare/app/xquareinfra/domain/container/application/port/in/SetContainerConfigUseCase.kt b/src/main/kotlin/xquare/app/xquareinfra/domain/container/application/port/in/SetContainerConfigUseCase.kt
new file mode 100644
index 0000000..489aa26
--- /dev/null
+++ b/src/main/kotlin/xquare/app/xquareinfra/domain/container/application/port/in/SetContainerConfigUseCase.kt
@@ -0,0 +1,12 @@
+package xquare.app.xquareinfra.domain.container.application.port.`in`
+
+import xquare.app.xquareinfra.domain.container.adapter.dto.request.SetContainerConfigRequest
+import xquare.app.xquareinfra.domain.container.domain.ContainerEnvironment
+import java.util.UUID
+
+interface SetContainerConfigUseCase {
+    fun setContainerConfig(
+        deployId: UUID,
+        setContainerConfigRequest: SetContainerConfigRequest
+    )
+}
\ No newline at end of file
diff --git a/src/main/kotlin/xquare/app/xquareinfra/domain/container/application/service/SetContainerConfigService.kt b/src/main/kotlin/xquare/app/xquareinfra/domain/container/application/service/SetContainerConfigService.kt
new file mode 100644
index 0000000..358ac88
--- /dev/null
+++ b/src/main/kotlin/xquare/app/xquareinfra/domain/container/application/service/SetContainerConfigService.kt
@@ -0,0 +1,80 @@
+package xquare.app.xquareinfra.domain.container.application.service
+
+import org.springframework.stereotype.Service
+import org.springframework.transaction.annotation.Transactional
+import xquare.app.xquareinfra.domain.container.adapter.dto.request.ContainerConfigDetails
+import xquare.app.xquareinfra.domain.container.adapter.dto.request.SetContainerConfigRequest
+import xquare.app.xquareinfra.domain.container.application.port.`in`.SetContainerConfigUseCase
+import xquare.app.xquareinfra.domain.container.application.port.out.FindContainerPort
+import xquare.app.xquareinfra.domain.container.application.port.out.SaveContainerPort
+import xquare.app.xquareinfra.domain.container.domain.Container
+import xquare.app.xquareinfra.domain.container.domain.ContainerEnvironment
+import xquare.app.xquareinfra.domain.deploy.application.port.out.FindDeployPort
+import xquare.app.xquareinfra.domain.deploy.domain.Deploy
+import xquare.app.xquareinfra.infrastructure.exception.BusinessLogicException
+import xquare.app.xquareinfra.infrastructure.feign.client.github.GithubClient
+import xquare.app.xquareinfra.infrastructure.feign.client.github.dto.request.DispatchEventRequest
+import xquare.app.xquareinfra.infrastructure.global.env.github.GithubProperties
+import java.time.LocalDateTime
+import java.util.*
+
+@Transactional
+@Service
+class SetContainerConfigService(
+    private val findDeployPort: FindDeployPort,
+    private val findContainerPort: FindContainerPort,
+    private val githubClient: GithubClient,
+    private val githubProperties: GithubProperties,
+    private val saveContainerPort: SaveContainerPort
+
+) : SetContainerConfigUseCase{
+    override fun setContainerConfig(deployId: UUID, setContainerConfigRequest: SetContainerConfigRequest) {
+        val deploy = findDeployPort.findById(deployId) ?: throw BusinessLogicException.DEPLOY_NOT_FOUND
+
+        setContainerConfigRequest.stag?.let {
+            processContainerConfig(deploy, it, ContainerEnvironment.stag)
+        }
+
+        setContainerConfigRequest.prod?.let {
+            processContainerConfig(deploy, it, ContainerEnvironment.prod)
+        }
+    }
+
+    private fun processContainerConfig(deploy: Deploy, config: ContainerConfigDetails, environment: ContainerEnvironment) {
+        var container = findContainerPort.findByDeployAndEnvironment(deploy, environment)
+        var containerId: UUID? = null
+        if (container != null) {
+            containerId = container.id
+        }
+
+        container = saveContainerPort.save(
+            Container(
+                id = containerId,
+                deploy = deploy,
+                containerEnvironment = environment,
+                lastDeploy = LocalDateTime.now(),
+                subDomain = null,
+                environmentVariable = container?.environmentVariable ?: mapOf(),
+                githubBranch = config.branch,
+                containerPort = config.containerPort
+            )
+        )
+
+        githubClient.dispatchWorkflow(
+            authorization = "Bearer ${githubProperties.token}",
+            accept = "application/vnd.github.v3+json",
+            request = DispatchEventRequest(
+                event_type = "write-values",
+                client_payload = mapOf(
+                    "club" to deploy.team.teamNameEn,
+                    "name" to deploy.deployName,
+                    "organization" to deploy.organization,
+                    "repository" to deploy.repository,
+                    "branch" to container.githubBranch!!,
+                    "environment" to container.containerEnvironment.name,
+                    "containerPort" to container.containerPort!!
+                )
+            )
+        )
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/xquare/app/xquareinfra/domain/container/domain/Container.kt b/src/main/kotlin/xquare/app/xquareinfra/domain/container/domain/Container.kt
index 1277297..7f3f14f 100644
--- a/src/main/kotlin/xquare/app/xquareinfra/domain/container/domain/Container.kt
+++ b/src/main/kotlin/xquare/app/xquareinfra/domain/container/domain/Container.kt
@@ -13,7 +13,9 @@ class Container(
     containerEnvironment: ContainerEnvironment,
     lastDeploy: LocalDateTime,
     subDomain: String?,
-    environmentVariable: Map<String, String>
+    environmentVariable: Map<String, String>,
+    githubBranch: String? = null,
+    containerPort: Int? = null
 ) : BaseUUIDEntity(id) {
     @OneToOne
     @JoinColumn(name = "deploy_id")
@@ -33,6 +35,12 @@ class Container(
     var subDomain: String? = subDomain
         protected set
 
+    @Column(name = "github_branch", nullable = true)
+    var githubBranch: String? = githubBranch
+
+    @Column(name = "container_port", nullable = true)
+    var containerPort: Int? = containerPort
+
     @ElementCollection
     @MapKeyColumn(name="variable_key", length=100)
     @Column(name = "environment_variable", columnDefinition = "TEXT")
@@ -42,4 +50,12 @@ class Container(
     fun updateEnvironmentVariable(environmentVariable: Map<String, String>) {
         this.environmentVariable = environmentVariable
     }
+
+    fun updateGithubBranch(githubBranch: String) {
+        this.githubBranch = githubBranch
+    }
+
+    fun updateContainerPort(containerPort: Int) {
+        this.containerPort = containerPort
+    }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/xquare/app/xquareinfra/infrastructure/feign/client/github/GithubClient.kt b/src/main/kotlin/xquare/app/xquareinfra/infrastructure/feign/client/github/GithubClient.kt
new file mode 100644
index 0000000..a102fdb
--- /dev/null
+++ b/src/main/kotlin/xquare/app/xquareinfra/infrastructure/feign/client/github/GithubClient.kt
@@ -0,0 +1,19 @@
+package xquare.app.xquareinfra.infrastructure.feign.client.github
+
+import org.springframework.cloud.openfeign.FeignClient
+import org.springframework.web.bind.annotation.PathVariable
+import org.springframework.web.bind.annotation.PostMapping
+import org.springframework.web.bind.annotation.RequestBody
+import org.springframework.web.bind.annotation.RequestHeader
+import xquare.app.xquareinfra.infrastructure.feign.client.github.dto.request.DispatchEventRequest
+
+
+@FeignClient(name = "github", url = "\${github.url}")
+interface GithubClient {
+    @PostMapping("/repos/team-xquare/xquare-gitops-repo/dispatches")
+    fun dispatchWorkflow(
+        @RequestHeader("Authorization") authorization: String?,
+        @RequestHeader("Accept") accept: String?,
+        @RequestBody request: DispatchEventRequest?
+    )
+}
\ No newline at end of file
diff --git a/src/main/kotlin/xquare/app/xquareinfra/infrastructure/feign/client/github/dto/request/DispatchEventRequest.kt b/src/main/kotlin/xquare/app/xquareinfra/infrastructure/feign/client/github/dto/request/DispatchEventRequest.kt
new file mode 100644
index 0000000..f1dbe62
--- /dev/null
+++ b/src/main/kotlin/xquare/app/xquareinfra/infrastructure/feign/client/github/dto/request/DispatchEventRequest.kt
@@ -0,0 +1,6 @@
+package xquare.app.xquareinfra.infrastructure.feign.client.github.dto.request
+
+data class DispatchEventRequest(
+    val event_type: String,
+    val client_payload: Map<String, Any>
+)
diff --git a/src/main/kotlin/xquare/app/xquareinfra/infrastructure/global/env/github/GithubProperties.kt b/src/main/kotlin/xquare/app/xquareinfra/infrastructure/global/env/github/GithubProperties.kt
new file mode 100644
index 0000000..4f5f739
--- /dev/null
+++ b/src/main/kotlin/xquare/app/xquareinfra/infrastructure/global/env/github/GithubProperties.kt
@@ -0,0 +1,10 @@
+package xquare.app.xquareinfra.infrastructure.global.env.github
+
+import org.springframework.boot.context.properties.ConfigurationProperties
+import org.springframework.boot.context.properties.ConstructorBinding
+
+@ConstructorBinding
+@ConfigurationProperties(value = "github")
+data class GithubProperties(
+    val token: String
+)
\ No newline at end of file
diff --git a/src/main/kotlin/xquare/app/xquareinfra/infrastructure/security/config/RequestPermitConfig.kt b/src/main/kotlin/xquare/app/xquareinfra/infrastructure/security/config/RequestPermitConfig.kt
index 28d1db8..50bf6ad 100644
--- a/src/main/kotlin/xquare/app/xquareinfra/infrastructure/security/config/RequestPermitConfig.kt
+++ b/src/main/kotlin/xquare/app/xquareinfra/infrastructure/security/config/RequestPermitConfig.kt
@@ -12,11 +12,11 @@ class RequestPermitConfig : SecurityConfigurerAdapter<DefaultSecurityFilterChain
     override fun configure(builder: HttpSecurity) {
         builder.authorizeRequests().run {
             requestMatchers(CorsUtils::isCorsRequest).permitAll()
-                .antMatchers("/team").permitAll()
-                .antMatchers("/auth/**").permitAll()
-                .antMatchers("/deploy/**/approve").permitAll()
-                .antMatchers(("/container/sync")).permitAll()
-                .antMatchers("/logs").permitAll()
+                .antMatchers("/v1/team").permitAll()
+                .antMatchers("/v1/auth/**").permitAll()
+                .antMatchers("/v1/deploy/**/approve").permitAll()
+                .antMatchers(("/v1/container/sync")).permitAll()
+                .antMatchers("/v1/logs").permitAll()
             anyRequest().authenticated()
         }
     }
diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml
index 9877a47..86fe14b 100644
--- a/src/main/resources/application.yaml
+++ b/src/main/resources/application.yaml
@@ -28,6 +28,9 @@ redis:
   host: ${REDIS_HOST:localhost}
   port: ${REDIS_PORT:6379}
 
+github:
+  token: ${GITHUB_TOKEN}
+  url: https://api.github.com
 logging:
   level:
     root: info