Преглед на файлове

feat: pipeline deployment service层 创建部署

370774330@qq.com преди 5 години
родител
ревизия
5b11f74d93
променени са 48 файла, в които са добавени 502 реда и са изтрити 357 реда
  1. 1 1
      api/mvnw.cmd
  2. 1 1
      common/mvnw.cmd
  3. 1 1
      core/mvnw.cmd
  4. 5 0
      core/src/main/java/seecoder/devcloud/core/pipeline/PipelineException.java
  5. 19 20
      core/src/main/java/seecoder/devcloud/core/pipeline/PipelineFactory.java
  6. 6 2
      core/src/main/java/seecoder/devcloud/core/pipeline/config/HandlerConfig.java
  7. 7 2
      core/src/main/java/seecoder/devcloud/core/pipeline/config/HandlerConfigTable.java
  8. 0 29
      core/src/main/java/seecoder/devcloud/core/pipeline/config/PipelineConfig.java
  9. 6 14
      core/src/main/java/seecoder/devcloud/core/pipeline/handler/DockerImageBuildHandler.java
  10. 13 7
      core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sDeploymentHandler.java
  11. 15 8
      core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sIngressHandler.java
  12. 2 1
      core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sNamespaceHandler.java
  13. 10 3
      core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sServiceHandler.java
  14. 37 9
      core/src/main/java/seecoder/devcloud/core/pipeline/template/PipelineTemplateTable.java
  15. 30 0
      core/src/main/resources/template/config/JAVA8.json
  16. 0 9
      core/src/main/resources/template/config/test.json
  17. 0 0
      core/src/main/resources/template/dockerfile/JAVA8
  18. 57 4
      core/src/test/java/seecoder/devcloud/core/CoreApplicationTests.java
  19. 1 1
      web/mvnw.cmd
  20. 5 5
      web/src/main/java/seecoder/devcloud/web/aspect/TreeLoggingAspect.java
  21. 8 6
      web/src/main/java/seecoder/devcloud/web/controller/pipeline/PipelineController.java
  22. 0 1
      web/src/main/java/seecoder/devcloud/web/controller/user/UserController.java
  23. 15 0
      web/src/main/java/seecoder/devcloud/web/dao/pipeline/DeploymentMapper.java
  24. 3 3
      web/src/main/java/seecoder/devcloud/web/dao/pipeline/PipelineHistoryMapper.java
  25. 4 5
      web/src/main/java/seecoder/devcloud/web/dao/pipeline/PipelineMapper.java
  26. 2 2
      web/src/main/java/seecoder/devcloud/web/dao/user/GroupMemberMapper.java
  27. 2 3
      web/src/main/java/seecoder/devcloud/web/infrastructure/security/JwtAuthenticationTokenFilter.java
  28. 1 1
      web/src/main/java/seecoder/devcloud/web/model/po/pipeline/DeploymentPO.java
  29. 1 1
      web/src/main/java/seecoder/devcloud/web/model/po/pipeline/PipelineHistoryPO.java
  30. 1 6
      web/src/main/java/seecoder/devcloud/web/model/po/pipeline/PipelinePO.java
  31. 30 30
      web/src/main/java/seecoder/devcloud/web/model/po/user/Group.java
  32. 2 3
      web/src/main/java/seecoder/devcloud/web/model/po/user/UserPO.java
  33. 3 3
      web/src/main/java/seecoder/devcloud/web/model/vo/pipeline/PipelineConfigVO.java
  34. 2 2
      web/src/main/java/seecoder/devcloud/web/model/vo/pipeline/PipelineHistoryVO.java
  35. 9 10
      web/src/main/java/seecoder/devcloud/web/model/vo/pipeline/PipelineInfoVO.java
  36. 3 6
      web/src/main/java/seecoder/devcloud/web/model/vo/user/UserVO.java
  37. 35 26
      web/src/main/java/seecoder/devcloud/web/service/impl/pipeline/PipelineServiceImpl.java
  38. 110 110
      web/src/main/java/seecoder/devcloud/web/service/impl/user/GroupServiceImpl.java
  39. 2 2
      web/src/main/java/seecoder/devcloud/web/service/impl/user/UserServiceImpl.java
  40. 3 3
      web/src/main/java/seecoder/devcloud/web/service/user/UserService.java
  41. 6 12
      web/src/main/resources/devcloud-k8s-init
  42. 4 1
      web/src/main/resources/sql/deployment.sql
  43. 12 0
      web/src/main/resources/sql/pipeline.sql
  44. 13 0
      web/src/main/resources/sql/pipeline_history.sql
  45. 3 4
      web/src/main/resources/sql/project.sql
  46. 12 0
      web/src/main/resources/sql/project_user.sql
  47. 0 0
      web/src/main/resources/sql/tree_log.sql
  48. 0 0
      web/src/main/resources/sql/trees.sql

+ 1 - 1
api/mvnw.cmd

@@ -43,7 +43,7 @@ title %0
 @REM set %HOME% to equivalent of $HOME
 if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
 
-@REM Execute a user defined script before this one
+@REM Execute a userPO defined script before this one
 if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
 @REM check for pre script, once with legacy .bat ending and once with .cmd ending
 if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"

+ 1 - 1
common/mvnw.cmd

@@ -43,7 +43,7 @@ title %0
 @REM set %HOME% to equivalent of $HOME
 if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
 
-@REM Execute a user defined script before this one
+@REM Execute a userPO defined script before this one
 if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
 @REM check for pre script, once with legacy .bat ending and once with .cmd ending
 if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"

+ 1 - 1
core/mvnw.cmd

@@ -43,7 +43,7 @@ title %0
 @REM set %HOME% to equivalent of $HOME
 if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
 
-@REM Execute a user defined script before this one
+@REM Execute a userPO defined script before this one
 if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
 @REM check for pre script, once with legacy .bat ending and once with .cmd ending
 if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"

+ 5 - 0
core/src/main/java/seecoder/devcloud/core/pipeline/PipelineException.java

