瀏覽代碼

feat: mysql部署模板

370774330@qq.com 5 年之前
父節點
當前提交
f9b67560c4

+ 1 - 0
web/src/main/java/cn/seecoder/web/core/pipeline/config/HandlerConfigTable.java

@@ -37,6 +37,7 @@ public class HandlerConfigTable {
         handlerConfigMap.put("k8s-namespace", K8sNamespaceHandler.class);
         handlerConfigMap.put("deploy", DeployHandler.class);
         handlerConfigMap.put("api-test", ApiTestHandler.class);
+        handlerConfigMap.put("mysql-deploy", MysqlDeployHandler.class);
     }
 
     public static Handler transToHandler(String name, JsonNode config) throws Exception {

+ 176 - 0
web/src/main/java/cn/seecoder/web/core/pipeline/handler/MysqlDeployHandler.java

@@ -0,0 +1,176 @@
+package cn.seecoder.web.core.pipeline.handler;
+
+
+import cn.seecoder.api.ApplicationProperties;
+import cn.seecoder.api.k8s.*;
+import cn.seecoder.api.k8s.exception.K8sApiException;
+import cn.seecoder.api.k8s.model.*;
+import cn.seecoder.api.k8s.vo.SecretVO;
+import cn.seecoder.common.util.SpringUtil;
+import cn.seecoder.web.core.pipeline.Context;
+import cn.seecoder.web.core.pipeline.PipelineException;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpStatus;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/6/13
+ * @description:
+ * devcloud Mysql部署
+ * 目前seecoder平台无法暴露tcp端口,所以只部署service和deployment供集群使用
+ */
+@Slf4j
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class MysqlDeployHandler extends AbstractHandler{
+
+    private final SecretApi secretApi;
+
+    private final DeploymentApi deploymentApi;
+
+    private final ApplicationProperties applicationProperties;
+
+    private final NamespaceApi namespaceApi;
+
+    private final ServiceApi serviceApi;
+
+    private final static String DEFAULT_IMAGE_PULL_SECRET_NAME = "seecoder-devcloud-image-pull-secret";
+
+    public MysqlDeployHandler(){
+        this.applicationProperties = SpringUtil.getBean(ApplicationProperties.class);
+        secretApi = SpringUtil.getBean(SecretApi.class);
+        deploymentApi = SpringUtil.getBean(DeploymentApi.class);
+        namespaceApi = SpringUtil.getBean(NamespaceApi.class);
+        serviceApi = SpringUtil.getBean(ServiceApi.class);
+    }
+
+    private String version = "5.7";
+
+    private Integer port = 3306;
+
+    private String password = "root";
+
+    @Override
+    public void process(Context context) throws PipelineException {
+
+        //1. 创建namespace
+        Namespace k8sNamespace = new Namespace();
+        k8sNamespace.setName(context.getNamespace());
+        //todo namespace在底下资源未删除时,不能轻易删除重建,只能直接通过异常查是否已创建,丑陋,待修改
+        try {
+            List<Namespace> namespaces = namespaceApi.getByCondition(K8sObjectRequest.builder()
+                    .name(context.getNamespace()).build());
+            if (namespaces.size() == 0) {
+                namespaceApi.create(k8sNamespace);
+                log.info("Namespace创建成功: [namespace: " + context.getNamespace() + ", deployName: " + context.getDeployName() + "]");
+            } else {
+                log.info("Namespace已经存在, 无需新建: [namespace: " + context.getNamespace() + ", deployName: " + context.getDeployName() + "]");
+            }
+        } catch (K8sApiException e) {
+            context.appendErrorResult(PipelineException.NAMESPACE_CREATE_ERROR, e);
+            throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE, PipelineException.NAMESPACE_CREATE_ERROR, e);
+        }
+        context.appendSuccessResult("K8s Namespace创建成功: [namespace: " + context.getNamespace() + ", deployName: " + context.getDeployName() + "]");
+
+
+        //2. 创建deployment
+        //2.0. 镜像配置信息获取
+        String imageName = "mysql";
+        String imageTag = version;
+        int replicas = 1;
+        String namespace = context.getNamespace();
+        String deployName = context.getDeployName();
+
+        //2.1. 配置容器暴露端口
+        ContainerPort containerPort = ContainerPort.builder()
+                .port(port)
+                .build();
+
+        //2.2. 配置容器
+        Container container = Container.builder()
+                .image(imageName + ":" + imageTag)
+                .name(deployName + K8sConstants.CONTAINER_SUFFIX)
+                .ports(Collections.singleton(containerPort))
+                .env(Collections.singletonMap("MYSQL_ROOT_PASSWORD", password))
+                .build();
+
+        //2.3. 配置deployment
+        Deployment deployment = Deployment.builder()
+                .replicas(replicas)
+                .containers(Collections.singletonList(container))
+                .build();
+        deployment.setName(deployName + K8sConstants.DEPLOYMENT_SUFFIX);
+        deployment.setNamespace(namespace);
+        deployment.setLabel(K8sConstants.APPLICATION_LABEL, deployName);
+
+        //2.4. 检查镜像仓库secret是否存在,没有则创建。
+        SecretVO secretVO = secretApi.getSecretByName(namespace, DEFAULT_IMAGE_PULL_SECRET_NAME);
+        if (secretVO == null) {
+            secretApi.createPrivateRegistrySecret(
+                    namespace,
+                    DEFAULT_IMAGE_PULL_SECRET_NAME,
+                    applicationProperties.getDocker().getRegistry(),
+                    applicationProperties.getDocker().getRegistryUsername(),
+                    applicationProperties.getDocker().getRegistryPassword()
+            );
+        }
+        deployment.setImagePullSecrets(Collections.singletonList(DEFAULT_IMAGE_PULL_SECRET_NAME));
+
+
+        //2.5. 创建Deployment实例
+        try {
+            List<Deployment> deployments = deploymentApi.getByCondition(K8sObjectRequest.builder()
+                    .namespace(context.getNamespace())
+                    .name(context.getDeployName() + K8sConstants.DEPLOYMENT_SUFFIX)
+                    .build());
+            if (deployments.size() == 0) {
+                deploymentApi.create(deployment);
+                log.info("deployment创建成功: [namespace: " + context.getNamespace() + ", deployName: " + context.getDeployName() + "]");
+            } else {
+                deploymentApi.update(deployment);
+                log.info("deployment更新成功: [namespace: " + context.getNamespace() + ", deployName: " + context.getDeployName() + "]");
+
+            }
+        } catch (K8sApiException e) {
+            context.appendErrorResult(PipelineException.DEPLOYMENT_CREATE_ERROR, e);
+            throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE, PipelineException.DEPLOYMENT_CREATE_ERROR, e);
+        }
+
+        //3. 创建service
+        //3.1. 配置K8s的service
+        Service service = new Service();
+        service.setNamespace(context.getNamespace());
+        service.setName(context.getDeployName() + K8sConstants.SERVICE_SUFFIX);
+        //标签选择器选择 此项目对应的deployment的name
+        service.setSelectors(Collections.singletonMap(K8sConstants.APPLICATION_LABEL, context.getDeployName()));
+        service.setServicePorts(
+                Collections.singleton(ServicePort.builder().port(port).targetPort(port).build())
+        );
+
+        //3.2. 创建service实例
+        try {
+            List<Service> services = serviceApi.getByCondition(K8sObjectRequest.builder()
+                    .namespace(context.getNamespace())
+                    .name(context.getDeployName() + K8sConstants.SERVICE_SUFFIX)
+                    .build());
+            if (services.size() == 0) {
+                serviceApi.create(service);
+                log.info("service创建成功: [namespace: " + context.getNamespace() + ", deployName: " + context.getDeployName() + "]");
+            } else {
+                serviceApi.update(service);
+                log.info("service更新成功: [namespace: " + context.getNamespace() + ", deployName: " + context.getDeployName() + "]");
+            }
+        } catch (K8sApiException e) {
+            context.appendErrorResult(PipelineException.SERVICE_CREATE_ERROR, e);
+            throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE, PipelineException.SERVICE_CREATE_ERROR, e);
+        }
+        context.appendSuccessResult("K8s Service创建成功: [namespace: " + context.getNamespace() + ", deployName: " + context.getDeployName() + "]");
+
+
+    }
+}

