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

feat: project与gitlab交互的接口mock 模板解析方式扩展

370774330@qq.com преди 5 години
родител
ревизия
5c23da3f9a

+ 2 - 2
core/src/main/java/seecoder/devcloud/core/pipeline/Handler.java

@@ -1,7 +1,5 @@
 package seecoder.devcloud.core.pipeline;
 
-import seecoder.devcloud.core.pipeline.handler.AbstractHandler;
-
 /**
  * @author PuHong Weng
  * @date 2021/1/18
@@ -16,4 +14,6 @@ public interface Handler {
     void invokeNext(Context context) throws PipelineException;
 
     void setNextHandler(Handler nextHandler);
+
+    Handler getNextHandler();
 }

+ 25 - 35
core/src/main/java/seecoder/devcloud/core/pipeline/PipelineFactory.java

@@ -1,16 +1,15 @@
 package seecoder.devcloud.core.pipeline;
 
-import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.apache.http.HttpStatus;
-import seecoder.devcloud.core.pipeline.config.HandlerConfig;
 import seecoder.devcloud.core.pipeline.config.HandlerConfigTable;
+import seecoder.devcloud.core.pipeline.handler.AbstractHandler;
 import seecoder.devcloud.core.pipeline.pipeline.PipelineImpl;
 
-import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 
 /**
  * @author PuHong Weng
@@ -28,15 +27,6 @@ public class PipelineFactory {
      * @return
      */
     public static Pipeline init(String configJson, String namespace, String deployName, Integer pipelineId, String templateName) throws PipelineException {
-
-        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()
                 .deployName(deployName)
@@ -44,36 +34,36 @@ public class PipelineFactory {
                 .pipelineId(pipelineId)
                 .templateName(templateName)
                 .build();
-
-        Handler firstHandler = initHandlerChainAndContext(handlerConfigs,context.getConfigs());
-
+        Handler firstHandler = initHandlerChainAndContext(configJson);
         return new PipelineImpl(firstHandler, context);
     }
 
     /**
      * 根据 handlerConfig 构筑 Handler 的流水线,以及将配置属性统一放入 Context
-     * @param handlerConfigs 流水线配置
-     * @param configs 将每一个handler config配置的configs中的值加入context中的configs中
-     *                (所以这一步要避免配置的覆盖,即不要用相同名字的key)
-     * @return
      */
-    private static Handler initHandlerChainAndContext(List<HandlerConfig> handlerConfigs, Map<String,String> configs) throws PipelineException {
-        Handler firstHandler = null;
-        Handler currentHandler = null;
+    private static Handler initHandlerChainAndContext(String configJson) throws PipelineException {
+        //写法方便做个头结点,没有任何用
+        AbstractHandler head = new AbstractHandler() {
+            @Override
+            public void process(Context context) throws PipelineException {
 
-        HandlerConfig firstHandlerConfig = handlerConfigs.get(0);
-        configs.putAll(firstHandlerConfig.getConfigs());
-        firstHandler = HandlerConfigTable.transToHandler(firstHandlerConfig);
-        currentHandler = firstHandler;
+            }
+        };
+        Handler cur = head;
 
-        for (int i = 1; i < handlerConfigs.size(); i++){
-            HandlerConfig nextHandlerConfig = handlerConfigs.get(i);
-            configs.putAll(nextHandlerConfig.getConfigs());
-            Handler nextHandler = HandlerConfigTable.transToHandler(nextHandlerConfig);
-            currentHandler.setNextHandler(nextHandler);
-            currentHandler = nextHandler;
+        ObjectMapper mapper = new ObjectMapper();
+        List<ObjectNode> handlers;
+        try {
+            handlers = mapper.readValue(configJson, new TypeReference<List<ObjectNode>>() {});
+            for (ObjectNode node : handlers){
+                String name = node.get("name").toString().replaceAll("\"","");
+                JsonNode configs = node.get("configs");
+                cur.setNextHandler(HandlerConfigTable.transToHandler(name,configs));
+                cur = cur.getNextHandler();
+            }
+        } catch (Exception e) {
+            throw new PipelineException(HttpStatus.SC_BAD_REQUEST,PipelineException.CONFIG_TRANSFER_ERROR,e);
         }
-
-        return firstHandler;
+        return head.getNextHandler();
     }
 }

+ 0 - 35
core/src/main/java/seecoder/devcloud/core/pipeline/config/HandlerConfig.java

@@ -1,35 +0,0 @@
-package seecoder.devcloud.core.pipeline.config;
-
-/**
- * @author PuHong Weng
- * @date 2021/3/10
- * @description:
- */
-
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-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;
-
-    /**
-     * 需要加入Context.configs中的参数
-     */
-    @Builder.Default
-    private Map<String,String> configs = new HashMap<>();
-
-}

+ 20 - 4
core/src/main/java/seecoder/devcloud/core/pipeline/config/HandlerConfigTable.java

@@ -1,19 +1,23 @@
 package seecoder.devcloud.core.pipeline.config;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
 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.lang.reflect.Field;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.Map;
 
 /**
  * @author PuHong Weng
  * @date 2021/3/10
  * @description: 表驱动,记录HandlerConfig到Handler的映射
- *      todo doc config配置关系
+ * todo doc config配置关系
  */
 @Slf4j
 public class HandlerConfigTable {
@@ -34,12 +38,24 @@ public class HandlerConfigTable {
         handlerConfigMap.put("k8s-namespace", K8sNamespaceHandler.class);
     }
 
-    public static Handler transToHandler(HandlerConfig config) throws PipelineException {
+    public static Handler transToHandler(String name, JsonNode config) throws Exception {
         Handler handler = null;
         try {
-            handler = (Handler) handlerConfigMap.get(config.getName()).newInstance();
+            handler = (Handler) handlerConfigMap.get(name).newInstance();
         } catch (InstantiationException | IllegalAccessException e) {
-            throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE,PipelineException.CONFIG_TRANSFER_ERROR, e);
+            throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE, PipelineException.CONFIG_TRANSFER_ERROR, e);
+        }
+        //通过反射注入配置对应Handler类
+        Iterator<Map.Entry<String, JsonNode>> jsonNodeIterator = config.fields();
+        while (jsonNodeIterator.hasNext()) {
+            Map.Entry<String, JsonNode> entry = jsonNodeIterator.next();
+            String propertyName = entry.getKey();
+            JsonNode propertyValues = entry.getValue();
+            ObjectMapper mapper = new ObjectMapper();
+            Field field = null;
+            field = handler.getClass().getDeclaredField(propertyName);
+            field.setAccessible(true);
+            field.set(handler, mapper.readValue(propertyValues.traverse(), field.getType()));
         }
         return handler;
     }

+ 7 - 1
core/src/main/java/seecoder/devcloud/core/pipeline/handler/AbstractHandler.java

@@ -14,7 +14,7 @@ import seecoder.devcloud.core.pipeline.PipelineException;
 public abstract class AbstractHandler implements Handler {
 
 
-    public Handler nextHandler;
+    private Handler nextHandler;
 
     @Override
     public void invoke(Context context) throws PipelineException {
@@ -33,4 +33,10 @@ public abstract class AbstractHandler implements Handler {
     public void setNextHandler(Handler nextHandler) {
         this.nextHandler = nextHandler;
     }
+
+    @Override
+    public Handler getNextHandler() {
+        return nextHandler;
+    }
+
 }

+ 8 - 3
core/src/main/java/seecoder/devcloud/core/pipeline/handler/JavaImageBuildHandler.java

@@ -20,7 +20,10 @@ import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import java.io.File;
 import java.io.IOException;
-import java.nio.file.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
 import java.util.Date;
 import java.util.List;
 
@@ -41,11 +44,13 @@ public class JavaImageBuildHandler extends AbstractHandler {
         gitApi = SpringUtil.getBean(GitApi.class);
     }
 
+    private String repoUrl;
+
+    private String branchName;
+
     @Override
     public void process(Context context) throws PipelineException {
         //0. 变量准备
-        String repoUrl = context.getConfigs().get("repoUrl");
-        String branchName = context.getConfigs().getOrDefault("branchName","master");
         String templateName = context.getTemplateName();
         String imageName = context.getNamespace() + "-" + context.getDeployName();
 

+ 2 - 16
core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sDeploymentHandler.java

@@ -45,23 +45,9 @@ public class K8sDeploymentHandler extends AbstractHandler {
         deploymentApi = SpringUtil.getBean(DeploymentApi.class);
     }
 
-    /**
-     * 环境变量配置
-     */
-    @JsonProperty("envs")
-    private Map<String, String> envs;
+    private String repoUrl;
 
-    /**
-     * 启动参数配置 CMD space split
-     */
-    @JsonProperty("runArgs")
-    private String runArgs;
-
-    /**
-     * 运行命令配置 ENTRYPOINT space split
-     */
-    @JsonProperty("runCommands")
-    private String runCommands;
+    private String branchName;
 
     /**
      * 挂载文件配置

+ 6 - 1
core/src/main/resources/template/config/SPRINGBOOT-JAVA8.json

@@ -3,7 +3,12 @@
     "name": "java-image-build",
     "configs": {
       "repoUrl": "#todo",
-      "branchName": "#todo"
+      "branchName": "#todo",
+      "env" : {
+        "username" : "root",
+        "password" : "root"
+      }
+
     }
   },
   {

+ 51 - 29
core/src/test/java/seecoder/devcloud/core/CoreApplicationTests.java

@@ -1,8 +1,9 @@
 package seecoder.devcloud.core;
 
-import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.spotify.docker.client.DefaultDockerClient;
 import com.spotify.docker.client.DockerCertificates;
 import com.spotify.docker.client.DockerClient;
@@ -25,7 +26,7 @@ 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.config.HandlerConfigTable;
 import seecoder.devcloud.core.pipeline.handler.*;
 
 import javax.xml.parsers.DocumentBuilder;
@@ -35,10 +36,7 @@ import java.io.FileNotFoundException;
 import java.net.URI;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.List;
 
 @RunWith(SpringRunner.class)
 @SpringBootTest
@@ -156,32 +154,56 @@ class CoreApplicationTests {
     @Test
     void jsonTrans(){
         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;
+        List<ObjectNode> handlerConfigs = null;
+        String configJson = "[\n" +
+                "  {\n" +
+                "    \"name\": \"java-image-build\",\n" +
+                "    \"configs\": {\n" +
+                "      \"repoUrl\": \"#todo\",\n" +
+                "      \"branchName\": \"#todo\",\n" +
+                "      \"env\" : {\n" +
+                "        \"username\" : \"root\",\n" +
+                "        \"password\" : \"root\"\n" +
+                "      }\n" +
+                "\n" +
+                "    }\n" +
+                "  },\n" +
+                "  {\n" +
+                "    \"name\": \"k8s-namespace\",\n" +
+                "    \"configs\": {\n" +
+                "    }\n" +
+                "  },\n" +
+                "  {\n" +
+                "    \"name\": \"k8s-deployment\",\n" +
+                "    \"configs\": {\n" +
+                "      \"port\": \"#todo\"\n" +
+                "    }\n" +
+                "  },\n" +
+                "  {\n" +
+                "    \"name\": \"k8s-service\",\n" +
+                "    \"configs\": {\n" +
+                "    }\n" +
+                "  },\n" +
+                "  {\n" +
+                "    \"name\": \"k8s-ingress\",\n" +
+                "    \"configs\": {\n" +
+                "    }\n" +
+                "  }\n" +
+                "]";
+
         try {
-            lendReco = mapper.readValue(jjj,new TypeReference<ArrayList<HandlerConfig>>(){});
-        } catch (JsonProcessingException e) {
+            handlerConfigs = mapper.readValue(configJson, new TypeReference<List<ObjectNode>>() {
+            });
+            for (ObjectNode node : handlerConfigs){
+                String name = node.get("name").toString().replaceAll("\"","");
+                JsonNode configs = node.get("configs");
+                HandlerConfigTable.transToHandler(name,configs);
+            }
+            System.out.println(handlerConfigs);
+        } catch (Exception e) {
             e.printStackTrace();
         }
-        System.out.println();
+
     }
 
     @Test

+ 19 - 2
web/src/main/java/seecoder/devcloud/web/controller/project/ProjectController.java

@@ -2,6 +2,7 @@ package seecoder.devcloud.web.controller.project;
 
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
@@ -9,6 +10,7 @@ import seecoder.devcloud.common.exceptions.ServiceException;
 import seecoder.devcloud.web.model.vo.Response;
 import seecoder.devcloud.web.model.vo.project.ProjectCreateVO;
 import seecoder.devcloud.web.model.vo.project.ProjectVO;
+import seecoder.devcloud.web.model.vo.user.UserVO;
 import seecoder.devcloud.web.service.project.ProjectService;
 
 import java.util.List;
@@ -48,10 +50,25 @@ public class ProjectController {
     @ApiOperation(value = "创建项目,传入的参数中不必带有效的projectId字段,返回一个创建后的结果,注入id", httpMethod = "POST")
     @PostMapping("/create")
     @ApiImplicitParam(name = "projectCreateVO",dataType = "object", paramType = "body")
-    public Response<ProjectVO> createProject(@RequestParam("projectCreateVO") ProjectCreateVO projectCreateVO) throws ServiceException {
+    public Response<ProjectVO> createProject(@RequestBody ProjectCreateVO projectCreateVO) throws ServiceException {
         return Response.buildSuccess(projectService.createProject(projectCreateVO));
     }
 
+    @ApiOperation(value = "获取一个项目所有成员信息", httpMethod = "GET")
+    @GetMapping("/members")
+    @ApiImplicitParam(name = "projectId", dataType = "int", paramType = "query")
+    public Response<List<UserVO>> getProjectMember(@RequestParam("projectId") Integer projectId){
+        return Response.buildSuccess(projectService.getProjectMembers(projectId));
+    }
 
-
+    @ApiOperation(value = "给项目添加成员", httpMethod = "POST")
+    @PostMapping("/members")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "projectId", dataType = "int", paramType = "query"),
+            @ApiImplicitParam(name = "userId", dataType = "int", paramType = "query")
+    })
+    public Response addMember(@RequestParam("projectId") Integer projectId,@RequestParam("userId") Integer userId){
+        projectService.addMember(projectId, userId);
+        return Response.buildSuccess();
+    }
 }

+ 0 - 6
web/src/main/java/seecoder/devcloud/web/controller/tree/TreeNodesController.java

@@ -25,12 +25,6 @@ import java.util.List;
 public class TreeNodesController {
     @Autowired
     private TreeNodeService treeNodeService;
-//    //注意 这里混用po和vo了
-//    @ApiOperation("获取所有nodes")
-//    @GetMapping("/all")
-//    public Response<List<TreeNodeVO>> getAllNodes(){
-//        return Response.buildSuccess(treeNodeService.getAllNodes());
-//    }
 
     /**
      * 获取某个项目所有需求情况

+ 14 - 0
web/src/main/java/seecoder/devcloud/web/service/impl/project/ProjectServiceImpl.java

@@ -12,6 +12,7 @@ import seecoder.devcloud.web.dao.project.ProjectMapper;
 import seecoder.devcloud.web.model.po.project.ProjectPO;
 import seecoder.devcloud.web.model.vo.project.ProjectCreateVO;
 import seecoder.devcloud.web.model.vo.project.ProjectVO;
+import seecoder.devcloud.web.model.vo.user.UserVO;
 import seecoder.devcloud.web.service.project.ProjectService;
 
 import java.util.List;
@@ -74,8 +75,21 @@ public class ProjectServiceImpl implements ProjectService {
 
     }
 
+    @Override
+    public List<UserVO> getProjectMembers(Integer projectId) {
+        //todo 调用gitlab
+        return null;
+    }
+
     @Override
     public void deleteProject(int projectId) {
         //TODO:不知道该怎么做,懒删除?还是直接删? 暂时不提供
     }
+
+    @Override
+    public void refresh() {
+
+        //todo 获取项目存储
+        projectMapper.insertProject(null);
+    }
 }

+ 3 - 3
web/src/main/java/seecoder/devcloud/web/service/project/ProjectService.java

@@ -3,6 +3,7 @@ package seecoder.devcloud.web.service.project;
 import seecoder.devcloud.common.exceptions.ServiceException;
 import seecoder.devcloud.web.model.vo.project.ProjectCreateVO;
 import seecoder.devcloud.web.model.vo.project.ProjectVO;
+import seecoder.devcloud.web.model.vo.user.UserVO;
 
 import java.util.List;
 
@@ -36,9 +37,8 @@ public interface ProjectService {
 
     void addMember(Integer projectId, Integer userId);
 
-    //todo 项目获取所有用户id
-
-    //todo 用户id获取所有项目
+    List<UserVO> getProjectMembers(Integer projectId);
 
+    void refresh();
     //todo refresh 同步软工二信息
 }