@@ -16,6 +16,11 @@ public class PipelineException extends Exception{
     public static final String SERVICE_CREATE_ERROR = "K8S service 创建错误";
     public static final String DEPLOYMENT_CREATE_ERROR = "K8S deployment 创建错误";
     public static final String NAMESPACE_CREATE_ERROR = "K8S namespace 创建错误";
+    public static final String CONFIG_JSON_ERROR = "获取模板的config json错误";
+    public static final String DOCKERFILE_ERROR = "获取模板的dockerfile错误";
+
+
+
     private int code;
     private String msg;
 

+ 19 - 20
core/src/main/java/seecoder/devcloud/core/pipeline/PipelineFactory.java

@@ -1,10 +1,14 @@
 package seecoder.devcloud.core.pipeline;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.http.HttpStatus;
 import seecoder.devcloud.core.pipeline.config.HandlerConfig;
 import seecoder.devcloud.core.pipeline.config.HandlerConfigTable;
-import seecoder.devcloud.core.pipeline.config.PipelineConfig;
 import seecoder.devcloud.core.pipeline.pipeline.PipelineImpl;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -17,54 +21,49 @@ public class PipelineFactory {
     /**
      * 流水线初始化
      * @param configJson configJson 流水线配置的json字符串
-     * @param namespace 流水线所属的namespace,需要用户自己指定,例如devcloud后端使用用户所属的groupName中作为namespace
-     * @param projectName 流水线所属的project,需要用户自己指定
-     * @param pipelineId 流水线标识符,需要用户自己指定
-     * @param pipelineName 流水线名称,需要用户自己指定
+     * @param namespace 流水线的k8s namespace,devcloud后端采用{@code Project}中的{@code name}作为namespace
+     * @param projectName 流水线部署k8s的应用名称,devcloud后端采用{@code Pipeline}中的{@code name} 作为project name
      * @return
      */
-    public static Pipeline init(String configJson, String namespace, String projectName, Integer pipelineId, String pipelineName) throws PipelineException {
+    public static Pipeline init(String configJson, String namespace, String projectName) throws PipelineException {
 
-        PipelineConfig pipelineConfig = PipelineConfig.init(configJson);
+        ObjectMapper mapper = new ObjectMapper();
+        List<HandlerConfig> handlerConfigs = null;
+        try {
+            handlerConfigs = mapper.readValue(configJson,new TypeReference<ArrayList<HandlerConfig>>(){});
+        } catch (JsonProcessingException e) {
+            throw new PipelineException(HttpStatus.SC_BAD_REQUEST,PipelineException.CONFIG_TRANSFER_ERROR,e);
+        }
 
         //初始化context
         Context context = Context.builder()
                 .projectName(projectName)
                 .namespace(namespace)
-                .pipelineId(pipelineId)
-                .pipelineName(pipelineName)
                 .build();
 
-        Handler firstHandler = initHandlerChainAndContext(pipelineConfig,context.getConfigs());
+        Handler firstHandler = initHandlerChainAndContext(handlerConfigs,context.getConfigs());
 
         return new PipelineImpl(firstHandler, context);
     }
 
     /**
      * 根据 handlerConfig 构筑 Handler 的流水线,以及将配置属性统一放入 Context
-     * @param pipelineConfig 流水线配置
-     * @param configs 将此handler配置的所有config加入context中的config
+     * @param handlerConfigs 流水线配置
+     * @param configs 将每一个handler config配置的configs中的值加入context中的configs
      *                (所以这一步要避免配置的覆盖,即不要用相同名字的key)
      * @return
      */
-    private static Handler initHandlerChainAndContext(PipelineConfig pipelineConfig, Map<String,String> configs) throws PipelineException {
+    private static Handler initHandlerChainAndContext(List<HandlerConfig> handlerConfigs, Map<String,String> configs) throws PipelineException {
         Handler firstHandler = null;
         Handler currentHandler = null;
 
-        //转换成对应的Handler实例
-        List<HandlerConfig> handlerConfigs = pipelineConfig.getHandlerConfigs();
-
-
         HandlerConfig firstHandlerConfig = handlerConfigs.get(0);
-        //todo 相同名字的key可能导致覆盖 这里应该抛出warning
         configs.putAll(firstHandlerConfig.getConfigs());
         firstHandler = HandlerConfigTable.transToHandler(firstHandlerConfig);
         currentHandler = firstHandler;
 
-
         for (int i = 1; i < handlerConfigs.size(); i++){
             HandlerConfig nextHandlerConfig = handlerConfigs.get(i);
-            //todo 相同名字的key可能导致覆盖 这里应该抛出warning
             configs.putAll(nextHandlerConfig.getConfigs());
             Handler nextHandler = HandlerConfigTable.transToHandler(nextHandlerConfig);
             currentHandler.setNextHandler(nextHandler);

+ 6 - 2
core/src/main/java/seecoder/devcloud/core/pipeline/config/HandlerConfig.java

@@ -6,24 +6,28 @@ package seecoder.devcloud.core.pipeline.config;
  * @description:
  */
 
+import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
-import seecoder.devcloud.core.pipeline.Handler;
+import lombok.NoArgsConstructor;
 
 import java.util.HashMap;
 import java.util.Map;
 
 /**
  * 代表着pipeline的一个handler配置实体
+ * 是pipeline配置的configJson的实体类
  */
 @Data
 @Builder
+@AllArgsConstructor
+@NoArgsConstructor
 public class HandlerConfig{
 
     private String name;
 
     /**
-     * 对应Handler的配置
+     * 需要加入Context.configs中的参数
      */
     @Builder.Default
     private Map<String,String> configs = new HashMap<>();

+ 7 - 2
core/src/main/java/seecoder/devcloud/core/pipeline/config/HandlerConfigTable.java

@@ -4,6 +4,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.http.HttpStatus;
 import seecoder.devcloud.core.pipeline.Handler;
 import seecoder.devcloud.core.pipeline.PipelineException;
+import seecoder.devcloud.core.pipeline.handler.*;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -25,13 +26,17 @@ public class HandlerConfigTable {
      */
     static {
         handlerConfigMap = new HashMap<>();
-        //todo 加入表
+        handlerConfigMap.put("image-build", DockerImageBuildHandler.class);
+        handlerConfigMap.put("k8s-deployment", K8sDeploymentHandler.class);
+        handlerConfigMap.put("k8s-service", K8sServiceHandler.class);
+        handlerConfigMap.put("k8s-ingress", K8sIngressHandler.class);
+        handlerConfigMap.put("k8s-namespace", K8sNamespaceHandler.class);
     }
 
     public static Handler transToHandler(HandlerConfig config) throws PipelineException {
         Handler handler = null;
         try {
-            handler = (Handler) handlerConfigMap.get(config).newInstance();
+            handler = (Handler) handlerConfigMap.get(config.getName()).newInstance();
         } catch (InstantiationException | IllegalAccessException e) {
             throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE,PipelineException.CONFIG_TRANSFER_ERROR, e);
         }

+ 0 - 29
core/src/main/java/seecoder/devcloud/core/pipeline/config/PipelineConfig.java

@@ -1,29 +0,0 @@
-package seecoder.devcloud.core.pipeline.config;
-
-import lombok.Builder;
-import lombok.Data;
-import seecoder.devcloud.core.pipeline.Context;
-import seecoder.devcloud.core.pipeline.Handler;
-import seecoder.devcloud.core.pipeline.Pipeline;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author PuHong Weng
- * @date 2021/2/2
- * @description: pipeline配置的实体,由对应的pipeline config json转换过来
- */
-@Data
-public class PipelineConfig {
-
-    private List<HandlerConfig> handlerConfigs;
-
-    public static PipelineConfig init(String configJson){
-        PipelineConfig pipelineConfig = null;
-        //todo jackson转换配置实体
-        return pipelineConfig;
-    }
-
-}

+ 6 - 14
core/src/main/java/seecoder/devcloud/core/pipeline/handler/DockerImageBuildHandler.java

@@ -4,11 +4,9 @@ import com.spotify.docker.client.ProgressHandler;
 import com.spotify.docker.client.exceptions.DockerException;
 import com.spotify.docker.client.messages.ProgressMessage;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.http.HttpStatus;
 import org.eclipse.jgit.api.Git;
-import org.springframework.util.ResourceUtils;
 import seecoder.devcloud.api.docker.DockerApi;
 import seecoder.devcloud.api.git.GitApi;
 import seecoder.devcloud.common.util.SpringUtil;
@@ -16,7 +14,6 @@ import seecoder.devcloud.core.pipeline.Context;
 import seecoder.devcloud.core.pipeline.PipelineException;
 import seecoder.devcloud.core.pipeline.template.PipelineTemplateTable;
 
-import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -44,12 +41,11 @@ public class DockerImageBuildHandler extends AbstractHandler {
 
     @Override
     public void process(Context context) throws PipelineException {
-
-        String imageName = context.getNamespace() + "-" + context.getProjectName();
+        //0. 变量准备
         String repoUrl = context.getConfigs().get("repoUrl");
-        //要构建的分支名
-        String branchName = context.getConfigs().get("branchName");
+        String branchName = context.getConfigs().getOrDefault("branchName","master");
         String templateName = context.getTemplateName();
+        String imageName = context.getNamespace() + "-" + context.getProjectName();
 
         // 1. 有git从git拿到地址仓库
         Path directory = null;
@@ -64,16 +60,12 @@ public class DockerImageBuildHandler extends AbstractHandler {
         }
         //2. 帮助学生创建dockerfile文件
         //todo 待测试创建非临时文件会不会有问题
-
         Path dockerfile = Paths.get(directory.toString(), "Dockerfile");
         try {
-            Files.createFile(dockerfile);
-            //todo 待测试模板文件要放在哪, 路径目录
-            File dFile = ResourceUtils.getFile("classpath:" + PipelineTemplateTable.getTemplateDockerfileName(templateName));
-            FileUtils.copyDirectory(dFile,dockerfile.toFile());
+            PipelineTemplateTable.copyTemplateDockerfile(templateName,dockerfile);
         } catch (IOException e) {
             context.appendErrorResult(PipelineException.DOCKERFILE_CREATE_ERROR,e);
-            throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE, PipelineException.DOCKERFILE_CREATE_ERROR,e);
+            throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE,PipelineException.DOCKERFILE_CREATE_ERROR,e);
         }
 
         //3. 镜像构建
@@ -102,7 +94,7 @@ public class DockerImageBuildHandler extends AbstractHandler {
         context.getConfigs().put("imageName", imageName);
         context.getConfigs().put("imageTag", imageTag);
 
-        context.appendSuccessResult("Success: DockerImageBuild");
+        context.appendSuccessResult("镜像构建成功,已推送进仓库");
     }
 }
 

+ 13 - 7
core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sDeploymentHandler.java

@@ -51,26 +51,27 @@ public class K8sDeploymentHandler extends AbstractHandler {
      */
     @Override
     public void process(Context context) throws PipelineException {
-        //配置初始化
+        //0. 配置初始化
         String imageName = context.getConfigs().get("imageName");
+        String imageTag = context.getConfigs().get("imageTag");
         int port = Integer.parseInt(context.getConfigs().getOrDefault("port", "8000"));
         int replicas = Integer.parseInt(context.getConfigs().getOrDefault("replicas", "1"));
         String namespace = context.getNamespace();
         String projectName = context.getProjectName();
 
-        //配置容器暴露端口
+        //1. 配置容器暴露端口
         ContainerPort containerPort = ContainerPort.builder()
                 .port(port)
                 .build();
 
-        //配置容器
+        //2. 配置容器
         Container container = Container.builder()
-                .image(imageName)
+                .image(imageName+":"+imageTag)
                 .name(projectName + K8sConstants.CONTAINER_SUFFIX)
                 .ports(Collections.singleton(containerPort))
                 .build();
 
-        //配置deployment
+        //3. 配置deployment
         Deployment deployment = Deployment.builder()
                 .replicas(replicas)
                 .containers(Collections.singletonList(container))
@@ -80,7 +81,7 @@ public class K8sDeploymentHandler extends AbstractHandler {
         deployment.setLabel(K8sConstants.APPLICATION_LABEL, projectName);
 
 
-        // 检查镜像仓库secret,没有则创建。 设置镜像镜像secret
+        //3. 检查镜像仓库secret是否存在,没有则创建。
         SecretVO secretVO = secretApi.getSecretByName(namespace, DEFAULT_IMAGE_PULL_SECRET_NAME);
         if (secretVO == null) {
             secretApi.createPrivateRegistrySecret(
@@ -92,7 +93,7 @@ public class K8sDeploymentHandler extends AbstractHandler {
             );
         }
         deployment.setImagePullSecrets(Collections.singletonList(DEFAULT_IMAGE_PULL_SECRET_NAME));
-
+        //4. 创建Deployment。
         try {
             deploymentApi.create(deployment);
             log.info("deployment创建成功");
@@ -101,9 +102,14 @@ public class K8sDeploymentHandler extends AbstractHandler {
                 deploymentApi.update(deployment);
                 log.info("deployment更新成功");
             } else {
+                context.appendErrorResult(PipelineException.DEPLOYMENT_CREATE_ERROR,e);
                 throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE,PipelineException.DEPLOYMENT_CREATE_ERROR,e);
             }
         }
+
+        //5. 存入暴露的端口
+        context.getConfigs().put("port",String.valueOf(port));
+        context.appendSuccessResult("K8s Deployment部署成功");
     }
 
 }

+ 15 - 8
core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sIngressHandler.java

@@ -34,15 +34,12 @@ public class K8sIngressHandler extends AbstractHandler {
 
     @Override
     public void process(Context context) throws PipelineException {
-
+        //0. 变量准备
         String namespace = context.getNamespace();
         String projectName = context.getProjectName();
         String servicePort = context.getConfigs().get("servicePort");
 
-        Ingress ingress = new Ingress();
-        ingress.setName(projectName + K8sConstants.INGRESS_SUFFIX);
-        ingress.setNamespace(namespace);
-
+        //1. ingress路径规则
         Ingress.IngressRule ingressRule = new Ingress.IngressRule();
         ingressRule.setHost(namespace + applicationProperties.getK8s().getIngressHostSuffix());
         Ingress.IngressPath path = new Ingress.IngressPath();
@@ -51,20 +48,30 @@ public class K8sIngressHandler extends AbstractHandler {
         path.setServiceName(projectName+K8sConstants.SERVICE_SUFFIX);
         path.setPort(Integer.parseInt(servicePort));
         ingressRule.setRuleValues(Collections.singleton(path));
-        ingress.setHttpRules(Collections.singletonList(ingressRule));
 
+        //2. 配置ingress
+        Ingress ingress = new Ingress();
+        ingress.setName(projectName + K8sConstants.INGRESS_SUFFIX);
+        ingress.setNamespace(namespace);
+        ingress.setHttpRules(Collections.singletonList(ingressRule));
         ingress.setLabel(K8sConstants.APPLICATION_LABEL, projectName);
 
+        //3. 创建
         try {
             ingressApi.create(ingress);
-            log.info("deployment创建成功");
+            log.info("ingress创建成功");
         } catch (K8sApiException e){
             if (e.getCode() == K8sApiException.ALREADY_EXIST){
                 ingressApi.update(ingress);
-                log.info("deployment更新成功");
+                log.info("ingress更新成功");
             } else {
+                context.appendErrorResult(PipelineException.INGRESS_CREATE_ERROR,e);
                 throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE,PipelineException.INGRESS_CREATE_ERROR,e);
             }
         }
+
+        //4. 存入访问路径
+        context.getConfigs().put("accessUrl",namespace + applicationProperties.getK8s().getIngressHostSuffix()+"/" + projectName + "/");
+        context.appendSuccessResult("K8s Ingress创建成功");
     }
 }

+ 2 - 1
core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sNamespaceHandler.java

@@ -40,10 +40,11 @@ public class K8sNamespaceHandler extends AbstractHandler {
             if (e.getCode() == K8sApiException.ALREADY_EXIST){
                 log.info("Namespace已经存在, 无需新建");
             } else{
+                context.appendErrorResult(PipelineException.NAMESPACE_CREATE_ERROR,e);
                 throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE,PipelineException.NAMESPACE_CREATE_ERROR,e);
             }
         }
 
-
+        context.appendSuccessResult("K8s Namespace创建成功");
     }
 }

+ 10 - 3
core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sServiceHandler.java

@@ -31,13 +31,14 @@ public class K8sServiceHandler extends AbstractHandler {
     @Override
     public void process(Context context) throws PipelineException {
 
-        //pod内容器暴露的端口
+        //0. 变量准备
+        // pod内容器暴露的端口
         int targetPort =  Integer.parseInt(context.getConfigs().get("port"));
         //service对集群内暴露的端口,这里默认与targetPort一致
         int servicePort = targetPort;
-        context.getConfigs().put("servicePort", String.valueOf(servicePort));
 
-        //配置K8s的service
+
+        //1. 配置K8s的service
         Service service = new Service();
         service.setNamespace(context.getNamespace());
         service.setName(context.getProjectName()+ K8sConstants.SERVICE_SUFFIX);
@@ -47,6 +48,7 @@ public class K8sServiceHandler extends AbstractHandler {
                 Collections.singleton(ServicePort.builder().port(servicePort).targetPort(targetPort).build())
         );
 
+        //2. 创建
         try {
             serviceApi.create(service);
             log.info("service创建成功");
@@ -55,8 +57,13 @@ public class K8sServiceHandler extends AbstractHandler {
                 serviceApi.update(service);
                 log.info("service更新成功");
             } else {
+                context.appendErrorResult(PipelineException.SERVICE_CREATE_ERROR,e);
                 throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE,PipelineException.SERVICE_CREATE_ERROR,e);
             }
         }
+
+        //3. 存放暴露的端口
+        context.getConfigs().put("servicePort", String.valueOf(servicePort));
+        context.appendSuccessResult("K8s Service创建成功");
     }
 }

+ 37 - 9
core/src/main/java/seecoder/devcloud/core/pipeline/template/PipelineTemplateTable.java

@@ -1,8 +1,14 @@
 package seecoder.devcloud.core.pipeline.template;
 
+import org.apache.commons.io.FileUtils;
 import org.apache.http.HttpStatus;
+import org.springframework.util.ResourceUtils;
 import seecoder.devcloud.core.pipeline.PipelineException;
 
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -14,13 +20,11 @@ import java.util.List;
  */
 public class PipelineTemplateTable {
 
-    private static final String TEMPLATE_DOCKERFILE_PREFIX = "TEMPLATE_DOCKERFILE_";
-    private static final String TEMPLATE_CONFIG_JSON_PREFIX = "TEMPLATE_CONFIG_JSON_";
 
     private static final HashSet<String> templateNames;
 
     /**
-     * 需要添加模板类型在这里添加,然后根据需求添加对应的imagename、dockerfile、configjson等
+     * 需要添加模板类型在这里添加,然后根据需求添加对应的dockerfile、configjson等
      * todo
      */
     static {
@@ -30,7 +34,7 @@ public class PipelineTemplateTable {
     }
 
     public static void validateTemplateName(String name) throws PipelineException {
-        if (!templateNames.contains(name)){
+        if (!templateNames.contains(name)) {
             throw new PipelineException(HttpStatus.SC_BAD_REQUEST, PipelineException.TEMPLATE_NAME_NOT_EXIST);
         }
     }
@@ -42,12 +46,36 @@ public class PipelineTemplateTable {
         return new ArrayList<String>(templateNames);
     }
 
-    public static String getTemplateDockerfileName(String templateName){
-        return TEMPLATE_DOCKERFILE_PREFIX + templateName;
+    /**
+     * 读取模板的dockerfile信息,写入指定文件
+     *
+     * @param templateName 模板名字
+     * @param dockerfile   需要写入的dockerfile文件路径
+     * @return
+     */
+    public static void copyTemplateDockerfile(String templateName, Path dockerfile) throws IOException {
+        Files.createFile(dockerfile);
+        File template = ResourceUtils.getFile("classpath:dockerfile/" + templateName);
+        FileUtils.copyDirectory(template, dockerfile.toFile());
     }
 
-
-    public static String getTemplateConfigJsonName(String templateName){
-        return TEMPLATE_DOCKERFILE_PREFIX + templateName;
+    /**
+     * 获取模板的json配置文件
+     */
+    public static String getTemplateConfigJson(String templateName) throws PipelineException {
+        File file = null;
+        String template = null;
+        try {
+            file = ResourceUtils.getFile("classpath:config/" + templateName + ".json");
+            List<String> lines = Files.readAllLines(file.toPath());
+            StringBuffer sb = new StringBuffer();
+            for (String line : lines) {
+                sb.append(line);
+            }
+            template = sb.toString();
+        } catch (IOException e) {
+            throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE, PipelineException.CONFIG_JSON_ERROR, e);
+        }
+        return template;
     }
 }

+ 30 - 0
core/src/main/resources/template/config/JAVA8.json

@@ -0,0 +1,30 @@
+[
+  {
+    "name": "image-build",
+    "configs": {
+      "repoUrl": "#todo",
+      "branchName": "#todo"
+    }
+  },
+  {
+    "name": "k8s-namespace",
+    "configs": {
+    }
+  },
+  {
+    "name": "k8s-deployment",
+    "configs": {
+      "port": "#todo"
+    }
+  },
+  {
+    "name": "k8s-service",
+    "configs": {
+    }
+  },
+  {
+    "name": "k8s-ingress",
+    "configs": {
+    }
+  }
+]

+ 0 - 9
core/src/main/resources/template/config/test.json

@@ -1,9 +0,0 @@
-{
-  "test": [
-
-    {
-      "name":
-
-    }
-  ]
-}

+ 0 - 0
core/src/main/resources/template/dockerfile/TEMPLATE_DOCKERFILE_JAVA8 → core/src/main/resources/template/dockerfile/JAVA8


+ 57 - 4
core/src/test/java/seecoder/devcloud/core/CoreApplicationTests.java

@@ -1,5 +1,8 @@
 package seecoder.devcloud.core;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.runner.RunWith;
@@ -11,11 +14,15 @@ import seecoder.devcloud.api.k8s.DeploymentApi;
 import seecoder.devcloud.api.k8s.IngressApi;
 import seecoder.devcloud.api.k8s.ServiceApi;
 import seecoder.devcloud.core.pipeline.Context;
+import seecoder.devcloud.core.pipeline.PipelineException;
+import seecoder.devcloud.core.pipeline.config.HandlerConfig;
 import seecoder.devcloud.core.pipeline.handler.K8sDeploymentHandler;
 import seecoder.devcloud.core.pipeline.handler.K8sIngressHandler;
 import seecoder.devcloud.core.pipeline.handler.K8sNamespaceHandler;
 import seecoder.devcloud.core.pipeline.handler.K8sServiceHandler;
 
+import java.util.*;
+
 @RunWith(SpringRunner.class)
 @SpringBootTest
 class CoreApplicationTests {
@@ -45,7 +52,11 @@ class CoreApplicationTests {
 
         K8sDeploymentHandler handler = new K8sDeploymentHandler();
         context.getConfigs().put("imageName","mysql:5.7");
-        handler.process(context);
+        try {
+            handler.process(context);
+        } catch (PipelineException e) {
+            e.printStackTrace();
+        }
 
     }
 
@@ -53,7 +64,11 @@ class CoreApplicationTests {
     void k8sNamespace() {
 
         K8sNamespaceHandler k8sNamespaceHandler = new K8sNamespaceHandler();
-        k8sNamespaceHandler.process(context);
+        try {
+            k8sNamespaceHandler.process(context);
+        } catch (PipelineException e) {
+            e.printStackTrace();
+        }
 
     }
 
@@ -62,16 +77,54 @@ class CoreApplicationTests {
     void k8sService() {
         context.getConfigs().put("port","8000");
         K8sServiceHandler k8sServiceHandler = new K8sServiceHandler();
-        k8sServiceHandler.process(context);
+        try {
+            k8sServiceHandler.process(context);
+        } catch (PipelineException e) {
+            e.printStackTrace();
+        }
     }
 
     @Test
     void k8sIngress() {
         context.getConfigs().put("servicePort","8000");
         K8sIngressHandler ingressHandler = new K8sIngressHandler();
-        ingressHandler.process(context);
+        try {
+            ingressHandler.process(context);
+        } catch (PipelineException e) {
+            e.printStackTrace();
+        }
     }
 
+    @Test
+    void json(){
+        ObjectMapper mapper = new ObjectMapper();
+        Map<String,String> m = new HashMap<String,String>();
+        m.put("go","go");
+        HandlerConfig handlerConfig = new HandlerConfig("jj",m);
+        String jjj = null;
+        try {
+            jjj = mapper.writeValueAsString(Collections.singletonList(handlerConfig));
+        } catch (JsonProcessingException e) {
+            e.printStackTrace();
+        }
+        String configJson ="{\n" +
+                "\t\"list\": [{\n" +
+                "\t\t\"name\": \"test\",\n" +
+                "\t\t\"configs\": {\n" +
+                "\t\t\t\"a\": \"1\",\n" +
+                "\t\t\t\"b\": \"2\"\n" +
+                "\t\t}\n" +
+                "\t}]\n" +
+                "}";
+        mapper = new ObjectMapper();
+        ArrayList<HandlerConfig> lendReco = null;
+        try {
+            lendReco = mapper.readValue(jjj,new TypeReference<ArrayList<HandlerConfig>>(){});
+        } catch (JsonProcessingException e) {
+            e.printStackTrace();
+        }
+        System.out.println();
+    }
 
     private void mockContext(){
         this.context = Context.builder()

+ 1 - 1
web/mvnw.cmd

@@ -43,7 +43,7 @@ title %0
 @REM set %HOME% to equivalent of $HOME
 if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
 
-@REM Execute a user defined script before this one
+@REM Execute a userPO defined script before this one
 if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
 @REM check for pre script, once with legacy .bat ending and once with .cmd ending
 if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"

+ 5 - 5
web/src/main/java/seecoder/devcloud/web/aspect/TreeLoggingAspect.java

@@ -10,7 +10,7 @@ import org.springframework.stereotype.Component;
 import seecoder.devcloud.web.aop.TreeLogging;
 import seecoder.devcloud.web.dao.tree.TreeLogMapper;
 import seecoder.devcloud.web.model.po.tree.TreeLog;
-import seecoder.devcloud.web.model.po.user.User;
+import seecoder.devcloud.web.model.po.user.UserPO;
 import seecoder.devcloud.web.model.vo.Response;
 import seecoder.devcloud.web.model.vo.TreeNodeVO;
 import seecoder.devcloud.web.service.user.UserService;
@@ -59,12 +59,12 @@ public class TreeLoggingAspect {
 //                    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
 //                    HttpSession session = request.getSession();
 //                    读取session中的用户
-//                    User user = (User) session.getAttribute("user");
+//                    UserPO userPO = (UserPO) session.getAttribute("userPO");
 //                    请求的IP
 //                    String ip = request.getRemoteAddr();
-                    User user = UserService.loginUser();
-                    log.setUserId(user.getId());
-                    log.setUserName(user.getUsername());
+                    UserPO userPO = UserService.loginUser();
+                    log.setUserId(userPO.getId());
+                    log.setUserName(userPO.getUsername());
                     log.setTime(sf.format(new Date()));
                     System.out.println(log);
                     treeLogMapper.insertTreeLog(log);

+ 8 - 6
web/src/main/java/seecoder/devcloud/web/controller/pipeline/PipelineController.java

@@ -7,6 +7,8 @@ import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
+import seecoder.devcloud.common.exceptions.AccessDeniedException;
+import seecoder.devcloud.common.exceptions.ServiceException;
 import seecoder.devcloud.web.model.vo.Response;
 import seecoder.devcloud.web.model.vo.pipeline.PipelineConfigVO;
 import seecoder.devcloud.web.model.vo.pipeline.PipelineCreateVO;
@@ -36,7 +38,7 @@ public class PipelineController {
     @GetMapping("/list")
     @ApiOperation(value = "获取指定项目的所有流水线基本信息", httpMethod = "GET")
     @ApiImplicitParam(name = "projectId", dataType ="int",paramType = "query")
-    public Response<List<PipelineInfoVO>> retrievePipelineInfos(@RequestParam("projectId") Integer projectId){
+    public Response<List<PipelineInfoVO>> retrievePipelineInfos(@RequestParam("projectId") Integer projectId) throws AccessDeniedException {
         return Response.buildSuccess(pipelineService.retrievePipelineInfos(projectId));
     }
 
@@ -47,7 +49,7 @@ public class PipelineController {
             @ApiImplicitParam(name = "pipelineId", dataType ="int",paramType = "query")
     })
     public Response<PipelineConfigVO> retrievePipelineConfig(@RequestParam("projectId")Integer projectId,
-                                                             @RequestParam("pipelineId")Integer pipelineId){
+                                                             @RequestParam("pipelineId")Integer pipelineId) throws AccessDeniedException {
 
         return Response.buildSuccess(pipelineService.retrievePipelineConfig(projectId, pipelineId));
     }
@@ -59,7 +61,7 @@ public class PipelineController {
             @ApiImplicitParam(name = "pipelineId", dataType ="int",paramType = "query")
     })
     public Response<List<PipelineHistoryVO>> retrievePipelineHistory(@RequestParam("projectId")Integer projectId,
-                                                                     @RequestParam("pipelineId")Integer pipelineId){
+                                                                     @RequestParam("pipelineId")Integer pipelineId) throws AccessDeniedException {
         return Response.buildSuccess(pipelineService.retrievePipelineHistory(projectId,pipelineId));
     }
 
@@ -67,7 +69,7 @@ public class PipelineController {
     @ApiOperation(value = "依据模板创建一个流水线配置", httpMethod = "POST")
     @ApiImplicitParam(name = "pipelineCreateVO", value = "流水线创建配置信息",dataType = "object",paramType = "body")
     @PostMapping
-    public Response createPipelineConfig(@RequestBody @Validated PipelineCreateVO pipelineCreateVO){
+    public Response createPipelineConfig(@RequestBody @Validated PipelineCreateVO pipelineCreateVO) throws ServiceException {
         pipelineService.createPipelineConfig(pipelineCreateVO);
         return Response.buildSuccess();
     }
@@ -81,7 +83,7 @@ public class PipelineController {
     })
     public Response savePipelineConfig(@RequestParam("projectId")Integer projectId,
                                        @RequestParam("pipelineId")Integer pipelineId,
-                                       @RequestParam("configJson")String configJson){
+                                       @RequestParam("configJson")String configJson) throws AccessDeniedException {
         //todo 验证configJson有效性
         pipelineService.savePipelineConfig(projectId,pipelineId, configJson);
         return Response.buildSuccess();
@@ -93,7 +95,7 @@ public class PipelineController {
             @ApiImplicitParam(name = "pipelineId", dataType ="int",paramType = "query"),
     })
     @DeleteMapping
-    public Response deletePipelineInfo(Integer projectId,Integer pipelineId){
+    public Response deletePipelineInfo(Integer projectId,Integer pipelineId) throws AccessDeniedException {
         pipelineService.deletePipelineConfig(projectId, pipelineId);
         return Response.buildSuccess();
     }

+ 0 - 1
web/src/main/java/seecoder/devcloud/web/controller/user/UserController.java

@@ -4,7 +4,6 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
-import seecoder.devcloud.web.model.po.user.User;
 import seecoder.devcloud.web.model.vo.Response;
 import seecoder.devcloud.web.model.vo.user.UserVO;
 import seecoder.devcloud.web.service.user.UserService;

+ 15 - 0
web/src/main/java/seecoder/devcloud/web/dao/pipeline/DeploymentMapper.java

@@ -0,0 +1,15 @@
+package seecoder.devcloud.web.dao.pipeline;
+
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/20
+ * @description:
+ */
+@Mapper
+public interface DeploymentMapper {
+
+
+
+}

+ 3 - 3
web/src/main/java/seecoder/devcloud/web/dao/pipeline/PipelineHistoryMapper.java

@@ -2,7 +2,7 @@ package seecoder.devcloud.web.dao.pipeline;
 
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Select;
-import seecoder.devcloud.web.model.po.pipeline.PipelineHistory;
+import seecoder.devcloud.web.model.po.pipeline.PipelineHistoryPO;
 
 import java.util.List;
 
@@ -15,7 +15,7 @@ import java.util.List;
 public interface PipelineHistoryMapper {
 
     @Select("select * from pipeline_history where pipeline_id = #{pipelineId}")
-    List<PipelineHistory> selectByPipelineId(Integer pipelineId);
+    List<PipelineHistoryPO> selectByPipelineId(Integer pipelineId);
 
 
     /**
@@ -29,6 +29,6 @@ public interface PipelineHistoryMapper {
             "   WHERE pipeline_id in" +
             "   <foreach collection='pipelineIds' open='(' item='pipelineId' separator=',' close=')'> #{pipelineId}</foreach>" +
             "   )")
-    List<PipelineHistory> selectRecentlyHistoryBy(List<Integer> pipelineIds);
+    List<PipelineHistoryPO> selectRecentlyHistoryBy(List<Integer> pipelineIds);
 
 }

+ 4 - 5
web/src/main/java/seecoder/devcloud/web/dao/pipeline/PipelineMapper.java

@@ -2,8 +2,7 @@ package seecoder.devcloud.web.dao.pipeline;
 
 import org.apache.ibatis.annotations.*;
 import seecoder.devcloud.web.dao.provider.GeneralInsertUpdateSqlProvider;
-import seecoder.devcloud.web.model.po.pipeline.Pipeline;
-import seecoder.devcloud.web.model.po.user.Group;
+import seecoder.devcloud.web.model.po.pipeline.PipelinePO;
 
 import java.util.List;
 
@@ -17,13 +16,13 @@ public interface PipelineMapper {
 
     @InsertProvider(type = GeneralInsertUpdateSqlProvider.class, method = "insert")
     @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
-    boolean insert(Pipeline pipeline, String... ignoredCols);
+    boolean insert(PipelinePO pipelinePO, String... ignoredCols);
 
     @Select("select * from pipeline where id = #{id}")
-    Pipeline selectById(Integer id);
+    PipelinePO selectById(Integer id);
 
     @Select("select * from pipeline where project_id = #{id}")
-    List<Pipeline> selectByProjectId(Integer id);
+    List<PipelinePO> selectByProjectId(Integer id);
 
     /**
      * 不级联删除历史构建信息以留档

+ 2 - 2
web/src/main/java/seecoder/devcloud/web/dao/user/GroupMemberMapper.java

@@ -2,7 +2,7 @@ package seecoder.devcloud.web.dao.user;
 
 import org.apache.ibatis.annotations.*;
 import seecoder.devcloud.web.model.po.user.Group;
-import seecoder.devcloud.web.model.po.user.User;
+import seecoder.devcloud.web.model.po.user.UserPO;
 
 import java.util.List;
 
@@ -27,7 +27,7 @@ public interface GroupMemberMapper {
     List<Integer> selectGroupIdsByUserId(int groupId);
 
     @Select("select u.* from group_member gm, user u where u.id = gm.user_id and gm.group_id = #{groupId}")
-    List<User> selectUsersByGroupId(int groupId);
+    List<UserPO> selectUsersByGroupId(int groupId);
 
     @Select("select g.* from group_member gm, group g where g.id = gm.group_id and gm.userId = #{userId}")
     List<Group> selectGroupsByUserId(int userId);

+ 2 - 3
web/src/main/java/seecoder/devcloud/web/infrastructure/security/JwtAuthenticationTokenFilter.java

@@ -1,7 +1,6 @@
 package seecoder.devcloud.web.infrastructure.security;
 
 import io.jsonwebtoken.Claims;
-import net.minidev.json.JSONObject;
 import org.apache.commons.lang.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
@@ -14,7 +13,7 @@ import org.springframework.stereotype.Component;
 import org.springframework.web.filter.OncePerRequestFilter;
 import seecoder.devcloud.common.util.JwtTokenUtil;
 import seecoder.devcloud.web.model.enums.UserIdentity;
-import seecoder.devcloud.web.model.po.user.User;
+import seecoder.devcloud.web.model.po.user.UserPO;
 import seecoder.devcloud.web.model.vo.Response;
 
 import javax.servlet.FilterChain;
@@ -53,7 +52,7 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
             Claims claims = jwtTokenUtil.getClaimsFromToken(authHeader);
             if (claims != null){
                 LinkedHashMap<String,Object> userInfo = claims.get("user_info", LinkedHashMap.class);
-                UserDetails userDetails = User.builder()
+                UserDetails userDetails = UserPO.builder()
                         .id((Integer) userInfo.get("id"))
                         .username((String) userInfo.get("name"))
                         .email((String) userInfo.get("email"))

+ 1 - 1
web/src/main/java/seecoder/devcloud/web/model/po/pipeline/Deployment.java → web/src/main/java/seecoder/devcloud/web/model/po/pipeline/DeploymentPO.java

@@ -7,7 +7,7 @@ import java.sql.Timestamp;
  * @date 2021/3/11
  * @description: 已部署的软件实例
  */
-public class Deployment {
+public class DeploymentPO {
 
     Integer id;
 

+ 1 - 1
web/src/main/java/seecoder/devcloud/web/model/po/pipeline/PipelineHistory.java → web/src/main/java/seecoder/devcloud/web/model/po/pipeline/PipelineHistoryPO.java

@@ -10,7 +10,7 @@ import java.sql.Timestamp;
  * @description:
  */
 @Data
-public class PipelineHistory {
+public class PipelineHistoryPO {
 
     /**
      * pipeline id

+ 1 - 6
web/src/main/java/seecoder/devcloud/web/model/po/pipeline/Pipeline.java → web/src/main/java/seecoder/devcloud/web/model/po/pipeline/PipelinePO.java

@@ -10,15 +10,10 @@ import lombok.Data;
  */
 @Data
 @Builder
-public class Pipeline {
-
-
+public class PipelinePO {
 
     Integer id;
 
-    /**
-     * 所属的项目id todo sql外键
-     */
     Integer projectId;
 
     String name;

+ 30 - 30
web/src/main/java/seecoder/devcloud/web/model/po/user/Group.java

@@ -1,30 +1,30 @@
-package seecoder.devcloud.web.model.po.user;
-
-
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * Description:
- * 小组的实体类
- *
- * @author xxz
- * Created on 10/26/2018
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class Group {
-
-    /**
-     * id并非由此后端生成,而是gitlab创建后,将gitlab group id填入
-     */
-    private Integer id;
-
-    private String name;
-
-
-}
+//package seecoder.devcloud.web.model.po.user;
+//
+//
+//import lombok.AllArgsConstructor;
+//import lombok.Builder;
+//import lombok.Data;
+//import lombok.NoArgsConstructor;
+//
+///**
+// * Description:
+// * 小组的实体类
+// *
+// * @author xxz
+// * Created on 10/26/2018
+// */
+//@Data
+//@Builder
+//@NoArgsConstructor
+//@AllArgsConstructor
+//public class Group {
+//
+//    /**
+//     * id并非由此后端生成,而是gitlab创建后,将gitlab group id填入
+//     */
+//    private Integer id;
+//
+//    private String name;
+//
+//
+//}

+ 2 - 3
web/src/main/java/seecoder/devcloud/web/model/po/user/User.java → web/src/main/java/seecoder/devcloud/web/model/po/user/UserPO.java

@@ -5,17 +5,16 @@ import lombok.Builder;
 import lombok.Data;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.userdetails.UserDetails;
-import seecoder.devcloud.web.model.enums.UserIdentity;
 import seecoder.devcloud.web.infrastructure.security.WebSecurityConstants;
+import seecoder.devcloud.web.model.enums.UserIdentity;
 
-import java.sql.Timestamp;
 import java.util.Collection;
 import java.util.Collections;
 
 
 @Data
 @Builder
-public class User implements UserDetails {
+public class UserPO implements UserDetails {
 
 	/**
 	 * 注意用户id并非由此后端数据库生成,而是gitlab创建后填入,以确保两者的关联性的正确

+ 3 - 3
web/src/main/java/seecoder/devcloud/web/model/vo/pipeline/PipelineConfigVO.java

@@ -4,7 +4,7 @@ import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import org.springframework.beans.BeanUtils;
-import seecoder.devcloud.web.model.po.pipeline.Pipeline;
+import seecoder.devcloud.web.model.po.pipeline.PipelinePO;
 
 /**
  * @author PuHong Weng
@@ -22,7 +22,7 @@ public class PipelineConfigVO {
     String configJson;
 
 
-    public PipelineConfigVO(Pipeline pipeline){
-        BeanUtils.copyProperties(pipeline,this);
+    public PipelineConfigVO(PipelinePO pipelinePO){
+        BeanUtils.copyProperties(pipelinePO,this);
     }
 }

+ 2 - 2
web/src/main/java/seecoder/devcloud/web/model/vo/pipeline/PipelineHistoryVO.java

@@ -5,7 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import org.springframework.beans.BeanUtils;
-import seecoder.devcloud.web.model.po.pipeline.PipelineHistory;
+import seecoder.devcloud.web.model.po.pipeline.PipelineHistoryPO;
 
 import java.sql.Timestamp;
 
@@ -39,7 +39,7 @@ public class PipelineHistoryVO {
     String details;
 
 
-    public PipelineHistoryVO(PipelineHistory history){
+    public PipelineHistoryVO(PipelineHistoryPO history){
         BeanUtils.copyProperties(history,this);
     }
 }

+ 9 - 10
web/src/main/java/seecoder/devcloud/web/model/vo/pipeline/PipelineInfoVO.java

@@ -5,9 +5,8 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
-import lombok.NoArgsConstructor;
-import seecoder.devcloud.web.model.po.pipeline.Pipeline;
-import seecoder.devcloud.web.model.po.pipeline.PipelineHistory;
+import seecoder.devcloud.web.model.po.pipeline.PipelinePO;
+import seecoder.devcloud.web.model.po.pipeline.PipelineHistoryPO;
 
 import java.sql.Timestamp;
 
@@ -40,13 +39,13 @@ public class PipelineInfoVO {
     @ApiModelProperty("最后一次发起流水线构建的执行结果详情")
     String details;
 
-    public PipelineInfoVO(Pipeline pipeline, PipelineHistory pipelineHistory){
-        startTime = pipelineHistory.getStartTime();
-        username = pipelineHistory.getUsername();
-        result = pipelineHistory.getResult();
-        details = pipelineHistory.getDetails();
-        name = pipeline.getName();
-        id =pipeline.getId();
+    public PipelineInfoVO(PipelinePO pipelinePO, PipelineHistoryPO pipelineHistoryPO){
+        startTime = pipelineHistoryPO.getStartTime();
+        username = pipelineHistoryPO.getUsername();
+        result = pipelineHistoryPO.getResult();
+        details = pipelineHistoryPO.getDetails();
+        name = pipelinePO.getName();
+        id = pipelinePO.getId();
     }
 
 }

+ 3 - 6
web/src/main/java/seecoder/devcloud/web/model/vo/user/UserVO.java

@@ -1,6 +1,5 @@
 package seecoder.devcloud.web.model.vo.user;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
@@ -8,9 +7,7 @@ import lombok.Data;
 import lombok.NoArgsConstructor;
 import org.springframework.beans.BeanUtils;
 import seecoder.devcloud.web.model.enums.UserIdentity;
-import seecoder.devcloud.web.model.po.user.User;
-
-import java.sql.Timestamp;
+import seecoder.devcloud.web.model.po.user.UserPO;
 
 @Data
 @NoArgsConstructor
@@ -28,7 +25,7 @@ public class UserVO {
     @ApiModelProperty("角色")
     private UserIdentity role;
 
-    public UserVO(User user) {
-        BeanUtils.copyProperties(user,this);
+    public UserVO(UserPO userPO) {
+        BeanUtils.copyProperties(userPO,this);
     }
 }

+ 35 - 26
web/src/main/java/seecoder/devcloud/web/service/impl/pipeline/PipelineServiceImpl.java

@@ -2,14 +2,17 @@ package seecoder.devcloud.web.service.impl.pipeline;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import seecoder.devcloud.common.exceptions.AccessDeniedException;
+import seecoder.devcloud.common.exceptions.ServiceException;
+import seecoder.devcloud.core.pipeline.PipelineException;
 import seecoder.devcloud.core.pipeline.template.PipelineTemplateTable;
 import seecoder.devcloud.web.dao.pipeline.PipelineHistoryMapper;
 import seecoder.devcloud.web.dao.pipeline.PipelineMapper;
 import seecoder.devcloud.web.dao.project.ProjectMapper;
-import seecoder.devcloud.web.model.po.pipeline.Pipeline;
-import seecoder.devcloud.web.model.po.pipeline.PipelineHistory;
+import seecoder.devcloud.web.model.po.pipeline.PipelinePO;
+import seecoder.devcloud.web.model.po.pipeline.PipelineHistoryPO;
 import seecoder.devcloud.web.model.po.project.Project;
-import seecoder.devcloud.web.model.po.user.User;
+import seecoder.devcloud.web.model.po.user.UserPO;
 import seecoder.devcloud.web.model.vo.pipeline.PipelineConfigVO;
 import seecoder.devcloud.web.model.vo.pipeline.PipelineCreateVO;
 import seecoder.devcloud.web.model.vo.pipeline.PipelineHistoryVO;
@@ -45,52 +48,58 @@ public class PipelineServiceImpl implements PipelineService {
 
 
     @Override
-    public List<PipelineInfoVO> retrievePipelineInfos(Integer projectId) {
+    public List<PipelineInfoVO> retrievePipelineInfos(Integer projectId) throws AccessDeniedException {
         projectAuthentication(projectId);
-        List<Pipeline> pipelines = pipelineMapper.selectByProjectId(projectId);
-        List<Integer> pipelineIds = pipelines.stream().map(Pipeline::getId).collect(Collectors.toList());
-        List<PipelineHistory> histories = pipelineHistoryMapper.selectRecentlyHistoryBy(pipelineIds);
-        Map<Integer,PipelineHistory> historyMap = histories.stream().collect(Collectors.toMap(PipelineHistory::getPipelineId, x->x));
-        return pipelines.stream().map(x->new PipelineInfoVO(x,historyMap.get(x.getId()))).collect(Collectors.toList());
+        List<PipelinePO> pipelinePOS = pipelineMapper.selectByProjectId(projectId);
+        List<Integer> pipelineIds = pipelinePOS.stream().map(PipelinePO::getId).collect(Collectors.toList());
+        List<PipelineHistoryPO> histories = pipelineHistoryMapper.selectRecentlyHistoryBy(pipelineIds);
+        Map<Integer, PipelineHistoryPO> historyMap = histories.stream().collect(Collectors.toMap(PipelineHistoryPO::getPipelineId, x->x));
+        return pipelinePOS.stream().map(x->new PipelineInfoVO(x,historyMap.get(x.getId()))).collect(Collectors.toList());
     }
 
     @Override
-    public PipelineConfigVO retrievePipelineConfig(Integer projectId, Integer pipelineId) {
+    public PipelineConfigVO retrievePipelineConfig(Integer projectId, Integer pipelineId) throws AccessDeniedException {
         projectAuthentication(projectId);
         return new PipelineConfigVO(pipelineMapper.selectById(pipelineId));
     }
 
     @Override
-    public List<PipelineHistoryVO> retrievePipelineHistory(Integer projectId, Integer pipelineId) {
+    public List<PipelineHistoryVO> retrievePipelineHistory(Integer projectId, Integer pipelineId) throws AccessDeniedException {
         projectAuthentication(projectId);
-        List<PipelineHistory> histories = pipelineHistoryMapper.selectByPipelineId(pipelineId);
+        List<PipelineHistoryPO> histories = pipelineHistoryMapper.selectByPipelineId(pipelineId);
         return histories.stream().map(PipelineHistoryVO::new).collect(Collectors.toList());
     }
 
     @Override
-    public void createPipelineConfig(PipelineCreateVO pipelineCreateVO) {
+    public void createPipelineConfig(PipelineCreateVO pipelineCreateVO) throws ServiceException {
         projectAuthentication(pipelineCreateVO.getProjectId());
-        Pipeline pipeline = Pipeline.builder()
-                .name(pipelineCreateVO.getName())
-                .projectId(pipelineCreateVO.getProjectId())
-                .configJson("") //todo 提供模板
-                .build();
+        PipelinePO pipeline = null;
+        try {
+            pipeline = PipelinePO.builder()
+                    .name(pipelineCreateVO.getName())
+                    .projectId(pipelineCreateVO.getProjectId())
+                    .configJson(PipelineTemplateTable.getTemplateConfigJson(pipelineCreateVO.getTemplateName()))
+                    .build();
+        } catch (PipelineException pipelineException) {
+            throw new ServiceException("创建流水线失败",pipelineException);
+        }
         pipelineMapper.insert(pipeline);
 
 
     }
 
     @Override
-    public void savePipelineConfig(Integer projectId, Integer pipelineId, String configJson) {
+    public void savePipelineConfig(Integer projectId, Integer pipelineId, String configJson) throws AccessDeniedException {
         projectAuthentication(projectId);
         pipelineMapper.updateConfigJson(pipelineId,configJson);
 
     }
 
     @Override
-    public void deletePipelineConfig(Integer projectId, Integer pipelineId) {
+    public void deletePipelineConfig(Integer projectId, Integer pipelineId) throws AccessDeniedException {
         projectAuthentication(projectId);
         pipelineMapper.delete(pipelineId);
+        //todo 部署要不要删
     }
 
     @Override
@@ -102,12 +111,12 @@ public class PipelineServiceImpl implements PipelineService {
      * 判断用户是否有权限修改这些流水线配置,
      * 防止用户修改提交的参数从而修改其他组的流水线
      */
-    private void projectAuthentication(Integer projectId){
-        User user = UserService.loginUser();
-        List<Project> projects = projectMapper.listProjectsByUserId(user.getId());
-
-        //todo 鉴权
-
+    private void projectAuthentication(Integer projectId) throws AccessDeniedException {
+        UserPO userPO = UserService.loginUser();
+        List<Project> projects = projectMapper.listProjectsByUserId(userPO.getId());
+        if (projects.stream().noneMatch(project -> project.getId()==projectId)){
+            throw new AccessDeniedException("您没有操作此项目的权限");
+        }
     }
 
 

+ 110 - 110
web/src/main/java/seecoder/devcloud/web/service/impl/user/GroupServiceImpl.java

@@ -1,112 +1,112 @@
-package seecoder.devcloud.web.service.impl.user;
-
-
-import com.nju.edu.gitlab.SeecoderGitlabApi;
-import com.nju.edu.gitlab.SeecoderGitlabException;
-import com.nju.edu.gitlab.dto.member.AccessLevelForm;
-import com.nju.edu.gitlab.vo.GitlabGroup;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import seecoder.devcloud.common.exceptions.AccessDeniedException;
-import seecoder.devcloud.common.exceptions.ConflictException;
-import seecoder.devcloud.common.exceptions.ServiceException;
-import seecoder.devcloud.web.dao.user.GroupMapper;
-import seecoder.devcloud.web.dao.user.GroupMemberMapper;
-import seecoder.devcloud.web.model.po.user.Group;
-import seecoder.devcloud.web.model.po.user.User;
-import seecoder.devcloud.web.model.vo.user.GroupVO;
-import seecoder.devcloud.web.service.user.GroupService;
-import seecoder.devcloud.web.service.user.UserService;
-
-import java.util.List;
-
-
-@Service
-@Slf4j
-public class GroupServiceImpl implements GroupService {
-    private final GroupMapper groupMapper;
-    private final GroupMemberMapper groupMemberMapper;
-
-    private final SeecoderGitlabApi seecoderGitlabApi;
-
-    private final String GROUP_NAME_PREFIX = "DEVCLOUD_";
-
-    @Autowired
-    public GroupServiceImpl(GroupMapper groupMapper, GroupMemberMapper groupMemberMapper, SeecoderGitlabApi seecoderGitlabApi) {
-        this.groupMapper = groupMapper;
-        this.groupMemberMapper = groupMemberMapper;
-        this.seecoderGitlabApi = seecoderGitlabApi;
-    }
-
-    @Override
-    public GroupVO getGroup(Integer groupId) {
-        return new GroupVO(groupMapper.findGroupById(groupId));
-    }
-
-    @Override
-    public List<Integer> getGroupMemberIds(Integer groupId) {
-        return groupMemberMapper.selectUserIdsByGroupId(groupId);
-    }
-
-    @Override
-    @Transactional
-    public GroupVO createGroup(String name) throws ServiceException {
-        if (groupMapper.findGroupByName(name) != null){
-            throw new ConflictException("您创建的小组名字已被使用!");
-        }
-        User user = UserService.loginUser();
-        GitlabGroup gitlabGroup = null;
-        try {
-            gitlabGroup = seecoderGitlabApi.createGroup(GROUP_NAME_PREFIX + name);
-            seecoderGitlabApi.addMember(gitlabGroup.getGroupId(), user.getId(), AccessLevelForm.MASTER);
-        } catch (SeecoderGitlabException e) {
-            throw new ServiceException("创建Group时发生异常[" + e.getMessage() + "]",e);
-        }
-        Group group = Group.builder()
-                .id(gitlabGroup.getGroupId())
-                .name(name)
-                .build();
-        groupMapper.insert(group);
-        groupMemberMapper.insert(gitlabGroup.getGroupId(), user.getId());
-        return new GroupVO(group);
-    }
-
-
-    @Override
-    @Transactional
-    public void addMember(Integer invitedUserId, Integer groupId) throws ServiceException {
-        //当前登陆的用户id
-        int userId = UserService.loginUser().getId();
-
-        //只有在组内的用户才能邀请
-        List<Integer> userIds = groupMemberMapper.selectUserIdsByGroupId(groupId);
-        if (!userIds.contains(userId)) {
-            throw new AccessDeniedException("小组邀请发生错误,用户没有权限");
-        }
-        if (userIds.contains(invitedUserId)) {
-            throw new ConflictException("邀请的用户已经加入小组!");
-        }
-        try {
-            seecoderGitlabApi.addMember(groupId, invitedUserId, AccessLevelForm.MASTER);
-        } catch (SeecoderGitlabException e) {
-            throw new ServiceException("将成员加入Group时发生异常[" + e.getMessage() + "]", e);
-        }
-        groupMemberMapper.insert(groupId, invitedUserId);
-        //Group group = groupMapper.findWithMembersById(groupId);
-    }
-
-    @Override
-    public void quitGroup(Integer groupId, Integer userId) throws ServiceException {
-
+//package seecoder.devcloud.web.service.impl.user;
+//
+//
+//import com.nju.edu.gitlab.SeecoderGitlabApi;
+//import com.nju.edu.gitlab.SeecoderGitlabException;
+//import com.nju.edu.gitlab.dto.member.AccessLevelForm;
+//import com.nju.edu.gitlab.vo.GitlabGroup;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.stereotype.Service;
+//import org.springframework.transaction.annotation.Transactional;
+//import seecoder.devcloud.common.exceptions.AccessDeniedException;
+//import seecoder.devcloud.common.exceptions.ConflictException;
+//import seecoder.devcloud.common.exceptions.ServiceException;
+//import seecoder.devcloud.web.dao.user.GroupMapper;
+//import seecoder.devcloud.web.dao.user.GroupMemberMapper;
+//import seecoder.devcloud.web.model.po.user.Group;
+//import seecoder.devcloud.web.model.po.user.UserPO;
+//import seecoder.devcloud.web.model.vo.user.GroupVO;
+//import seecoder.devcloud.web.service.user.GroupService;
+//import seecoder.devcloud.web.service.user.UserService;
+//
+//import java.util.List;
+//
+//
+//@Service
+//@Slf4j
+//public class GroupServiceImpl implements GroupService {
+//    private final GroupMapper groupMapper;
+//    private final GroupMemberMapper groupMemberMapper;
+//
+//    private final SeecoderGitlabApi seecoderGitlabApi;
+//
+//    private final String GROUP_NAME_PREFIX = "DEVCLOUD_";
+//
+//    @Autowired
+//    public GroupServiceImpl(GroupMapper groupMapper, GroupMemberMapper groupMemberMapper, SeecoderGitlabApi seecoderGitlabApi) {
+//        this.groupMapper = groupMapper;
+//        this.groupMemberMapper = groupMemberMapper;
+//        this.seecoderGitlabApi = seecoderGitlabApi;
+//    }
+//
+//    @Override
+//    public GroupVO getGroup(Integer groupId) {
+//        return new GroupVO(groupMapper.findGroupById(groupId));
+//    }
+//
+//    @Override
+//    public List<Integer> getGroupMemberIds(Integer groupId) {
+//        return groupMemberMapper.selectUserIdsByGroupId(groupId);
+//    }
+//
+//    @Override
+//    @Transactional
+//    public GroupVO createGroup(String name) throws ServiceException {
+//        if (groupMapper.findGroupByName(name) != null){
+//            throw new ConflictException("您创建的小组名字已被使用!");
+//        }
+//        UserPO user = UserService.loginUser();
+//        GitlabGroup gitlabGroup = null;
+//        try {
+//            gitlabGroup = seecoderGitlabApi.createGroup(GROUP_NAME_PREFIX + name);
+//            seecoderGitlabApi.addMember(gitlabGroup.getGroupId(), user.getId(), AccessLevelForm.MASTER);
+//        } catch (SeecoderGitlabException e) {
+//            throw new ServiceException("创建Group时发生异常[" + e.getMessage() + "]",e);
+//        }
+//        Group group = Group.builder()
+//                .id(gitlabGroup.getGroupId())
+//                .name(name)
+//                .build();
+//        groupMapper.insert(group);
+//        groupMemberMapper.insert(gitlabGroup.getGroupId(), user.getId());
+//        return new GroupVO(group);
+//    }
+//
+//
+//    @Override
+//    @Transactional
+//    public void addMember(Integer invitedUserId, Integer groupId) throws ServiceException {
+//        //当前登陆的用户id
+//        int userId = UserService.loginUser().getId();
+//
+//        //只有在组内的用户才能邀请
+//        List<Integer> userIds = groupMemberMapper.selectUserIdsByGroupId(groupId);
+//        if (!userIds.contains(userId)) {
+//            throw new AccessDeniedException("小组邀请发生错误,用户没有权限");
+//        }
+//        if (userIds.contains(invitedUserId)) {
+//            throw new ConflictException("邀请的用户已经加入小组!");
+//        }
 //        try {
-//            gitlabApi.quitGroup(groupId,userId);
-//        } catch (GitLabApiException e) {
-//            log.error(e.getMessage(), e);
-//            throw new ServiceException(e.getMessage());
+//            seecoderGitlabApi.addMember(groupId, invitedUserId, AccessLevelForm.MASTER);
+//        } catch (SeecoderGitlabException e) {
+//            throw new ServiceException("将成员加入Group时发生异常[" + e.getMessage() + "]", e);
 //        }
-//        groupMemberMapper.delete(groupId,userId);
-    }
-}
-
+//        groupMemberMapper.insert(groupId, invitedUserId);
+//        //Group group = groupMapper.findWithMembersById(groupId);
+//    }
+//
+//    @Override
+//    public void quitGroup(Integer groupId, Integer userId) throws ServiceException {
+//
+////        try {
+////            gitlabApi.quitGroup(groupId,userId);
+////        } catch (GitLabApiException e) {
+////            log.error(e.getMessage(), e);
+////            throw new ServiceException(e.getMessage());
+////        }
+////        groupMemberMapper.delete(groupId,userId);
+//    }
+//}
+//

+ 2 - 2
web/src/main/java/seecoder/devcloud/web/service/impl/user/UserServiceImpl.java

@@ -8,7 +8,7 @@ import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
 import org.springframework.stereotype.Service;
 
-import seecoder.devcloud.web.model.po.user.User;
+import seecoder.devcloud.web.model.po.user.UserPO;
 import seecoder.devcloud.web.model.vo.user.UserVO;
 import seecoder.devcloud.web.service.user.UserService;
 
@@ -18,7 +18,7 @@ public class UserServiceImpl implements UserService, UserDetailsService {
 
 	@Override
 	public UserVO getLoginUser(){
-		User loginUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+		UserPO loginUser = (UserPO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
 		return new UserVO(loginUser);
 	}
 

+ 3 - 3
web/src/main/java/seecoder/devcloud/web/service/user/UserService.java

@@ -2,7 +2,7 @@ package seecoder.devcloud.web.service.user;
 
 
 import org.springframework.security.core.context.SecurityContextHolder;
-import seecoder.devcloud.web.model.po.user.User;
+import seecoder.devcloud.web.model.po.user.UserPO;
 import seecoder.devcloud.web.model.vo.user.UserVO;
 
 public interface UserService {
@@ -12,7 +12,7 @@ public interface UserService {
     /**
      * 用于内部获取登陆用户PO
      */
-    static User loginUser(){
-        return (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+    static UserPO loginUser(){
+        return (UserPO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
     }
 }

+ 6 - 12
web/src/main/resources/devcloud-k8s-init

@@ -1,19 +1,14 @@
-# 这是我本地测试环境时用的配置,seecoder线上环境使用paas部署,无需配置k8s环境
-
+# 这是我本地测试环境minikube用的配置,seecoder线上环境使用paas部署,无需配置k8s环境
 apiVersion: v1
 kind: Namespace
 metadata:
   name: devcloud
 ---
-# todo 私有仓库secret创建
----
 apiVersion: v1
 kind: ServiceAccount
 metadata:
   name: admin
   namespace: devcloud
-imagePullSecrets:
-  - name: # todo 私有仓库secret名字
 ---
 # 用来帮助学生部署项目的权限角色
 apiVersion: rbac.authorization.k8s.io/v1
@@ -21,10 +16,10 @@ kind: ClusterRole
 metadata:
   name: devcloud-cr
 rules:
-  - apiGroups: [""]
-    resources: ["pods","secrets","deployments","ingresses","services","namespaces"]
-    verbs: ["create","update","patch","get", "watch", "list","delete"]
-  # todo 学生镜像 imagepullsecret
+  - apiGroups: ["","apps", "autoscaling", "batch", "extensions"]
+    # 在 HTTP 层面,用来访问 Secret 对象的资源的名称为 "secrets"
+    resources: ["ingresses", "services", "endpoints", "pods","secrets","configmaps","crontabs","deployments","jobs","nodes","rolebindings","clusterroles","daemonsets","replicasets","statefulsets","horizontalpodautoscalers","replicationcontrollers","cronjobs"]
+    verbs: ["get", "list", "watch", "create", "update", "patch", "delete", "exec"]
 ---
 # 权限角色绑定在devcloud下默认的service account ”default“ 下
 apiVersion: rbac.authorization.k8s.io/v1
@@ -34,9 +29,8 @@ metadata:
   name: devcloud-crb
 subjects:
   - kind: ServiceAccount
-    name: admin
+    name: default # Name is case sensitive
     namespace: devcloud
-    apiGroup: ""
 roleRef:
   kind: ClusterRole
   name: devcloud-cr

+ 4 - 1
web/src/main/resources/SQLScripts/deployment.sql → web/src/main/resources/sql/deployment.sql

@@ -4,6 +4,9 @@ create table if not exists devcloud.deployment
         primary key,
     name          varchar(23)                         not null,
     deployed_time timestamp default CURRENT_TIMESTAMP not null,
-    access_url    varchar(127)                        not null
+    access_url    varchar(127)                        not null,
+    pipeline_id   int                                 null,
+    constraint deployment_pipeline_id_fk
+        foreign key (pipeline_id) references devcloud.pipelinePO (id)
 );
 

+ 12 - 0
web/src/main/resources/sql/pipeline.sql

@@ -0,0 +1,12 @@
+-- auto-generated definition
+create table if not exists devcloud.pipelinePO
+(
+    id          int         not null
+        primary key,
+    project_id  int         null,
+    name        varchar(47) null,
+    config_json text        null,
+    constraint pipeline_project_id_fk
+        foreign key (project_id) references project (id)
+);
+

+ 13 - 0
web/src/main/resources/sql/pipeline_history.sql

@@ -0,0 +1,13 @@
+create table if not exists devcloud.pipeline_history
+(
+    id          int                                 not null
+        primary key,
+    pipeline_id int                                 null,
+    start_time  timestamp default CURRENT_TIMESTAMP not null,
+    user_id     int                                 null,
+    result      varchar(15)                         null,
+    details     text                                null,
+    constraint pipeline_history_pipeline_id_fk
+        foreign key (pipeline_id) references devcloud.pipelinePO (id)
+);
+

+ 3 - 4
web/src/main/resources/SQLScripts/project.sql → web/src/main/resources/sql/project.sql

@@ -13,7 +13,7 @@
 
  Date: 10/03/2021 23:54:40
 */
-
+use devcloud;
 SET NAMES utf8mb4;
 SET FOREIGN_KEY_CHECKS = 0;
 
@@ -26,14 +26,13 @@ CREATE TABLE `project`  (
   `name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
   `description` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
   `git_remote_url` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
-  `group_id` int(11) NOT NULL,
   PRIMARY KEY (`id`) USING BTREE
 ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
 
 -- ----------------------------
 -- Records of project
 -- ----------------------------
-INSERT INTO `project` VALUES (1, '前端', 'DevCloud前端', 'http://gogs.seecoder.cn/HuangKaiSheng/seecoder-devcloud-frontend/src/master', 1);
-INSERT INTO `project` VALUES (2, '后端开发', '后端测试测试测试测试测试', 'http://gogs.seecoder.cn/WengPuHong/seecoder-devcloud', 1);
+INSERT INTO `project` VALUES (1, '前端', 'DevCloud前端', 'http://gogs.seecoder.cn/HuangKaiSheng/seecoder-devcloud-frontend/src/master');
+INSERT INTO `project` VALUES (2, '后端开发', '后端测试测试测试测试测试', 'http://gogs.seecoder.cn/WengPuHong/seecoder-devcloud');
 
 SET FOREIGN_KEY_CHECKS = 1;

+ 12 - 0
web/src/main/resources/sql/project_user.sql

@@ -0,0 +1,12 @@
+create table if not exists devcloud.project_user
+(
+    projectId int null,
+    userId    int null,
+    constraint project_user_project_id_fk
+        foreign key (projectId) references devcloud.project (id)
+            on delete cascade
+);
+
+create index project_user_userId_index
+    on devcloud.project_user (user_id);
+

+ 0 - 0
web/src/main/resources/SQLScripts/tree_log.sql → web/src/main/resources/sql/tree_log.sql


+ 0 - 0
web/src/main/resources/SQLScripts/trees.sql → web/src/main/resources/sql/trees.sql