diff --git a/WIKI.md b/WIKI.md
new file mode 100644
index 0000000..b7c73b8
--- /dev/null
+++ b/WIKI.md
@@ -0,0 +1 @@
+# M-CMP mc-workflow-manager Wiki
**MC-Workflow-Manager** is one of the components of the [M-CMP](https://github.com/m-cmp/docs/tree/main) platform. With **MC-Workflow-Manager**, you can easily create and execute workflows, as well as modify and delete them as needed. For example, it allows you to create and manage multi-cloud infrastructures and seamlessly deploy applications across multiple clouds.
---
## 1. Overview
The **mc-workflow-manager** subsystem of **M-CMP** provides the following functions
- Oss management
- Workflow Stage management
- Workflow management
- Event Listener management
---
## 2. Flow
### 2-1. Workflow Manager Flow
M-CMP의 mc-workflow-manager 서브시스템의 Flow는 다음과 같다.
1. Oss 등록 (연동될 OSS 정보들응 등록)
- 연동되어 사용될 Workflow Engine(Jenkins) 등...
- Workflow Engine OSS인 Jenkins는 Workflow 관련 기능을 위해 필수로 등록한다.
2. Workflow Template 등록 (Workflow를 구성할 Stage 등록)
- 템플릿 개념의 Stage 등록 후 Workflow에서 사용 가능하다.
- 필수로 등록 하지 않아도 된다.
3. Workflow 생성
- 등록된 Stage등을 조합/직접 입력 하여 Workflow를 생성한다.
4. Workflow 실행
- UI 또는 API 를 활용하여 Workflow를 실행한다.
## 3. 기능 API
### 3-1. OSS Type
API
| Function | API | EndPoint | Parameter | DESC |
|:-----------------|:-------|:------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------|
| OSS Type List | GET | /ossType/list | - | OSS Type 목록을 조회한다. |
| OSS Type Regist | POST | /ossType | **RequestBody**
{
"ossTypeName": "JENKINS",
"ossTypeDesc": "jenkins"
} | OSS Type 을 등록한다. |
| OSS Type Update | PATCH | /oss/{ossTypeIdx} | **PathVariable**
ossTypeIdx
**RequestBody**
{
"ossTypeIdx": 1,
"ossTypeName": "JENKINS",
"ossTypeDesc": "JENKINS TEST"
} | OSS Type 을 수정한다. |
| OSS Type Delete | DELETE | /oss/{ossTypeIdx} | **PathVariable**
ossTypeIdx | OSS Type 을 삭제한다. |
| OSS Type Detail | GET | /oss/{ossTypeIdx} | **PathVariable**
ossTypeIdx | OSS Type 상세 정보를 조회한다. |
### 3-2. OSS
API
| Function | API | EndPoint | Parameter | DESC |
|:-----------------------|:-------|:----------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------|
| OSS List | GET | /oss/list | - | OSS 목록을 조회한다.
연동사용 OSS를 위한 정보를 조회 |
| OSS Regist | POST | /oss/{oddIdx} | **RequestBody**
{
"ossName": "OSS Name",
"ossDesc": "OSS Description",
"ossTypeIdx": 1,
"ossUrl": "http://workflow-engine:port_number",
"ossUsername": "ossId",
"ossPassword": "b3NzUHc=",
} | OSS를 등록한다.
등록시 PW는 Base64로 encoding 하여 요청 |
| OSS Update | PATCH | /oss/{oddIdx} | **RequestBody**
{
"ossIdx": 1,
"ossName": "OSS Name",
"ossDesc": "OSS Description",
"ossTypeIdx": 1,
"ossUrl": "http://workflow-engine:port_number",
"ossUsername": "ossId",
"ossPassword": "b3NzUHc=",
} | 툴체인을 수정한다.
수정시 PW는 Base64로 encoding 하여 요청 |
| OSS Delete | DELETE | /oss/{oddIdx} | **PathVariable**
ossIdx | 툴체인을 삭제한다. |
| OSS Detail | GET | /oss/{oddIdx} | **PathVariable**
ossIdx | 툴체인을 등록한다. |
| OSS Duplication Check | GET | /oss/duplicate | **RequestParam**
ossName=jenkins&
ossUrl=http://workflow-engine:port_number&
ossUsername=ossId | 등록될 툴체인 명 중복 검사를한다. |
| OSS Connection Check | POST | /oss/connection-check | **RequestBody**
{
"ossName": "OSS Name",
"ossDesc": "OSS Description",
"ossTypeIdx": 1,
"ossUrl": "http://workflow-engine:port_number",
"ossUsername": "ossId",
"ossPassword": "b3NzUHc=",
} | 등록될 툴체인의ID/PW/URL로 연결확인을한다.
확인시 PW는 Base64로 encoding 하여 요청 |
---
### 3-3. Workflow Stage Type
API
| Function | API | EndPoint | Parameter | DESC |
|:----------------------------|:-------|:--------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------|
| Workflow Stage Type List | GET | /workflowStageType/list | - | 스테이지 타입 목록을 조회한다. |
| Workflow Stage Type Regist | POST | /workflowStageType | **RequestBody**
{
"workflowStageTypeName": "workflow Stage Test",
"workflowStageTypeDesc": "테스트"
} | 스테이지 타입을 추가한다.
(여러 스테이지를 관리 할 상위 depth 개념) |
| Workflow Stage Type Update | PATCH | /workflowStageType/{workflowStageTypeIdx} | **RequestBody**
{
"workflowStageTypeIdx": 1,
"workflowStageTypeName": "workflow Stage Test",
"workflowStageTypeDesc": "테스트"
} | 스테이지 구분을 수정한다.
(여러 스테이지를 관리 할 상위 depth 개념) |
| Workflow Stage Type Delete | DELETE | /workflowStageType/{workflowStageTypeIdx} | **PathVariable**
workflowTypeIdx | 스테이지 구분을 삭제한다.
(여러 스테이지를 관리 할 상위 depth 개념) |
| Workflow Stage Type Detail | GET | /workflowStageType/{workflowStageTypeIdx} | **PathVariable**
workflowTypeIdx | 스테이지 구분 상세정보를 조회한다.
(여러 스테이지를 관리 할 상위 depth 개념) |
### 3-4. Workflow Stage
API
| Function | API | EndPoint | Parameter | DESC |
|:--------------------------------|:-------|:----------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------|
| Workflow Stage List | GET | /workflowStage/list | - | 스테이지 목록을 조회한다.
Workflow-engine 스테이지를 조합한 Workflow-engine job (workflow) 구성을 위한 스테이지 목록 |
| Workflow Stage Regist | POST | /workflowStage | **RequestBody**
{
"workflowStageTypeIdx": 1,
"workflowStageOrder": 1,
"workflowStageName": "test_stage",
"workflowStageDesc": "테스트",
"workflowStageContent":
stage('tumblebug') {\n TUMBLEBUG'\n \n steps {\n echo '>>>>>STAGE: // 스크립트를작성해주세요.\n }\n }\n \n"
} | 스테이지를 추가한다. |
| Workflow Stage Update | PATCH | /workflowStage/{workflowStageIdx} | **RequestBody**
{
"workflowStageIdx": 1,
"workflowStageTypeIdx": 1,
"workflowStageOrder": 1,
"workflowStageName": "test_stage",
"workflowStageDesc": "테스트",
"workflowStageContent":
stage('tumblebug') {\n TUMBLEBUG'\n \n steps {\n echo '>>>>>STAGE: // 스크립트를작성해주세요.\n }\n }\n \n"
} | 스테이지를 수정한다. |
| Workflow Stage Delete | DELETE | /workflowStage/{workflowStageIdx} | **PathVariable**
workflowStageIdx | 스테이지를 삭제한다. |
| Workflow Stage Detail | GET | /workflowStage/{workflowStageIdx} | **PathVariable**
workflowStageIdx | 스테이지 상세 정보를 조회 한다. |
| Workflow Stage Name Duplicate | GET | /workflowStage/duplicate | **QueryParam**
workflowStageTypeName={workflowStageTypeName}&
workflowStageName={workflowStageName} | 스테이지 Type에 종속된 스테이지명 중복검사를 한다. |
---
### 3-5. Workflow
API
| Function | API | EndPoint | Parameter | DESC |
|:------------------------|:-------|:----------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------|
| Workflow List | GET | /workflow/list | - | 워크플로우 목록을 조회한다. |
| Workflow Regist | POST | /workflow | **RequestBody**
{
"workflowInfo":{
"workflowName":"workflow-test",
"workflowPurpose":"test",
"ossIdx":1,
"script":"import groovy.json.JsonOutput\nimport groovy.json.JsonSlurper\nimport groovy.json.JsonSlurperClassic\n\n\nimport groovy.json.JsonSlurper\n\ndef getSSHKey(jsonInput) {\n def json = new JsonSlurper().parseText(jsonInput)\n return json.findResult { it.key == 'McisSubGroupAccessInfo' ? \n it.value.findResult { it.McisVmAccessInfo?.findResult { it.privateKey } } : null \n } ?: ''\n}\n\ndef getPublicInfoList(jsonInput) {\n def json = new JsonSlurper().parseText(jsonInput)\n return json.findAll { it.key == 'McisSubGroupAccessInfo' }\n .collectMany { it.value.McisVmAccessInfo*.publicIP }\n}\n\n\n\npipeline {\n agent any\n \n environment {\n env = ''\n }\n \n stages {\n\n\r\n stage('Start') {\r\n steps {\r\n echo 'Hello'\r\n }\r\n }\n\r\n stage('End') {\r\n steps {\r\n echo 'Job completed'\r\n }\r\n }\r\n }\r\n\n }\n}\n\n"},
"workflowParams":[
{
"paramKey":"paramkey",
"paramValue":"paramValue",
"eventListenerYn":"N"}
],
"workflowStageMappings":[
{
"mappingIdx":null,
"workflowIdx":null,
"stageOrder":null,
"workflowStageIdx":null,
"stageContent":"import groovy.json.JsonOutput\nimport groovy.json.JsonSlurper\nimport groovy.json.JsonSlurperClassic\n\n\nimport groovy.json.JsonSlurper\n\ndef getSSHKey(jsonInput) {\n def json = new JsonSlurper().parseText(jsonInput)\n return json.findResult { it.key == 'McisSubGroupAccessInfo' ? \n it.value.findResult { it.McisVmAccessInfo?.findResult { it.privateKey } } : null \n } ?: ''\n}\n\ndef getPublicInfoList(jsonInput) {\n def json = new JsonSlurper().parseText(jsonInput)\n return json.findAll { it.key == 'McisSubGroupAccessInfo' }\n .collectMany { it.value.McisVmAccessInfo*.publicIP }\n}\n\n\n\npipeline {\n agent any\n \n environment {\n env = ''\n }\n \n stages {\n\n",
"isDefaultScript":true,
"defaultScriptTag":"DEFAULT_START"
},
{
"stageOrder":1,
"workflowStageTypeIdx":4,
"stageContent":"\r\n stage('Start') {\r\n steps {\r\n echo 'Hello'\r\n }\r\n
}",
"defaultScriptTag":"null",
"isDefaultScript":false
},
{
"stageOrder":1,
"workflowStageTypeIdx":6,
"stageContent":"\r\n stage('End') {\r\n steps {\r\n echo 'Job completed'\r\n }\r\n }\r\n }\r\n",
"defaultScriptTag":"null",
"isDefaultScript":false
},
{
"mappingIdx":null,
"workflowIdx":null,
"stageOrder":null,
"workflowStageIdx":null,
"stageContent":"
}\n}\n\n",
"isDefaultScript":true,
"defaultScriptTag":"DEFAULT_END"
}
]
} | 워크플로우 생성과 함께 Workflow Engine에 등록된다.(v0.3.0 : Jenkins Job이 생성된다) |
| Workflow Update | PATCH | /workflow/{workflowIdx} | **RequestBody**
{
"workflowInfo":{
"workflowIdx":"1",
"workflowName":"workflow-test",
"workflowPurpose":"test",
"ossIdx":1,
"script":"import groovy.json.JsonOutput\nimport groovy.json.JsonSlurper\nimport groovy.json.JsonSlurperClassic\n\n\nimport groovy.json.JsonSlurper\n\ndef getSSHKey(jsonInput) {\n def json = new JsonSlurper().parseText(jsonInput)\n return json.findResult { it.key == 'McisSubGroupAccessInfo' ? \n it.value.findResult { it.McisVmAccessInfo?.findResult { it.privateKey } } : null \n } ?: ''\n}\n\ndef getPublicInfoList(jsonInput) {\n def json = new JsonSlurper().parseText(jsonInput)\n return json.findAll { it.key == 'McisSubGroupAccessInfo' }\n .collectMany { it.value.McisVmAccessInfo*.publicIP }\n}\n\n\n\npipeline {\n agent any\n \n environment {\n env = ''\n }\n \n stages {\n\n\n\r\n stage('Start') {\r\n steps {\r\n echo 'Hello'\r\n }\r\n }\n\r\n stage('End') {\r\n steps {\r\n echo 'Job completed'\r\n }\r\n }\r\n }\r\n\n }\n}\n\n\n" },
"workflowParams":
[
{
"workflowIdx":12,
"paramKey":"testparamkey",
"paramValue":"testparamValue",
"eventListenerYn":"N"
}
],
"workflowStageMappings":
[
{
"mappingIdx":51,
"workflowIdx":12,
"stageOrder":null,
"workflowStageIdx":null,
"stageContent":"import groovy.json.JsonOutput\nimport groovy.json.JsonSlurper\nimport groovy.json.JsonSlurperClassic\n\n\nimport groovy.json.JsonSlurper\n\ndef getSSHKey(jsonInput) {\n def json = new JsonSlurper().parseText(jsonInput)\n return json.findResult { it.key == 'McisSubGroupAccessInfo' ? \n it.value.findResult { it.McisVmAccessInfo?.findResult { it.privateKey } } : null \n } ?: ''\n}\n\ndef getPublicInfoList(jsonInput) {\n def json = new JsonSlurper().parseText(jsonInput)\n return json.findAll { it.key == 'McisSubGroupAccessInfo' }\n .collectMany { it.value.McisVmAccessInfo*.publicIP }\n}\n\n\n\npipeline {\n agent any\n \n environment {\n env = ''\n }\n \n stages {\n\n"},{"mappingIdx":52,"workflowIdx":12,"stageOrder":1,"workflowStageIdx":null,"stageContent":"\r\n stage('Start') {\r\n steps {\r\n echo 'Hello'\r\n }\r\n }"
},
{
"mappingIdx":53,
"workflowIdx":12,
"stageOrder":1,
"workflowStageIdx":null,
"stageContent":"\r\n stage('End') {\r\n steps {\r\n echo 'Job completed'\r\n }\r\n }\r\n }\r\n"
},
{
"mappingIdx":54,
"workflowIdx":12,
"stageOrder":null,
"workflowStageIdx":null,
"stageContent":" }\n}\n\n"
}
]
} | 등록된 워크플로우를 수정 한다. |
| Workflow Delete | DELETE | /workflow/{workflowIdx} | **PathVariable**
workflowIdx | 등록된 워크플로우를 삭제 한다. |
| Workflow Detail | GET | /workflow/{workflowIdx} | **PathVariable**
workflowIdx | 등록된 워크플로우 상세 정보를 조회 한다. |
| Workflow Name Duplicate | GET | /workflow/name/duplicate | **QueryParam**
workflowName=workflow-test | 등록될 워크플로우 명을 중복검사 한다. |
| Workflow Stage List | GET | /workflow/workflowStageList | - | 워크플로우 스테이지 목록을 조회한다. |
| Workflow Template | GET | /workflow/template/{workflowName} | **PathVariable**
workflowName | 워크플로우 기본 템플릿을 생성한다. |
| Workflow Run | GET | /workflow/run/{workflowIdx} | **PathVariable**
workflowIdx | 등록된 워크플로우를 실행 한다. |
| Workflow Run | POST | /workflow/run | **RequestBody**
{
"workflowInfo":
{
"workflowIdx":12,
"workflowName":"workflow-test",
"workflowPurpose":"run",
"ossIdx":1,
"script":"import groovy.json.JsonOutput\nimport groovy.json.JsonSlurper\nimport groovy.json.JsonSlurperClassic\n\n\nimport groovy.json.JsonSlurper\n\ndef getSSHKey(jsonInput) {\n def json = new JsonSlurper().parseText(jsonInput)\n return json.findResult { it.key == 'McisSubGroupAccessInfo' ? \n it.value.findResult { it.McisVmAccessInfo?.findResult { it.privateKey } } : null \n } ?: ''\n}\n\ndef getPublicInfoList(jsonInput) {\n def json = new JsonSlurper().parseText(jsonInput)\n return json.findAll { it.key == 'McisSubGroupAccessInfo' }\n .collectMany { it.value.McisVmAccessInfo*.publicIP }\n}\n\n\n\npipeline {\n agent any\n \n environment {\n env = ''\n }\n \n stages {\n\n\n\r\n stage('Start') {\r\n steps {\r\n echo 'Hello'\r\n }\r\n }\n\r\n stage('End') {\r\n steps {\r\n echo 'Job completed'\r\n }\r\n }\r\n }\r\n\n }\n}\n\n\n"},
"workflowParams":
[
{
"paramIdx":70,
"workflowIdx":12,
"paramKey":"testparamkey",
"paramValue":"testparamValue",
"eventListenerYn":"N"
}
],
"workflowStageMappings":
[
{
"mappingIdx":55,
"workflowIdx":12,
"stageOrder":null,
"workflowStageIdx":null,
"stageContent":"import groovy.json.JsonOutput\nimport groovy.json.JsonSlurper\nimport groovy.json.JsonSlurperClassic\n\n\nimport groovy.json.JsonSlurper\n\ndef getSSHKey(jsonInput) {\n def json = new JsonSlurper().parseText(jsonInput)\n return json.findResult { it.key == 'McisSubGroupAccessInfo' ? \n it.value.findResult { it.McisVmAccessInfo?.findResult { it.privateKey } } : null \n } ?: ''\n}\n\ndef getPublicInfoList(jsonInput) {\n def json = new JsonSlurper().parseText(jsonInput)\n return json.findAll { it.key == 'McisSubGroupAccessInfo' }\n .collectMany { it.value.McisVmAccessInfo*.publicIP }\n}\n\n\n\npipeline {\n agent any\n \n environment {\n env = ''\n }\n \n stages {\n\n"},{"mappingIdx":56,"workflowIdx":12,"stageOrder":1,"workflowStageIdx":null,"stageContent":"\r\n stage('Start') {\r\n steps {\r\n echo 'Hello'\r\n }\r\n }"
}
,
{
"mappingIdx":57,
"workflowIdx":12,
"stageOrder":1,
"workflowStageIdx":null,
"stageContent":"\r\n stage('End') {\r\n steps {\r\n echo 'Job completed'\r\n }\r\n }\r\n }\r\n"
},
{
"mappingIdx":58,
"workflowIdx":12,
"stageOrder":null,
"workflowStageIdx":null,
"stageContent":" }\n}\n\n"
}
]
} | 등록된 워크플로우를 실행 한다. |
| Workflow Log | GET | /workflow/log/{workflowIdx} | **PathVariable**
workflowIdx | 실행된 워크플로우 로그를 조회 한다. |
워크플로우 실행 추가 설명 *
등록된 workflow에 따라 실행 시 **추가로 필요한 데이터**가 존재할 수 있음(param)
GET방식 실행 시 설정된 value 기본값으로 실행
Ex) tomcat 9.0 설치 workflow
- MCIS, NAMESPACE 등 필요
- 개발서버기준 vm 삭제
API : (POST) /workflow/run
Param : (Request Body)
```JSON
{
"workflowId":47,
"pipelineParam": [
{
"paramKey":"MCIS",
"paramValue":"{mcisname}"
},
{
"paramKey":"NAMESPACE",
"paramValue":"{namespace}"
}
]
}
```
Ex2) 현재시간 반환 workflow, health check 등
- 단순실행(GET) 가능
\ No newline at end of file
diff --git a/bin/main/jenkins/kubernetes_helm_install_pipeline.xml b/bin/main/jenkins/kubernetes_helm_install_pipeline.xml
index a785a7d..6f5d64a 100644
--- a/bin/main/jenkins/kubernetes_helm_install_pipeline.xml
+++ b/bin/main/jenkins/kubernetes_helm_install_pipeline.xml
@@ -1,6 +1,5 @@
-
-
+
false
@@ -8,45 +7,38 @@
- CB_TUMBLEBUG_SWAGGER_URI
- CB-Tumblebug Swagger API URI
- http://localhost:1323/tumblebug
+ CB_TUMBLEBUG_URI
+ Tumblebug API URL
+ http://13.125.199.35:1323/tumblebug
true
NAMESPACE
- Namespace
+ Namespace ID
ns01
true
- MCIS_NAME
- MCIS Name
- mcis-01
- true
-
-
- CLOUD_CONNECTION_NAME
- Cloud Connection Name
- aws-conn-01
+ CLUSTERNAME
+ K8s Cluster Name
+ cluster01
true
- HELM_RELEASE_NAME
- Helm Release Name
- my-release
+ TUMBLEBUG_USER
+ Tumblebug User ID
+ default
true
+
+ TUMBLEBUG_PASSWORD
+ Tumblebug User Password
+ default
+
- HELM_CHART_NAME
- Helm Chart Name
- bitnami/nginx
- true
-
-
- HELM_CHART_VERSION
- Helm Chart Version
- latest
+ HELM_CHARTS
+ Helm Charts to Install (comma-separated)
+ nginx,grafana
true
@@ -55,107 +47,126 @@
true
diff --git a/src/main/java/kr/co/mcmp/ape/cbtumblebug/api/CbtumblebugRestApi.java b/src/main/java/kr/co/mcmp/ape/cbtumblebug/api/CbtumblebugRestApi.java
index 41793ea..ee01768 100644
--- a/src/main/java/kr/co/mcmp/ape/cbtumblebug/api/CbtumblebugRestApi.java
+++ b/src/main/java/kr/co/mcmp/ape/cbtumblebug/api/CbtumblebugRestApi.java
@@ -13,6 +13,8 @@
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
+import kr.co.mcmp.ape.cbtumblebug.dto.K8sClusterDto;
+import kr.co.mcmp.ape.cbtumblebug.dto.K8sClusterResponse;
import kr.co.mcmp.ape.cbtumblebug.dto.MciDto;
import kr.co.mcmp.ape.cbtumblebug.dto.MciResponse;
import kr.co.mcmp.ape.cbtumblebug.dto.NamespaceDto;
@@ -54,15 +56,16 @@ private String createApiUrl(String endpoint) {
return String.format("http://%s:%s%s", cbtumblebugUrl, cbtumblebugPort, endpoint);
}
- public boolean checkTumblebug(){
- log.info("check Tumblebug is ready");
- String apiUrl = createApiUrl("/readyz");
+ public boolean checkTumblebug() {
+ log.info("Checking if Tumblebug is ready");
+ String apiUrl = createApiUrl("/tumblebug/readyz");
HttpHeaders headers = createCommonHeaders();
try {
ResponseEntity response = restClient.request(apiUrl, headers, null, HttpMethod.GET, new ParameterizedTypeReference() {});
+ log.info("Tumblebug readyz response: {}", response.getBody());
return response.getStatusCode().is2xxSuccessful();
} catch (Exception e) {
- log.error("Tumblebug connection fail", e);
+ log.error("Tumblebug connection failed", e);
return false;
}
}
@@ -95,24 +98,48 @@ public List getMcisByNamespace(String namespace) {
});
}
- public String getK8sClusterInfo(){
- log.info("Fetching all K8sClusterInfo");
- return executeWithConnectionCheck("getK8sClusterInfo", () ->{
- String apiUrl = createApiUrl("/k8sClusterInfo");
+ // public String getK8sClusterInfo(){
+ // log.info("Fetching all K8sClusterInfo");
+ // return executeWithConnectionCheck("getK8sClusterInfo", () ->{
+ // String apiUrl = createApiUrl("/k8sClusterInfo");
+ // HttpHeaders headers = createCommonHeaders();
+ // ResponseEntity response = restClient.request(apiUrl, headers, headers, HttpMethod.GET, new ParameterizedTypeReference() {});
+ // return response.getBody() != null ? response.getBody() : null;
+ // });
+ // }
+
+ public List getAllK8sClusters(String namespace){
+ log.info("Fetching K8s Clusters by namespace: {}", namespace);
+ return executeWithConnectionCheck("getK8sClustersByNamespace", () -> {
+ String apiUrl = createApiUrl(String.format("/tumblebug/ns/%s/k8scluster", namespace));
HttpHeaders headers = createCommonHeaders();
- ResponseEntity response = restClient.request(apiUrl, headers, headers, HttpMethod.GET, new ParameterizedTypeReference() {});
- return response.getBody() != null ? response.getBody() : null;
+ ResponseEntity response = restClient.request(
+ apiUrl,
+ headers,
+ null,
+ HttpMethod.GET,
+ new ParameterizedTypeReference() {}
+ );
+ return response.getBody() != null ? response.getBody().getK8sClusterInfo() : Collections.emptyList();
});
}
- public String getK8sClusterByNamespace(String namespace){
- log.info("Fetching k8sCluster Info by namespace :{}", namespace);
- return executeWithConnectionCheck("getK8sClusterByNamespace", () ->{
- String apiUrl = createApiUrl(String.format("/ns/%s/k8scluster", namespace));
+ public K8sClusterDto getK8sClusterByName(String namespace, String clusterName){
+ log.info("Fetching K8s Cluster by name: {} in namespace: {}", clusterName, namespace);
+ return executeWithConnectionCheck("getK8sClusterByName", () -> {
+ String apiUrl = createApiUrl(String.format("/tumblebug/ns/%s/k8scluster/%s", namespace, clusterName));
HttpHeaders headers = createCommonHeaders();
- ResponseEntity response = restClient.request(apiUrl, headers, null, HttpMethod.GET, new ParameterizedTypeReference() {});
- return response.getBody() != null ? response.getBody() : null;
+ ResponseEntity response = restClient.request(
+ apiUrl,
+ headers,
+ null,
+ HttpMethod.GET,
+ new ParameterizedTypeReference() {}
+ );
+ return response.getBody();
});
}
+
+
}
diff --git a/src/main/java/kr/co/mcmp/ape/cbtumblebug/controller/CbtumblebugController.java b/src/main/java/kr/co/mcmp/ape/cbtumblebug/controller/CbtumblebugController.java
index 600022d..d659d20 100644
--- a/src/main/java/kr/co/mcmp/ape/cbtumblebug/controller/CbtumblebugController.java
+++ b/src/main/java/kr/co/mcmp/ape/cbtumblebug/controller/CbtumblebugController.java
@@ -10,6 +10,7 @@
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
+import kr.co.mcmp.ape.cbtumblebug.dto.K8sClusterDto;
import kr.co.mcmp.ape.cbtumblebug.dto.MciDto;
import kr.co.mcmp.ape.cbtumblebug.dto.NamespaceDto;
import kr.co.mcmp.ape.cbtumblebug.service.CbtumblebugService;
@@ -31,23 +32,27 @@ public List getAllNamespaces() {
return cbtumblebugService.getAllNamespaces();
}
- @GetMapping("/ns/{nsId}/mcis")
+ @GetMapping("/ns/{nsId}/mci")
@Operation(summary = "특정 네임스페이스의 MCIS 조회", description = "지정된 네임스페이스에 속한 모든 MCIS를 조회합니다.")
- public List getMCISByNamespace(@Parameter(description = "네임스페이스 ID", required = true)
+ public List getMicsByNamespace(@Parameter(description = "네임스페이스 ID", required = true)
@PathVariable String nsId) {
return cbtumblebugService.getMcisByNamespace(nsId);
}
- @GetMapping("/k8sCluster/info")
- @Operation(summary = "k8sCluster 정보 조회", description = "등록된 모든 K8s Cluster의 정보를 조회합니다.")
- public String getAllK8sClusterInfo() {
- return cbtumblebugService.getK8sClusterInfo();
- }
+ // @GetMapping("/k8sCluster/info")
+ // @Operation(summary = "k8sCluster 정보 조회", description = "등록된 모든 K8s Cluster의 정보를 조회합니다.")
+ // public String getAllK8sClusterInfo() {
+ // return cbtumblebugService.getK8sClusterInfo();
+ // }
@GetMapping("/ns/{nsId}/k8scluster")
- public String getK8sCluster(@PathVariable String nsId) {
- return cbtumblebugService.getK8sClusterByNamespace(nsId);
+ public List getK8sCluster(@PathVariable String nsId) {
+ return cbtumblebugService.getAllK8sClusters(nsId);
+ }
+
+ @GetMapping("/ns/{nsId}/k8scluster/{clusterName}")
+ public K8sClusterDto getK8sClusterByName(@PathVariable String nsId, @PathVariable String clusterName) {
+ return cbtumblebugService.getK8sClusterByName(nsId, clusterName);
}
-
}
diff --git a/src/main/java/kr/co/mcmp/ape/cbtumblebug/dto/K8sClusterDto.java b/src/main/java/kr/co/mcmp/ape/cbtumblebug/dto/K8sClusterDto.java
new file mode 100644
index 0000000..0144406
--- /dev/null
+++ b/src/main/java/kr/co/mcmp/ape/cbtumblebug/dto/K8sClusterDto.java
@@ -0,0 +1,25 @@
+package kr.co.mcmp.ape.cbtumblebug.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class K8sClusterDto {
+ private String id;
+ private String name;
+ private String connectionName;
+ private String status;
+ private String version;
+ private AccessInfo accessInfo;
+
+ @Data
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class AccessInfo {
+ private String endpoint;
+ private String kubeconfig;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/kr/co/mcmp/ape/cbtumblebug/dto/K8sClusterResponse.java b/src/main/java/kr/co/mcmp/ape/cbtumblebug/dto/K8sClusterResponse.java
new file mode 100644
index 0000000..4be853d
--- /dev/null
+++ b/src/main/java/kr/co/mcmp/ape/cbtumblebug/dto/K8sClusterResponse.java
@@ -0,0 +1,14 @@
+package kr.co.mcmp.ape.cbtumblebug.dto;
+
+import java.util.List;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class K8sClusterResponse {
+ private List k8sClusterInfo;
+}
\ No newline at end of file
diff --git a/src/main/java/kr/co/mcmp/ape/cbtumblebug/service/CbtumblebugService.java b/src/main/java/kr/co/mcmp/ape/cbtumblebug/service/CbtumblebugService.java
index 8d078f0..b75f9c4 100644
--- a/src/main/java/kr/co/mcmp/ape/cbtumblebug/service/CbtumblebugService.java
+++ b/src/main/java/kr/co/mcmp/ape/cbtumblebug/service/CbtumblebugService.java
@@ -2,6 +2,7 @@
import java.util.List;
+import kr.co.mcmp.ape.cbtumblebug.dto.K8sClusterDto;
import kr.co.mcmp.ape.cbtumblebug.dto.MciDto;
import kr.co.mcmp.ape.cbtumblebug.dto.NamespaceDto;
@@ -12,7 +13,9 @@ public interface CbtumblebugService {
List getMcisByNamespace(String namespace);
- String getK8sClusterInfo();
+ // String getK8sClusterInfo();
- String getK8sClusterByNamespace(String namespace);
+ List getAllK8sClusters(String namespace);
+
+ K8sClusterDto getK8sClusterByName(String namespace, String clusterName);
}
diff --git a/src/main/java/kr/co/mcmp/ape/cbtumblebug/service/CbtumblebugServiceImpl.java b/src/main/java/kr/co/mcmp/ape/cbtumblebug/service/CbtumblebugServiceImpl.java
index 07b298b..164568c 100644
--- a/src/main/java/kr/co/mcmp/ape/cbtumblebug/service/CbtumblebugServiceImpl.java
+++ b/src/main/java/kr/co/mcmp/ape/cbtumblebug/service/CbtumblebugServiceImpl.java
@@ -5,6 +5,7 @@
import org.springframework.stereotype.Service;
import kr.co.mcmp.ape.cbtumblebug.api.CbtumblebugRestApi;
+import kr.co.mcmp.ape.cbtumblebug.dto.K8sClusterDto;
import kr.co.mcmp.ape.cbtumblebug.dto.MciDto;
import kr.co.mcmp.ape.cbtumblebug.dto.NamespaceDto;
import lombok.RequiredArgsConstructor;
@@ -25,14 +26,19 @@ public List getMcisByNamespace(String namespace) {
return api.getMcisByNamespace(namespace);
}
+ // @Override
+ // public String getK8sClusterInfo() {
+ // return api.getK8sClusterInfo();
+ // }
+
@Override
- public String getK8sClusterInfo() {
- return api.getK8sClusterInfo();
+ public List getAllK8sClusters(String namespace) {
+ return api.getAllK8sClusters(namespace);
}
@Override
- public String getK8sClusterByNamespace(String namespace) {
- return api.getK8sClusterByNamespace(namespace);
+ public K8sClusterDto getK8sClusterByName(String namespace, String clusterName) {
+ return api.getK8sClusterByName(namespace, clusterName);
}
}
diff --git a/src/main/java/kr/co/mcmp/ape/controller/AppProvEngineController.java b/src/main/java/kr/co/mcmp/ape/controller/AppProvEngineController.java
index c2ac0a7..d8f8678 100644
--- a/src/main/java/kr/co/mcmp/ape/controller/AppProvEngineController.java
+++ b/src/main/java/kr/co/mcmp/ape/controller/AppProvEngineController.java
@@ -2,6 +2,7 @@
import java.util.List;
+import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@@ -46,11 +47,11 @@ public ResponseWrapper triggerVmInstall(@RequestBody JenkinsJobDto.VmApp
return triggerJenkinsJob(jobDto);
}
- // @PostMapping("/vm/uninstall")
- // @Operation(summary = "Uninstall VM Application", description = "VM에서 애플리케이션을 제거하기 위해 Jenkins 작업을 트리거합니다.")
- // public ResponseWrapper triggerVmUninstall(@RequestBody JenkinsJobDto.VmApplicationUninstall jobDto) {
- // return triggerJenkinsJob(jobDto);
- // }
+ @PostMapping("/vm/uninstall")
+ @Operation(summary = "Uninstall VM Application", description = "VM에서 애플리케이션을 제거하기 위해 Jenkins 작업을 트리거합니다.")
+ public ResponseWrapper triggerVmUninstall(@RequestBody JenkinsJobDto.VmApplicationUninstall jobDto) {
+ return triggerJenkinsJob(jobDto);
+ }
// @PostMapping("/helm/install")
// @Operation(summary = "Install Kubernetes Helm Chart", description = "Kubernetes에 Helm 차트를 설치하기 위해 Jenkins 작업을 트리거합니다.")
@@ -83,25 +84,6 @@ private ResponseWrapper triggerJenkinsJob(JenkinsJobDto jobDto) {
// }
// }
- @GetMapping("/ns")
- @Operation(summary = "모든 네임스페이스 조회", description = "시스템에 등록된 모든 네임스페이스를 조회합니다.")
- public List getAllNamespaces() {
- // return appProvEngineService.getAllNamespaces();
- return null;
- }
-
- @GetMapping("/ns/{nsId}/mcis")
- @Operation(summary = "특정 네임스페이스의 MCIS 조회", description = "지정된 네임스페이스에 속한 모든 MCIS를 조회합니다.")
- public List getMCISByNamespace(@Parameter(description = "네임스페이스 ID", required = true)
- @PathVariable String nsId) {
- // return appProvEngineService.getMcisByNamespace(nsId);
- return null;
- }
- @GetMapping("/readyz")
- @Operation(summary="", description="")
- public boolean checkReadyz(){
- return true;
- }
}
diff --git a/src/main/java/kr/co/mcmp/ape/dto/reqDto/JenkinsJobDto.java b/src/main/java/kr/co/mcmp/ape/dto/reqDto/JenkinsJobDto.java
index 3ed26fd..169e997 100644
--- a/src/main/java/kr/co/mcmp/ape/dto/reqDto/JenkinsJobDto.java
+++ b/src/main/java/kr/co/mcmp/ape/dto/reqDto/JenkinsJobDto.java
@@ -7,6 +7,7 @@
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@@ -39,7 +40,7 @@ public Map> convertToJenkinsParams() {
@Setter
@Schema(description = "VM 애플리케이션 설치 작업")
public static class VmApplicationInstall extends JenkinsJobDto {
- @Schema(description = "설치할 애플리케이션 목록", example = "[\"nginx\", \"mysql\"]")
+ @Schema(description = "설치할 애플리케이션 목록", example = "[\"nginx\", \"tomcat9\", \"mariadb-server\", \"mariadb-server\", \"redis-server\", \"grafana\", \"prometheus\"]")
private List applications;
@Override
@@ -56,4 +57,52 @@ public Map> convertToSpecificParams() {
return params;
}
}
+ @Getter
+ @Setter
+ @Schema(description = "VM 애플리케이션 삭제 작업")
+ public static class VmApplicationUninstall extends JenkinsJobDto {
+ @Schema(description = "설치할 애플리케이션 목록", example = "[\"nginx\", \"tomcat9\", \"mariadb-server\", \"mariadb-server\", \"redis-server\", \"grafana\", \"prometheus\"]")
+ private List applications;
+
+ @Override
+ @JsonIgnore
+ @Schema(hidden = true)
+ public String getJobName() {
+ return "vm_application_uninstall";
+ }
+
+ @Override
+ public Map> convertToSpecificParams() {
+ Map> params = new HashMap<>();
+ params.put("APPLICATIONS", List.of(String.join(",", this.applications)));
+ return params;
+ }
+ }
+
+ @Getter
+ @Setter
+ @Schema(description = "Helm 차트 설치 작업")
+ public static class HelmChartInstall extends JenkinsJobDto {
+ @Schema(description = "K8s 클러스터 이름", example = "cluster01", required = true)
+ private String clusterName;
+
+ @Schema(description = "설치할 Helm 차트 목록", example = "[\"nginx\", \"grafana\"]")
+ private List helmCharts;
+
+ @Override
+ @JsonIgnore
+ @Schema(hidden = true)
+ public String getJobName() {
+ return "helm_application_install";
+ }
+
+ @Override
+ public Map> convertToSpecificParams() {
+ Map> params = new HashMap<>();
+ params.put("CLUSTERNAME", List.of(this.clusterName));
+ params.put("HELM_CHARTS", List.of(String.join(",", this.helmCharts)));
+ return params;
+ }
+ }
+
}
\ No newline at end of file
diff --git a/src/main/java/kr/co/mcmp/ape/service/AppProvEngineService.java b/src/main/java/kr/co/mcmp/ape/service/AppProvEngineService.java
index e483092..f8ce1c4 100644
--- a/src/main/java/kr/co/mcmp/ape/service/AppProvEngineService.java
+++ b/src/main/java/kr/co/mcmp/ape/service/AppProvEngineService.java
@@ -2,10 +2,13 @@
import java.util.List;
+import kr.co.mcmp.ape.cbtumblebug.dto.MciDto;
+import kr.co.mcmp.ape.cbtumblebug.dto.NamespaceDto;
import kr.co.mcmp.ape.dto.reqDto.JenkinsJobDto;
import kr.co.mcmp.ape.dto.resDto.ApeLogResDto;
import kr.co.mcmp.oss.dto.OssDto;
import kr.co.mcmp.oss.dto.OssTypeDto;
+import kr.co.mcmp.oss.entity.Oss;
public interface AppProvEngineService {
@@ -15,4 +18,6 @@ public interface AppProvEngineService {
String triggerJenkinsJob(JenkinsJobDto dto);
+ OssDto getJenkinsOss();
+
}
diff --git a/src/main/java/kr/co/mcmp/ape/service/AppProvEngineServiceImpl.java b/src/main/java/kr/co/mcmp/ape/service/AppProvEngineServiceImpl.java
index 3f3f277..4fbc2e9 100644
--- a/src/main/java/kr/co/mcmp/ape/service/AppProvEngineServiceImpl.java
+++ b/src/main/java/kr/co/mcmp/ape/service/AppProvEngineServiceImpl.java
@@ -64,7 +64,7 @@ public List getApeLog(String jobName) {
return fetchLogs(jenkinsOss, jobName);
}
- private OssDto getJenkinsOss() {
+ public OssDto getJenkinsOss() {
return ossService.getOssListNotDecryptPassword("JENKINS").stream()
.findFirst()
.orElseThrow(() -> new IllegalStateException("Jenkins OSS 정보를 찾을 수 없습니다."));
@@ -126,4 +126,5 @@ private String makeTumblebugUri(String url, String port){
StringBuilder builder = new StringBuilder();
return builder.append("http://").append(url).append(":").append(port).append("/tumblebug").toString();
}
+
}
diff --git a/src/main/java/kr/co/mcmp/ape/service/jenkins/service/JenkinsService.java b/src/main/java/kr/co/mcmp/ape/service/jenkins/service/JenkinsService.java
index 2aace30..a5814cb 100644
--- a/src/main/java/kr/co/mcmp/ape/service/jenkins/service/JenkinsService.java
+++ b/src/main/java/kr/co/mcmp/ape/service/jenkins/service/JenkinsService.java
@@ -56,9 +56,9 @@ public class JenkinsService {
private static final String PIPELINE_XML_PATH = "/flow-definition/definition/script";
private static final List PIPELINE_XML_FILE_PATHS = Arrays.asList(
- "jenkins/vm_application_install_pipeline.xml"
- // "jenkins/vm_application_uninstall_pipeline.xml",
- // "jenkins/kubernetes_helm_install_pipeline.xml",
+ "jenkins/vm_application_install_pipeline.xml",
+ "jenkins/vm_application_uninstall_pipeline.xml",
+ "jenkins/kubernetes_helm_install_pipeline.xml"
// "jenkins/kubernetes_helm_uninstall_pipeline.xml"
);
diff --git a/src/main/java/kr/co/mcmp/applicationmanager/controller/ApplicationManagerController.java b/src/main/java/kr/co/mcmp/applicationmanager/controller/ApplicationManagerController.java
new file mode 100644
index 0000000..234d3f6
--- /dev/null
+++ b/src/main/java/kr/co/mcmp/applicationmanager/controller/ApplicationManagerController.java
@@ -0,0 +1,36 @@
+package kr.co.mcmp.applicationmanager.controller;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import io.swagger.v3.oas.annotations.Operation;
+import kr.co.mcmp.ape.cbtumblebug.api.CbtumblebugRestApi;
+import kr.co.mcmp.ape.service.AppProvEngineService;
+import kr.co.mcmp.applicationmanager.dto.ReadyzResponse;
+import kr.co.mcmp.oss.dto.OssDto;
+import lombok.RequiredArgsConstructor;
+
+@RestController
+@RequiredArgsConstructor
+public class ApplicationManagerController {
+
+ private final AppProvEngineService appProvEngineService;
+
+ private final CbtumblebugRestApi cbtumblebugRestApi;
+
+ @GetMapping("/readyz")
+ @Operation(summary="Check Application-Manager is ready", description="")
+ public ResponseEntity checkReadyz(){
+ OssDto jenkinsOss = appProvEngineService.getJenkinsOss();
+ boolean checkTumblebug = cbtumblebugRestApi.checkTumblebug();
+ if(jenkinsOss != null && checkTumblebug){
+ return ResponseEntity.ok(new ReadyzResponse("application-manager is ready"));
+ }else{
+ return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body(new ReadyzResponse("application-manager is not ready"));
+ }
+
+ }
+
+}
diff --git a/src/main/java/kr/co/mcmp/applicationmanager/dto/ReadyzResponse.java b/src/main/java/kr/co/mcmp/applicationmanager/dto/ReadyzResponse.java
new file mode 100644
index 0000000..16edd7c
--- /dev/null
+++ b/src/main/java/kr/co/mcmp/applicationmanager/dto/ReadyzResponse.java
@@ -0,0 +1,13 @@
+package kr.co.mcmp.applicationmanager.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@AllArgsConstructor
+public class ReadyzResponse {
+
+ private String message;
+}
diff --git a/src/main/resources/jenkins/kubernetes_helm_install_pipeline.xml b/src/main/resources/jenkins/kubernetes_helm_install_pipeline.xml
index a785a7d..6f5d64a 100644
--- a/src/main/resources/jenkins/kubernetes_helm_install_pipeline.xml
+++ b/src/main/resources/jenkins/kubernetes_helm_install_pipeline.xml
@@ -1,6 +1,5 @@
-
-
+
false
@@ -8,45 +7,38 @@
- CB_TUMBLEBUG_SWAGGER_URI
- CB-Tumblebug Swagger API URI
- http://localhost:1323/tumblebug
+ CB_TUMBLEBUG_URI
+ Tumblebug API URL
+ http://13.125.199.35:1323/tumblebug
true
NAMESPACE
- Namespace
+ Namespace ID
ns01
true
- MCIS_NAME
- MCIS Name
- mcis-01
- true
-
-
- CLOUD_CONNECTION_NAME
- Cloud Connection Name
- aws-conn-01
+ CLUSTERNAME
+ K8s Cluster Name
+ cluster01
true
- HELM_RELEASE_NAME
- Helm Release Name
- my-release
+ TUMBLEBUG_USER
+ Tumblebug User ID
+ default
true
+
+ TUMBLEBUG_PASSWORD
+ Tumblebug User Password
+ default
+
- HELM_CHART_NAME
- Helm Chart Name
- bitnami/nginx
- true
-
-
- HELM_CHART_VERSION
- Helm Chart Version
- latest
+ HELM_CHARTS
+ Helm Charts to Install (comma-separated)
+ nginx,grafana
true
@@ -55,107 +47,126 @@
true
diff --git a/src/main/resources/static/assets/OssList-BQpm2x0n.js b/src/main/resources/static/assets/OssList-B3-YhXJJ.js
similarity index 96%
rename from src/main/resources/static/assets/OssList-BQpm2x0n.js
rename to src/main/resources/static/assets/OssList-B3-YhXJJ.js
index dd619f0..2dbc0d7 100644
--- a/src/main/resources/static/assets/OssList-BQpm2x0n.js
+++ b/src/main/resources/static/assets/OssList-B3-YhXJJ.js
@@ -1,4 +1,4 @@
-import{_ as q}from"./TableHeader.vue_vue_type_script_setup_true_lang-DvHOi1u5.js";import{_ as R}from"./Tabulator.vue_vue_type_style_index_0_lang-CakFavge.js";import{s as v}from"./request-9qA3DSor.js";import{d as D,u as N,c as A,w as I,o as T,r as p,a as u,b as s,t as k,e as g,v as M,F as G,f as W,g as O,h as m,i as S}from"./index-CgL-XxLM.js";const j=()=>v.get("/ossType/list"),z=()=>v.get("/ossType/filter/list"),H=()=>v.get("/oss/list");function J(o){return v.get(`/oss/duplicate?ossName=${o.ossName}&ossUrl=${o.ossUrl}&ossUsername=${o.ossUsername}`)}function K(o){return v.post("/oss/connection-check",o)}function Q(o){return v.get("/oss/"+o)}function X(o){return v.post("/oss",o)}function Y(o){return v.patch(`/oss/${o.ossIdx}`,o)}function Z(o){return v.delete(`/oss/${o}`)}const ss={class:"modal",id:"ossForm",tabindex:"-1"},es={class:"modal-dialog modal-xl",role:"document"},ts={class:"modal-content"},os=s("button",{type:"button",class:"btn-close","data-bs-dismiss":"modal","aria-label":"Close"},null,-1),as={class:"modal-body text-left py-4"},ls={class:"mb-5"},ns={class:"mb-3"},cs=s("label",{class:"form-label required"},"OSS Type",-1),is={class:"grid gap-0 column-gap-3"},ds=s("option",{value:0},"Select OSS Type",-1),rs=["value"],us={class:"row mb-3"},ms=s("label",{class:"form-label required"},"OSS Name",-1),ps={class:"grid gap-0 column-gap-3"},vs={class:"mb-3"},_s=s("label",{class:"form-label required"},"OSS Description",-1),bs={class:"mb-3"},hs=s("label",{class:"form-label required"},"URL",-1),fs={class:"row"},gs={class:"col"},ys=s("label",{class:"form-label required"},"OSS ID",-1),ws={class:"col"},Os=s("label",{class:"form-label required"},"OSS PW",-1),Ss={class:"col mt-4 row"},ks={key:1,class:"btn btn-success col",style:{"margin-right":"3px"}},xs={key:3,class:"btn btn-success col"},Cs={class:"modal-footer"},Us=D({__name:"ossForm",props:{mode:{},ossIdx:{}},emits:["get-oss-list"],setup(o,{emit:y}){const n=N(),c=o,_=y,b=A(()=>c.ossIdx);I(b,async()=>{await r()}),I(()=>c.mode,async()=>{await f(c.mode)}),T(async()=>{await f("init"),await r()});const e=p({}),r=async()=>{if(c.mode==="new")e.value.ossTypeIdx=0,e.value.ossName="",e.value.ossDesc="",e.value.ossUrl="",e.value.ossUsername="",e.value.ossPassword="",i.value=!1,d.value=!1;else{const{data:a}=await Q(c.ossIdx);e.value=a,e.value.ossPassword=V(e.value.ossPassword),i.value=!0,d.value=!0}},h=p([]),f=async a=>{try{if(a==="new"||a==="init"){const{data:t}=await z();h.value=t}else{const{data:t}=await j();h.value=t}}catch(t){console.log(t)}},x=()=>{e.value.ossPassword="",d.value=!1},i=p(!1),w=async()=>{const a={ossName:e.value.ossName,ossUrl:e.value.ossUrl,ossUsername:e.value.ossUsername},{data:t}=await J(a);t?n.error("이미 사용중인 이름입니다."):(n.success("사용 가능한 이름입니다."),i.value=!0)},d=p(!1),C=async()=>{const a={ossUrl:e.value.ossUrl,ossUsername:e.value.ossUsername,ossPassword:$(e.value.ossPassword),ossTypeIdx:e.value.ossTypeIdx},{data:t}=await K(a);t?(n.success("사용 가능한 OSS입니다."),d.value=!0):n.error("사용 불가능한 OSS입니다.")},L=()=>{i.value=!1},U=()=>{d.value=!1},P=async()=>{e.value.ossPassword=$(e.value.ossPassword),c.mode==="new"?await F().then(()=>{_("get-oss-list")}):await E().then(()=>{_("get-oss-list")}),r()},F=async()=>{const{data:a}=await X(e.value);a?n.success("등록되었습니다."):n.error("등록 할 수 없습니다.")},E=async()=>{const{data:a}=await Y(e.value);a?n.success("등록되었습니다."):n.error("등록 할 수 없습니다.")},$=a=>btoa(a),V=a=>atob(a);return(a,t)=>(m(),u("div",ss,[s("div",es,[s("div",ts,[os,s("div",as,[s("h3",ls,k(c.mode==="new"?"New":"Edit")+" OSS ",1),s("div",null,[s("div",ns,[cs,s("div",is,[g(s("select",{"onUpdate:modelValue":t[0]||(t[0]=l=>e.value.ossTypeIdx=l),class:"form-select p-2 g-col-12"},[ds,(m(!0),u(G,null,W(h.value,(l,B)=>(m(),u("option",{value:l.ossTypeIdx,key:B},k(l.ossTypeName),9,rs))),128))],512),[[M,e.value.ossTypeIdx]])])]),s("div",us,[ms,s("div",ps,[g(s("input",{type:"text",class:"form-control p-2 g-col-11",placeholder:"Enter the OSS Name","onUpdate:modelValue":t[1]||(t[1]=l=>e.value.ossName=l),onChange:L},null,544),[[O,e.value.ossName]])])]),s("div",vs,[_s,g(s("input",{type:"text",class:"form-control p-2 g-col-11",placeholder:"Enter the OSS Description","onUpdate:modelValue":t[2]||(t[2]=l=>e.value.ossDesc=l)},null,512),[[O,e.value.ossDesc]])]),s("div",bs,[hs,g(s("input",{type:"text",class:"form-control p-2 g-col-7",placeholder:"Enter the Server URL","onUpdate:modelValue":t[3]||(t[3]=l=>e.value.ossUrl=l),onFocus:U},null,544),[[O,e.value.ossUrl]])]),s("div",fs,[s("div",gs,[ys,g(s("input",{type:"text",class:"form-control p-2 g-col-7",placeholder:"Enter the OSS ID","onUpdate:modelValue":t[4]||(t[4]=l=>e.value.ossUsername=l),onFocus:U},null,544),[[O,e.value.ossUsername]])]),s("div",ws,[Os,g(s("input",{type:"password",class:"form-control p-2 g-col-11",placeholder:"Enter the OSS Password","onUpdate:modelValue":t[5]||(t[5]=l=>e.value.ossPassword=l),onClick:x,onFocus:U},null,544),[[O,e.value.ossPassword]])]),s("div",Ss,[i.value?(m(),u("button",ks,"Duplicate Check")):(m(),u("button",{key:0,class:"btn btn-primary col",onClick:w,style:{"margin-right":"3px"}},"Duplicate Check")),d.value?(m(),u("button",xs,"Connection Check")):(m(),u("button",{key:2,class:"btn btn-primary col",onClick:C},"Connection Check"))])])])]),s("div",Cs,[s("a",{href:"#",class:"btn btn-link link-secondary","data-bs-dismiss":"modal",onClick:t[6]||(t[6]=l=>r())}," Cancel "),s("a",{href:"#",class:"btn btn-primary ms-auto","data-bs-dismiss":"modal",onClick:t[7]||(t[7]=l=>P())},k(c.mode==="new"?"Regist":"Edit"),1)])])])]))}}),Ds={class:"modal",id:"deleteOss",tabindex:"-1"},Ns={class:"modal-dialog modal-lg",role:"document"},$s={class:"modal-content"},Is=s("button",{type:"button",class:"btn-close","data-bs-dismiss":"modal","aria-label":"Close"},null,-1),Ts=s("div",{class:"modal-status bg-danger"},null,-1),Ls={class:"modal-body text-left py-4"},Ps=s("h3",{class:"mb-5"}," Delete OSS ",-1),Fs={class:"modal-footer"},Es=s("a",{href:"#",class:"btn btn-link link-secondary","data-bs-dismiss":"modal"}," Cancel ",-1),Vs=D({__name:"deleteOss",props:{ossName:{},ossIdx:{}},emits:["get-oss-list"],setup(o,{emit:y}){const n=N(),c=o,_=y,b=async()=>{const{data:e}=await Z(c.ossIdx);e?n.success("삭제되었습니다."):n.error("삭제하지 못했습니다."),_("get-oss-list")};return(e,r)=>(m(),u("div",Ds,[s("div",Ns,[s("div",$s,[Is,Ts,s("div",Ls,[Ps,s("h4",null,"Are you sure you want to delete "+k(c.ossName)+"?",1)]),s("div",Fs,[Es,s("a",{href:"#",class:"btn btn-primary ms-auto","data-bs-dismiss":"modal",onClick:r[0]||(r[0]=h=>b())}," Delete ")])])])]))}}),Bs={class:"card card-flush w-100"},Gs=D({__name:"OssList",setup(o){const y=N(),n=p([]),c=p([]);T(async()=>{r(),await _()});const _=async()=>{try{const{data:i}=await H();n.value=i}catch(i){console.log(i),y.error("데이터를 가져올 수 없습니다.")}},b=p(0),e=p(""),r=()=>{c.value=[{title:"OSS Name",field:"ossName",width:400},{title:"OSS Desc",field:"ossDesc",width:500},{title:"URL",field:"ossUrl",width:600},{title:"Action",width:400,formatter:h,cellClick:function(i,w){const d=i.target,C=d==null?void 0:d.getAttribute("id");b.value=w.getRow().getData().ossIdx,C==="edit-btn"?f.value="edit":e.value=w.getRow().getData().ossName}}]},h=()=>`
+import{_ as q}from"./TableHeader.vue_vue_type_script_setup_true_lang-Dr4xpgtN.js";import{_ as R}from"./Tabulator.vue_vue_type_style_index_0_lang-nl4qvysp.js";import{s as v}from"./request-DZxlDuop.js";import{d as D,u as N,c as A,w as I,o as T,r as p,a as u,b as s,t as k,e as g,v as M,F as G,f as W,g as O,h as m,i as S}from"./index-uzfNJ_P6.js";const j=()=>v.get("/ossType/list"),z=()=>v.get("/ossType/filter/list"),H=()=>v.get("/oss/list");function J(o){return v.get(`/oss/duplicate?ossName=${o.ossName}&ossUrl=${o.ossUrl}&ossUsername=${o.ossUsername}`)}function K(o){return v.post("/oss/connection-check",o)}function Q(o){return v.get("/oss/"+o)}function X(o){return v.post("/oss",o)}function Y(o){return v.patch(`/oss/${o.ossIdx}`,o)}function Z(o){return v.delete(`/oss/${o}`)}const ss={class:"modal",id:"ossForm",tabindex:"-1"},es={class:"modal-dialog modal-xl",role:"document"},ts={class:"modal-content"},os=s("button",{type:"button",class:"btn-close","data-bs-dismiss":"modal","aria-label":"Close"},null,-1),as={class:"modal-body text-left py-4"},ls={class:"mb-5"},ns={class:"mb-3"},cs=s("label",{class:"form-label required"},"OSS Type",-1),is={class:"grid gap-0 column-gap-3"},ds=s("option",{value:0},"Select OSS Type",-1),rs=["value"],us={class:"row mb-3"},ms=s("label",{class:"form-label required"},"OSS Name",-1),ps={class:"grid gap-0 column-gap-3"},vs={class:"mb-3"},_s=s("label",{class:"form-label required"},"OSS Description",-1),bs={class:"mb-3"},hs=s("label",{class:"form-label required"},"URL",-1),fs={class:"row"},gs={class:"col"},ys=s("label",{class:"form-label required"},"OSS ID",-1),ws={class:"col"},Os=s("label",{class:"form-label required"},"OSS PW",-1),Ss={class:"col mt-4 row"},ks={key:1,class:"btn btn-success col",style:{"margin-right":"3px"}},xs={key:3,class:"btn btn-success col"},Cs={class:"modal-footer"},Us=D({__name:"ossForm",props:{mode:{},ossIdx:{}},emits:["get-oss-list"],setup(o,{emit:y}){const n=N(),c=o,_=y,b=A(()=>c.ossIdx);I(b,async()=>{await r()}),I(()=>c.mode,async()=>{await f(c.mode)}),T(async()=>{await f("init"),await r()});const e=p({}),r=async()=>{if(c.mode==="new")e.value.ossTypeIdx=0,e.value.ossName="",e.value.ossDesc="",e.value.ossUrl="",e.value.ossUsername="",e.value.ossPassword="",i.value=!1,d.value=!1;else{const{data:a}=await Q(c.ossIdx);e.value=a,e.value.ossPassword=V(e.value.ossPassword),i.value=!0,d.value=!0}},h=p([]),f=async a=>{try{if(a==="new"||a==="init"){const{data:t}=await z();h.value=t}else{const{data:t}=await j();h.value=t}}catch(t){console.log(t)}},x=()=>{e.value.ossPassword="",d.value=!1},i=p(!1),w=async()=>{const a={ossName:e.value.ossName,ossUrl:e.value.ossUrl,ossUsername:e.value.ossUsername},{data:t}=await J(a);t?n.error("이미 사용중인 이름입니다."):(n.success("사용 가능한 이름입니다."),i.value=!0)},d=p(!1),C=async()=>{const a={ossUrl:e.value.ossUrl,ossUsername:e.value.ossUsername,ossPassword:$(e.value.ossPassword),ossTypeIdx:e.value.ossTypeIdx},{data:t}=await K(a);t?(n.success("사용 가능한 OSS입니다."),d.value=!0):n.error("사용 불가능한 OSS입니다.")},L=()=>{i.value=!1},U=()=>{d.value=!1},P=async()=>{e.value.ossPassword=$(e.value.ossPassword),c.mode==="new"?await F().then(()=>{_("get-oss-list")}):await E().then(()=>{_("get-oss-list")}),r()},F=async()=>{const{data:a}=await X(e.value);a?n.success("등록되었습니다."):n.error("등록 할 수 없습니다.")},E=async()=>{const{data:a}=await Y(e.value);a?n.success("등록되었습니다."):n.error("등록 할 수 없습니다.")},$=a=>btoa(a),V=a=>atob(a);return(a,t)=>(m(),u("div",ss,[s("div",es,[s("div",ts,[os,s("div",as,[s("h3",ls,k(c.mode==="new"?"New":"Edit")+" OSS ",1),s("div",null,[s("div",ns,[cs,s("div",is,[g(s("select",{"onUpdate:modelValue":t[0]||(t[0]=l=>e.value.ossTypeIdx=l),class:"form-select p-2 g-col-12"},[ds,(m(!0),u(G,null,W(h.value,(l,B)=>(m(),u("option",{value:l.ossTypeIdx,key:B},k(l.ossTypeName),9,rs))),128))],512),[[M,e.value.ossTypeIdx]])])]),s("div",us,[ms,s("div",ps,[g(s("input",{type:"text",class:"form-control p-2 g-col-11",placeholder:"Enter the OSS Name","onUpdate:modelValue":t[1]||(t[1]=l=>e.value.ossName=l),onChange:L},null,544),[[O,e.value.ossName]])])]),s("div",vs,[_s,g(s("input",{type:"text",class:"form-control p-2 g-col-11",placeholder:"Enter the OSS Description","onUpdate:modelValue":t[2]||(t[2]=l=>e.value.ossDesc=l)},null,512),[[O,e.value.ossDesc]])]),s("div",bs,[hs,g(s("input",{type:"text",class:"form-control p-2 g-col-7",placeholder:"Enter the Server URL","onUpdate:modelValue":t[3]||(t[3]=l=>e.value.ossUrl=l),onFocus:U},null,544),[[O,e.value.ossUrl]])]),s("div",fs,[s("div",gs,[ys,g(s("input",{type:"text",class:"form-control p-2 g-col-7",placeholder:"Enter the OSS ID","onUpdate:modelValue":t[4]||(t[4]=l=>e.value.ossUsername=l),onFocus:U},null,544),[[O,e.value.ossUsername]])]),s("div",ws,[Os,g(s("input",{type:"password",class:"form-control p-2 g-col-11",placeholder:"Enter the OSS Password","onUpdate:modelValue":t[5]||(t[5]=l=>e.value.ossPassword=l),onClick:x,onFocus:U},null,544),[[O,e.value.ossPassword]])]),s("div",Ss,[i.value?(m(),u("button",ks,"Duplicate Check")):(m(),u("button",{key:0,class:"btn btn-primary col",onClick:w,style:{"margin-right":"3px"}},"Duplicate Check")),d.value?(m(),u("button",xs,"Connection Check")):(m(),u("button",{key:2,class:"btn btn-primary col",onClick:C},"Connection Check"))])])])]),s("div",Cs,[s("a",{href:"#",class:"btn btn-link link-secondary","data-bs-dismiss":"modal",onClick:t[6]||(t[6]=l=>r())}," Cancel "),s("a",{href:"#",class:"btn btn-primary ms-auto","data-bs-dismiss":"modal",onClick:t[7]||(t[7]=l=>P())},k(c.mode==="new"?"Regist":"Edit"),1)])])])]))}}),Ds={class:"modal",id:"deleteOss",tabindex:"-1"},Ns={class:"modal-dialog modal-lg",role:"document"},$s={class:"modal-content"},Is=s("button",{type:"button",class:"btn-close","data-bs-dismiss":"modal","aria-label":"Close"},null,-1),Ts=s("div",{class:"modal-status bg-danger"},null,-1),Ls={class:"modal-body text-left py-4"},Ps=s("h3",{class:"mb-5"}," Delete OSS ",-1),Fs={class:"modal-footer"},Es=s("a",{href:"#",class:"btn btn-link link-secondary","data-bs-dismiss":"modal"}," Cancel ",-1),Vs=D({__name:"deleteOss",props:{ossName:{},ossIdx:{}},emits:["get-oss-list"],setup(o,{emit:y}){const n=N(),c=o,_=y,b=async()=>{const{data:e}=await Z(c.ossIdx);e?n.success("삭제되었습니다."):n.error("삭제하지 못했습니다."),_("get-oss-list")};return(e,r)=>(m(),u("div",Ds,[s("div",Ns,[s("div",$s,[Is,Ts,s("div",Ls,[Ps,s("h4",null,"Are you sure you want to delete "+k(c.ossName)+"?",1)]),s("div",Fs,[Es,s("a",{href:"#",class:"btn btn-primary ms-auto","data-bs-dismiss":"modal",onClick:r[0]||(r[0]=h=>b())}," Delete ")])])])]))}}),Bs={class:"card card-flush w-100"},Gs=D({__name:"OssList",setup(o){const y=N(),n=p([]),c=p([]);T(async()=>{r(),await _()});const _=async()=>{try{const{data:i}=await H();n.value=i}catch(i){console.log(i),y.error("데이터를 가져올 수 없습니다.")}},b=p(0),e=p(""),r=()=>{c.value=[{title:"OSS Name",field:"ossName",width:400},{title:"OSS Desc",field:"ossDesc",width:500},{title:"URL",field:"ossUrl",width:600},{title:"Action",width:400,formatter:h,cellClick:function(i,w){const d=i.target,C=d==null?void 0:d.getAttribute("id");b.value=w.getRow().getData().ossIdx,C==="edit-btn"?f.value="edit":e.value=w.getRow().getData().ossName}}]},h=()=>`