+ 3 - 1
web/src/main/java/cn/seecoder/web/core/pipeline/template/PipelineTemplateTable.java

@@ -1,9 +1,9 @@
 package cn.seecoder.web.core.pipeline.template;
 
+import cn.seecoder.web.core.pipeline.PipelineException;
 import org.apache.commons.io.IOUtils;
 import org.apache.http.HttpStatus;
 import org.springframework.core.io.ClassPathResource;
-import cn.seecoder.web.core.pipeline.PipelineException;
 
 import java.io.IOException;
 import java.nio.file.Files;
@@ -27,6 +27,7 @@ public class PipelineTemplateTable {
     //模板名
     public static final String SPRINGBOOT_JAVA8 = "SPRINGBOOT_JAVA8";
     public static final String NODE_10 = "NODE_10";
+    public static final String MYSQL = "MYSQL";
 
 
     /**
@@ -36,6 +37,7 @@ public class PipelineTemplateTable {
         templateNames = new HashSet<String>();
         templateNames.add(NODE_10);
         templateNames.add(SPRINGBOOT_JAVA8);
+        templateNames.add(MYSQL);
 
     }
 

+ 9 - 0
web/src/main/resources/template/config/MYSQL.json

@@ -0,0 +1,9 @@
+[
+  {
+    "name": "mysql-deploy",
+    "active": true,
+    "configs": {
+      "password": "root"
+    }
+  }
+]