1
0
Просмотр исходного кода

feat: 部署功能完善 异步、转换方式

370774330@qq.com 5 лет назад
Родитель
Сommit
bd511c0746

+ 0 - 8
core/src/main/java/seecoder/devcloud/core/pipeline/Pipeline.java

@@ -11,12 +11,4 @@ public interface Pipeline {
 
     Context getContext();
 
-    /**
-     * 用于方便用户给pipeline中context的config添加配置
-     */
-    default Context addContextConfig(String key, String value) {
-        Context context = getContext( );
-        context.getConfigs().put(key, value);
-        return context;
-    };
 }

+ 2 - 0
core/src/main/java/seecoder/devcloud/core/pipeline/handler/JavaImageBuildHandler.java

@@ -3,6 +3,7 @@ package seecoder.devcloud.core.pipeline.handler;
 import com.spotify.docker.client.ProgressHandler;
 import com.spotify.docker.client.exceptions.DockerException;
 import com.spotify.docker.client.messages.ProgressMessage;
+import lombok.Data;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.StringUtils;
 import org.apache.http.HttpStatus;
@@ -33,6 +34,7 @@ import java.util.List;
  * @description: docker镜像构建
  */
 @Slf4j
+@Data
 public class JavaImageBuildHandler extends AbstractHandler {
 
     public final DockerApi dockerApi;

+ 0 - 2
core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sIngressHandler.java

@@ -26,8 +26,6 @@ public class K8sIngressHandler extends AbstractHandler {
     private final IngressApi ingressApi;
 
     public K8sIngressHandler() {
-//        ObjectMapper objectMapper = new ObjectMapper();
-//        objectMapper.convertValue()
         this.ingressApi = SpringUtil.getBean(IngressApi.class);
         this.applicationProperties = SpringUtil.getBean(ApplicationProperties.class);
     }

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

@@ -27,13 +27,15 @@ public class K8sServiceHandler extends AbstractHandler {
         serviceApi = SpringUtil.getBean(ServiceApi.class);
     }
 
+    private Integer port;
+
 
     @Override
     public void process(Context context) throws PipelineException {
 
         //0. 变量准备
         // pod内容器暴露的端口
-        int targetPort =  Integer.parseInt(context.getConfigs().get("port"));
+        int targetPort =  port;
         //service对集群内暴露的端口,这里默认与targetPort一致
         int servicePort = targetPort;
 

+ 9 - 2
core/src/main/java/seecoder/devcloud/core/pipeline/handler/NodeImageBuildHandler.java

@@ -3,6 +3,7 @@ package seecoder.devcloud.core.pipeline.handler;
 import com.spotify.docker.client.ProgressHandler;
 import com.spotify.docker.client.exceptions.DockerException;
 import com.spotify.docker.client.messages.ProgressMessage;
+import lombok.Data;
 import org.apache.commons.lang.StringUtils;
 import org.apache.http.HttpStatus;
 import org.eclipse.jgit.api.Git;
@@ -25,6 +26,7 @@ import java.util.Date;
  * @description:
  * 前端镜像构建
  */
+@Data
 public class NodeImageBuildHandler extends AbstractHandler{
     public final DockerApi dockerApi;
 
@@ -35,11 +37,15 @@ public class NodeImageBuildHandler extends AbstractHandler{
         gitApi = SpringUtil.getBean(GitApi.class);
     }
 
+    private String repoUrl;
+
+    private String branchName;
+
+    private String nginxConfig;
+
     @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();
 
@@ -72,6 +78,7 @@ public class NodeImageBuildHandler extends AbstractHandler{
                     if (!StringUtils.isEmpty(message.error())) {
                         sb.append(message.error()+"\n");
                     }
+                    System.out.println(message.stream());
 
                 }
             });

+ 0 - 1
core/src/main/java/seecoder/devcloud/core/pipeline/inspector/PipelineInspector.java

@@ -38,7 +38,6 @@ public class PipelineInspector {
 
 
     public void delete(){
-        //todo 异步
         Namespace namespace = new Namespace();
         namespace.setName(context.getNamespace());
         namespaceApi.delete(namespace);

+ 1 - 0
core/src/main/resources/template/dockerfile/NODE-10

@@ -6,5 +6,6 @@ ADD package.json /code
 RUN yarn install
 ADD . /code
 RUN yarn build
+
 FROM nginx:1.19-alpine
 COPY --from=builder /code/dist/ /var/www/html/dist/

+ 13 - 35
core/src/test/java/seecoder/devcloud/core/CoreApplicationTests.java

@@ -4,20 +4,12 @@ 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;
-import com.spotify.docker.client.DockerConfigReader;
-import com.spotify.docker.client.auth.ConfigFileRegistryAuthSupplier;
-import com.spotify.docker.client.auth.RegistryAuthSupplier;
-import com.spotify.docker.client.exceptions.DockerCertificateException;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.junit4.SpringRunner;
-import org.springframework.util.ResourceUtils;
 import org.w3c.dom.Document;
 import org.w3c.dom.NodeList;
 import seecoder.devcloud.api.ApplicationProperties;
@@ -32,9 +24,6 @@ import seecoder.devcloud.core.pipeline.handler.*;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import java.io.File;
-import java.io.FileNotFoundException;
-import java.net.URI;
-import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.List;
 
@@ -113,11 +102,11 @@ class CoreApplicationTests {
     }
 
     @Test
-    void k8sImageBuild() {
-        context.getConfigs().put("repoUrl","http://gitlab.192.168.99.105.nip.io/root/imagebuildetest.git");
-        context.getConfigs().put("branchName", "master");
+    void k8sImageBackendBuild() {
+        context.setDeployName("pb");
         JavaImageBuildHandler javaImageBuildHandler = new JavaImageBuildHandler();
-
+        javaImageBuildHandler.setRepoUrl("http://gitlab.192.168.99.105.nip.io/root/imagebuildetest.git");
+        javaImageBuildHandler.setBranchName("master");
         try {
             javaImageBuildHandler.process(context);
         } catch (PipelineException e) {
@@ -126,31 +115,20 @@ class CoreApplicationTests {
     }
 
     @Test
-    void k8sImagePush() {
-        String registry = "192.168.99.105:30060";
-        String imageName = "seecoder-devcloud-g-p";
-        String imageTag = "1616399211969";
-        Path dockerConfigPath = null;
-        DockerClient client = null;
-        try {
-            dockerConfigPath = ResourceUtils.getFile("classpath:docker").toPath();
-            if (properties.getDocker().getTls()){
-                client = new DefaultDockerClient(URI.create(properties.getDocker().getHost()), new DockerCertificates(dockerConfigPath));
-            } else {
-                client = new DefaultDockerClient(properties.getDocker().getHost());
-            }
-        } catch (FileNotFoundException | DockerCertificateException e) {
-            e.printStackTrace();
-        }
+    void k8sImageFrontendBuild() {
+        context.setDeployName("pf");
+        context.setTemplateName("NODE-10");
+        NodeImageBuildHandler nodeImageBuildHandler = new NodeImageBuildHandler();
+        nodeImageBuildHandler.setRepoUrl("http://gitlab.192.168.99.105.nip.io/root/frontendimage.git");
+        nodeImageBuildHandler.setBranchName("master");
         try {
-            RegistryAuthSupplier registryAuthSupplier = new ConfigFileRegistryAuthSupplier(new DockerConfigReader(), Paths.get(dockerConfigPath.toString(),"docker-config.json"));
-            client.push(registry + "/" + imageName + ":" + imageTag, registryAuthSupplier.authFor("http://" + registry + "/" + imageName + ":" + imageTag));
-        } catch (Exception e){
+            nodeImageBuildHandler.process(context);
+        } catch (PipelineException e) {
             e.printStackTrace();
         }
-
     }
 
+
     @Test
     void jsonTrans(){
         ObjectMapper mapper = new ObjectMapper();

+ 3 - 2
web/src/main/java/seecoder/devcloud/web/controller/pipeline/DeploymentController.java

@@ -7,6 +7,7 @@ import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
 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.DeploymentInfoVO;
 import seecoder.devcloud.web.service.pipeline.DeploymentService;
@@ -45,7 +46,7 @@ public class DeploymentController {
     })
     @PostMapping
     public Response deploy(@RequestParam("projectId")Integer projectId,
-                           @RequestParam("pipelineId")Integer pipelineId) throws AccessDeniedException {
+                           @RequestParam("pipelineId")Integer pipelineId) throws ServiceException {
         deploymentService.deploy(projectId,pipelineId);
         return Response.buildSuccess();
     }
@@ -57,7 +58,7 @@ public class DeploymentController {
     })
     @DeleteMapping
     public Response delete(@RequestParam("projectId")Integer projectId,
-                @RequestParam("pipelineId")Integer pipelineId) throws AccessDeniedException {
+                @RequestParam("pipelineId")Integer pipelineId) throws ServiceException {
         deploymentService.deploy(projectId,pipelineId);
         return Response.buildSuccess();
     }

+ 21 - 4
web/src/main/java/seecoder/devcloud/web/service/impl/pipeline/DeploymentServiceImpl.java

@@ -1,10 +1,13 @@
 package seecoder.devcloud.web.service.impl.pipeline;
 
+import org.apache.http.HttpStatus;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import seecoder.devcloud.api.ApplicationProperties;
 import seecoder.devcloud.api.k8s.model.DeploymentStatus;
 import seecoder.devcloud.common.exceptions.AccessDeniedException;
+import seecoder.devcloud.common.exceptions.ServiceException;
 import seecoder.devcloud.core.pipeline.Pipeline;
 import seecoder.devcloud.core.pipeline.PipelineException;
 import seecoder.devcloud.core.pipeline.PipelineFactory;
@@ -83,7 +86,16 @@ public class DeploymentServiceImpl implements DeploymentService {
     }
 
     @Override
-    public void deploy(Integer projectId, Integer pipelineId) throws AccessDeniedException {
+    @Async
+    public void deploy(Integer projectId, Integer pipelineId) throws ServiceException {
+        try {
+            Thread.sleep(3000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        System.out.println(Thread.currentThread().getName());
+        System.out.println(System.currentTimeMillis());
+
         //projectAuthentication(projectId);
         PipelinePO pipelinePO = pipelineMapper.selectById(pipelineId);
         ProjectPO projectPO = projectMapper.getProjectById(projectId);
@@ -94,17 +106,22 @@ public class DeploymentServiceImpl implements DeploymentService {
                 .details("")
                 .build();
         pipelineHistoryMapper.insert(history,"id","startTime");
+        Pipeline pipeline = null;
         try {
-            Pipeline pipeline = PipelineFactory.init(pipelinePO.getConfigJson(), projectPO.getName(), pipelinePO.getName(), pipelineId, pipelinePO.getTemplateName());
-            //todo 异步记录结果
+            pipeline = PipelineFactory.init(pipelinePO.getConfigJson(), projectPO.getName(), pipelinePO.getName(), pipelineId, pipelinePO.getTemplateName());
             pipeline.start();
+            history.setResult("部署成功");
+            history.setDetails(pipeline.getContext().getResult());
         } catch (PipelineException pipelineException) {
-            pipelineException.printStackTrace();
+            history.setResult("部署失败");
+            history.setDetails(pipeline.getContext().getResult());
+            throw new ServiceException(HttpStatus.SC_INTERNAL_SERVER_ERROR,"应用部署失败",pipelineException);
         }
 
     }
 
     @Override
+    @Async
     public void delete(Integer projectId, Integer pipelineId) throws AccessDeniedException {
         //projectAuthentication(projectId);
         ProjectPO project = projectMapper.getProjectById(projectId);

+ 2 - 2
web/src/main/java/seecoder/devcloud/web/service/pipeline/DeploymentService.java

@@ -1,6 +1,7 @@
 package seecoder.devcloud.web.service.pipeline;
 
 import seecoder.devcloud.common.exceptions.AccessDeniedException;
+import seecoder.devcloud.common.exceptions.ServiceException;
 import seecoder.devcloud.web.model.vo.pipeline.DeploymentInfoVO;
 
 import java.util.List;
@@ -20,9 +21,8 @@ public interface DeploymentService {
 
     /**
      * 执行一条pipepine
-     * todo 异步/异步异常捕获刷新result
      */
-    void deploy(Integer projectId,Integer pipelineId) throws AccessDeniedException;
+    void deploy(Integer projectId,Integer pipelineId) throws ServiceException;
 
     /**
      * 删除一个实例

+ 0 - 2
web/src/main/java/seecoder/devcloud/web/service/tree/TreeNodeService.java

@@ -24,13 +24,11 @@ public interface TreeNodeService {
 
     /**
      * 新增一条需求
-     * @param treeNodeVO
      */
     void insertTreeNode(TreeNodeCreateVO treeNodeCreateVO) throws ServiceException;
 
     /**
      * 更新一条需求
-     * @param treeNodeVO
      */
     void updateTreeNode(TreeNodeUpdateBasicVO treeNodeUpdateBasicVO);
 

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

@@ -1,9 +1,11 @@
 package seecoder.devcloud.web.service.user;
 
 
+import com.nju.edu.gitlab.SeecoderGitlabApi;
 import org.springframework.security.core.context.SecurityContextHolder;
 import seecoder.devcloud.common.exceptions.AccessDeniedException;
 import seecoder.devcloud.common.exceptions.ServiceException;
+import seecoder.devcloud.common.util.SpringUtil;
 import seecoder.devcloud.web.model.po.user.UserPO;
 import seecoder.devcloud.web.model.vo.user.GitlabUserCreateVO;
 import seecoder.devcloud.web.model.vo.user.UserVO;
@@ -31,6 +33,7 @@ public interface UserService {
     static void projectAuthentication(Integer projectId) throws AccessDeniedException {
         UserPO userPO = UserService.loginUser();
         //todo gitlab获取
+        SeecoderGitlabApi seecoderGitlabApi = SpringUtil.getBean(SeecoderGitlabApi.class);
         //List<ProjectPO> projectPOS = SpringUtil.getBean(ProjectMapper.class).listProjectsByUserId(userPO.getId());
 //        if (projectPOS.stream().noneMatch(project -> project.getId()==projectId)){
 //            throw new AccessDeniedException("您没有操作此项目的权限");

+ 54 - 0
web/src/test/java/seecoder/devcloud/web/service/pipeline/DeploymentServiceTest.java

@@ -0,0 +1,54 @@
+package seecoder.devcloud.web.service.pipeline;
+
+import org.junit.jupiter.api.Test;
+import org.junit.runner.RunWith;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import seecoder.devcloud.common.exceptions.ServiceException;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/31
+ * @description:
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@MapperScan(basePackages = {"seecoder.devcloud.web.dao"})
+class DeploymentServiceTest {
+
+    private final DeploymentService deploymentService;
+
+    @Autowired
+    DeploymentServiceTest(DeploymentService deploymentService) {
+        this.deploymentService = deploymentService;
+    }
+
+    @Test
+    void retrieveDeploymentInfos() {
+    }
+
+    @Test
+    void deploy() {
+        System.out.println(Thread.currentThread().getName());
+        System.out.println(System.currentTimeMillis());
+        try {
+            deploymentService.deploy(1,2);
+        } catch (ServiceException serviceException) {
+            serviceException.printStackTrace();
+        }
+        System.out.println(Thread.currentThread().getName());
+        System.out.println(System.currentTimeMillis());
+        try {
+            System.out.println("父线程等待");
+            Thread.sleep(100000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    void delete() {
+    }
+}