|
|
@@ -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);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|