Ver código fonte

feat: docker镜像构建

370774330@qq.com 5 anos atrás
pai
commit
9e7175ac32

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

@@ -5,6 +5,9 @@ package seecoder.devcloud.core.pipeline;
  * @date 2021/3/10
  * @date 2021/3/10
  * @description: 流水线模块出现的异常的包装
  * @description: 流水线模块出现的异常的包装
  */
  */
-public class PipelineException extends RuntimeException{
-    //todo exception
+public class PipelineException extends Exception{
+
+    public PipelineException(String msg){
+        super(msg);
+    }
 }
 }

+ 121 - 168
core/src/main/java/seecoder/devcloud/core/pipeline/handler/DockerImageBuildHandler.java

@@ -1,168 +1,121 @@
-//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 io.kubernetes.client.openapi.models.*;
-//import lombok.extern.slf4j.Slf4j;
-//import org.apache.commons.io.FileUtils;
-//import org.apache.commons.lang.StringUtils;
-//import org.eclipse.jgit.api.Git;
-//import org.eclipse.jgit.api.ResetCommand;
-//import org.springframework.util.CollectionUtils;
-//import seecoder.devcloud.api.ApplicationProperties;
-//import seecoder.devcloud.api.docker.DockerApi;
-//import seecoder.devcloud.api.git.GitApi;
-//import seecoder.devcloud.api.gitlab.GitlabApi;
-//import seecoder.devcloud.common.exceptions.Asserts;
-//import seecoder.devcloud.common.util.SpringUtil;
-//import seecoder.devcloud.core.pipeline.Context;
-//import seecoder.devcloud.core.pipeline.Handler;
-//
-//import java.io.*;
-//import java.nio.file.Files;
-//import java.nio.file.Path;
-//import java.nio.file.Paths;
-//import java.time.LocalDateTime;
-//import java.util.*;
-//import java.util.stream.Collectors;
-//
-///**
-// * @author PuHong Weng
-// * @date 2021/1/18
-// * @description: docker镜像构建
-// */
-//@Slf4j
-//public class DockerImageBuildHandler extends AbstractHandler {
-//
-//    private static final String TEMP_PREFIX = "SEECODER-DEVCLOUD-";
-//
-//    public DockerApi dockerApi;
-//
-//    public GitlabApi gitlabApi;
-//
-//    public GitApi gitApi;
-//
-//    public DockerImageBuildHandler() {
-//        gitlabApi = SpringUtil.getBean(GitlabApi.class);
-//        dockerApi = SpringUtil.getBean(DockerApi.class);
-//        gitApi = SpringUtil.getBean(GitApi.class);
-//    }
-//
-//    @Override
-//    public void process(Context context) {
-//        try {
-//            String imageName = context.getGroupName() + "-" + context.getProjectName();
-//            String repoUrl = context.getConfigs().get("repoUrl");
-//
-//
-//            // 1. 有git从git拿到地址进行镜像构建构建并push
-//            try {
-//                Path directory = Files.createTempDirectory("seecoder-devcloud-");
-//                Git git = gitApi.clone(repoUrl, directory.toString());
-//                if (Files.exists(Paths.get(directory.toString(), "Dockerfile"))) {
-//                    git.reset().setMode(ResetCommand.ResetType.HARD).setRef(result.getBuildTypeValue()).call();
-//                    String imageTag = String.valueOf(new Date().getTime());
-//                    StringBuilder sb = new StringBuilder();
-//                    final int DEFAULT_BUFFER_LENGTH = 200;
-//                    final long MAX_BUFFER_SIZE = 1 << 18;
-//                    dockerApi.buildAndPush(directory.toString(), "seecoder-paas-" + labelValue, imageTag, new ProgressHandler() {
-//                        @Override
-//                        public void progress(ProgressMessage message) throws DockerException {
-//                            String value = message.stream();
-//                            if (value == null) {
-//                                value = "";
-//                            }
-//                            if (!StringUtils.isEmpty(message.error())) {
-//                                value += "\n" + message.error();
-//                            }
-//                            sb.append(value);
-//                            if (sb.length() > DEFAULT_BUFFER_LENGTH) {
-//                                result.setBuildOutput(result.getBuildOutput() + sb.toString());
-//                                if (result.getBuildOutput().length() > MAX_BUFFER_SIZE) {
-//                                    result.setBuildOutput(result.getBuildOutput().substring((int) (result.getBuildOutput().length() - MAX_BUFFER_SIZE)));
-//                                }
-//                                sb.setLength(0);
-//                                environmentDAO.save(result);
-//                            }
-//                        }
-//                    });
-//                    if (sb.length() > 0) {
-//                        result.setBuildOutput(result.getBuildOutput() + sb.toString());
-//                    }
-//                    imageName = applicationProperties.getK8s().getImageRegistry() + "/seecoder-paas-" + labelValue + ":" + imageTag;
-//                    result.setBuildStatus(BuildStatus.SUCCESS);
-//                    result.setDeployStatus(DeployStatus.DEPLOYING);
-//                    result.setDeployStartTime(LocalDateTime.now());
-//                    result.setImage(imageName);
-//                    environmentDAO.save(result);
-//                } else {
-//                    result.setBuildStatus(BuildStatus.FAIL);
-//                    result.setBuildOutput("找不到构建文件Dockerfile!");
-//                    environmentDAO.save(result);
-//                    throw new ServiceException("102", "找不到构建文件Dockerfile!");
-//                }
-//            } catch (Exception e) {
-//                result.setBuildStatus(BuildStatus.FAIL);
-//                if (!e.getLocalizedMessage().contains("Could not acquire image ID or digest following build")) {
-//                    result.setBuildOutput(e.getLocalizedMessage());
-//                }
-//                environmentDAO.save(result);
-//                LoggerUtil.error(logger, e, "构建失败!gitUrl={}, branchOrCommit={}", application.getGitUrl(), result.getBuildTypeValue());
-//                return;
-//            }
-//        } else if (result.getBuildType() == BuildType.FROM_IMAGE) {
-//            result.setBuildStatus(BuildStatus.SUCCESS);
-//            result.setBuildOutput("镜像构建无需部署");
-//            result.setDeployStatus(DeployStatus.DEPLOYING);
-//            result.setDeployStartTime(LocalDateTime.now());
-//            result.setImage(imageName);
-//            environmentDAO.save(result);
-//        }
-//
-//        String[] ports = (configContent.getServicePort() == null ? "" : configContent.getServicePort()).split(",");
-//        if (!StringUtils.isEmpty(configContent.getHostPrefix())) {
-//            for (String port : ports) {
-//                // ingress
-//                List<Ingress> ingresses = ingressApi.getByCondition(K8sObjectRequest.builder()
-//                        .name(labelValue + "-" + port)
-//                        .namespace(deploymentNamespace).labels(labelsMap).build());
-//                Ingress ingress = new Ingress();
-//                ingress.setNamespace(deploymentNamespace);
-//                ingress.setName(labelValue + "-" + port);
-//                ingress.setLabels(labelsMap);
-//                if (configContent.getIngressAnnotations() != null && configContent.getIngressAnnotations().get(port) != null) {
-//                    ingress.setAnnotations(configContent.getIngressAnnotations().get(port));
-//                }
-//                String ingressHost = configContent.getHostPrefix() + "-" + port + "." + deploymentHost;
-//                if (configContent.getIngressPort() != null) {
-//                    if (port.equals(configContent.getIngressPort())) {
-//                        ingressHost = configContent.getHostPrefix() + "." + deploymentHost;
-//                    }
-//                } else {
-//                    if (ports.length == 1 || port.equals("80")) {
-//                        ingressHost = configContent.getHostPrefix() + "." + deploymentHost;
-//                    }
-//                }
-//                ingress.setAnnotation(Ingress.REWRITE_ANNOTATION, Ingress.DEFAULT_REWRITE_PATH);
-//                ingress.setHttpRules(Collections.singletonList(
-//                        Ingress.IngressRule.builder().host(ingressHost).ruleValues(
-//                                Collections.singleton(Ingress.IngressPath.builder()
-//                                        .path("/")
-//                                        .serviceName(labelValue)
-//                                        .port(Integer.parseInt(port))
-//                                        .build())
-//                        ).build()
-//                ));
-//                if (CollectionUtils.isEmpty(ingresses) || ingresses.size() != 1) {
-//                    ingressApi.create(ingress);
-//                } else {
-//                    ingressApi.update(ingress);
-//                }
-//            }
-//        }
-//
-//        return;
-//    }
-//}
-//
+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 io.kubernetes.client.openapi.models.*;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.ResetCommand;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ResourceUtils;
+import seecoder.devcloud.api.ApplicationProperties;
+import seecoder.devcloud.api.docker.DockerApi;
+import seecoder.devcloud.api.git.GitApi;
+import seecoder.devcloud.api.gitlab.GitlabApi;
+import seecoder.devcloud.common.exceptions.Asserts;
+import seecoder.devcloud.common.util.SpringUtil;
+import seecoder.devcloud.core.pipeline.Context;
+import seecoder.devcloud.core.pipeline.Handler;
+import seecoder.devcloud.core.pipeline.PipelineException;
+import seecoder.devcloud.core.pipeline.template.PipelineTemplateTable;
+
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/1/18
+ * @description: docker镜像构建
+ */
+@Slf4j
+public class DockerImageBuildHandler extends AbstractHandler {
+
+    private static final String TEMP_PREFIX = "SEECODER-DEVCLOUD-";
+
+    public DockerApi dockerApi;
+
+    public GitlabApi gitlabApi;
+
+    public GitApi gitApi;
+
+    public DockerImageBuildHandler() {
+        gitlabApi = SpringUtil.getBean(GitlabApi.class);
+        dockerApi = SpringUtil.getBean(DockerApi.class);
+        gitApi = SpringUtil.getBean(GitApi.class);
+    }
+
+    @Override
+    public void process(Context context) throws PipelineException {
+
+        String imageName = context.getNamespace() + "-" + context.getProjectName();
+        String repoUrl = context.getConfigs().get("repoUrl");
+        //要构建的分支名
+        String branchName = context.getConfigs().get("branchName");
+        String templateName = context.getTemplateName();
+
+        // 1. 有git从git拿到地址仓库
+        Path directory = null;
+        try {
+            //注:temp文件/目录系统会定时删,实际文件名喂 prefix + 它生成的suffix随机数,所以不会命名冲突
+            directory = Files.createTempDirectory("seecoder-devcloud-");
+            Git git = gitApi.clone(repoUrl, directory.toString());
+            git.checkout().setName(branchName).call();
+        } catch (Exception e) {
+            String error = "Error: 从仓库拉取代码发生错误, " + e.getMessage() + "\n";
+            context.setResult(context.getResult() + error);
+            throw new PipelineException(error);
+        }
+        //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());
+        } catch (IOException e) {
+            String error = "Error: 常见dockerfile文件错误, " + e.getMessage() + "\n";
+            context.setResult(context.getResult() + error);
+            throw new PipelineException(error);
+        }
+
+        //3. 镜像构建
+        String imageTag = String.valueOf(new Date().getTime());
+        StringBuilder sb = new StringBuilder();
+        try {
+            dockerApi.buildAndPush(directory.toString(), "seecoder-devcloud-" + imageName, imageTag, new ProgressHandler() {
+                @Override
+                public void progress(ProgressMessage message) throws DockerException {
+                    String value = message.stream();
+                    if (value == null) {
+                        value = "";
+                    }
+                    if (!StringUtils.isEmpty(message.error())) {
+                        value += "\n" + message.error();
+                    }
+                    sb.append(value);
+                    context.setResult(context.getResult() + sb.toString());
+                }
+            });
+        } catch (Exception e) {
+            String error = "Error: 构建镜像推送到仓库错误, " + e.getMessage() + "\n";
+            context.setResult(context.getResult() + error);
+            throw new PipelineException(error);
+        }
+        //4. 将镜像名字加入context
+        context.getConfigs().put("imageName", imageName);
+        context.getConfigs().put("imageTag", imageTag);
+    }
+}
+