|
@@ -29,7 +29,6 @@ import org.apache.commons.lang.StringUtils;
|
|
|
import org.eclipse.jgit.api.Git;
|
|
import org.eclipse.jgit.api.Git;
|
|
|
import org.eclipse.jgit.api.ResetCommand;
|
|
import org.eclipse.jgit.api.ResetCommand;
|
|
|
import org.eclipse.jgit.api.errors.GitAPIException;
|
|
import org.eclipse.jgit.api.errors.GitAPIException;
|
|
|
-import org.eclipse.jgit.lib.ObjectId;
|
|
|
|
|
import org.eclipse.jgit.revwalk.RevCommit;
|
|
import org.eclipse.jgit.revwalk.RevCommit;
|
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.Logger;
|
|
|
import org.springframework.beans.BeanUtils;
|
|
import org.springframework.beans.BeanUtils;
|
|
@@ -214,12 +213,38 @@ public class EnvironmentServiceImpl implements EnvironmentService {
|
|
|
@Override
|
|
@Override
|
|
|
@Transactional
|
|
@Transactional
|
|
|
public EnvironmentVO deploy(Integer id, Boolean useCache) throws ServiceException {
|
|
public EnvironmentVO deploy(Integer id, Boolean useCache) throws ServiceException {
|
|
|
|
|
+ Environment result = getEnvironment(id);
|
|
|
|
|
+ TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void afterCommit() {
|
|
|
|
|
+ super.afterCommit();
|
|
|
|
|
+ asyncWrapper.asyncInvoke(() -> buildAndDeploy(id, useCache));
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ return EnvironmentConverter.convertToVO(environmentDAO.save(result));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ @Transactional
|
|
|
|
|
+ public EnvironmentVO build(Integer id) throws ServiceException {
|
|
|
|
|
+ Environment result = getEnvironment(id);
|
|
|
|
|
+ TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void afterCommit() {
|
|
|
|
|
+ super.afterCommit();
|
|
|
|
|
+ asyncWrapper.asyncInvoke(() -> buildImage(id));
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ return EnvironmentConverter.convertToVO(environmentDAO.save(result));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Environment getEnvironment(Integer id) throws ServiceException {
|
|
|
Environment result = environmentDAO.findById(id).orElse(null);
|
|
Environment result = environmentDAO.findById(id).orElse(null);
|
|
|
if (result == null) {
|
|
if (result == null) {
|
|
|
throw ServiceException.BAD_REQUEST;
|
|
throw ServiceException.BAD_REQUEST;
|
|
|
}
|
|
}
|
|
|
- if (result.getBuildStatus() == BuildStatus.BUILDING || result.getDeployStatus() == DeployStatus.DEPLOYING || result.getDeployStatus() == DeployStatus.RESTARTING) {
|
|
|
|
|
- throw new ServiceException("101", "存在正在进行的构建或部署!");
|
|
|
|
|
|
|
+ if (result.getBuildStatus() == BuildStatus.BUILDING) {
|
|
|
|
|
+ throw new ServiceException("101", "存在正在进行的构建!");
|
|
|
}
|
|
}
|
|
|
Config config = configDAO.findByConfigBelongsAndAndEntityId(ConfigBelongsToType.ENVIRONMENT, id);
|
|
Config config = configDAO.findByConfigBelongsAndAndEntityId(ConfigBelongsToType.ENVIRONMENT, id);
|
|
|
if (config == null) {
|
|
if (config == null) {
|
|
@@ -228,19 +253,11 @@ public class EnvironmentServiceImpl implements EnvironmentService {
|
|
|
result.setBuildOutput("");
|
|
result.setBuildOutput("");
|
|
|
result.setBuildStatus(BuildStatus.BUILDING);
|
|
result.setBuildStatus(BuildStatus.BUILDING);
|
|
|
result.setBuildStartTime(LocalDateTime.now());
|
|
result.setBuildStartTime(LocalDateTime.now());
|
|
|
- result.setDeployStatus(DeployStatus.NOT_STARTED);
|
|
|
|
|
- TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
|
|
|
|
|
- @Override
|
|
|
|
|
- public void afterCommit() {
|
|
|
|
|
- super.afterCommit();
|
|
|
|
|
- asyncWrapper.asyncInvoke(() -> buildAsync(id,useCache));
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
- return EnvironmentConverter.convertToVO(environmentDAO.save(result));
|
|
|
|
|
|
|
+ return result;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
- public Map<String,String> getLog(Integer id, String podName) throws ServiceException {
|
|
|
|
|
|
|
+ public Map<String, String> getLog(Integer id, String podName) throws ServiceException {
|
|
|
Environment result = environmentDAO.findById(id).orElse(null);
|
|
Environment result = environmentDAO.findById(id).orElse(null);
|
|
|
if (result == null) {
|
|
if (result == null) {
|
|
|
throw ServiceException.BAD_REQUEST;
|
|
throw ServiceException.BAD_REQUEST;
|
|
@@ -345,10 +362,10 @@ public class EnvironmentServiceImpl implements EnvironmentService {
|
|
|
if (!CollectionUtils.isEmpty(pods)) {
|
|
if (!CollectionUtils.isEmpty(pods)) {
|
|
|
V1PodStatus status = pods.get(0).getPodStatus();
|
|
V1PodStatus status = pods.get(0).getPodStatus();
|
|
|
List<V1PodCondition> conditions = status.getConditions() == null ? Collections.emptyList() : status.getConditions();
|
|
List<V1PodCondition> conditions = status.getConditions() == null ? Collections.emptyList() : status.getConditions();
|
|
|
- Collections.sort(conditions, Comparator.comparingLong(c -> ((V1PodCondition)c).getLastTransitionTime().getMillis()).reversed());
|
|
|
|
|
|
|
+ Collections.sort(conditions, Comparator.comparingLong(c -> ((V1PodCondition) c).getLastTransitionTime().getMillis()).reversed());
|
|
|
String deployOutput = "Type\tStatus\tMessage\tReason\tTime\n";
|
|
String deployOutput = "Type\tStatus\tMessage\tReason\tTime\n";
|
|
|
deployOutput += conditions.stream().map(condition -> {
|
|
deployOutput += conditions.stream().map(condition -> {
|
|
|
- return condition.getType() + "\t" + condition.getStatus() + "\t" + condition.getMessage() + "\t" + condition.getReason() + "\t" + condition.getLastTransitionTime().toString();
|
|
|
|
|
|
|
+ return condition.getType() + "\t" + condition.getStatus() + "\t" + condition.getMessage() + "\t" + condition.getReason() + "\t" + condition.getLastTransitionTime().toString();
|
|
|
}).collect(Collectors.joining("\n"));
|
|
}).collect(Collectors.joining("\n"));
|
|
|
switch (status.getPhase()) {
|
|
switch (status.getPhase()) {
|
|
|
case "Succeeded":
|
|
case "Succeeded":
|
|
@@ -376,8 +393,24 @@ public class EnvironmentServiceImpl implements EnvironmentService {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- void buildAsync(Integer id, Boolean useCache) {
|
|
|
|
|
|
|
+ private void buildImage(Integer id) {
|
|
|
Environment result = environmentDAO.findById(id).get();
|
|
Environment result = environmentDAO.findById(id).get();
|
|
|
|
|
+ try {
|
|
|
|
|
+ String labelValue = ResourceLabel.RESOURCE.getGenerator().gen("environment", String.valueOf(result.getAppId()), String.valueOf(result.getId()));
|
|
|
|
|
+ // 构建镜像阶段
|
|
|
|
|
+ buildImageHelper(result, labelValue);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ result.setBuildStatus(BuildStatus.FAIL);
|
|
|
|
|
+ result.setBuildOutput(e.getLocalizedMessage());
|
|
|
|
|
+ environmentDAO.save(result);
|
|
|
|
|
+ LoggerUtil.error(logger, e, "构建镜像失败!");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void deployToPod(Integer id) {
|
|
|
|
|
+ Environment result = environmentDAO.findById(id).get();
|
|
|
|
|
+ result.setDeployStatus(DeployStatus.DEPLOYING);
|
|
|
|
|
+ environmentDAO.save(result);
|
|
|
try {
|
|
try {
|
|
|
Config config = configDAO.findByConfigBelongsAndAndEntityId(ConfigBelongsToType.ENVIRONMENT, id);
|
|
Config config = configDAO.findByConfigBelongsAndAndEntityId(ConfigBelongsToType.ENVIRONMENT, id);
|
|
|
Application application = applicationDAO.findById(result.getAppId()).get();
|
|
Application application = applicationDAO.findById(result.getAppId()).get();
|
|
@@ -387,13 +420,8 @@ public class EnvironmentServiceImpl implements EnvironmentService {
|
|
|
Map<String, String> labelsMap = Collections.singletonMap(labelKey, labelValue);
|
|
Map<String, String> labelsMap = Collections.singletonMap(labelKey, labelValue);
|
|
|
String deploymentNamespace = applicationProperties.getDeploymentNamespace();
|
|
String deploymentNamespace = applicationProperties.getDeploymentNamespace();
|
|
|
String deploymentHost = applicationProperties.getDeploymentHost();
|
|
String deploymentHost = applicationProperties.getDeploymentHost();
|
|
|
-
|
|
|
|
|
- // 构建镜像阶段
|
|
|
|
|
- buildImage(result,useCache, labelValue);
|
|
|
|
|
-
|
|
|
|
|
// 读取构建之后的镜像名称
|
|
// 读取构建之后的镜像名称
|
|
|
String imageName = result.getImage();
|
|
String imageName = result.getImage();
|
|
|
-
|
|
|
|
|
String[] ports = (configContent.getServicePort() == null ? "" : configContent.getServicePort()).split(",");
|
|
String[] ports = (configContent.getServicePort() == null ? "" : configContent.getServicePort()).split(",");
|
|
|
if (!StringUtils.isEmpty(configContent.getHostPrefix())) {
|
|
if (!StringUtils.isEmpty(configContent.getHostPrefix())) {
|
|
|
for (String port : ports) {
|
|
for (String port : ports) {
|
|
@@ -572,51 +600,39 @@ public class EnvironmentServiceImpl implements EnvironmentService {
|
|
|
deleteAllPods(id);
|
|
deleteAllPods(id);
|
|
|
}
|
|
}
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
- if (result.getBuildStatus() == BuildStatus.BUILDING) {
|
|
|
|
|
- result.setBuildStatus(BuildStatus.FAIL);
|
|
|
|
|
- result.setBuildOutput(e.getLocalizedMessage());
|
|
|
|
|
- }
|
|
|
|
|
- if (result.getDeployStatus() == DeployStatus.DEPLOYING) {
|
|
|
|
|
- result.setDeployStatus(DeployStatus.FAIL);
|
|
|
|
|
- result.setDeployOutput(e.getLocalizedMessage());
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ result.setDeployStatus(DeployStatus.FAIL);
|
|
|
|
|
+ result.setDeployOutput(e.getLocalizedMessage());
|
|
|
environmentDAO.save(result);
|
|
environmentDAO.save(result);
|
|
|
- LoggerUtil.error(logger, e, "流程失败!");
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ LoggerUtil.error(logger, e, "部署流程失败!");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void buildAndDeploy(Integer id, Boolean useCache) {
|
|
|
|
|
+ if (!useCache) {
|
|
|
|
|
+ buildImage(id);
|
|
|
}
|
|
}
|
|
|
|
|
+ deployToPod(id);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
//获取当前git语境下的最后一次commit记录。
|
|
//获取当前git语境下的最后一次commit记录。
|
|
|
private static String getLatestCommitHash(Git git) throws GitAPIException {
|
|
private static String getLatestCommitHash(Git git) throws GitAPIException {
|
|
|
Iterable<RevCommit> commits = git.log().setMaxCount(1).call();
|
|
Iterable<RevCommit> commits = git.log().setMaxCount(1).call();
|
|
|
return commits.iterator().next().getId().getName();
|
|
return commits.iterator().next().getId().getName();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 若判断是否命中hash,若命中hash,则不需要重新构建
|
|
|
|
|
- private Boolean useLastImage(Environment result, String lastCommitHash) throws GitAPIException {
|
|
|
|
|
- if(lastCommitHash.equals(result.getLastSuccessCommitHash())){
|
|
|
|
|
- logger.info("commitId: "+lastCommitHash+" 与上次构建成功的commitId相同,无需构建");
|
|
|
|
|
- result.setBuildOutput("commitId: "+lastCommitHash+" 与上次构建成功的commitId相同,无需构建");
|
|
|
|
|
-
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
/**
|
|
/**
|
|
|
- *
|
|
|
|
|
- * @author fanyanpeng
|
|
|
|
|
- * @date 2023/11/14 11:34
|
|
|
|
|
- * @param result 环境
|
|
|
|
|
- * @param useCache 是否使用缓存
|
|
|
|
|
|
|
+ * @param result 环境
|
|
|
* @param labelValue 标签值
|
|
* @param labelValue 标签值
|
|
|
* @return void
|
|
* @return void
|
|
|
|
|
+ * @author fanyanpeng
|
|
|
|
|
+ * @date 2023/11/14 11:34
|
|
|
*/
|
|
*/
|
|
|
- private void buildImage(Environment result, Boolean useCache, String labelValue) {
|
|
|
|
|
|
|
+ private void buildImageHelper(Environment result, String labelValue) {
|
|
|
Application application = applicationDAO.findById(result.getAppId()).get();
|
|
Application application = applicationDAO.findById(result.getAppId()).get();
|
|
|
String imageName = "";
|
|
String imageName = "";
|
|
|
-// 1. 有git从git拿到地址进行构建并push
|
|
|
|
|
if (result.getBuildType() == BuildType.FROM_BRANCH_OR_COMMIT) {
|
|
if (result.getBuildType() == BuildType.FROM_BRANCH_OR_COMMIT) {
|
|
|
try {
|
|
try {
|
|
|
|
|
+ // 有git从git拿到地址进行构建并push
|
|
|
Path directory = Files.createTempDirectory("seecoder-paas-");
|
|
Path directory = Files.createTempDirectory("seecoder-paas-");
|
|
|
Git git = gitApi.clone(application.getGitUrl(), directory.toString());
|
|
Git git = gitApi.clone(application.getGitUrl(), directory.toString());
|
|
|
try {
|
|
try {
|
|
@@ -630,50 +646,35 @@ public class EnvironmentServiceImpl implements EnvironmentService {
|
|
|
// 获取最新的commitId
|
|
// 获取最新的commitId
|
|
|
String currentCommitHash = getLatestCommitHash(git);
|
|
String currentCommitHash = getLatestCommitHash(git);
|
|
|
|
|
|
|
|
- // 若成功使用上一次的镜像,就不重新构建了
|
|
|
|
|
- if(useCache && useLastImage(result, currentCommitHash)){
|
|
|
|
|
-
|
|
|
|
|
- result.setBuildStatus(BuildStatus.SUCCESS);
|
|
|
|
|
- result.setDeployStatus(DeployStatus.DEPLOYING);
|
|
|
|
|
- result.setDeployStartTime(LocalDateTime.now());
|
|
|
|
|
- // imageName 无需修改
|
|
|
|
|
- environmentDAO.save(result);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
|
|
|
|
|
if (Files.exists(Paths.get(directory.toString(), "Dockerfile"))) {
|
|
if (Files.exists(Paths.get(directory.toString(), "Dockerfile"))) {
|
|
|
String imageTag = String.valueOf(new Date().getTime());
|
|
String imageTag = String.valueOf(new Date().getTime());
|
|
|
StringBuilder sb = new StringBuilder();
|
|
StringBuilder sb = new StringBuilder();
|
|
|
final int DEFAULT_BUFFER_LENGTH = 200;
|
|
final int DEFAULT_BUFFER_LENGTH = 200;
|
|
|
final long MAX_BUFFER_SIZE = 1 << 18;
|
|
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);
|
|
|
|
|
|
|
+ dockerApi.buildAndPush(directory.toString(), "seecoder-paas-" + labelValue, imageTag, message -> {
|
|
|
|
|
+ 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);
|
|
|
|
|
+ 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);
|
|
|
}
|
|
}
|
|
|
- },useCache);
|
|
|
|
|
|
|
+ }, false);
|
|
|
if (sb.length() > 0) {
|
|
if (sb.length() > 0) {
|
|
|
- result.setBuildOutput(result.getBuildOutput() + sb.toString());
|
|
|
|
|
|
|
+ result.setBuildOutput(result.getBuildOutput() + sb);
|
|
|
}
|
|
}
|
|
|
imageName = applicationProperties.getK8s().getImageRegistry() + "/seecoder-paas-" + labelValue + ":" + imageTag;
|
|
imageName = applicationProperties.getK8s().getImageRegistry() + "/seecoder-paas-" + labelValue + ":" + imageTag;
|
|
|
result.setBuildStatus(BuildStatus.SUCCESS);
|
|
result.setBuildStatus(BuildStatus.SUCCESS);
|
|
|
- result.setDeployStatus(DeployStatus.DEPLOYING);
|
|
|
|
|
result.setDeployStartTime(LocalDateTime.now());
|
|
result.setDeployStartTime(LocalDateTime.now());
|
|
|
result.setImage(imageName);
|
|
result.setImage(imageName);
|
|
|
result.setLastSuccessCommitHash(currentCommitHash);
|
|
result.setLastSuccessCommitHash(currentCommitHash);
|
|
@@ -691,19 +692,15 @@ public class EnvironmentServiceImpl implements EnvironmentService {
|
|
|
}
|
|
}
|
|
|
environmentDAO.save(result);
|
|
environmentDAO.save(result);
|
|
|
LoggerUtil.error(logger, e, "构建失败!gitUrl={}, branchOrCommit={}", application.getGitUrl(), result.getBuildTypeValue());
|
|
LoggerUtil.error(logger, e, "构建失败!gitUrl={}, branchOrCommit={}", application.getGitUrl(), result.getBuildTypeValue());
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
} else if (result.getBuildType() == BuildType.FROM_IMAGE) {
|
|
} else if (result.getBuildType() == BuildType.FROM_IMAGE) {
|
|
|
imageName = result.getBuildTypeValue();
|
|
imageName = result.getBuildTypeValue();
|
|
|
result.setBuildStatus(BuildStatus.SUCCESS);
|
|
result.setBuildStatus(BuildStatus.SUCCESS);
|
|
|
- result.setBuildOutput("镜像构建无需部署");
|
|
|
|
|
- result.setDeployStatus(DeployStatus.DEPLOYING);
|
|
|
|
|
|
|
+ result.setBuildOutput("已有镜像构建无需构建");
|
|
|
result.setDeployStartTime(LocalDateTime.now());
|
|
result.setDeployStartTime(LocalDateTime.now());
|
|
|
result.setImage(imageName);
|
|
result.setImage(imageName);
|
|
|
environmentDAO.save(result);
|
|
environmentDAO.save(result);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|