1
0
370774330@qq.com 5 лет назад
Родитель
Сommit
a5545b972c
100 измененных файлов с 609 добавлено и 2579 удалено
  1. 5 0
      api/pom.xml
  2. 10 53
      api/src/main/java/seecoder/devcloud/api/ApplicationProperties.java
  3. 4 22
      api/src/main/java/seecoder/devcloud/api/DevcloudApiAutoConfiguration.java
  4. 3 5
      api/src/main/java/seecoder/devcloud/api/docker/impl/DockerApiImpl.java
  5. 2 3
      api/src/main/java/seecoder/devcloud/api/git/impl/GitApiImpl.java
  6. 0 144
      api/src/main/java/seecoder/devcloud/api/gitlab/GitlabApi.java
  7. 0 381
      api/src/main/java/seecoder/devcloud/api/gitlab/impl/GitlabApiImpl.java
  8. 0 18
      api/src/main/java/seecoder/devcloud/api/gitlab/model/CommitDetails.java
  9. 0 19
      api/src/main/java/seecoder/devcloud/api/gitlab/model/GitlabGroup.java
  10. 0 10
      api/src/main/java/seecoder/devcloud/api/gitlab/model/GitlabUser.java
  11. 0 66
      api/src/main/java/seecoder/devcloud/api/jenkins/JenkinsApi.java
  12. 0 195
      api/src/main/java/seecoder/devcloud/api/jenkins/impl/JenkinsApiImpl.java
  13. 0 38
      api/src/main/java/seecoder/devcloud/api/jenkins/impl/PoolingJenkinsHttpClient.java
  14. 0 19
      api/src/main/java/seecoder/devcloud/api/jenkins/model/BuildDetails.java
  15. 0 27
      api/src/main/java/seecoder/devcloud/api/jenkins/model/CoverageResult.java
  16. 0 11
      api/src/main/java/seecoder/devcloud/api/jenkins/model/CoverageResultElement.java
  17. 0 9
      api/src/main/java/seecoder/devcloud/api/jenkins/model/MutationResult.java
  18. 1 1
      api/src/main/java/seecoder/devcloud/api/k8s/DeploymentApi.java
  19. 1 2
      api/src/main/java/seecoder/devcloud/api/k8s/ExecApi.java
  20. 0 4
      api/src/main/java/seecoder/devcloud/api/k8s/K8sApiConfiguration.java
  21. 1 1
      api/src/main/java/seecoder/devcloud/api/k8s/PodApi.java
  22. 0 1
      api/src/main/java/seecoder/devcloud/api/k8s/SecretApi.java
  23. 13 12
      api/src/main/java/seecoder/devcloud/api/k8s/impl/ConfigMapApiImpl.java
  24. 13 11
      api/src/main/java/seecoder/devcloud/api/k8s/impl/DeploymentApiImpl.java
  25. 7 5
      api/src/main/java/seecoder/devcloud/api/k8s/impl/ExecApiImpl.java
  26. 13 15
      api/src/main/java/seecoder/devcloud/api/k8s/impl/IngressApiImpl.java
  27. 7 7
      api/src/main/java/seecoder/devcloud/api/k8s/impl/NamespaceApiImpl.java
  28. 11 10
      api/src/main/java/seecoder/devcloud/api/k8s/impl/PersistentVolumeClaimImpl.java
  29. 6 7
      api/src/main/java/seecoder/devcloud/api/k8s/impl/PodApiImpl.java
  30. 6 4
      api/src/main/java/seecoder/devcloud/api/k8s/impl/SecretApiImpl.java
  31. 12 14
      api/src/main/java/seecoder/devcloud/api/k8s/impl/ServiceApiImpl.java
  32. 3 3
      api/src/main/java/seecoder/devcloud/api/k8s/model/ConfigMap.java
  33. 0 1
      api/src/main/java/seecoder/devcloud/api/k8s/model/ContainerPort.java
  34. 2 1
      api/src/main/java/seecoder/devcloud/api/k8s/model/Deployment.java
  35. 2 2
      api/src/main/java/seecoder/devcloud/api/k8s/model/Ingress.java
  36. 0 3
      api/src/main/java/seecoder/devcloud/api/k8s/model/K8sObject.java
  37. 2 1
      api/src/main/java/seecoder/devcloud/api/k8s/model/Namespace.java
  38. 1 1
      api/src/main/java/seecoder/devcloud/api/k8s/model/PersistentVolumeClaim.java
  39. 1 1
      api/src/main/java/seecoder/devcloud/api/k8s/model/Pod.java
  40. 4 1
      api/src/main/java/seecoder/devcloud/api/k8s/model/Service.java
  41. 0 1
      api/src/main/java/seecoder/devcloud/api/k8s/vo/SecretVO.java
  42. 0 19
      api/src/main/java/seecoder/devcloud/api/nexus/AssetApi.java
  43. 0 79
      api/src/main/java/seecoder/devcloud/api/nexus/ComponentApi.java
  44. 0 187
      api/src/main/java/seecoder/devcloud/api/nexus/NexusApi.java
  45. 0 16
      api/src/main/java/seecoder/devcloud/api/nexus/NexusApiBean.java
  46. 0 53
      api/src/main/java/seecoder/devcloud/api/nexus/TaskApi.java
  47. 0 73
      api/src/main/java/seecoder/devcloud/api/nexus/exception/NexusApiException.java
  48. 0 99
      api/src/main/java/seecoder/devcloud/api/nexus/impl/AbstractApi.java
  49. 0 67
      api/src/main/java/seecoder/devcloud/api/nexus/impl/AssetApiImpl.java
  50. 0 144
      api/src/main/java/seecoder/devcloud/api/nexus/impl/ComponentApiImpl.java
  51. 0 28
      api/src/main/java/seecoder/devcloud/api/nexus/impl/Constants.java
  52. 0 89
      api/src/main/java/seecoder/devcloud/api/nexus/impl/TaskApiImpl.java
  53. 0 17
      api/src/main/java/seecoder/devcloud/api/nexus/model/ApiVersion.java
  54. 0 21
      api/src/main/java/seecoder/devcloud/api/nexus/model/Asset.java
  55. 0 13
      api/src/main/java/seecoder/devcloud/api/nexus/model/AssetList.java
  56. 0 23
      api/src/main/java/seecoder/devcloud/api/nexus/model/Component.java
  57. 0 16
      api/src/main/java/seecoder/devcloud/api/nexus/model/ComponentList.java
  58. 0 9
      api/src/main/java/seecoder/devcloud/api/nexus/model/NexusList.java
  59. 0 25
      api/src/main/java/seecoder/devcloud/api/nexus/model/Task.java
  60. 0 15
      api/src/main/java/seecoder/devcloud/api/nexus/model/TaskList.java
  61. 0 1
      common/src/main/java/seecoder/devcloud/common/CommonAutoConfiguration.java
  62. 1 1
      common/src/main/java/seecoder/devcloud/common/exceptions/ServiceException.java
  63. 1 0
      common/src/main/java/seecoder/devcloud/common/util/FileUtil.java
  64. 0 2
      common/src/main/java/seecoder/devcloud/common/util/JwtTokenUtil.java
  65. 1 1
      common/src/main/java/seecoder/devcloud/common/util/RandomStringUtil.java
  66. 0 1
      common/src/main/java/seecoder/devcloud/common/util/SpringUtil.java
  67. 8 1
      core/src/main/java/seecoder/devcloud/core/pipeline/Context.java
  68. 3 3
      core/src/main/java/seecoder/devcloud/core/pipeline/Handler.java
  69. 1 1
      core/src/main/java/seecoder/devcloud/core/pipeline/Pipeline.java
  70. 5 2
      core/src/main/java/seecoder/devcloud/core/pipeline/PipelineException.java
  71. 2 2
      core/src/main/java/seecoder/devcloud/core/pipeline/PipelineFactory.java
  72. 3 3
      core/src/main/java/seecoder/devcloud/core/pipeline/config/HandlerConfigTable.java
  73. 3 8
      core/src/main/java/seecoder/devcloud/core/pipeline/handler/AbstractHandler.java
  74. 108 168
      core/src/main/java/seecoder/devcloud/core/pipeline/handler/DockerImageBuildHandler.java
  75. 23 30
      core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sDeploymentHandler.java
  76. 56 53
      core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sIngressHandler.java
  77. 0 4
      core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sNamespaceHandler.java
  78. 2 1
      core/src/main/java/seecoder/devcloud/core/pipeline/pipeline/PipelineImpl.java
  79. 43 0
      core/src/main/java/seecoder/devcloud/core/pipeline/template/PipelineTemplateTable.java
  80. 9 0
      core/src/main/resources/template/config/test.json
  81. 15 0
      core/src/main/resources/template/dockerfile/TEMPLATE_DOCKERFILE_JAVA8
  82. 7 2
      web/pom.xml
  83. 9 4
      web/src/main/java/seecoder/devcloud/web/controller/pipeline/PipelineController.java
  84. 5 6
      web/src/main/java/seecoder/devcloud/web/controller/project/ProjectController.java
  85. 58 0
      web/src/main/java/seecoder/devcloud/web/controller/user/GroupController.java
  86. 1 13
      web/src/main/java/seecoder/devcloud/web/dao/user/GroupMapper.java
  87. 20 3
      web/src/main/java/seecoder/devcloud/web/infrastructure/GlobalExceptionHandler.java
  88. 21 0
      web/src/main/java/seecoder/devcloud/web/infrastructure/ValidationExceptionHandler.java
  89. 0 1
      web/src/main/java/seecoder/devcloud/web/infrastructure/security/JwtAuthenticationTokenFilter.java
  90. 1 27
      web/src/main/java/seecoder/devcloud/web/model/po/user/Group.java
  91. 2 1
      web/src/main/java/seecoder/devcloud/web/model/vo/pipeline/PipelineCreateVO.java
  92. 0 9
      web/src/main/java/seecoder/devcloud/web/model/vo/user/GroupVO.java
  93. 0 49
      web/src/main/java/seecoder/devcloud/web/model/vo/user/RegisterVO.java
  94. 20 5
      web/src/main/java/seecoder/devcloud/web/service/impl/project/ProjectServiceImpl.java
  95. 38 45
      web/src/main/java/seecoder/devcloud/web/service/impl/user/GroupServiceImpl.java
  96. 2 0
      web/src/main/java/seecoder/devcloud/web/service/project/ProjectService.java
  97. 9 2
      web/src/main/java/seecoder/devcloud/web/service/user/GroupService.java
  98. 1 1
      web/src/main/java/seecoder/devcloud/web/service/user/UserService.java
  99. 1 4
      web/src/main/resources/SQLscripts/group.sql
  100. 0 3
      web/src/main/resources/SQLscripts/group_member.sql

+ 5 - 0
api/pom.xml

@@ -25,6 +25,11 @@
 
 
     <dependencies>
+        <dependency>
+            <groupId>com.nju.edu</groupId>
+            <artifactId>seecoder-gitlab-client</artifactId>
+            <version>0.1.0</version>
+        </dependency>
         <!-- https://mvnrepository.com/artifact/org.eclipse.jgit/org.eclipse.jgit -->
         <dependency>
             <groupId>org.eclipse.jgit</groupId>

+ 10 - 53
api/src/main/java/seecoder/devcloud/api/ApplicationProperties.java

@@ -1,7 +1,6 @@
 package seecoder.devcloud.api;
 
 import lombok.Data;
-import org.apache.commons.lang3.StringUtils;
 import org.hibernate.validator.constraints.URL;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.context.annotation.Configuration;
@@ -10,10 +9,6 @@ import org.springframework.validation.annotation.Validated;
 import javax.validation.Valid;
 import javax.validation.constraints.Email;
 import javax.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Pattern;
-import java.util.HashMap;
-import java.util.Map;
 
 @Data
 @Configuration
@@ -24,16 +19,12 @@ public class ApplicationProperties {
 	@Valid
 	private Gitlab gitlab = new Gitlab();
 	@Valid
-	private Jenkins jenkins = new Jenkins();
-	@Valid
 	private Docker docker = new Docker();
 	@Valid
 	private Mail mail = new Mail();
 	@Valid
 	private K8s k8s = new K8s();
 	@Valid
-	private Registry registry = new Registry();
-	@Valid
 	private Git git = new Git();
 
 	@Data
@@ -43,18 +34,6 @@ public class ApplicationProperties {
 		@NotEmpty
 		private String host;
 
-		//private String gitProxy;
-		/**
-		 * 回调地址
-		 */
-		@URL
-		@NotEmpty
-		private String webHookProxy;
-
-
-        @NotNull
-        private Integer userId = 1;
-
 		/**
 		 * 采用的Personal/project access tokens的认证方式
 		 * 这里使用管理员的token
@@ -67,22 +46,15 @@ public class ApplicationProperties {
 	}
 
 	@Data
-	public static class Jenkins {
-		@URL
-		@NotEmpty
+	public static class Docker {
+
 		private String host;
-		@NotEmpty
-		private String username = "root";
-		@NotEmpty
-		private String token;
-	}
 
-	@Data
-	public static class Docker {
-		@NotEmpty
-		private String host = "unix:///var/run/docker.sock";
-		@NotEmpty
 		private String registry;
+
+		private String registryUsername;
+
+		private String registryPassword;
 	}
 
 	@Data
@@ -106,27 +78,12 @@ public class ApplicationProperties {
 		private Boolean validateSSL = false;
 
 		private Boolean debugging = false;
-	}
-
-	@Data
-	public static class Registry{
-		@NotEmpty
-		private String host;
 
-		@NotEmpty
-		private String username;
-
-		@NotEmpty
-		private String password;
-
-		@NotEmpty
-		private String nexusServer;
-
-        @NotEmpty
-        private String repoName = "sec-repo";
+		/**
+		 * k8s配置ingress时候的host后缀
+		 */
+		private String ingressHostSuffix;
 
-		@NotEmpty
-		private String cleanUpTask = "4da7e1e1-2b28-46b5-a080-9d834cc96019";
 	}
 
 	@Data

+ 4 - 22
api/src/main/java/seecoder/devcloud/api/DevcloudApiAutoConfiguration.java

@@ -1,6 +1,7 @@
 package seecoder.devcloud.api;
 
-import org.eclipse.jgit.api.Git;
+import com.nju.edu.gitlab.SeecoderGitlabApi;
+import com.nju.edu.gitlab.SeecoderGitlabClient;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -8,14 +9,8 @@ import seecoder.devcloud.api.docker.DockerApi;
 import seecoder.devcloud.api.docker.impl.DockerApiImpl;
 import seecoder.devcloud.api.git.GitApi;
 import seecoder.devcloud.api.git.impl.GitApiImpl;
-import seecoder.devcloud.api.gitlab.GitlabApi;
-import seecoder.devcloud.api.gitlab.impl.GitlabApiImpl;
-import seecoder.devcloud.api.jenkins.JenkinsApi;
-import seecoder.devcloud.api.jenkins.impl.JenkinsApiImpl;
 import seecoder.devcloud.api.k8s.*;
 import seecoder.devcloud.api.k8s.impl.*;
-import seecoder.devcloud.api.nexus.NexusApi;
-import seecoder.devcloud.api.nexus.model.ApiVersion;
 
 /**
  * @author PuHong Weng
@@ -32,8 +27,8 @@ public class DevcloudApiAutoConfiguration {
 
     @Bean
     @ConditionalOnBean(ApplicationProperties.class)
-    public GitlabApi gitlabApi(){
-        return new GitlabApiImpl(applicationProperties());
+    public SeecoderGitlabApi seecoderGitlabApi(){
+        return new SeecoderGitlabClient(applicationProperties().getGitlab().getHost(),applicationProperties().getGitlab().getToken());
     }
 
     @Bean
@@ -48,19 +43,6 @@ public class DevcloudApiAutoConfiguration {
         return new K8sApiConfiguration(applicationProperties());
     }
 
-    @Bean
-    @ConditionalOnBean(ApplicationProperties.class)
-    public JenkinsApi jenkinsApi(){
-        return new JenkinsApiImpl(applicationProperties());
-    }
-
-    @Bean
-    @ConditionalOnBean(ApplicationProperties.class)
-    public NexusApi nexusApi(){
-        ApplicationProperties properties = applicationProperties();
-        return new NexusApi(properties.getRegistry().getNexusServer(), ApiVersion.V1, properties.getRegistry().getUsername(), properties.getRegistry().getPassword());
-    }
-
     @Bean
     @ConditionalOnBean(ApplicationProperties.class)
     public DockerApi dockerApi(){

+ 3 - 5
api/src/main/java/seecoder/devcloud/api/docker/impl/DockerApiImpl.java

@@ -61,9 +61,7 @@ public class DockerApiImpl implements DockerApi {
         List<Image> images = new ArrayList<>();
         try {
             images = client.listImages(DockerClient.ListImagesParam.allImages());
-        } catch (DockerException e) {
-            e.printStackTrace();
-        } catch (InterruptedException e) {
+        } catch (DockerException | InterruptedException e) {
             e.printStackTrace();
         }
         return images;
@@ -73,14 +71,14 @@ public class DockerApiImpl implements DockerApi {
         client.removeImage(imageId);
     }
 
-    private class NoActionProgressHandler implements ProgressHandler {
+    private static class NoActionProgressHandler implements ProgressHandler {
         @Override
         public void progress(ProgressMessage message) {
             //IGNORE THE MESSAGE
         }
     }
 
-    private class LogActionProgressHandler implements ProgressHandler {
+    private static class LogActionProgressHandler implements ProgressHandler {
         @Override
         public void progress(ProgressMessage message) {
 //            if (message.error() != null)

+ 2 - 3
api/src/main/java/seecoder/devcloud/api/git/impl/GitApiImpl.java

@@ -14,7 +14,7 @@ import java.io.File;
 @Component
 public class GitApiImpl implements GitApi {
 
-    private CredentialsProvider credentialsProvider;
+    private final CredentialsProvider credentialsProvider;
 
     @Autowired
     public GitApiImpl(ApplicationProperties properties) {
@@ -24,10 +24,9 @@ public class GitApiImpl implements GitApi {
 
     @Override
     public Git clone(String repoUrl, String directory) throws Exception {
-        Git git = Git.cloneRepository()
+        return Git.cloneRepository()
                 .setCredentialsProvider(credentialsProvider)
                 .setURI(repoUrl)
                 .setDirectory(new File(directory)).call();
-        return git;
     }
 }

+ 0 - 144
api/src/main/java/seecoder/devcloud/api/gitlab/GitlabApi.java

@@ -1,144 +0,0 @@
-package seecoder.devcloud.api.gitlab;
-
-
-
-import seecoder.devcloud.api.gitlab.model.CommitDetails;
-import seecoder.devcloud.api.gitlab.model.GitlabGroup;
-import seecoder.devcloud.api.gitlab.model.GitlabUser;
-import org.gitlab4j.api.GitLabApiException;
-import org.gitlab4j.api.models.CommitAction;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.util.List;
-import java.util.Set;
-
-public interface GitlabApi {
-	GitlabUser createUser(String username, String email, String password) throws GitLabApiException;
-
-
-	//10 => Guest access
-	//20 => Reporter access
-	//30 => Developer access
-	//40 => Maintainer access
-	//50 => Owner access # Only valid for groups
-	GitlabGroup createGroup(String groupName) throws GitLabApiException;
-
-
-	void addMemberToGroup(Integer groupId, Integer userId) throws GitLabApiException;
-
-	void quitGroup(Integer groupId, Integer userId) throws GitLabApiException;
-
-	Integer addProjectToGroup(Integer groupId, String projectName) throws GitLabApiException;
-
-	/**
-	 * 创建internal项目,默认登录用户可见,在个人作业中使用,因为个人项目的fork,只能用户来fork,所以设置为internal
-	 * @param name
-	 * @return
-	 * @throws GitLabApiException
-	 */
-	Integer createProject(String name) throws GitLabApiException;
-
-	/**
-	 * 创建私有项目,在团队作业中使用,因为root是在每个小组中的,所以root用户可以把该私有项目fork到指定组
-	 * 目前用户在团队里是master权限,团队的私有项目,目前团队里成员可见
-	 * @param name
-	 * @return
-	 * @throws GitLabApiException
-	 */
-	Integer createPrivateProject(String name) throws GitLabApiException;
-
-	Integer createProjectForGroup(String name, int groupId) throws GitLabApiException;
-
-	Integer forkProject(int userId, int projectId, int namespaceId) throws GitLabApiException;
-
-	Set<String> compare(int projectId, String from, String to) throws GitLabApiException;
-
-	void archiveProject(int projectId) throws GitLabApiException;
-
-	void changePassword(int userId, String password) throws GitLabApiException;
-
-	void deleteUser(int userId) throws GitLabApiException;
-
-	void deleteProject(int projectId) throws GitLabApiException;
-
-	/**
-	 * get file content
-	 * @param projectId
-	 * @param branch
-	 * @param path
-	 * @return
-	 */
-	String getRepositoryFile(int projectId, String branch, String path) throws GitLabApiException, UnsupportedEncodingException;
-
-	/**
-	 * create a commit
-	 * @param projectId
-	 * @param branch
-	 * @param commitMessage
-	 * @param email
-	 * @param username
-	 * @param actions
-	 */
-	void createCommit(int projectId, String branch, String commitMessage, String email, String username, List<CommitAction> actions) throws GitLabApiException;
-
-	/**
-	 * 获取root用户的id
-	 * @return
-	 **/
-	Integer getRootUserId();
-
-    /**
-     * 为文档作业fork项目,主要涉及webhook不同
-     * @param userId
-     * @param projectId
-     * @param namespaceId
-     * @return
-     * @throws GitLabApiException
-     */
-	Integer forkProjectForDocumentWork(int userId, int projectId, int namespaceId) throws GitLabApiException;
-
-    /**
-     * 为代码作业fork项目同时设置WebHook
-     * @param userId
-     * @param projectId
-     * @param namespaceId
-     * @return
-     * @throws GitLabApiException
-     */
-	Integer forkProjectForCodeWork(int userId, int projectId, int namespaceId) throws GitLabApiException;
-
-    /**
-     * 为深度学习作业fork项目并设置WebHook
-     *
-     * @param baseRepoId  需要fork的源项目Id
-     * @param namespaceId namespace的Id
-     * @return fork出的repository的Id
-     */
-    Integer forkProjectForDLWork(int baseRepoId, int namespaceId) throws GitLabApiException;
-
-    /**
-     * 获取某次提交后的文件内容
-     * @param projectId the id of the project in gitlab
-     * @param commit hash of the commit
-     * @param path path of the file
-     * @return
-     * @throws GitLabApiException
-     * @throws IOException
-     */
-    String getRawRepositoryFile(int projectId, String commit, String path) throws GitLabApiException, IOException;
-
-    CommitDetails getCommitMessage(int projectId, String commitHash) throws GitLabApiException;
-
-	/**
-	 * 找到该次commit所对应的branch 因为分支签出的关系,某个commit有可能属于多个分支
-	 * @param projectId
-	 * @param commitHash
-	 * @return
-	 * @throws GitLabApiException
-	 */
-	List<CommitDetails> getAllCommits(int projectId, String commitHash) throws GitLabApiException;
-
-
-
-}

+ 0 - 381
api/src/main/java/seecoder/devcloud/api/gitlab/impl/GitlabApiImpl.java

@@ -1,381 +0,0 @@
-package seecoder.devcloud.api.gitlab.impl;
-
-
-import seecoder.devcloud.api.ApplicationProperties;
-import seecoder.devcloud.api.gitlab.GitlabApi;
-import seecoder.devcloud.api.gitlab.model.CommitDetails;
-import seecoder.devcloud.api.gitlab.model.GitlabGroup;
-import seecoder.devcloud.api.gitlab.model.GitlabUser;
-import org.gitlab4j.api.*;
-import org.gitlab4j.api.models.*;
-import org.gitlab4j.api.models.ImpersonationToken.Scope;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-import seecoder.devcloud.common.util.ToolKit;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
-import java.nio.charset.StandardCharsets;
-import java.time.Instant;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-import java.util.*;
-import java.util.stream.Collectors;
-
-@Component
-public class GitlabApiImpl implements GitlabApi {
-    private final ApplicationProperties.Gitlab gitlab;
-
-    private final GitLabApi server;
-
-    @Autowired
-    public GitlabApiImpl(ApplicationProperties properties) {
-        gitlab = properties.getGitlab();
-        this.server = new GitLabApi(gitlab.getHost(), gitlab.getToken());
-    }
-
-    @Override
-    public synchronized GitlabUser createUser(String username, String email,
-                                              String password) throws GitLabApiException {
-        User user = new User();
-        user.setUsername(username);
-        user.setEmail(email);
-        user.setName(username);
-        user.setSkipConfirmation(true);
-        user = server.getUserApi().createUser(user, password, 1000);
-        GitlabUser gitlabUser = new GitlabUser();
-        gitlabUser.setId(user.getId());
-        gitlabUser.setNamespace(fetchNamespace(username));
-        gitlabUser.setToken(createToken(user.getId()));
-        return gitlabUser;
-    }
-
-    //10 => Guest access
-    //20 => Reporter access
-    //30 => Developer access
-    //40 => Maintainer access
-    //50 => Owner access # Only valid for groups
-    @Override
-    public synchronized GitlabGroup createGroup(String groupName) throws GitLabApiException {
-
-        final Group group = server.getGroupApi().addGroup(groupName, groupName);//todo:Group默认private
-        GitlabGroup gitlabGroup = new GitlabGroup();
-        gitlabGroup.setId(group.getId());
-        final Integer ns1 = fetchNamespace("group", groupName);
-        gitlabGroup.setNamespace(ns1);//todo:Namespace
-
-//		server.getGroupApi().addMember(group.getId(), userId, 50);
-
-        return gitlabGroup;
-    }
-
-    @Override
-    public void addMemberToGroup(Integer groupId, Integer userId) throws GitLabApiException {
-        server.getGroupApi().addMember(groupId, userId, AccessLevel.MASTER);
-    }
-
-    @Override
-    public void quitGroup(Integer groupId, Integer userId) throws GitLabApiException {
-        server.getGroupApi().removeMember(groupId,userId);
-    }
-
-
-    @Override
-    public synchronized Integer addProjectToGroup(Integer groupId, String projectName) throws GitLabApiException {
-        final Project project = server.getProjectApi().createProject(groupId, projectName);
-        return project != null ? project.getId() : null;
-    }
-
-    private Integer fetchNamespace(String username) throws GitLabApiException {
-        Namespace namespace;
-        namespace = server.getNamespaceApi().findNamespaces(username)
-                .stream()
-                .filter(ns -> "user".equals(ns.getKind()))
-                .reduce((ns1, ns2) -> ns1.getId() > ns2.getId() ? ns1 : ns2)
-                .orElse(null);
-        return namespace != null ? namespace.getId() : null;
-    }
-
-    private Integer fetchNamespace(String type, String name) throws GitLabApiException {
-        Namespace namespace;
-        namespace = server.getNamespaceApi().findNamespaces(name)
-                .stream()
-                .filter(ns -> type.equals(ns.getKind()))
-                .reduce((ns1, ns2) -> ns1.getId() > ns2.getId() ? ns1 : ns2)
-                .orElse(null);
-        return namespace != null ? namespace.getId() : null;
-    }
-
-    private String createToken(int userId) throws GitLabApiException {
-        Scope[] scopes = new Scope[]{Scope.API};
-        ImpersonationToken token;
-        token = server.getUserApi().createImpersonationToken(userId, "AES-" + ToolKit.randomUUID(), null, scopes);
-        return token.getToken();
-    }
-
-    @Override
-    public synchronized Integer createProject(String name) throws GitLabApiException {
-        Project project = new Project();
-        project.setName(name);
-        project.setVisibility(Visibility.INTERNAL);
-        project = server.getProjectApi().createProject(project);
-        return project != null ? project.getId() : null;
-    }
-
-    @Override
-    public synchronized Integer createPrivateProject(String name) throws GitLabApiException {
-        Project project = new Project();
-        project.setName(name);
-        project.setVisibility(Visibility.PRIVATE);
-        project = server.getProjectApi().createProject(project);
-        return project != null ? project.getId() : null;
-    }
-
-    @Override
-    public synchronized Integer createProjectForGroup(String name, int groupId) throws GitLabApiException {
-        Project project = server.getProjectApi().createProject(groupId, name);
-        return project != null ? project.getId() : null;
-    }
-
-    @Override
-    public synchronized Integer forkProject(int userId, int projectId, int namespaceId) throws GitLabApiException {
-        Project project;
-        try {
-            server.setSudoAsId(userId);
-            project = server.getProjectApi().forkProject(projectId, namespaceId);
-            project.setVisibility(Visibility.PRIVATE);
-            project = server.getProjectApi().updateProject(project);
-        } finally {
-            server.unsudo();
-        }
-        if (project != null) {
-            createWebHook(project.getId());
-        }
-        return project != null ? project.getId() : null;
-    }
-
-    @Override
-    public synchronized Set<String> compare(int projectId, String from, String to) throws GitLabApiException {
-        CompareResults compareResults = server.getRepositoryApi().compare(projectId, from, to);
-        return compareResults.getDiffs().stream()
-                .map(Diff::getNewPath)
-                .map(p -> {
-                    int end = p.indexOf('/');
-                    if (end == -1) {
-                        end = p.length();
-                    }
-                    return p.substring(0, end);
-                })
-                .collect(Collectors.toSet());
-    }
-
-    private void createWebHook(int id) throws GitLabApiException {
-        String url = gitlab.getWebHookProxy() + "/internal/notify/webhook/" + id;
-        server.getProjectApi().addHook(id, url, true, false, false);
-    }
-
-    @Override
-    public synchronized void archiveProject(int projectId) throws GitLabApiException {
-        server.getProjectApi().archiveProject(projectId);
-    }
-
-    @Override
-    public synchronized void changePassword(int userId, String password) throws GitLabApiException {
-        User user = server.getUserApi().getUser(userId);
-        //server.getUserApi().modifyUser(user, password, user.getProjectsLimit());
-        server.getUserApi().updateUser(user, password);
-    }
-
-    @Override
-    public synchronized void deleteUser(int userId) throws GitLabApiException {
-        server.getUserApi().deleteUser(userId, true);
-    }
-
-    @Override
-    public void deleteProject(int projectId) throws GitLabApiException {
-        server.getProjectApi().deleteProject(projectId);
-    }
-
-    /**
-     * 获得项目下的文件
-     *
-     * @param path 文件的相对路径
-     * @return 文件内容
-     */
-    @Override
-    public String getRepositoryFile(int projectId, String branch,
-                                    String path) throws GitLabApiException, UnsupportedEncodingException {
-        RepositoryFileApi repositoryFileApi = server.getRepositoryFileApi();
-        RepositoryFile repositoryFile = repositoryFileApi.getFile(path, projectId, branch);
-        if (repositoryFile != null) {
-            return new String(Base64.getDecoder().decode(repositoryFile.getContent()), StandardCharsets.UTF_8);
-        }
-        return null;
-    }
-
-    @Override
-    public String getRawRepositoryFile(int projectId, String commit,
-                                       String path) throws GitLabApiException, IOException {
-        RepositoryFileApi repositoryFileApi = server.getRepositoryFileApi();
-        InputStream repositoryFile = repositoryFileApi.getRawFile(projectId, commit, path);
-        InputStreamReader reader = new InputStreamReader(repositoryFile);
-        StringBuilder stringBuilder = new StringBuilder();
-        char[] content = new char[1024];
-        int readCount = 0;
-        while ((readCount = reader.read(content)) > 0) {
-            stringBuilder.append(Arrays.copyOfRange(content, 0, readCount));
-        }
-        return stringBuilder.toString();
-    }
-
-    @Override
-    public void createCommit(int projectId, String branch, String commitMessage, String email, String username,
-                             List<CommitAction> actions) throws GitLabApiException {
-        CommitsApi commitsApi = server.getCommitsApi();
-        commitsApi.createCommit(projectId, branch, commitMessage, null, email, username, actions);
-    }
-
-    @Override
-    public Integer getRootUserId() {
-        return gitlab.getUserId();
-    }
-
-    @Override
-    public synchronized Integer forkProjectForDocumentWork(int userId, int projectId,
-                                                           int namespaceId) throws GitLabApiException {
-        Project project;
-        try {
-            server.setSudoAsId(userId);
-            project = server.getProjectApi().forkProject(projectId, namespaceId);
-            project.setVisibility(Visibility.PRIVATE);
-            project = server.getProjectApi().updateProject(project);
-        } finally {
-            server.unsudo();
-        }
-        if (project != null) {
-            String url = gitlab.getWebHookProxy() + "/internal/notify/webhook/document/" + project.getId();
-            server.getProjectApi().addHook(project, url, true, false, false);
-        }
-        return project != null ? project.getId() : null;
-    }
-
-    @Override
-    public Integer forkProjectForCodeWork(int userId, int projectId, int namespaceId) throws GitLabApiException {
-        Project project;
-        try {
-            server.setSudoAsId(userId);
-            project = server.getProjectApi().forkProject(projectId, namespaceId);
-            project.setVisibility(Visibility.PRIVATE);
-            project = server.getProjectApi().updateProject(project);
-        } finally {
-            server.unsudo();
-        }
-        if (project != null) {
-            // TODO
-            String url_build = gitlab.getWebHookProxy() + "/internal/notify/webhook/code/build/" + project.getId();
-            server.getProjectApi().addHook(project, url_build, true, false, false);
-            // TODO
-            String url_test = gitlab.getWebHookProxy() + "/internal/notify/webhook/code/unit/" + project.getId();
-            server.getProjectApi().addHook(project, url_test, true, false, false);
-        }
-        return project != null ? project.getId() : null;
-    }
-
-    @Override
-    public Integer forkProjectForDLWork(int baseRepoId, int namespaceId) throws GitLabApiException {
-        Project project;
-        ProjectApi projectApi = server.getProjectApi();
-        try {
-            server.setSudoAsId(getRootUserId());
-            project = projectApi.forkProject(baseRepoId, namespaceId);
-            project.setVisibility(Visibility.PRIVATE);
-            project = projectApi.updateProject(project);
-        } finally {
-            server.unsudo();
-        }
-
-        if (project != null) {
-            Integer newProjectId = project.getId();
-            final String webHookUrl = gitlab.getWebHookProxy() + "/internal/notify/webhook/dlwork/" + newProjectId;
-            projectApi.addHook(project, webHookUrl, true, false, false);
-            return newProjectId;
-        }
-        return null;
-    }
-
-
-    @Override
-    public CommitDetails getCommitMessage(int projectId, String commitHash) throws GitLabApiException {
-        CommitsApi commitsApi = server.getCommitsApi();
-        CommitDetails commitDetails = new CommitDetails();
-
-        commitDetails.setProjectId(projectId);
-        commitDetails.setCommitHash(commitHash);
-
-        Commit currentCommit = commitsApi.getCommit(projectId, commitHash);
-
-        RepositoryApi repositoryApi = server.getRepositoryApi();
-        List<Branch> branches = repositoryApi.getBranches(projectId);
-
-        branches.forEach(branch -> {
-            try {
-                List<Commit> commitList = commitsApi.getCommits(projectId, branch.getName(), null);
-                Commit theCommit = commitList.stream().filter(commit -> commit.getId().equals(currentCommit.getId()))
-                        .findFirst().orElse(null);
-
-                if(theCommit!=null){
-                    commitDetails.setBranch(branch.getName());
-                    commitDetails.setCommitMessage(theCommit.getMessage());
-                    commitDetails.setUrl(theCommit.getUrl());
-                    Instant instant = theCommit.getCommittedDate().toInstant();
-                    ZoneId zoneId = ZoneId.systemDefault();
-                    LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
-                    commitDetails.setTime(localDateTime);
-                    commitDetails.setAuthor(theCommit.getAuthorName());
-                }
-            } catch (GitLabApiException e) {
-                e.printStackTrace();
-            }
-        });
-
-        return commitDetails;
-    }
-    @Override
-    public List<CommitDetails> getAllCommits(int projectId, String commitHash) throws GitLabApiException {
-        CommitsApi commitsApi = server.getCommitsApi();
-        List<CommitDetails> list = new ArrayList<>();
-
-        Commit currentCommit = commitsApi.getCommit(projectId, commitHash);
-
-        RepositoryApi repositoryApi = server.getRepositoryApi();
-        List<Branch> branches = repositoryApi.getBranches(projectId);
-
-        branches.forEach(branch -> {
-            try {
-                List<Commit> commitList = commitsApi.getCommits(projectId, branch.getName(), null);
-                Commit theCommit = commitList.stream().filter(commit -> commit.getId().equals(currentCommit.getId()))
-                        .findFirst().orElse(null);
-
-                if(theCommit != null){
-                    CommitDetails commitDetails = new CommitDetails();
-                    commitDetails.setProjectId(projectId);
-                    commitDetails.setCommitHash(commitHash);
-                    commitDetails.setBranch(branch.getName());
-                    commitDetails.setCommitMessage(theCommit.getMessage());
-
-                    Instant instant = theCommit.getCommittedDate().toInstant();
-                    ZoneId zoneId = ZoneId.systemDefault();
-                    LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
-                    commitDetails.setTime(localDateTime);
-                    commitDetails.setAuthor(theCommit.getAuthorName());
-                    list.add(commitDetails);
-                }
-            } catch (GitLabApiException e) {
-                e.printStackTrace();
-            }
-        });
-        return list;
-    }
-}

+ 0 - 18
api/src/main/java/seecoder/devcloud/api/gitlab/model/CommitDetails.java

@@ -1,18 +0,0 @@
-package seecoder.devcloud.api.gitlab.model;
-
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-@Data
-public class CommitDetails {
-    private int projectId;
-    private String commitHash;
-    private LocalDateTime time;
-    private String commitMessage;
-    private String branch;
-    private String author;
-    private String url;
-    private boolean isBranchValid;
-    private boolean isMessageValid;
-}

+ 0 - 19
api/src/main/java/seecoder/devcloud/api/gitlab/model/GitlabGroup.java

@@ -1,19 +0,0 @@
-package seecoder.devcloud.api.gitlab.model;
-import lombok.Data;
-
-/**
- * @ClassName GitlabGroup
- * @PackageName com.moekr.moocoder.logic.api.vo
- * @Author sheen
- * @Date 2018/12/24
- * @Version 1.0
- * @Description //TODO
- **/
-
-
-@Data
-
-public class GitlabGroup {
-    private Integer id;
-    private Integer namespace;
-}

+ 0 - 10
api/src/main/java/seecoder/devcloud/api/gitlab/model/GitlabUser.java

@@ -1,10 +0,0 @@
-package seecoder.devcloud.api.gitlab.model;
-
-import lombok.Data;
-
-@Data
-public class GitlabUser {
-	private Integer id;
-	private Integer namespace;
-	private String token;
-}

+ 0 - 66
api/src/main/java/seecoder/devcloud/api/jenkins/JenkinsApi.java

@@ -1,66 +0,0 @@
-package seecoder.devcloud.api.jenkins;
-
-import com.offbytwo.jenkins.model.QueueItem;
-import seecoder.devcloud.api.jenkins.model.BuildDetails;
-
-import java.io.IOException;
-import java.util.Map;
-
-public interface JenkinsApi {
-    /**
-     * 创建一个Job,加载配置模板
-     *
-     * @param id Job的Id,其实是Result的Id,也就是repo的Id,参照{@link com.moekr.moocoder.logic.service.impl.exam.ExamServiceImpl#join(int, int)}
-     * @throws IOException
-     */
-    void createJob(int id) throws IOException;
-
-    /**
-     * 通知构建
-     *
-     * @param id       Job的Id,其实是Result的Id,也就是repo的Id,参照{@link com.moekr.moocoder.logic.service.impl.exam.ExamServiceImpl#join(int, int)}
-     * @param paramMap 需要填写的各项参数
-     * @return
-     * @throws IOException
-     */
-    QueueItem invokeBuild(int id, Map<String, String> paramMap) throws IOException;
-
-    /**
-     * 通知构建
-     *
-     * @param jobName       JobName
-     * @param paramMap 需要填写的各项参数
-     * @return
-     * @throws IOException
-     */
-    QueueItem invokeBuild(String jobName, Map<String, String> paramMap) throws IOException;
-
-    /**
-     * 删除Job
-     *
-     * @param id Job的Id,其实是Result的Id,也就是repo的Id,参照{@link com.moekr.moocoder.logic.service.impl.exam.ExamServiceImpl#join(int, int)}
-     * @throws IOException
-     */
-    void deleteJob(int id) throws IOException;
-
-    // waitFinished: 是否等待直到构建完全完成
-    BuildDetails fetchBuildDetails(int id, int buildNumber, String target, boolean waitFinished) throws IOException;
-
-    BuildDetails fetchBuildDetails(String jobName, int buildNumber, String target, boolean waitFinished) throws IOException;
-
-    void createBuildJob(String jobName) throws IOException;
-
-	void createTestJob(String jobName) throws IOException;
-
-    void createFunctionTestJob(String jobName) throws IOException;
-
-    /**
-     * 创建深度学习需要的Job
-     *
-     * @param jobName Job名称
-     */
-    void createDLJob(String jobName) throws IOException;
-
-
-    void deleteJob(String jobName) throws IOException;
-}

+ 0 - 195
api/src/main/java/seecoder/devcloud/api/jenkins/impl/JenkinsApiImpl.java

@@ -1,195 +0,0 @@
-package seecoder.devcloud.api.jenkins.impl;
-
-
-import com.offbytwo.jenkins.JenkinsServer;
-import com.offbytwo.jenkins.client.JenkinsHttpClient;
-import com.offbytwo.jenkins.model.Artifact;
-import com.offbytwo.jenkins.model.BuildWithDetails;
-import com.offbytwo.jenkins.model.QueueItem;
-import com.offbytwo.jenkins.model.QueueReference;
-import seecoder.devcloud.api.jenkins.JenkinsApi;
-import seecoder.devcloud.api.jenkins.model.BuildDetails;
-import seecoder.devcloud.api.jenkins.model.CoverageResult;
-import seecoder.devcloud.api.jenkins.model.MutationResult;
-import seecoder.devcloud.api.ApplicationProperties;
-import lombok.extern.apachecommons.CommonsLog;
-import org.apache.commons.io.output.ByteArrayOutputStream;
-import org.dom4j.*;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.PostConstruct;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.List;
-import java.util.Map;
-
-@Component
-@CommonsLog
-public class JenkinsApiImpl implements JenkinsApi {
-    private final ApplicationProperties properties;
-
-    private JenkinsServer server;
-    private String configTemplate;
-    private String buildConfigTemplate;
-    private String testConfigTemplate;
-    private String functionTestConfigTemplate;
-    private String dlConfigTemplate;
-
-    public JenkinsApiImpl(ApplicationProperties properties) {
-        this.properties = properties;
-    }
-
-    @PostConstruct
-    private void initialize() throws URISyntaxException, IOException {
-        ApplicationProperties.Jenkins jenkins = properties.getJenkins();
-        URI uri = new URI(jenkins.getHost());
-        String username = jenkins.getUsername();
-        String token = jenkins.getToken();
-        JenkinsHttpClient client = new PoolingJenkinsHttpClient(uri, username, token);
-        server = new JenkinsServer(client);
-//        configTemplate = FileUtil.readResource("jenkins/config.xml");
-//        // TODO
-//        buildConfigTemplate = FileUtil.readResource("jenkins/codework/build-config.xml");
-//
-//        testConfigTemplate = FileUtil.readResource("jenkins/codework/test-config.xml");
-//        functionTestConfigTemplate = FileUtil.readResource("jenkins/codework/function-test-config.xml");
-//
-//        dlConfigTemplate = FileUtil.readResource("jenkins/dlConfig.xml");
-    }
-
-    @Override
-    public void createJob(int id) throws IOException {
-        server.createJob(String.valueOf(id), configTemplate);
-    }
-
-    @Override
-    public QueueItem invokeBuild(String jobName, Map<String, String> paramMap) throws IOException {
-        QueueReference reference;
-        if (paramMap == null) {
-            reference = server.getJob(jobName).build();
-        } else {
-            // 0.3.7版本的Jenkins客户端库中build(Map<String, String> params)方法存在BUG,会触发两次构建
-            reference = server.getJob(jobName).build(paramMap, false);
-        }
-        QueueItem item = server.getQueueItem(reference);
-        while (item.getExecutable() == null) {
-            try {
-                Thread.sleep(500);
-            } catch (InterruptedException e) {
-                Thread.currentThread().interrupt();
-            }
-            item = server.getQueueItem(reference);
-        }
-        return item;
-    }
-
-    @Override
-    public QueueItem invokeBuild(int id, Map<String, String> paramMap) throws IOException {
-        return invokeBuild(String.valueOf(id), paramMap);
-    }
-
-    @Override
-    public void deleteJob(int id) throws IOException {
-        server.deleteJob(String.valueOf(id));
-    }
-
-    @Override
-    public BuildDetails fetchBuildDetails(String jobName, int buildNumber, String target, boolean waitFinished) throws IOException {
-        BuildDetails result = new BuildDetails();
-        BuildWithDetails build;
-        build = server.getJob(jobName).getBuildByNumber(buildNumber).details();
-        while (waitFinished && (build.getResult() == null || build.getDuration() == 0)) {
-            try {
-                Thread.sleep(500);
-            } catch (InterruptedException e) {
-                Thread.currentThread().interrupt();
-            }
-            build = server.getJob(jobName).getBuildByNumber(buildNumber).details();
-        }
-        result.setConsoleOutput(build.getConsoleOutputText());
-        result.setNumber(build.getNumber());
-        result.setDuration(build.getDuration());
-        result.setBuildResult(build.getResult());
-        fetchTargetResult(result, build, target);
-        return result;
-    }
-
-    @Override
-    public BuildDetails fetchBuildDetails(int id, int buildNumber, String target,
-                                          boolean waitFinished) throws IOException {
-        return fetchBuildDetails(String.valueOf(id), buildNumber, target, waitFinished);
-    }
-
-    @Override
-    public void createBuildJob(String jobName) throws IOException {
-        server.createJob(jobName, buildConfigTemplate);
-    }
-
-    @Override
-    public void createTestJob(String jobName) throws IOException {
-        server.createJob(jobName, testConfigTemplate);
-    }
-
-    @Override
-    public void createFunctionTestJob(String jobName) throws IOException {
-        server.createJob(jobName, functionTestConfigTemplate);
-    }
-
-    @Override
-    public void createDLJob(String jobName) throws IOException {
-        server.createJob(jobName, dlConfigTemplate);
-    }
-
-    @Override
-    public void deleteJob(String jobName) throws IOException {
-        server.deleteJob(jobName);
-    }
-
-    private void fetchTargetResult(BuildDetails result, BuildWithDetails build, String target) {
-        try {
-            if ("TEST".equals(target)) {
-                fetchTestResult(result, build);
-            } else if ("COVERAGE".equals(target)) {
-                fetchCoverageResult(result, build);
-            } else if ("MUTATION".equals(target)) {
-                fetchMutationResult(result, build);
-            }
-        } catch (Exception ignore) {
-        }
-    }
-
-    private void fetchTestResult(BuildDetails result, BuildWithDetails build) throws IOException {
-        result.setTestResult(build.getTestResult());
-    }
-
-    private void fetchCoverageResult(BuildDetails result, BuildWithDetails build) throws IOException {
-        result.setCoverageResult(build.getClient().get(build.getUrl() + "/cobertura/?depth=2", CoverageResult.class));
-    }
-
-    private void fetchMutationResult(BuildDetails result, BuildWithDetails build) throws IOException, URISyntaxException, DocumentException {
-        List<Artifact> artifactList = build.getArtifacts();
-        Artifact artifact = artifactList.stream().filter(a -> a.getFileName().equals("mutations.xml")).findFirst().orElse(null);
-        if (artifact != null) {
-            MutationResult mutationResult = new MutationResult();
-            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-            outputStream.write(build.downloadArtifact(artifact));
-            String mutationReport = new String(outputStream.toByteArray());
-            Document document = DocumentHelper.parseText(mutationReport);
-            Element root = document.getRootElement();
-            for (Object element : root.elements("mutation")) {
-                if (element instanceof Element) {
-                    Attribute attribute = ((Element) element).attribute("detected");
-                    if (attribute != null) {
-                        mutationResult.setMutations(mutationResult.getMutations() + 1);
-                        if ("true".equals(attribute.getValue())) {
-                            mutationResult.setDetectedMutations(mutationResult.getDetectedMutations() + 1);
-                        }
-                    }
-                }
-            }
-            result.setMutationResult(mutationResult);
-        }
-    }
-
-}

+ 0 - 38
api/src/main/java/seecoder/devcloud/api/jenkins/impl/PoolingJenkinsHttpClient.java

@@ -1,38 +0,0 @@
-package seecoder.devcloud.api.jenkins.impl;
-
-import com.offbytwo.jenkins.client.JenkinsHttpClient;
-import org.apache.commons.lang.StringUtils;
-import org.apache.http.client.config.RequestConfig;
-import org.apache.http.impl.auth.BasicScheme;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClientBuilder;
-import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
-import org.apache.http.protocol.BasicHttpContext;
-import org.apache.http.protocol.HttpContext;
-
-import java.net.URI;
-
-class PoolingJenkinsHttpClient extends JenkinsHttpClient {
-	PoolingJenkinsHttpClient(URI uri, String username, String password) {
-		super(uri, poolingHttpClient(uri, username, password));
-		if (StringUtils.isNotBlank(username)) {
-			HttpContext localContext = new BasicHttpContext();
-			localContext.setAttribute("preemptive-auth", new BasicScheme());
-			super.setLocalContext(localContext);
-		}
-	}
-
-	private static CloseableHttpClient poolingHttpClient(URI uri, String username, String password) {
-		HttpClientBuilder builder = addAuthentication(HttpClientBuilder.create(), uri, username, password);
-		PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager();
-		manager.setMaxTotal(256);
-		manager.setDefaultMaxPerRoute(128);
-		builder.setDefaultRequestConfig(RequestConfig.custom()
-				.setConnectTimeout(3000)
-				.setConnectionRequestTimeout(5000)
-				.setSocketTimeout(10000)
-				.build())
-				.setConnectionManager(manager);
-		return builder.build();
-	}
-}

+ 0 - 19
api/src/main/java/seecoder/devcloud/api/jenkins/model/BuildDetails.java

@@ -1,19 +0,0 @@
-package seecoder.devcloud.api.jenkins.model;
-
-
-import com.offbytwo.jenkins.model.BuildResult;
-import com.offbytwo.jenkins.model.TestResult;
-import lombok.Data;
-import lombok.ToString;
-
-@Data
-@ToString(exclude = "consoleOutput")
-public class BuildDetails {
-	private int number;
-	private long duration;
-	private BuildResult buildResult;
-	private String consoleOutput;
-	private TestResult testResult;
-	private CoverageResult coverageResult;
-	private MutationResult mutationResult;
-}

+ 0 - 27
api/src/main/java/seecoder/devcloud/api/jenkins/model/CoverageResult.java

@@ -1,27 +0,0 @@
-package seecoder.devcloud.api.jenkins.model;
-
-import com.offbytwo.jenkins.model.BaseModel;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.Setter;
-import lombok.ToString;
-
-import java.util.List;
-
-@Setter
-@EqualsAndHashCode(callSuper = true)
-@ToString
-public class CoverageResult extends BaseModel {
-	private Results results;
-
-	public List<CoverageResultElement> getElements() {
-		return results.getElements();
-	}
-
-	@Data
-	@EqualsAndHashCode
-	@ToString
-	private static class Results {
-		private List<CoverageResultElement> elements;
-	}
-}

+ 0 - 11
api/src/main/java/seecoder/devcloud/api/jenkins/model/CoverageResultElement.java

@@ -1,11 +0,0 @@
-package seecoder.devcloud.api.jenkins.model;
-
-import lombok.Data;
-
-@Data
-public class CoverageResultElement {
-	private String name;
-	private int numerator;
-	private int denominator;
-	private int ratio;
-}

+ 0 - 9
api/src/main/java/seecoder/devcloud/api/jenkins/model/MutationResult.java

@@ -1,9 +0,0 @@
-package seecoder.devcloud.api.jenkins.model;
-
-import lombok.Data;
-
-@Data
-public class MutationResult {
-	private int mutations;
-	private int detectedMutations;
-}

+ 1 - 1
api/src/main/java/seecoder/devcloud/api/k8s/DeploymentApi.java

@@ -9,7 +9,7 @@ import seecoder.devcloud.api.k8s.model.DeploymentStatus;
  * author: rale
  * createdAt: 12/23/18
  */
-public interface DeploymentApi extends AbstractApi<Deployment>{
+public interface DeploymentApi extends AbstractApi<Deployment> {
 
     /**
      * 查询deployment的状态

+ 1 - 2
api/src/main/java/seecoder/devcloud/api/k8s/ExecApi.java

@@ -1,7 +1,6 @@
 package seecoder.devcloud.api.k8s;
 
 
-
 import seecoder.devcloud.api.k8s.exception.K8sApiException;
 
 import java.util.List;
@@ -9,7 +8,7 @@ import java.util.List;
 /**
  * 进入容器执行指令
  *
- * todo 传入输入流,获得输出流
+ * @todo 传入输入流,获得输出流
  */
 public interface ExecApi {
 

+ 0 - 4
api/src/main/java/seecoder/devcloud/api/k8s/K8sApiConfiguration.java

@@ -6,15 +6,12 @@ import io.kubernetes.client.openapi.apis.AppsV1Api;
 import io.kubernetes.client.openapi.apis.CoreV1Api;
 import io.kubernetes.client.openapi.apis.ExtensionsV1beta1Api;
 import io.kubernetes.client.util.Config;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
 import seecoder.devcloud.api.ApplicationProperties;
 
 
 @Configuration
-@ComponentScan("seecoder.devcloud.api.k8s.impl")
 public class K8sApiConfiguration {
 
     private final ApiClient apiClient;
@@ -36,7 +33,6 @@ public class K8sApiConfiguration {
 
     private final AppsV1Api watchAppsV1Api;
 
-    @Autowired
     public K8sApiConfiguration(ApplicationProperties applicationProperties) {
         ApplicationProperties.K8s k8s = applicationProperties.getK8s();
         this.apiClient = Config.fromToken(k8s.getApiServer(), k8s.getToken(), k8s.getValidateSSL());

+ 1 - 1
api/src/main/java/seecoder/devcloud/api/k8s/PodApi.java

@@ -3,5 +3,5 @@ package seecoder.devcloud.api.k8s;
 
 import seecoder.devcloud.api.k8s.model.Pod;
 
-public interface PodApi extends AbstractApi<Pod>{
+public interface PodApi extends AbstractApi<Pod> {
 }

+ 0 - 1
api/src/main/java/seecoder/devcloud/api/k8s/SecretApi.java

@@ -1,6 +1,5 @@
 package seecoder.devcloud.api.k8s;
 
-
 import seecoder.devcloud.api.k8s.util.SecretTypeEnum;
 import seecoder.devcloud.api.k8s.vo.SecretVO;
 

+ 13 - 12
api/src/main/java/seecoder/devcloud/api/k8s/impl/ConfigMapApiImpl.java

@@ -2,7 +2,6 @@ package seecoder.devcloud.api.k8s.impl;
 
 
 import com.google.gson.JsonSyntaxException;
-
 import io.kubernetes.client.openapi.ApiException;
 import io.kubernetes.client.openapi.apis.CoreV1Api;
 import io.kubernetes.client.openapi.models.V1ConfigMap;
@@ -12,8 +11,8 @@ import io.kubernetes.client.openapi.models.V1DeleteOptionsBuilder;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import seecoder.devcloud.api.k8s.exception.K8sApiException;
 import seecoder.devcloud.api.k8s.ConfigMapApi;
+import seecoder.devcloud.api.k8s.exception.K8sApiException;
 import seecoder.devcloud.api.k8s.model.ConfigMap;
 import seecoder.devcloud.api.k8s.model.K8sObjectRequest;
 import seecoder.devcloud.api.k8s.model.LabelSelector;
@@ -25,6 +24,8 @@ import java.util.stream.Collectors;
 
 import static seecoder.devcloud.api.k8s.K8sConstants.FOREGROUND_PROPAGATION_POLICY;
 import static seecoder.devcloud.api.k8s.K8sConstants.PRETTY_FORMAT;
+import static seecoder.devcloud.api.k8s.exception.K8sApiException.ALREADY_EXIST;
+import static seecoder.devcloud.api.k8s.exception.K8sApiException.NOT_FOUND;
 
 
 @Service
@@ -48,10 +49,10 @@ public class ConfigMapApiImpl implements ConfigMapApi {
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "configMap创建失败, configMap={}, response={}", configMap, e.getResponseBody());
 
-            if (e.getCode() == K8sApiException.NOT_FOUND) {
-                throw new K8sApiException(K8sApiException.NOT_FOUND, "namespace不存在");
-            } else if (e.getCode() == K8sApiException.ALREADY_EXIST) {
-                throw new K8sApiException(K8sApiException.ALREADY_EXIST, "configMap已经存在");
+            if (e.getCode() == NOT_FOUND) {
+                throw new K8sApiException(NOT_FOUND, "namespace不存在");
+            } else if (e.getCode() == ALREADY_EXIST) {
+                throw new K8sApiException(ALREADY_EXIST, "configMap已经存在");
             } else {
                 throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
             }
@@ -71,10 +72,10 @@ public class ConfigMapApiImpl implements ConfigMapApi {
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "configMap更新失败, configMap={}, response={}", configMap, e.getResponseBody());
 
-            if (e.getCode() == K8sApiException.NOT_FOUND) {
-                throw new K8sApiException(K8sApiException.NOT_FOUND, "namespace不存在");
-            } else if (e.getCode() == K8sApiException.ALREADY_EXIST) {
-                throw new K8sApiException(K8sApiException.ALREADY_EXIST, "configMap已经存在");
+            if (e.getCode() == NOT_FOUND) {
+                throw new K8sApiException(NOT_FOUND, "namespace不存在");
+            } else if (e.getCode() == ALREADY_EXIST) {
+                throw new K8sApiException(ALREADY_EXIST, "configMap已经存在");
             } else {
                 throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
             }
@@ -103,7 +104,7 @@ public class ConfigMapApiImpl implements ConfigMapApi {
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "删除ConfigMap失败,namespace={}, name={}, response={}", configMap.getNamespace(), configMap.getName(), e.getResponseBody());
 
-            if (e.getCode() == K8sApiException.NOT_FOUND) {
+            if (e.getCode() == NOT_FOUND) {
                 return;
             }else {
                 return;
@@ -153,7 +154,7 @@ public class ConfigMapApiImpl implements ConfigMapApi {
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "查找configMap失败,namespace = {}, response={}",
                     request.getNamespace(), e.getResponseBody());
-            if (e.getCode() == K8sApiException.NOT_FOUND) {
+            if (e.getCode() == NOT_FOUND) {
                 return Collections.emptyList();
             }else {
                 return Collections.emptyList();

+ 13 - 11
api/src/main/java/seecoder/devcloud/api/k8s/impl/DeploymentApiImpl.java

@@ -1,5 +1,6 @@
 package seecoder.devcloud.api.k8s.impl;
 
+
 import com.google.gson.JsonSyntaxException;
 import io.kubernetes.client.openapi.ApiException;
 import io.kubernetes.client.openapi.apis.AppsV1Api;
@@ -24,6 +25,7 @@ import java.util.stream.Collectors;
 
 import static seecoder.devcloud.api.k8s.K8sConstants.FOREGROUND_PROPAGATION_POLICY;
 import static seecoder.devcloud.api.k8s.K8sConstants.PRETTY_FORMAT;
+import static seecoder.devcloud.api.k8s.exception.K8sApiException.*;
 
 
 /**
@@ -58,12 +60,12 @@ public class DeploymentApiImpl implements DeploymentApi {
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "deployment创建失败, deployment={}, response={}", deployment, e.getResponseBody());
 
-            if (e.getCode() == K8sApiException.NOT_FOUND) {
-                throw new K8sApiException(K8sApiException.NOT_FOUND, "namespace不存在");
-            } else if (e.getCode() == K8sApiException.ALREADY_EXIST) {
-                throw new K8sApiException(K8sApiException.ALREADY_EXIST, "deployment已经存在");
+            if (e.getCode() == NOT_FOUND) {
+                throw new K8sApiException(NOT_FOUND, "namespace不存在");
+            } else if (e.getCode() == ALREADY_EXIST) {
+                throw new K8sApiException(ALREADY_EXIST, "deployment已经存在");
             } else {
-                throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+                throw K8s_SYSTEM_ERROR_EXCEPTION;
             }
         } catch (Exception e) {
             LoggerUtil.error(logger, e, "deployment创建异常, deployment={}", deployment);
@@ -91,14 +93,14 @@ public class DeploymentApiImpl implements DeploymentApi {
             return new Deployment(v1Deployment);
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "deployment更新异常, deployment={}, response={}", deployment,  e.getResponseBody());
-            if (e.getCode() == K8sApiException.NOT_FOUND) {
-                throw new K8sApiException(K8sApiException.NOT_FOUND);
+            if (e.getCode() == NOT_FOUND) {
+                throw new K8sApiException(NOT_FOUND);
             } else {
-                throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+                throw K8s_SYSTEM_ERROR_EXCEPTION;
             }
         } catch (Exception e) {
             LoggerUtil.error(logger, e, "deployment更新异常, deployment={}", deployment);
-            throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+            throw K8s_SYSTEM_ERROR_EXCEPTION;
         }
     }
 
@@ -121,7 +123,7 @@ public class DeploymentApiImpl implements DeploymentApi {
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "删除Deployment失败,namespace={}, name={}, response={}", deployment.getNamespace(), deployment.getName(), e.getResponseBody());
 
-            if (e.getCode() == K8sApiException.NOT_FOUND) {
+            if (e.getCode() == NOT_FOUND) {
                 return;
             }else {
                 return;
@@ -171,7 +173,7 @@ public class DeploymentApiImpl implements DeploymentApi {
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "查找deployment失败,namespace = {}, response={}",
                     request.getNamespace(), e.getResponseBody());
-            if (e.getCode() == K8sApiException.NOT_FOUND) {
+            if (e.getCode() == NOT_FOUND) {
                 return Collections.emptyList();
             }else {
                 return Collections.emptyList();

+ 7 - 5
api/src/main/java/seecoder/devcloud/api/k8s/impl/ExecApiImpl.java

@@ -1,5 +1,6 @@
 package seecoder.devcloud.api.k8s.impl;
 
+
 import io.kubernetes.client.Exec;
 import io.kubernetes.client.openapi.ApiException;
 import org.slf4j.Logger;
@@ -8,12 +9,13 @@ import org.springframework.stereotype.Service;
 import seecoder.devcloud.api.k8s.ExecApi;
 import seecoder.devcloud.api.k8s.exception.K8sApiException;
 import seecoder.devcloud.common.util.LoggerUtil;
-import seecoder.devcloud.api.nexus.exception.NexusApiException;
 
 import java.io.IOException;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
+import static seecoder.devcloud.api.k8s.exception.K8sApiException.NOT_FOUND;
+
 
 @Service
 public class ExecApiImpl implements ExecApi {
@@ -51,8 +53,8 @@ public class ExecApiImpl implements ExecApi {
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "指令执行异常, namespace={}, podName={}, commands={}, response={}",
                 namespace, podName, commands, e.getResponseBody());
-            if (e.getCode() == NexusApiException.NOT_FOUND) {
-                throw new K8sApiException(NexusApiException.NOT_FOUND, "容器不存在");
+            if (e.getCode() == NOT_FOUND) {
+                throw new K8sApiException(NOT_FOUND, "容器不存在");
             }else{
                 throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
             }
@@ -81,8 +83,8 @@ public class ExecApiImpl implements ExecApi {
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "指令执行异常, namespace={}, podName={}, response={}",
                     namespace, podName, e.getResponseBody());
-            if (e.getCode() == NexusApiException.NOT_FOUND) {
-                throw new K8sApiException(NexusApiException.NOT_FOUND, "容器不存在");
+            if (e.getCode() == NOT_FOUND) {
+                throw new K8sApiException(NOT_FOUND, "容器不存在");
             }else{
                 throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
             }

+ 13 - 15
api/src/main/java/seecoder/devcloud/api/k8s/impl/IngressApiImpl.java

@@ -1,6 +1,5 @@
 package seecoder.devcloud.api.k8s.impl;
 
-
 import com.google.gson.JsonSyntaxException;
 import io.kubernetes.client.openapi.ApiException;
 import io.kubernetes.client.openapi.apis.ExtensionsV1beta1Api;
@@ -17,7 +16,6 @@ import seecoder.devcloud.api.k8s.model.Ingress;
 import seecoder.devcloud.api.k8s.model.K8sObjectRequest;
 import seecoder.devcloud.api.k8s.model.LabelSelector;
 import seecoder.devcloud.common.util.LoggerUtil;
-import seecoder.devcloud.api.nexus.exception.NexusApiException;
 
 import java.util.Collections;
 import java.util.List;
@@ -25,7 +23,7 @@ import java.util.stream.Collectors;
 
 import static seecoder.devcloud.api.k8s.K8sConstants.FOREGROUND_PROPAGATION_POLICY;
 import static seecoder.devcloud.api.k8s.K8sConstants.PRETTY_FORMAT;
-
+import static seecoder.devcloud.api.k8s.exception.K8sApiException.*;
 
 /**
  * author: rale
@@ -63,16 +61,16 @@ public class IngressApiImpl implements IngressApi {
             return result == null ? null : new Ingress(result);
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "ingress 创建失败,ingress={}, response={}", ingress, e.getResponseBody());
-            if (e.getCode() == NexusApiException.NOT_FOUND) {
-                throw new K8sApiException(NexusApiException.NOT_FOUND);
-            } else if (e.getCode() == K8sApiException.ALREADY_EXIST) {
-                throw new K8sApiException(K8sApiException.ALREADY_EXIST);
+            if (e.getCode() == NOT_FOUND) {
+                throw new K8sApiException(NOT_FOUND);
+            } else if (e.getCode() == ALREADY_EXIST) {
+                throw new K8sApiException(ALREADY_EXIST);
             } else {
-                throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+                throw K8s_SYSTEM_ERROR_EXCEPTION;
             }
         } catch (Exception e) {
             LoggerUtil.error(logger, e, "ingress 创建异常,ingress={}", ingress);
-            throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+            throw K8s_SYSTEM_ERROR_EXCEPTION;
         }
     }
 
@@ -99,14 +97,14 @@ public class IngressApiImpl implements IngressApi {
             return new Ingress(ExtensionsV1beta1Ingress);
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "ingress更新失败,ingress={}, response={}", ingress, e.getResponseBody());
-            if (e.getCode() == NexusApiException.NOT_FOUND) {
-                throw new K8sApiException(NexusApiException.NOT_FOUND, "资源不存在");
+            if (e.getCode() == NOT_FOUND) {
+                throw new K8sApiException(NOT_FOUND, "资源不存在");
             }else {
-                throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+                throw K8s_SYSTEM_ERROR_EXCEPTION;
             }
         } catch (Exception e) {
             LoggerUtil.error(logger, e, "ingress更新失败,ingress={}", ingress);
-            throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+            throw K8s_SYSTEM_ERROR_EXCEPTION;
         }
     }
 
@@ -128,7 +126,7 @@ public class IngressApiImpl implements IngressApi {
                     v1DeleteOptions);
         }catch (ApiException e) {
             LoggerUtil.error(logger, e, "ingress 删除失败,name={}, namespace={}, response={}", ingress.getName(), ingress.getNamespace(), e.getResponseBody());
-            if (e.getCode() == NexusApiException.NOT_FOUND) {
+            if (e.getCode() == NOT_FOUND) {
                 return;
             }else {
                 return;
@@ -178,7 +176,7 @@ public class IngressApiImpl implements IngressApi {
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "查找ingresses失败,namespace = {}, response={}",
                     request.getNamespace(), e.getResponseBody());
-            if (e.getCode() == NexusApiException.NOT_FOUND) {
+            if (e.getCode() == NOT_FOUND) {
                 return Collections.emptyList();
             } else {
                 return Collections.emptyList();

+ 7 - 7
api/src/main/java/seecoder/devcloud/api/k8s/impl/NamespaceApiImpl.java

@@ -1,6 +1,5 @@
 package seecoder.devcloud.api.k8s.impl;
 
-
 import com.google.gson.JsonSyntaxException;
 import io.kubernetes.client.openapi.ApiException;
 import io.kubernetes.client.openapi.apis.CoreV1Api;
@@ -24,6 +23,7 @@ import java.util.stream.Collectors;
 
 import static seecoder.devcloud.api.k8s.K8sConstants.FOREGROUND_PROPAGATION_POLICY;
 import static seecoder.devcloud.api.k8s.K8sConstants.PRETTY_FORMAT;
+import static seecoder.devcloud.api.k8s.exception.K8sApiException.*;
 
 
 @Service
@@ -53,20 +53,20 @@ public class NamespaceApiImpl implements NamespaceApi {
             return result == null ? null : new Namespace(result);
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "Namespace创建失败,namespace={}, v1Namespace={}, response={}", namespace, v1Namespace, e.getResponseBody());
-            if (e.getCode() == K8sApiException.ALREADY_EXIST) {
-                throw new K8sApiException(K8sApiException.ALREADY_EXIST);
+            if (e.getCode() == ALREADY_EXIST) {
+                throw new K8sApiException(ALREADY_EXIST);
             } else {
-                throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+                throw K8s_SYSTEM_ERROR_EXCEPTION;
             }
         } catch (Exception e) {
             LoggerUtil.error(logger, e, "Namespace创建异常, namespace={}, v1Namespace={}", namespace, v1Namespace);
-            throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+            throw K8s_SYSTEM_ERROR_EXCEPTION;
         }
     }
 
     @Override
     public Namespace update(Namespace namespace) {
-        throw K8sApiException.K8s_NOT_SUPPORT_METHOD;
+        throw K8s_NOT_SUPPORT_METHOD;
     }
 
     @Override
@@ -86,7 +86,7 @@ public class NamespaceApiImpl implements NamespaceApi {
                     v1DeleteOptions);
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "Namespace删除失败,name={}, response={}", namespace.getName() , e.getResponseBody());
-            if (e.getCode() == K8sApiException.NOT_FOUND) {
+            if (e.getCode() == NOT_FOUND) {
                 return;
             }else {
                 return;

+ 11 - 10
api/src/main/java/seecoder/devcloud/api/k8s/impl/PersistentVolumeClaimImpl.java

@@ -1,6 +1,5 @@
 package seecoder.devcloud.api.k8s.impl;
 
-
 import com.google.gson.JsonSyntaxException;
 import io.kubernetes.client.custom.V1Patch;
 import io.kubernetes.client.openapi.ApiException;
@@ -26,6 +25,8 @@ import java.util.stream.Collectors;
 
 import static seecoder.devcloud.api.k8s.K8sConstants.FOREGROUND_PROPAGATION_POLICY;
 import static seecoder.devcloud.api.k8s.K8sConstants.PRETTY_FORMAT;
+import static seecoder.devcloud.api.k8s.exception.K8sApiException.ALREADY_EXIST;
+import static seecoder.devcloud.api.k8s.exception.K8sApiException.NOT_FOUND;
 
 
 @Service
@@ -54,10 +55,10 @@ public class PersistentVolumeClaimImpl implements PersistentVolumeClaimApi {
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "pvc 创建失败, persistentVolumeClaim={}, response={}", persistentVolumeClaim, e.getResponseBody());
 
-            if (e.getCode() == K8sApiException.NOT_FOUND) {
-                throw new K8sApiException(K8sApiException.NOT_FOUND, "namespace不存在");
-            } else if (e.getCode() == K8sApiException.ALREADY_EXIST) {
-                throw new K8sApiException(K8sApiException.ALREADY_EXIST, "persistentVolumeClaim已经存在");
+            if (e.getCode() == NOT_FOUND) {
+                throw new K8sApiException(NOT_FOUND, "namespace不存在");
+            } else if (e.getCode() == ALREADY_EXIST) {
+                throw new K8sApiException(ALREADY_EXIST, "persistentVolumeClaim已经存在");
             } else {
                 throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
             }
@@ -79,10 +80,10 @@ public class PersistentVolumeClaimImpl implements PersistentVolumeClaimApi {
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "persistentVolumeClaim 更新失败, persistentVolumeClaim={}, response={}", persistentVolumeClaim, e.getResponseBody());
 
-            if (e.getCode() == K8sApiException.NOT_FOUND) {
-                throw new K8sApiException(K8sApiException.NOT_FOUND, "namespace不存在");
-            } else if (e.getCode() == K8sApiException.ALREADY_EXIST) {
-                throw new K8sApiException(K8sApiException.ALREADY_EXIST, "persistentVolumeClaim 已经存在");
+            if (e.getCode() == NOT_FOUND) {
+                throw new K8sApiException(NOT_FOUND, "namespace不存在");
+            } else if (e.getCode() == ALREADY_EXIST) {
+                throw new K8sApiException(ALREADY_EXIST, "persistentVolumeClaim 已经存在");
             } else {
                 throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
             }
@@ -161,7 +162,7 @@ public class PersistentVolumeClaimImpl implements PersistentVolumeClaimApi {
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "查找 persistentVolumeClaim 失败,namespace = {}, response={}",
                     request.getNamespace(), e.getResponseBody());
-            if (e.getCode() == K8sApiException.NOT_FOUND) {
+            if (e.getCode() == NOT_FOUND) {
                 return Collections.emptyList();
             }else {
                 return Collections.emptyList();

+ 6 - 7
api/src/main/java/seecoder/devcloud/api/k8s/impl/PodApiImpl.java

@@ -1,6 +1,5 @@
 package seecoder.devcloud.api.k8s.impl;
 
-
 import com.google.gson.JsonSyntaxException;
 import io.kubernetes.client.openapi.ApiException;
 import io.kubernetes.client.openapi.apis.CoreV1Api;
@@ -17,7 +16,6 @@ import seecoder.devcloud.api.k8s.model.LabelSelector;
 import seecoder.devcloud.api.k8s.model.Namespace;
 import seecoder.devcloud.api.k8s.model.Pod;
 import seecoder.devcloud.common.util.LoggerUtil;
-import seecoder.devcloud.api.k8s.exception.K8sApiException;
 
 import java.util.Collections;
 import java.util.List;
@@ -25,7 +23,8 @@ import java.util.stream.Collectors;
 
 import static seecoder.devcloud.api.k8s.K8sConstants.FOREGROUND_PROPAGATION_POLICY;
 import static seecoder.devcloud.api.k8s.K8sConstants.PRETTY_FORMAT;
-
+import static seecoder.devcloud.api.k8s.exception.K8sApiException.K8s_NOT_SUPPORT_METHOD;
+import static seecoder.devcloud.api.k8s.exception.K8sApiException.NOT_FOUND;
 
 /**
  * author: rale
@@ -45,12 +44,12 @@ public class PodApiImpl implements PodApi {
 
     @Override
     public Pod create(Pod pod) {
-        throw  K8sApiException.K8s_NOT_SUPPORT_METHOD;
+        throw  K8s_NOT_SUPPORT_METHOD;
     }
 
     @Override
     public Pod update(Pod pod) {
-        throw  K8sApiException.K8s_NOT_SUPPORT_METHOD;
+        throw  K8s_NOT_SUPPORT_METHOD;
     }
 
     @Override
@@ -71,7 +70,7 @@ public class PodApiImpl implements PodApi {
                     v1DeleteOptions);
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "Pod删除失败,name={}, response={}", pod.getName() , e.getResponseBody());
-            if (e.getCode() == K8sApiException.NOT_FOUND) {
+            if (e.getCode() == NOT_FOUND) {
                 return;
             }else {
                 return;
@@ -121,7 +120,7 @@ public class PodApiImpl implements PodApi {
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "查找pod失败,namespace = {}, response={}",
                     request.getNamespace(), e.getResponseBody());
-            if (e.getCode() == K8sApiException.NOT_FOUND) {
+            if (e.getCode() == NOT_FOUND) {
                 return Collections.emptyList();
             }else {
                 return Collections.emptyList();

+ 6 - 4
api/src/main/java/seecoder/devcloud/api/k8s/impl/SecretApiImpl.java

@@ -13,7 +13,6 @@ import seecoder.devcloud.api.k8s.exception.K8sApiException;
 import seecoder.devcloud.api.k8s.util.SecretTypeEnum;
 import seecoder.devcloud.api.k8s.vo.SecretVO;
 import seecoder.devcloud.common.util.LoggerUtil;
-import seecoder.devcloud.api.k8s.K8sConstants;
 
 import java.util.Base64;
 import java.util.HashMap;
@@ -21,6 +20,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 
+import static seecoder.devcloud.api.k8s.K8sConstants.PRETTY_FORMAT;
+
 
 @Service
 public class SecretApiImpl implements SecretApi {
@@ -35,6 +36,7 @@ public class SecretApiImpl implements SecretApi {
         this.coreV1Api = coreV1Api;
     }
 
+
     @Override
     public SecretVO createGenericSecret(String namespace, String name, Map<String, byte[]> data) throws K8sApiException {
         return createGenericSecret(namespace, name, data, SecretTypeEnum.Generic);
@@ -56,7 +58,7 @@ public class SecretApiImpl implements SecretApi {
         v1Secret.setType(type.getValue());
 
         try {
-            return new SecretVO(coreV1Api.createNamespacedSecret(namespace, v1Secret, K8sConstants.PRETTY_FORMAT, null, null));
+            return new SecretVO(coreV1Api.createNamespacedSecret(namespace, v1Secret, PRETTY_FORMAT, null, null));
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "Secret创建失败, Secret={}, response={}", v1Secret, e.getResponseBody());
             switch (e.getCode()) {
@@ -98,7 +100,7 @@ public class SecretApiImpl implements SecretApi {
         try {
             V1SecretList v1SecretList = coreV1Api.listNamespacedSecret(
                     namespace,
-                    K8sConstants.PRETTY_FORMAT,
+                    PRETTY_FORMAT,
                     null,
                     "",
                     null,
@@ -140,7 +142,7 @@ public class SecretApiImpl implements SecretApi {
         V1DeleteOptions body = new V1DeleteOptions();
         try {
             //暂时没有用到deleteNamespacedSecret()中的其他参数。
-            V1Status v1Status = coreV1Api.deleteNamespacedSecret(name, namespace, K8sConstants.PRETTY_FORMAT, null, 5, false, "", body);
+            V1Status v1Status = coreV1Api.deleteNamespacedSecret(name, namespace, PRETTY_FORMAT, null, 5, false, "", body);
         } catch (ApiException e) {
             if (e.getCode() == K8sApiException.NOT_FOUND) {
                 return;

+ 12 - 14
api/src/main/java/seecoder/devcloud/api/k8s/impl/ServiceApiImpl.java

@@ -1,6 +1,5 @@
 package seecoder.devcloud.api.k8s.impl;
 
-
 import io.kubernetes.client.openapi.ApiException;
 import io.kubernetes.client.openapi.apis.CoreV1Api;
 import io.kubernetes.client.openapi.models.V1DeleteOptions;
@@ -22,13 +21,12 @@ import java.util.stream.Collectors;
 
 import static seecoder.devcloud.api.k8s.K8sConstants.FOREGROUND_PROPAGATION_POLICY;
 import static seecoder.devcloud.api.k8s.K8sConstants.PRETTY_FORMAT;
-
+import static seecoder.devcloud.api.k8s.exception.K8sApiException.*;
 
 @org.springframework.stereotype.Service
 public class ServiceApiImpl implements ServiceApi {
     private static final Logger logger = LoggerUtil.getLogger(ServiceApi.class);
 
-
     private final CoreV1Api coreV1Api;
 
     @Autowired
@@ -51,12 +49,12 @@ public class ServiceApiImpl implements ServiceApi {
             return v1Service == null ? null : new Service(v1Service);
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "service创建失败, service={}, response={}", service, e.getResponseBody());
-            if (e.getCode() == K8sApiException.ALREADY_EXIST) {
-                throw new K8sApiException(K8sApiException.ALREADY_EXIST, "Service已经存在");
-            }else if (e.getCode() == K8sApiException.NOT_FOUND){
-                throw new K8sApiException(K8sApiException.NOT_FOUND, "Namespace不存在");
+            if (e.getCode() == ALREADY_EXIST) {
+                throw new K8sApiException(ALREADY_EXIST, "Service已经存在");
+            }else if (e.getCode() == NOT_FOUND){
+                throw new K8sApiException(NOT_FOUND, "Namespace不存在");
             }else {
-                throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+                throw K8s_SYSTEM_ERROR_EXCEPTION;
             }
         }
     }
@@ -79,14 +77,14 @@ public class ServiceApiImpl implements ServiceApi {
             return v1Service == null ? null : new Service(v1Service);
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "service替换失败, service={}, response={}", service, e.getResponseBody());
-            if (e.getCode() == K8sApiException.NOT_FOUND){
-                throw new K8sApiException(K8sApiException.NOT_FOUND, "Service不存在");
+            if (e.getCode() == NOT_FOUND){
+                throw new K8sApiException(NOT_FOUND, "Service不存在");
             }else {
-                throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+                throw K8s_SYSTEM_ERROR_EXCEPTION;
             }
         } catch (Exception e) {
             LoggerUtil.error(logger, e, "service替换异常, service={}", service);
-            throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+            throw K8s_SYSTEM_ERROR_EXCEPTION;
         }
     }
 
@@ -109,7 +107,7 @@ public class ServiceApiImpl implements ServiceApi {
         }catch (ApiException e) {
             LoggerUtil.error(logger, e, "Service删除失败,namespace={}, name={}, response={}",
                     service.getNamespace(), service.getName(), e.getResponseBody());
-            if (e.getCode() == K8sApiException.NOT_FOUND) {
+            if (e.getCode() == NOT_FOUND) {
                 return;
             }else {
                 return;
@@ -156,7 +154,7 @@ public class ServiceApiImpl implements ServiceApi {
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "查找pod失败,namespace = {}, response={}",
                     request.getNamespace(), e.getResponseBody());
-            if (e.getCode() == K8sApiException.NOT_FOUND) {
+            if (e.getCode() == NOT_FOUND) {
                 return Collections.emptyList();
             }else {
                 return Collections.emptyList();

+ 3 - 3
api/src/main/java/seecoder/devcloud/api/k8s/model/ConfigMap.java

@@ -1,7 +1,5 @@
 package seecoder.devcloud.api.k8s.model;
 
-
-
 import io.kubernetes.client.openapi.models.V1ConfigMap;
 import io.kubernetes.client.openapi.models.V1ConfigMapBuilder;
 import lombok.*;
@@ -13,18 +11,20 @@ import java.util.Map;
 @AllArgsConstructor
 @NoArgsConstructor
 @Builder
-@EqualsAndHashCode(callSuper=false)
+@EqualsAndHashCode(callSuper=true)
 public class ConfigMap extends K8sAbstractObject<V1ConfigMap> {
 
     public static final String API_VERSION = "v1";
 
     public static final String KIND = "ConfigMap";
+
     @Builder.Default
     private Map<String, String> data = new HashMap<>();
 
 
     public ConfigMap(V1ConfigMap v1ConfigMap) {
         super(v1ConfigMap);
+        this.data = v1ConfigMap.getData();
     }
 
     public void merge(V1ConfigMap v1ConfigMap) {

+ 0 - 1
api/src/main/java/seecoder/devcloud/api/k8s/model/ContainerPort.java

@@ -1,6 +1,5 @@
 package seecoder.devcloud.api.k8s.model;
 
-
 import io.kubernetes.client.openapi.models.V1ContainerPort;
 import io.kubernetes.client.openapi.models.V1ContainerPortBuilder;
 import lombok.*;

+ 2 - 1
api/src/main/java/seecoder/devcloud/api/k8s/model/Deployment.java

@@ -19,7 +19,7 @@ import java.util.stream.Collectors;
 @NoArgsConstructor
 @AllArgsConstructor
 @Builder
-@EqualsAndHashCode(callSuper=false)
+@EqualsAndHashCode(callSuper=true)
 public class Deployment extends K8sAbstractObject<V1Deployment> {
 
     public static final String API_VERSION = "apps/v1";
@@ -43,6 +43,7 @@ public class Deployment extends K8sAbstractObject<V1Deployment> {
 
     @Builder.Default
     private Map<String, String> nodeSelectors = new HashMap<>();
+
     @Range(min = 1, max = 3)
     private int replicas;
 

+ 2 - 2
api/src/main/java/seecoder/devcloud/api/k8s/model/Ingress.java

@@ -10,13 +10,13 @@ import java.util.stream.Collectors;
 /**
  * author: rale
  * createdAt: 1/5/19
- * TODO: 3/25/19 添加标签字段 以后应当是一个分支上的代码可以创建一个deployment
+ * @// TODO: 3/25/19 添加标签字段 以后应当是一个分支上的代码可以创建一个deployment 
  */
 @Data
 @NoArgsConstructor
 @AllArgsConstructor
 @Builder
-@EqualsAndHashCode(callSuper=false)
+@EqualsAndHashCode(callSuper=true)
 public class Ingress extends K8sAbstractObject<ExtensionsV1beta1Ingress> {
 
     public static final String API_VERSION = "extensions/v1beta1";

+ 0 - 3
api/src/main/java/seecoder/devcloud/api/k8s/model/K8sObject.java

@@ -1,8 +1,5 @@
 package seecoder.devcloud.api.k8s.model;
 
-
-
-
 import io.kubernetes.client.openapi.models.V1ObjectMeta;
 import io.kubernetes.client.openapi.models.V1ObjectMetaBuilder;
 

+ 2 - 1
api/src/main/java/seecoder/devcloud/api/k8s/model/Namespace.java

@@ -1,9 +1,9 @@
 package seecoder.devcloud.api.k8s.model;
 
-
 import io.kubernetes.client.openapi.models.V1Namespace;
 import io.kubernetes.client.openapi.models.V1NamespaceBuilder;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 import lombok.NoArgsConstructor;
 import seecoder.devcloud.common.util.DateUtil;
 
@@ -11,6 +11,7 @@ import java.time.LocalDateTime;
 
 @Data
 @NoArgsConstructor
+@EqualsAndHashCode(callSuper=true)
 public class Namespace extends K8sAbstractObject<V1Namespace> {
 
     private static final String KIND = "Namespace";

+ 1 - 1
api/src/main/java/seecoder/devcloud/api/k8s/model/PersistentVolumeClaim.java

@@ -15,7 +15,7 @@ import java.util.List;
 @NoArgsConstructor
 @AllArgsConstructor
 @Builder
-@EqualsAndHashCode(callSuper=false)
+@EqualsAndHashCode(callSuper=true)
 public class PersistentVolumeClaim extends K8sAbstractObject<V1PersistentVolumeClaim> {
 
     public static final String API_VERSION = "v1";

+ 1 - 1
api/src/main/java/seecoder/devcloud/api/k8s/model/Pod.java

@@ -17,9 +17,9 @@ import java.util.stream.Collectors;
  * createdAt: 3/4/19
  */
 @Data
-@EqualsAndHashCode
 @NoArgsConstructor
 @AllArgsConstructor
+@EqualsAndHashCode(callSuper=true)
 public class Pod extends K8sAbstractObject<V1Pod> {
 
     public static final String API_VERSION = "v1";

+ 4 - 1
api/src/main/java/seecoder/devcloud/api/k8s/model/Service.java

@@ -16,7 +16,7 @@ import java.util.stream.Collectors;
 @NoArgsConstructor
 @AllArgsConstructor
 @Builder
-@EqualsAndHashCode(callSuper=false)
+@EqualsAndHashCode(callSuper=true)
 public class Service extends K8sAbstractObject<V1Service> {
 
     public static final String API_VERSION = "v1";
@@ -29,10 +29,13 @@ public class Service extends K8sAbstractObject<V1Service> {
 
     @Builder.Default
     private Map<String, String> labels = new HashMap<>();
+
     @Builder.Default
     private Map<String, String> annotations = new HashMap<>();
+
     @Builder.Default
     private Set<ServicePort> servicePorts = new HashSet<>();
+
     @Builder.Default
     private Map<String, String> selectors = new HashMap<>();
 

+ 0 - 1
api/src/main/java/seecoder/devcloud/api/k8s/vo/SecretVO.java

@@ -1,6 +1,5 @@
 package seecoder.devcloud.api.k8s.vo;
 
-
 import io.kubernetes.client.openapi.models.V1Secret;
 import lombok.Data;
 import lombok.NoArgsConstructor;

+ 0 - 19
api/src/main/java/seecoder/devcloud/api/nexus/AssetApi.java

@@ -1,19 +0,0 @@
-package seecoder.devcloud.api.nexus;
-
-
-
-import seecoder.devcloud.api.nexus.exception.NexusApiException;
-import seecoder.devcloud.api.nexus.model.Asset;
-import seecoder.devcloud.api.nexus.model.AssetList;
-
-import java.util.List;
-
-public interface AssetApi {
-
-    AssetList listAssets(String repository, String continuationToken) throws NexusApiException;
-
-    List<Asset> listAllAssets(String repository) throws NexusApiException;
-
-    Asset readAsset(String id) throws NexusApiException;
-
-}

+ 0 - 79
api/src/main/java/seecoder/devcloud/api/nexus/ComponentApi.java

@@ -1,79 +0,0 @@
-package seecoder.devcloud.api.nexus;
-
-
-
-import seecoder.devcloud.api.nexus.exception.NexusApiException;
-import seecoder.devcloud.api.nexus.model.Component;
-import seecoder.devcloud.api.nexus.model.ComponentList;
-
-import java.util.List;
-
-public interface ComponentApi {
-
-    /**
-     * 查看仓库下的component列表,continuationToken是上一次请求返回的,用来查询下一页的内容
-     * 如果continuation为空 默认查找第一页的内容
-     * @param repo 不能为空
-     * @param continuationToken 可以为空
-     * @return
-     * @throws NexusApiException 如果仓库不存在,抛出404
-     * @throws NexusApiException 如果continuationToken有误,抛出500
-     */
-    ComponentList listComponents(String repo, String continuationToken) throws NexusApiException;
-
-    /**
-     * 获取所有的Component
-     * 具体的实现是采用continuationToken通过HTTP发出下一页请求并将请求结果合并到结果集中
-     * 如果仓库中Component较多且变化频繁,强烈建议不要使用该接口
-     * @param repo
-     * @return
-     * @throws NexusApiException 如果仓库不存在,抛出404
-     */
-    List<Component> listAllComponents(String repo) throws NexusApiException;
-
-    /**
-     * 根据id获取component
-     * @param id 不能为空
-     * @return
-     * @throws NexusApiException 如果组件不存在 抛出404
-     */
-    Component readComponent(String id) throws NexusApiException;
-
-    /**
-     * 根据仓库名,镜像名和默认镜像标签latest找到Docker镜像Component
-     * @param repository 不能为空
-     * @param imageName 不能为空
-     * @return
-     * @throws NexusApiException 如果镜像不存在 抛出404
-     */
-    Component findDockerImage(String repository, String imageName) throws NexusApiException;
-
-    /**
-     * 根据仓库名,镜像名和镜像标签找到Docker镜像Component
-     * @param repository 不能为空
-     * @param imageName 不能为空
-     * @param tag 不能为空
-     * @return
-     * @throws NexusApiException 如果镜像不存在,抛出404
-     */
-    Component findDockerImage(String repository, String imageName, String tag) throws NexusApiException;
-
-    /**
-     * 根据仓库名,镜像名找到所有的Docker镜像Component
-     * continuationToken是上一次请求返回的,用来查询下一页的内容
-     * 如果continuation为空 默认查找第一页的内容
-     * @param repository 不能为空
-     * @param imageName 不能为空
-     * @param continuationToken 可以为空
-     * @return
-     * @throws NexusApiException 如果continuationToken有误,抛出500
-     */
-    ComponentList findDockerImages(String repository, String imageName, String continuationToken) throws NexusApiException;
-
-    /**
-     * 根据组件ID,删除组件
-     * @param id 不能为空
-     * @throws NexusApiException 如果组件不存在,抛出404
-     */
-    void deleteComponent(String id) throws NexusApiException;
-}

+ 0 - 187
api/src/main/java/seecoder/devcloud/api/nexus/NexusApi.java

@@ -1,187 +0,0 @@
-package seecoder.devcloud.api.nexus;
-
-
-
-import seecoder.devcloud.api.nexus.impl.AssetApiImpl;
-import seecoder.devcloud.api.nexus.impl.ComponentApiImpl;
-import seecoder.devcloud.api.nexus.impl.TaskApiImpl;
-import seecoder.devcloud.api.nexus.model.ApiVersion;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.web.client.RestTemplateBuilder;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.ResponseEntity;
-import org.springframework.http.client.ClientHttpRequestInterceptor;
-import org.springframework.util.CollectionUtils;
-import org.springframework.util.MultiValueMap;
-import org.springframework.web.client.RestTemplate;
-import org.springframework.web.util.UriComponentsBuilder;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-@Slf4j
-public class NexusApi {
-
-    private static final String DEFAULT_USER = "admin";
-    private static final String DEFAULT_PASSWORD = "admin123";
-    private static final String CONTENT_TYPE = "application/json";
-
-    private ApiVersion apiVersion;
-    private String username = DEFAULT_USER;
-    private String password = DEFAULT_PASSWORD;
-    private String nexusServerUrl;
-    private String restApiUrl;
-    private AssetApi assetApi;
-    private ComponentApi componentApi;
-    private TaskApi taskApi;
-
-    private RestTemplate restTemplate; //惰性调用getRestTemplate方法初始化
-
-    public NexusApi(String nexusServerUrl) {
-        this(nexusServerUrl, ApiVersion.V1);
-    }
-
-    public NexusApi(String nexusServerUrl, ApiVersion apiVersion) {
-        this(nexusServerUrl, apiVersion, DEFAULT_USER, DEFAULT_PASSWORD);
-    }
-
-    public NexusApi(String nexusServerUrl, ApiVersion apiVersion, String username, String password) {
-        this.nexusServerUrl = nexusServerUrl.endsWith("/") ? nexusServerUrl.replaceAll("/$", "") : nexusServerUrl;
-        this.nexusServerUrl = nexusServerUrl.startsWith("http") ? nexusServerUrl : "http://" + nexusServerUrl;
-        this.apiVersion = apiVersion;
-        this.username = username;
-        this.password = password;
-    }
-
-    public AssetApi getAssetApi(){
-        if (assetApi == null) {
-            synchronized (this) {
-                if (assetApi == null) {
-                    assetApi = new AssetApiImpl(this);
-                }
-            }
-        }
-        return this.assetApi;
-    }
-
-    public ComponentApi getComponentApi(){
-        if (componentApi == null) {
-            synchronized (this) {
-                if (componentApi == null) {
-                    componentApi = new ComponentApiImpl(this);
-                }
-            }
-        }
-        return this.componentApi;
-    }
-
-    public TaskApi getTaskApi(){
-        if (taskApi == null) {
-            synchronized (this) {
-                if (taskApi == null) {
-                    taskApi = new TaskApiImpl(this);
-                }
-            }
-        }
-        return this.taskApi;
-    }
-
-    public ApiVersion getApiVersion() {
-        return apiVersion;
-    }
-
-    public <T> ResponseEntity<T> get(String path, Class<T> responseType, Map<String, List<String>> params, Object... pathVariables) {
-        String url = buildUri(path, params, pathVariables);
-        log.debug("生成的url={}", url);
-        return getRestTemplate().getForEntity(url, responseType);
-    }
-
-    public <T> ResponseEntity<T> get(String path, Class<T> responseType, Map<String, List<String>> params, Map<String, Object> pathVariables) {
-        String url = buildUri(path, params, pathVariables);
-        log.debug("生成的url={}", url);
-        return getRestTemplate().getForEntity(url, responseType);
-    }
-
-    public <T> ResponseEntity<T> post(String path, Class<T> responseType, Object data, Map<String, List<String>> params, Object... pathVariables) {
-        String url = buildUri(path, params, pathVariables);
-        return getRestTemplate().postForEntity(url, data, responseType);
-    }
-
-    public <T> ResponseEntity<T> post(String path, Class<T> responseType, Object data, Map<String, List<String>> params, Map<String, Object> pathVariables) {
-        String url = buildUri(path, params, pathVariables);
-        return getRestTemplate().postForEntity(url, data, responseType);
-    }
-
-    public ResponseEntity<Void> delete(String path, Map<String, List<String>> params, Object... pathVariables) {
-        String url = buildUri(path, params, pathVariables);
-        return getRestTemplate().exchange(url, HttpMethod.DELETE, HttpEntity.EMPTY, Void.class);
-    }
-
-    public ResponseEntity<Void> delete(String path, Map<String, List<String>> params, Map<String, Object> pathVariables) {
-        String url = buildUri(path, params, pathVariables);
-        return getRestTemplate().exchange(url, HttpMethod.DELETE, HttpEntity.EMPTY, Void.class);
-    }
-
-    private String buildUri(String path, Map<String, List<String>> params, Object... pathVariables) {
-        path = validatePath(path);
-        MultiValueMap<String, String> paramMap = toMultiValueMap(params);
-        return UriComponentsBuilder.fromHttpUrl(getRestApiUrl())
-                .path(path)
-                .queryParams(paramMap)
-                .build(pathVariables)
-                .toString();
-    }
-    private String buildUri(String path, Map<String, List<String>> params, Map<String, Object> pathVariables) {
-        path = validatePath(path);
-        MultiValueMap<String, String> paramMap = toMultiValueMap(params);
-        return UriComponentsBuilder.fromHttpUrl(getRestApiUrl())
-                .path(path)
-                .queryParams(paramMap)
-                .build(pathVariables)
-                .toString();
-    }
-
-
-    private String validatePath(String path) {
-        return path.startsWith("/") ? path : "/" + path;
-    }
-
-    private MultiValueMap<String, String> toMultiValueMap(Map<String, List<String>> params) {
-        return (params == null) ?
-                CollectionUtils.toMultiValueMap(Collections.EMPTY_MAP) :
-                CollectionUtils.toMultiValueMap(params);
-    }
-
-    private String getRestApiUrl() {
-        if (this.restApiUrl == null) {
-            synchronized (this) {
-                if (this.restApiUrl == null) {
-                    restApiUrl = this.nexusServerUrl + ApiVersion.V1.getApiNamespace();
-                }
-            }
-
-        }
-        return this.restApiUrl;
-    }
-
-    private RestTemplate getRestTemplate() {
-        if (this.restTemplate == null) {
-            synchronized (this) {
-                if (this.restTemplate == null) {
-                    this.restTemplate = new RestTemplateBuilder()
-                            .basicAuthentication(username, password)
-                            .additionalInterceptors((ClientHttpRequestInterceptor) (httpRequest, bytes, clientHttpRequestExecution) -> {
-                                HttpHeaders headers = httpRequest.getHeaders();
-                                headers.add("Accept", CONTENT_TYPE);
-                                return clientHttpRequestExecution.execute(httpRequest, bytes);
-                            })
-                            .build();
-                }
-            }
-        }
-        return restTemplate;
-    }
-}

+ 0 - 16
api/src/main/java/seecoder/devcloud/api/nexus/NexusApiBean.java

@@ -1,16 +0,0 @@
-package seecoder.devcloud.api.nexus;
-
-import seecoder.devcloud.api.ApplicationProperties;
-import seecoder.devcloud.api.nexus.model.ApiVersion;
-import org.springframework.context.annotation.Bean;
-import org.springframework.stereotype.Component;
-
-@Component
-public class NexusApiBean {
-
-    @Bean
-    public NexusApi getNexusApi(ApplicationProperties applicationProperties) {
-        return new NexusApi(applicationProperties.getRegistry().getNexusServer(), ApiVersion.V1, applicationProperties.getRegistry().getUsername(), applicationProperties.getRegistry().getPassword());
-    }
-
-}

+ 0 - 53
api/src/main/java/seecoder/devcloud/api/nexus/TaskApi.java

@@ -1,53 +0,0 @@
-package seecoder.devcloud.api.nexus;
-
-
-
-import seecoder.devcloud.api.nexus.exception.NexusApiException;
-import seecoder.devcloud.api.nexus.model.Task;
-import seecoder.devcloud.api.nexus.model.TaskList;
-
-import java.util.List;
-
-public interface TaskApi {
-
-    /**
-     * 根据continuationToken获取下一页的Task列表
-     * 如果continuationToken为空 则获取第一页的Task列表
-     * @param continuationToken 可以为空
-     * @return
-     * @throws NexusApiException 500 非法continuationToken
-     */
-    TaskList listTasks(String continuationToken) throws NexusApiException;
-
-    /**
-     * 获取所有的任务
-     * 具体实现采用continuationToken获取下一页Task列表,直到continuationToken为空
-     * 如果task数量较多,不要频繁使用该接口机
-     * @return
-     * @throws NexusApiException
-     */
-    List<Task> listAllTasks() throws NexusApiException;
-
-    /**
-     * 根据id获取任务的详细信息
-     * @param id 不能为空
-     * @return
-     * @throws NexusApiException 404 任务不存在
-     */
-    Task readTask(String id) throws NexusApiException;
-
-    /**
-     * 根据id启动任务
-     * @param id 不能为空
-     * @throws NexusApiException 404 任务不存在
-     */
-    void runTask(String id) throws NexusApiException;
-
-    /**
-     * 根据id停止任务
-     * @param id 不能为空
-     * @throws NexusApiException 404 任务不存在
-     * @throws NexusApiException 409 任务无法停止或已经停止
-     */
-    void stopTask(String id) throws NexusApiException;
-}

+ 0 - 73
api/src/main/java/seecoder/devcloud/api/nexus/exception/NexusApiException.java

@@ -1,73 +0,0 @@
-package seecoder.devcloud.api.nexus.exception;
-
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class NexusApiException extends Exception {
-
-    private int code;
-
-    private String message;
-
-    public static final int INSUFFICIENT_PERMISSION = 403;
-    public static final int NOT_FOUND = 404;
-    public static final int CONFLICT = 409;
-    public static final int INVALID_PARAMS = 422;
-    public static final int INTERNAL_SERVER_ERROR = 500;
-
-    public static final String INSUFFICIENT_PERMISSION_DESCRIPTION = "权限不足";
-    public static final String NOT_FOUND_DESCRIPTION = "资源不存在";
-    public static final String INVALID_PARAMS_DESCRIPTION = "非法参数";
-    public static final String INTERNAL_SERVER_ERROR_DESCRIPTION = "内部服务异常";
-    public static final String CONFLICT_DESCRIPTION = "请求与服务器端目标资源的当前状态相冲突";
-
-    public static final Map<Integer, String> error;
-    static {
-        error = new HashMap<>();
-        error.put(INSUFFICIENT_PERMISSION, INSUFFICIENT_PERMISSION_DESCRIPTION);
-        error.put(NOT_FOUND, NOT_FOUND_DESCRIPTION);
-        error.put(INVALID_PARAMS, INVALID_PARAMS_DESCRIPTION);
-        error.put(INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR_DESCRIPTION);
-        error.put(CONFLICT, CONFLICT_DESCRIPTION);
-    }
-
-    public NexusApiException(int code, String message) {
-        super(message);
-        this.code = code;
-        this.message = message;
-    }
-
-    public NexusApiException(int code) {
-        this.code = error.containsKey(code) ? code : INTERNAL_SERVER_ERROR;
-        this.message = error.get(this.code);
-    }
-
-    public NexusApiException(Exception e) {
-        super(e);
-        code = INTERNAL_SERVER_ERROR;
-        message = e.getMessage();
-    }
-
-
-    @Override
-    public String getMessage() {
-        return message;
-    }
-
-    public void setMessage(String message) {
-        this.message = message;
-    }
-
-    public int getCode() {
-        return code;
-    }
-
-    public void setCode(int code) {
-        this.code = code;
-    }
-
-    public boolean isNotFound() {
-        return this.getCode() == NOT_FOUND;
-    }
-}

+ 0 - 99
api/src/main/java/seecoder/devcloud/api/nexus/impl/AbstractApi.java

@@ -1,99 +0,0 @@
-package seecoder.devcloud.api.nexus.impl;
-
-
-import seecoder.devcloud.api.nexus.NexusApi;
-import seecoder.devcloud.api.nexus.exception.NexusApiException;
-import seecoder.devcloud.api.nexus.model.ApiVersion;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.client.HttpClientErrorException;
-
-import java.util.List;
-import java.util.Map;
-
-@Slf4j
-public abstract class AbstractApi implements Constants{
-
-    private final NexusApi nexusApi;
-
-    public AbstractApi(NexusApi nexusApi) {
-        this.nexusApi = nexusApi;
-    }
-
-    /**
-     * 默认处理资源不存在和无权限执行异常,其它异常可以在具体的子接口中覆盖重写
-     * @param responseEntity
-     * @param <T>
-     * @return
-     * @throws NexusApiException
-     */
-    protected <T> ResponseEntity<T> validate(ResponseEntity<T> responseEntity) throws NexusApiException {
-        if (responseEntity.getStatusCode().value() == NexusApiException.NOT_FOUND) {
-            throw new NexusApiException(NexusApiException.NOT_FOUND);
-        } else if (responseEntity.getStatusCode().value() == NexusApiException.INSUFFICIENT_PERMISSION) {
-            throw new NexusApiException(NexusApiException.INSUFFICIENT_PERMISSION);
-        } else if (responseEntity.getStatusCodeValue() == NexusApiException.INTERNAL_SERVER_ERROR) {
-            throw new NexusApiException(NexusApiException.INTERNAL_SERVER_ERROR);
-        } else if (responseEntity.getStatusCodeValue() == NexusApiException.INVALID_PARAMS) {
-            throw new NexusApiException(NexusApiException.INVALID_PARAMS);
-        }
-        return responseEntity;
-    }
-
-    protected  <T> ResponseEntity<T> get(String path, Class<T> responseType, Map<String, List<String>> params, Object... pathVariables) throws NexusApiException {
-        return validate(nexusApi.get(path, responseType, params, pathVariables));
-    }
-
-    protected  <T> ResponseEntity<T> get(String path, Class<T> responseType, Map<String, List<String>> params, Map<String, Object> pathVariables) throws NexusApiException {
-        return validate(nexusApi.get(path, responseType, params, pathVariables));
-    }
-
-    protected  <T> ResponseEntity<T> post(String path, Class<T> responseType, Object data, Map<String, List<String>> params, Object... pathVariables) throws NexusApiException {
-        return validate(nexusApi.post(path, responseType, data, params, pathVariables));
-    }
-
-    protected  <T> ResponseEntity<T> post(String path, Class<T> responseType, Object data, Map<String, List<String>> params, Map<String, Object> pathVariables) throws NexusApiException {
-        return validate(nexusApi.post(path, responseType, data, params, pathVariables));
-    }
-
-    protected ResponseEntity<Void> delete(String path, Map<String, List<String>> params, Object... pathVariables) throws NexusApiException {
-        return validate(nexusApi.delete(path, params, pathVariables));
-    }
-
-    protected ResponseEntity<Void> delete(String path, Map<String, List<String>> params, Map<String, Object> pathVariables) throws NexusApiException {
-        return validate(nexusApi.delete(path, params, pathVariables));
-    }
-
-    protected NexusApiException handle(Exception thrown) {
-        log.error("Nexus异常", thrown);
-        if (thrown instanceof NexusApiException) {
-            return ((NexusApiException) thrown);
-        }
-        if (thrown instanceof HttpClientErrorException) {
-            HttpClientErrorException e = (HttpClientErrorException) thrown;
-            return new NexusApiException(e.getRawStatusCode());
-        }
-        return (new NexusApiException(thrown));
-    }
-
-    protected ApiVersion getApiVersion() {
-        return nexusApi.getApiVersion();
-    }
-
-    protected boolean isApiVersion(ApiVersion apiVersion) {
-        return nexusApi.getApiVersion() == apiVersion;
-    }
-
-    protected NexusApi getNexusApi(){
-        return this.nexusApi;
-    }
-
-    protected void validateId(String id) throws NexusApiException {
-        if (id == null || id.isEmpty()) throw new NexusApiException(NexusApiException.INVALID_PARAMS, "id不能为空");
-    }
-
-    protected void validateRepo(String repo) throws NexusApiException {
-        if (repo == null || repo.isEmpty()) throw new NexusApiException(NexusApiException.INVALID_PARAMS, "仓库名称不能为空");
-    }
-
-}

+ 0 - 67
api/src/main/java/seecoder/devcloud/api/nexus/impl/AssetApiImpl.java

@@ -1,67 +0,0 @@
-package seecoder.devcloud.api.nexus.impl;
-
-
-
-import seecoder.devcloud.api.nexus.AssetApi;
-import seecoder.devcloud.api.nexus.NexusApi;
-import seecoder.devcloud.api.nexus.exception.NexusApiException;
-import seecoder.devcloud.api.nexus.model.Asset;
-import seecoder.devcloud.api.nexus.model.AssetList;
-
-import java.util.*;
-
-public class AssetApiImpl extends AbstractApi implements AssetApi {
-
-    private static final String LIST_ASSETS_PATH = ASSET_PATH;
-    private static final String GET_ASSET_PATH = ASSET_PATH + "/{id}";
-
-    public AssetApiImpl(NexusApi nexusApi) {
-        super(nexusApi);
-    }
-
-    @Override
-    public AssetList listAssets(String repository, String continuationToken) throws NexusApiException {
-        try {
-            validateRepo(repository);
-            Map<String, List<String>> params = new HashMap<>();
-            params.put(REQUEST_PARAM_REPOSITORY, Collections.singletonList(repository));
-            if (continuationToken != null && !continuationToken.isEmpty()) {
-                params.put(REQUEST_PARAM_CONTINUATION_TOKEN, Collections.singletonList(continuationToken));
-            }
-            return get(LIST_ASSETS_PATH, AssetList.class, params).getBody();
-        } catch (Exception e) {
-            throw handle(e);
-        }
-    }
-
-    @Override
-    public List<Asset> listAllAssets(String repository) throws NexusApiException {
-        try {
-            validateRepo(repository);
-            List<Asset> result = new ArrayList<>();
-            String continuationToken = "";
-            AssetList assetList;
-            boolean hasNext = true;
-            while (hasNext) {
-                 assetList = listAssets(repository, continuationToken);
-                result.addAll(assetList.getItems());
-                continuationToken = assetList.getContinuationToken();
-                hasNext = (continuationToken != null);
-            }
-            return result;
-        } catch (Exception e) {
-            throw handle(e);
-        }
-    }
-
-    @Override
-    public Asset readAsset(String id) throws NexusApiException {
-        try {
-            validateId(id);
-            return get(GET_ASSET_PATH, Asset.class, null, id).getBody();
-        }catch (Exception e) {
-            throw handle(e);
-        }
-    }
-
-}

+ 0 - 144
api/src/main/java/seecoder/devcloud/api/nexus/impl/ComponentApiImpl.java

@@ -1,144 +0,0 @@
-package seecoder.devcloud.api.nexus.impl;
-
-
-
-import seecoder.devcloud.api.nexus.ComponentApi;
-import seecoder.devcloud.api.nexus.NexusApi;
-import seecoder.devcloud.api.nexus.exception.NexusApiException;
-import seecoder.devcloud.api.nexus.model.Component;
-import seecoder.devcloud.api.nexus.model.ComponentList;
-import org.springframework.http.ResponseEntity;
-
-import java.util.*;
-
-public class ComponentApiImpl extends AbstractApi implements ComponentApi {
-
-    private static final String LIST_COMPONENTS_PATH = COMPONENTS_PATH;
-    private static final String GET_COMPONENT_PATH = COMPONENTS_PATH + "/{id}";
-    private static final String DELETE_COMPONENT_PATH = COMPONENTS_PATH + "/{id}";
-    private static final String SEARCH_COMPONENT_PATH = SEARCH_PATH;
-    private static final String DOCKER_IMAGE_DEFAULT_VERSION = "latest";
-
-    public ComponentApiImpl(NexusApi nexusApi) {
-        super(nexusApi);
-    }
-
-    @Override
-    public ComponentList listComponents(String repo, String continuationToken) throws NexusApiException {
-        try {
-            validateRepo(repo);
-            Map<String, List<String>> params = new HashMap<>();
-            params.put(REQUEST_PARAM_REPOSITORY, Collections.singletonList(repo));
-            if (continuationToken != null && !continuationToken.isEmpty()) {
-                params.put(REQUEST_PARAM_CONTINUATION_TOKEN, Collections.singletonList(continuationToken));
-            }
-            ResponseEntity<ComponentList> responseEntity = get(LIST_COMPONENTS_PATH, ComponentList.class, params);
-            return responseEntity.getBody();
-        }catch (Exception e) {
-            throw handle(e);
-        }
-    }
-
-    @Override
-    public List<Component> listAllComponents(String repo) throws NexusApiException {
-        try {
-            validateRepo(repo);
-            List<Component> result = new ArrayList<>();
-            String continuationToken = "";
-            ComponentList componentList;
-            boolean hasNext = true;
-            while (hasNext) {
-                componentList = listComponents(repo, continuationToken);
-                result.addAll(componentList.getItems());
-                continuationToken = componentList.getContinuationToken();
-                hasNext = (continuationToken != null);
-            }
-            return result;
-        } catch (Exception e) {
-            throw handle(e);
-        }
-    }
-
-    @Override
-    public Component readComponent(String id) throws NexusApiException {
-        try {
-            validateId(id);
-            ResponseEntity<Component> responseEntity = get(GET_COMPONENT_PATH, Component.class, null, id);
-            return responseEntity.getBody();
-        }catch (Exception e) {
-            throw handle(e);
-        }
-    }
-
-    @Override
-    public Component findDockerImage(String repository, String imageName) throws NexusApiException {
-        return findDockerImage(repository, imageName, DOCKER_IMAGE_DEFAULT_VERSION);
-    }
-
-    @Override
-    public Component findDockerImage(String repository, String imageName, String imageTag) throws NexusApiException {
-        try {
-            validateRepo(repository);
-            validateName(imageName);
-            validateVersion(imageTag);
-
-            Map<String, List<String>> params = new HashMap<>();
-            params.put(REQUEST_PARAM_REPOSITORY, Collections.singletonList(repository));
-            params.put(REQUEST_PARAM_DOCKER_IMAGE_NAME, Collections.singletonList(imageName));
-            params.put(REQUEST_PARAM_DOCKER_IMAGE_TAG, Collections.singletonList(imageTag));
-            ResponseEntity<ComponentList> responseEntity = get(SEARCH_COMPONENT_PATH, ComponentList.class, params);
-
-            ComponentList componentList = responseEntity.getBody();
-            Component result = null;
-            if (!componentList.getItems().isEmpty()) {
-                result = componentList.getItems().get(0);
-            }
-            if (result == null) {
-                throw new NexusApiException(NexusApiException.NOT_FOUND);
-            }
-            return result;
-        } catch (Exception e) {
-            throw handle(e);
-        }
-    }
-
-    @Override
-    public ComponentList findDockerImages(String repository, String imageName, String continuationToken) throws NexusApiException {
-        try {
-            validateRepo(repository);
-            validateName(imageName);
-
-            Map<String, List<String>> params = new HashMap<>();
-            params.put(REQUEST_PARAM_REPOSITORY, Collections.singletonList(repository));
-            params.put(REQUEST_PARAM_DOCKER_IMAGE_NAME, Collections.singletonList(imageName));
-            if (continuationToken != null && !continuationToken.isEmpty()) {
-                params.put(REQUEST_PARAM_CONTINUATION_TOKEN, Collections.singletonList(continuationToken));
-            }
-            ResponseEntity<ComponentList> responseEntity = get(SEARCH_COMPONENT_PATH, ComponentList.class, params);
-
-            ComponentList componentList = responseEntity.getBody();
-            return componentList;
-        } catch (Exception e) {
-            throw handle(e);
-        }
-    }
-
-    @Override
-    public void deleteComponent(String id) throws NexusApiException {
-        try {
-            validateId(id);
-            delete(DELETE_COMPONENT_PATH, null, id);
-        }catch (Exception e) {
-            throw handle(e);
-        }
-    }
-
-
-    private void validateName(String name) throws NexusApiException {
-        if (name == null || name.isEmpty()) throw new NexusApiException(NexusApiException.INVALID_PARAMS, "镜像名称不能为空");
-    }
-
-    private void validateVersion(String version) throws NexusApiException {
-        if (version == null || version.isEmpty()) throw new NexusApiException(NexusApiException.INVALID_PARAMS, "版本不能为空");
-    }
-}

+ 0 - 28
api/src/main/java/seecoder/devcloud/api/nexus/impl/Constants.java

@@ -1,28 +0,0 @@
-package seecoder.devcloud.api.nexus.impl;
-
-/**
- * author: rale
- * createdAt: 3/25/19
- */
-public interface Constants {
-
-    String ASSET_PATH = "/assets";
-    String BLOL_STORE_PATH = "/blobstores";
-    String COMPONENTS_PATH = "/components";
-    String FORMATS_PATH = "/formats";
-    String READONLY_PATH = "/read-only";
-    String REPOSITORIES_PATH = "/repositories";
-    String SCRIPT_PATH = "/script";
-    String SEARCH_PATH = "/search";
-    String SUPPORT_PATH = "/support";
-    String TASKS_PATH = "/tasks";
-
-    String REQUEST_PARAM_ID = "id";
-    String REQUEST_PARAM_CONTINUATION_TOKEN = "continuationToken";
-    String REQUEST_PARAM_REPOSITORY = "repository";
-    String REQUEST_PARAM_DOCKER_IMAGE_NAME = "docker.imageName";
-    String REQUEST_PARAM_DOCKER_IMAGE_TAG = "docker.imageTag";
-
-    String DOCKER_COMPONENT_FORMAT = "docker";
-    String MAVEN2_COMPONENT_FORMAT = "maven2";
-}

+ 0 - 89
api/src/main/java/seecoder/devcloud/api/nexus/impl/TaskApiImpl.java

@@ -1,89 +0,0 @@
-package seecoder.devcloud.api.nexus.impl;
-
-
-import seecoder.devcloud.api.nexus.NexusApi;
-import seecoder.devcloud.api.nexus.TaskApi;
-import seecoder.devcloud.api.nexus.exception.NexusApiException;
-import seecoder.devcloud.api.nexus.model.Task;
-import seecoder.devcloud.api.nexus.model.TaskList;
-import org.springframework.http.ResponseEntity;
-
-import java.util.*;
-
-public class TaskApiImpl extends AbstractApi implements TaskApi {
-
-    private static final String LIST_TASKS_PATH = TASKS_PATH;
-    private static final String GET_TASK_PATH = TASKS_PATH + "/{id}";
-    private static final String RUN_TASK_PATH = TASKS_PATH + "/{id}/run";
-    private static final String STOP_TASK_PATH = TASKS_PATH + "/{id}/stop";
-
-    public TaskApiImpl(NexusApi nexusApi) {
-        super(nexusApi);
-    }
-
-    @Override
-    public TaskList listTasks(String continuationToken) throws NexusApiException {
-        try {
-            Map<String, List<String>> params = new HashMap<>();
-            if (continuationToken != null && !continuationToken.isEmpty()) {
-                params.put(REQUEST_PARAM_CONTINUATION_TOKEN, Collections.singletonList(continuationToken));
-            }
-            return get(LIST_TASKS_PATH, TaskList.class, params).getBody();
-        } catch (Exception e) {
-            throw handle(e);
-        }
-    }
-
-    @Override
-    public List<Task> listAllTasks() throws NexusApiException {
-        try {
-            List<Task> result = new ArrayList<>();
-            String continuationToken = "";
-            TaskList taskList;
-            boolean hasNext = true;
-            while (hasNext) {
-                taskList = listTasks(continuationToken);
-                result.addAll(taskList.getItems());
-                continuationToken = taskList.getContinuationToken();
-                hasNext = continuationToken != null;
-            }
-            return result;
-        } catch (Exception e) {
-            throw handle(e);
-        }
-    }
-
-    @Override
-    public Task readTask(String id) throws NexusApiException {
-        try {
-            validateId(id);
-            return get(GET_TASK_PATH, Task.class, null, id).getBody();
-        } catch (Exception e) {
-            throw handle(e);
-        }
-    }
-
-    @Override
-    public void runTask(String id) throws NexusApiException {
-        try {
-            validateId(id);
-            post(RUN_TASK_PATH, Void.class, null,null, id);
-        } catch (Exception e) {
-            throw handle(e);
-        }
-    }
-
-    @Override
-    public void stopTask(String id) throws NexusApiException {
-        try {
-            validateId(id);
-            ResponseEntity<Void> responseEntity = post(STOP_TASK_PATH, Void.class, null,null, id);
-            if (responseEntity.getStatusCodeValue() == NexusApiException.CONFLICT) {
-                throw new NexusApiException(NexusApiException.CONFLICT, "无法停止该任务");
-            }
-        } catch (Exception e) {
-            throw handle(e);
-        }
-    }
-
-}

+ 0 - 17
api/src/main/java/seecoder/devcloud/api/nexus/model/ApiVersion.java

@@ -1,17 +0,0 @@
-package seecoder.devcloud.api.nexus.model;
-
-/**
- * author: rale
- * createdAt: 3/21/19
- */
-public enum ApiVersion {
-    V1;
-
-    private ApiVersion() {
-
-    }
-
-    public String getApiNamespace() {
-        return ("/service/rest/" + name().toLowerCase());
-    }
-}

+ 0 - 21
api/src/main/java/seecoder/devcloud/api/nexus/model/Asset.java

@@ -1,21 +0,0 @@
-package seecoder.devcloud.api.nexus.model;
-
-import lombok.Data;
-
-import java.util.Map;
-
-@Data
-public class Asset{
-
-    private String downloadUrl;
-
-    private String path;
-
-    private String id;
-
-    private String repository;
-
-    private String format;
-
-    private Map<String, Object> checksum;
-}

+ 0 - 13
api/src/main/java/seecoder/devcloud/api/nexus/model/AssetList.java

@@ -1,13 +0,0 @@
-package seecoder.devcloud.api.nexus.model;
-
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.util.List;
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-public class AssetList extends NexusList{
-
-    private List<Asset> items;
-}

+ 0 - 23
api/src/main/java/seecoder/devcloud/api/nexus/model/Component.java

@@ -1,23 +0,0 @@
-package seecoder.devcloud.api.nexus.model;
-
-import lombok.Data;
-
-import java.util.List;
-
-@Data
-public class Component {
-
-    private String id;
-
-    private String repository;
-
-    private String format;
-
-    private String group;
-
-    private String name;
-
-    private String version;
-
-    private List<Asset> assets;
-}

+ 0 - 16
api/src/main/java/seecoder/devcloud/api/nexus/model/ComponentList.java

@@ -1,16 +0,0 @@
-package seecoder.devcloud.api.nexus.model;
-
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class ComponentList extends NexusList{
-
-    private List<Component> items = new ArrayList<>();
-}

+ 0 - 9
api/src/main/java/seecoder/devcloud/api/nexus/model/NexusList.java

@@ -1,9 +0,0 @@
-package seecoder.devcloud.api.nexus.model;
-
-import lombok.Data;
-
-@Data
-public abstract class NexusList {
-
-    protected String continuationToken;
-}

+ 0 - 25
api/src/main/java/seecoder/devcloud/api/nexus/model/Task.java

@@ -1,25 +0,0 @@
-package seecoder.devcloud.api.nexus.model;
-
-import lombok.Data;
-
-import java.util.Date;
-
-@Data
-public class Task {
-
-    private String id;
-
-    private String name;
-
-    private String type;
-
-    private String message;
-
-    private String currentState;
-
-    private String lastRunResult;
-
-    private Date nextRun;
-
-    private Date lastRun;
-}

+ 0 - 15
api/src/main/java/seecoder/devcloud/api/nexus/model/TaskList.java

@@ -1,15 +0,0 @@
-package seecoder.devcloud.api.nexus.model;
-
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-import java.util.List;
-
-@Data
-@ToString(callSuper = true)
-@EqualsAndHashCode(callSuper = true)
-public class TaskList extends NexusList{
-
-    private List<Task> items;
-}

+ 0 - 1
common/src/main/java/seecoder/devcloud/common/CommonAutoConfiguration.java

@@ -1,6 +1,5 @@
 package seecoder.devcloud.common;
 
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import seecoder.devcloud.common.util.JwtTokenUtil;

+ 1 - 1
common/src/main/java/seecoder/devcloud/common/exceptions/ServiceException.java

@@ -7,7 +7,7 @@ import org.springframework.http.HttpStatus;
 @Getter
 @ToString
 public class ServiceException extends RuntimeException {
-	private int code;
+	private final int code;
 
 	public ServiceException() {
 		this(HttpStatus.INTERNAL_SERVER_ERROR.value(), HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase());

+ 1 - 0
common/src/main/java/seecoder/devcloud/common/util/FileUtil.java

@@ -10,6 +10,7 @@ public class FileUtil {
     public static String readResource(String filepath) throws IOException {
         StringBuilder stringBuilder = new StringBuilder();
         InputStream inputStream = FileUtil.class.getClassLoader().getResourceAsStream(filepath);
+        assert inputStream != null;
         BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
         String buffer;
         while ((buffer = bufferedReader.readLine()) != null) {

+ 0 - 2
common/src/main/java/seecoder/devcloud/common/util/JwtTokenUtil.java

@@ -2,11 +2,9 @@ package seecoder.devcloud.common.util;
 
 import io.jsonwebtoken.Claims;
 import io.jsonwebtoken.Jwts;
-import io.jsonwebtoken.SignatureAlgorithm;
 import lombok.Data;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.security.core.userdetails.UserDetails;
 
 import java.util.Date;
 

+ 1 - 1
common/src/main/java/seecoder/devcloud/common/util/RandomStringUtil.java

@@ -12,7 +12,7 @@ public class RandomStringUtil {
     private static final Random random = new Random();
 
     public static String getRandomString(int length) {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
 
         for (int i = 0; i < length; ++i) {
             int number = random.nextInt(str.length());// [0,62)

+ 0 - 1
common/src/main/java/seecoder/devcloud/common/util/SpringUtil.java

@@ -3,7 +3,6 @@ package seecoder.devcloud.common.util;
 import org.springframework.beans.BeansException;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
-import org.springframework.stereotype.Component;
 
 import javax.annotation.PostConstruct;
 

+ 8 - 1
core/src/main/java/seecoder/devcloud/core/pipeline/Context.java

@@ -1,5 +1,6 @@
 package seecoder.devcloud.core.pipeline;
 
+import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
@@ -16,6 +17,7 @@ import java.util.Map;
 @Data
 @Builder
 @NoArgsConstructor
+@AllArgsConstructor
 public class Context {
 
     private ApplicationProperties applicationProperties;
@@ -24,6 +26,8 @@ public class Context {
 
     private String pipelineName;
 
+    private String templateName;
+
 
     /**
      * 流水线所属namespace
@@ -42,5 +46,8 @@ public class Context {
     @Builder.Default
     private Map<String, String> configs = new HashMap<>();
 
-
+    /**
+     * 整个构建流程的记录, 每一个模块的各种运行信息(正常运行的结果,异常信息)都应该写入这里
+     */
+    private String result;
 }

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

@@ -9,11 +9,11 @@ import seecoder.devcloud.core.pipeline.handler.AbstractHandler;
  */
 public interface Handler {
 
-    void invoke(Context context);
+    void invoke(Context context) throws PipelineException;
 
-    void process(Context context);
+    void process(Context context) throws PipelineException;
 
-    void invokeNext(Context context);
+    void invokeNext(Context context) throws PipelineException;
 
     void setNextHandler(Handler nextHandler);
 }

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

@@ -7,7 +7,7 @@ package seecoder.devcloud.core.pipeline;
  */
 public interface Pipeline {
 
-    void start();
+    void start() throws PipelineException;
 
     Context getContext();
 

+ 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
  * @description: 流水线模块出现的异常的包装
  */
-public class PipelineException extends RuntimeException{
-    //todo exception
+public class PipelineException extends Exception{
+
+    public PipelineException(String msg){
+        super(msg);
+    }
 }

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

@@ -23,7 +23,7 @@ public class PipelineFactory {
      * @param pipelineName 流水线名称,需要用户自己指定
      * @return
      */
-    public static Pipeline init(String configJson, String namespace, String projectName, Integer pipelineId, String pipelineName) {
+    public static Pipeline init(String configJson, String namespace, String projectName, Integer pipelineId, String pipelineName) throws PipelineException {
 
         PipelineConfig pipelineConfig = PipelineConfig.init(configJson);
 
@@ -47,7 +47,7 @@ public class PipelineFactory {
      *                (所以这一步要避免配置的覆盖,即不要用相同名字的key)
      * @return
      */
-    private static Handler initHandlerChainAndContext(PipelineConfig pipelineConfig, Map<String,String> configs){
+    private static Handler initHandlerChainAndContext(PipelineConfig pipelineConfig, Map<String,String> configs) throws PipelineException {
         Handler firstHandler = null;
         Handler currentHandler = null;
 

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

@@ -2,6 +2,7 @@ package seecoder.devcloud.core.pipeline.config;
 
 import lombok.extern.slf4j.Slf4j;
 import seecoder.devcloud.core.pipeline.Handler;
+import seecoder.devcloud.core.pipeline.PipelineException;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -26,13 +27,12 @@ public class HandlerConfigTable {
         //todo 加入表
     }
 
-    public static Handler transToHandler(HandlerConfig config){
+    public static Handler transToHandler(HandlerConfig config) throws PipelineException {
         Handler handler = null;
         try {
             handler = (Handler) handlerConfigMap.get(config).newInstance();
         } catch (InstantiationException | IllegalAccessException e) {
-            log.error("流水线配置转换发生错误",e);
-            //todo throw pipeline exception
+            throw new PipelineException("Error: config.getName() 流水线配置转换发生错误: " + e.getMessage());
         }
         return handler;
     }

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

@@ -3,6 +3,7 @@ package seecoder.devcloud.core.pipeline.handler;
 import lombok.Data;
 import seecoder.devcloud.core.pipeline.Context;
 import seecoder.devcloud.core.pipeline.Handler;
+import seecoder.devcloud.core.pipeline.PipelineException;
 
 /**
  * @author PuHong Weng
@@ -15,20 +16,14 @@ public abstract class AbstractHandler implements Handler {
 
     public Handler nextHandler;
 
-//    /**
-//     * 用来存放Handler的配置
-//     */
-//    public HashMap<String,String> configs = new HashMap<>();
-
     @Override
-    public void invoke(Context context) {
-        //todo 改成异步的
+    public void invoke(Context context) throws PipelineException {
         process(context);
         invokeNext(context);
     }
 
     @Override
-    public void invokeNext(Context context) {
+    public void invokeNext(Context context) throws PipelineException {
         if (nextHandler != null){
             nextHandler.invoke(context);
         }

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

@@ -1,168 +1,108 @@
-//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 lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+import org.eclipse.jgit.api.Git;
+import org.springframework.util.ResourceUtils;
+import seecoder.devcloud.api.docker.DockerApi;
+import seecoder.devcloud.api.git.GitApi;
+import seecoder.devcloud.common.util.SpringUtil;
+import seecoder.devcloud.core.pipeline.Context;
+import seecoder.devcloud.core.pipeline.PipelineException;
+import seecoder.devcloud.core.pipeline.template.PipelineTemplateTable;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Date;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/1/18
+ * @description: docker镜像构建
+ */
+@Slf4j
+public class DockerImageBuildHandler extends AbstractHandler {
+
+    private static final String TEMP_PREFIX = "SEECODER-DEVCLOUD-";
+
+    public final DockerApi dockerApi;
+
+    public final GitApi gitApi;
+
+    public DockerImageBuildHandler() {
+        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);
+    }
+}
+

+ 23 - 30
core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sDeploymentHandler.java

@@ -1,6 +1,7 @@
 package seecoder.devcloud.core.pipeline.handler;
 
 import lombok.extern.slf4j.Slf4j;
+import seecoder.devcloud.api.ApplicationProperties;
 import seecoder.devcloud.api.k8s.DeploymentApi;
 import seecoder.devcloud.api.k8s.K8sConstants;
 import seecoder.devcloud.api.k8s.SecretApi;
@@ -33,18 +34,12 @@ public class K8sDeploymentHandler extends AbstractHandler {
 
     private final DeploymentApi deploymentApi;
 
+    private final ApplicationProperties applicationProperties;
 
-    //容器所使用的镜像
-    private String image;
+    private final static String DEFAULT_IMAGE_PULL_SECRET_NAME = "seecoder-devcloud-image-pull-secret";
 
-    //副本数
-    private int replicas;
-
-    //
-    private int port;
-
-
-    public K8sDeploymentHandler() {
+    public K8sDeploymentHandler(ApplicationProperties applicationProperties) {
+        this.applicationProperties = SpringUtil.getBean(ApplicationProperties.class);
         secretApi = SpringUtil.getBean(SecretApi.class);
         deploymentApi = SpringUtil.getBean(DeploymentApi.class);
     }
@@ -58,8 +53,10 @@ public class K8sDeploymentHandler extends AbstractHandler {
     @Override
     public void process(Context context) {
         //配置初始化
-        initConfig(context);
-        String groupName = context.getNamespace();
+        String imageName = context.getConfigs().getOrDefault("imageName", "");
+        int port = Integer.parseInt(context.getConfigs().getOrDefault("port", "8000"));
+        int replicas = Integer.parseInt(context.getConfigs().getOrDefault("replicas", "1"));
+        String namespace = context.getNamespace();
         String projectName = context.getProjectName();
 
         //配置容器暴露端口
@@ -69,7 +66,7 @@ public class K8sDeploymentHandler extends AbstractHandler {
 
         //配置容器
         Container container = Container.builder()
-                .image(image)
+                .image(imageName)
                 .name(projectName + K8sConstants.CONTAINER_SUFFIX)
                 .ports(Collections.singleton(containerPort))
                 .build();
@@ -80,21 +77,22 @@ public class K8sDeploymentHandler extends AbstractHandler {
                 .containers(Collections.singletonList(container))
                 .build();
         deployment.setName(projectName + K8sConstants.DEPLOYMENT_SUFFIX);
-        deployment.setNamespace(groupName);
+        deployment.setNamespace(namespace);
         deployment.setLabel(K8sConstants.APPLICATION_LABEL, projectName);
 
-        // 密钥来源:在命名空间创建时,创建对应的secret存放密钥,见 K8sNamespaceHandler.class
-        // 将registry密钥作为imagePullSecrets注入, 使得此deployment可以访问私有镜像仓库
-        List<String> registrySecrets = secretApi
-                .getSecretListByType(
-                        groupName,
-                        SecretTypeEnum.REGISTRY)
-                .stream()
-                .map(SecretVO::getName)
-                .collect(Collectors.toList()
-                );
-        deployment.setImagePullSecrets(registrySecrets);
 
+        // 检查镜像仓库secret,没有则创建。 设置镜像镜像secret
+        SecretVO secretVO = secretApi.getSecretByName(namespace, DEFAULT_IMAGE_PULL_SECRET_NAME);
+        if (secretVO == null) {
+            secretApi.createPrivateRegistrySecret(
+                    namespace,
+                    DEFAULT_IMAGE_PULL_SECRET_NAME,
+                    applicationProperties.getDocker().getRegistry(),
+                    applicationProperties.getDocker().getRegistryUsername(),
+                    applicationProperties.getDocker().getRegistryPassword()
+            );
+        }
+        deployment.setImagePullSecrets(Collections.singletonList(secretVO.getName()));
 
         try {
             deploymentApi.create(deployment);
@@ -109,9 +107,4 @@ public class K8sDeploymentHandler extends AbstractHandler {
         }
     }
 
-    private void initConfig(Context context) {
-        this.image = context.getConfigs().getOrDefault("image", "");
-        this.port = Integer.parseInt(context.getConfigs().getOrDefault("port", "8000"));
-        this.replicas = Integer.parseInt(context.getConfigs().getOrDefault("replicas", "1"));
-    }
 }

+ 56 - 53
core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sIngressHandler.java

@@ -1,53 +1,56 @@
-//package seecoder.devcloud.core.pipeline.handler;
-//
-//import seecoder.devcloud.api.k8s.model.Ingress;
-//import seecoder.devcloud.core.pipeline.Context;
-//import seecoder.devcloud.core.pipeline.Handler;
-//
-//
-//import java.util.Collection;
-//import java.util.HashSet;
-//import java.util.List;
-//import java.util.Set;
-//import java.util.stream.Collectors;
-//
-///**
-// * @author PuHong Weng
-// * @date 2021/1/18
-// * @description:
-// */
-//public class K8sIngressHandler extends AbstractHandler {
-//
-//    @Override
-//    public void process(Context context) {
-//
-//
-//
-//        String groupName = context.getGroupName();
-//
-//        String projectName = context.getProjectName();
-//
-//        Ingress ingress = new Ingress();
-//
-//        ingress.setName(appName + "-" + applicationDTO.getDeployEnvironment());
-//        Set<String> alreadyTaken = new HashSet<>();
-//        List<Ingress.IngressRule> ingressRules = applicationDTO.getContainers()
-//                .stream()
-//                .map(ContainerDTO::getPorts)
-//                .flatMap(Collection::stream)
-//                .filter(PortDTO::isExpose)
-//                .map(portDTO -> {
-//                    Ingress.IngressRule ingressRule = new Ingress.IngressRule();
-//                    ingressRule.setHost(getUniqueHost(projectName, environment, alreadyTaken));
-//                    Ingress.IngressPath ingressPath = new Ingress.IngressPath();
-//                    ingressPath.setPath("/");
-//                    ingressPath.setPort(portDTO.getPort());
-//                    ingressPath.setServiceName(applicationDTO.getName() + "-" + applicationDTO.getDeployEnvironment());
-//                    ingressRule.addRuleValue(ingressPath);
-//                    return ingressRule;
-//                })
-//                .collect(Collectors.toList());
-//        ingress.setHttpRules(ingressRules);
-//        return ingress;
-//    }
-//}
+package seecoder.devcloud.core.pipeline.handler;
+
+import seecoder.devcloud.api.ApplicationProperties;
+import seecoder.devcloud.api.k8s.IngressApi;
+import seecoder.devcloud.api.k8s.K8sConstants;
+import seecoder.devcloud.api.k8s.model.Ingress;
+import seecoder.devcloud.common.util.SpringUtil;
+import seecoder.devcloud.core.pipeline.Context;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/1/18
+ * @description:
+ */
+public class K8sIngressHandler extends AbstractHandler {
+
+    private final ApplicationProperties applicationProperties;
+
+    private final IngressApi ingressApi;
+
+    public K8sIngressHandler() {
+        this.ingressApi = SpringUtil.getBean(IngressApi.class);
+        this.applicationProperties = SpringUtil.getBean(ApplicationProperties.class);
+    }
+
+
+
+    @Override
+    public void process(Context context) {
+
+        String namespace = context.getNamespace();
+        String projectName = context.getProjectName();
+        String servicePort = context.getConfigs().get("servicePort");
+
+        Ingress ingress = new Ingress();
+        ingress.setName(projectName + K8sConstants.INGRESS_SUFFIX);
+        ingress.setNamespace(namespace);
+        Set<String> alreadyTaken = new HashSet<>();
+
+        Ingress.IngressRule ingressRule = new Ingress.IngressRule();
+        ingressRule.setHost(namespace + "." + projectName + applicationProperties.getK8s().getIngressHostSuffix());
+        Ingress.IngressPath path = new Ingress.IngressPath();
+        path.setPath(projectName+K8sConstants.DEPLOYMENT_SUFFIX);
+        path.setPort(Integer.parseInt(servicePort));
+        ingressRule.setRuleValues(Collections.singleton(path));
+        ingress.setHttpRules(Collections.singletonList(ingressRule));
+
+        ingress.setLabel(K8sConstants.APPLICATION_LABEL, projectName);
+
+        ingressApi.create(ingress);
+    }
+}

+ 0 - 4
core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sNamespaceHandler.java

@@ -34,10 +34,6 @@ public class K8sNamespaceHandler extends AbstractHandler {
         try {
             namespace = namespaceApi.create(namespace);
             log.info("Namespace创建成功, {}", namespace);
-            // todo namespace 镜像secret是否改成从service account注入,待调查
-//            //为命名空间配置私有镜像仓库密钥,使得此命名空间可以访问镜像仓库来部署容器
-//            ApplicationProperties.Registry registry = context.getApplicationProperties().getRegistry();
-//            secretApi.createPrivateRegistrySecret(context.getGroupName(), registry.getHost(), registry.getUsername(), registry.getPassword());
         } catch (K8sApiException e){
             if (e.getCode() == K8sApiException.ALREADY_EXIST){
                 log.info("Namespace已经存在, 无需新建");

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

@@ -3,6 +3,7 @@ package seecoder.devcloud.core.pipeline.pipeline;
 import seecoder.devcloud.core.pipeline.Context;
 import seecoder.devcloud.core.pipeline.Handler;
 import seecoder.devcloud.core.pipeline.Pipeline;
+import seecoder.devcloud.core.pipeline.PipelineException;
 
 /**
  * @author PuHong Weng
@@ -24,7 +25,7 @@ public class PipelineImpl implements Pipeline {
 
 
     @Override
-    public void start() {
+    public void start() throws PipelineException {
         //todo 流水线开始事件监听
         firstHandler.invoke(context);
         //todo 流水线开始事件监听

+ 43 - 0
core/src/main/java/seecoder/devcloud/core/pipeline/template/PipelineTemplateTable.java

@@ -0,0 +1,43 @@
+package seecoder.devcloud.core.pipeline.template;
+
+import seecoder.devcloud.core.pipeline.PipelineException;
+
+import java.util.HashSet;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/16
+ * @description: 记录了pipeline的所有可用模板名
+ */
+public class PipelineTemplateTable {
+
+    private static final String TEMPLATE_DOCKERFILE_PREFIX = "TEMPLATE_DOCKERFILE_";
+    private static final String TEMPLATE_CONFIG_JSON_PREFIX = "TEMPLATE_CONFIG_JSON_";
+
+    private static final HashSet<String> templateNames;
+
+    /**
+     * 需要添加模板类型在这里添加,然后根据需求添加对应的imagename、dockerfile、configjson等
+     * todo
+     */
+    static {
+        templateNames = new HashSet<String>();
+        templateNames.add("JAVA8");
+
+    }
+
+    public static void validateTemplateName(String name) throws PipelineException {
+        if (!templateNames.contains(name)){
+            throw new PipelineException("pipeline模板名不存在");
+        }
+    }
+
+    public static String getTemplateDockerfileName(String templateName){
+        return TEMPLATE_DOCKERFILE_PREFIX + templateName;
+    }
+
+
+    public static String getTemplateConfigJsonName(String templateName){
+        return TEMPLATE_DOCKERFILE_PREFIX + templateName;
+    }
+}

+ 9 - 0
core/src/main/resources/template/config/test.json

@@ -0,0 +1,9 @@
+{
+  "test": [
+
+    {
+      "name":
+
+    }
+  ]
+}

+ 15 - 0
core/src/main/resources/template/dockerfile/TEMPLATE_DOCKERFILE_JAVA8

@@ -0,0 +1,15 @@
+# 用于为学生java8项目打包成镜像的dockerfile
+FROM maven:3.6.1 AS compile_stage
+ENV PROJECT_NAME seecoder-paas
+ENV WORK_PATH /opt/$PROJECT_NAME
+COPY settings.xml /root/.m2/settings.xml
+COPY . $WORK_PATH
+RUN cd $WORK_PATH && mvn clean package -DskipTests -DfinalName=$PROJECT_NAME
+
+FROM java:8-jre-alpine
+ENV PROJECT_NAME seecoder-paas
+ENV WORK_PATH /opt/$PROJECT_NAME
+RUN apk add --no-cache git
+WORKDIR /app
+COPY --from=compile_stage $WORK_PATH/target/${PROJECT_NAME}.jar .
+CMD ["sh", "-c", "java -Xdebug -Xrunjdwp:transport=dt_socket,address=8888,server=y,suspend=n -jar -server /app/${PROJECT_NAME}.jar"]

+ 7 - 2
web/pom.xml

@@ -44,10 +44,9 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-thymeleaf</artifactId>
         </dependency>
-
         <dependency>
             <groupId>seecoder.devcloud</groupId>
-            <artifactId>api</artifactId>
+            <artifactId>core</artifactId>
             <version>0.0.1-SNAPSHOT</version>
         </dependency>
         <dependency>
@@ -102,6 +101,12 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>com.nju.edu</groupId>
+            <artifactId>seecoder-gitlab-client</artifactId>
+            <version>0.1.0</version>
+        </dependency>
     </dependencies>
 
     <dependencyManagement>

+ 9 - 4
web/src/main/java/seecoder/devcloud/web/controller/pipeline/PipelineController.java

@@ -4,8 +4,8 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
-import org.apache.ibatis.annotations.Delete;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 import seecoder.devcloud.web.model.vo.Response;
 import seecoder.devcloud.web.model.vo.pipeline.PipelineConfigVO;
@@ -14,8 +14,7 @@ import seecoder.devcloud.web.model.vo.pipeline.PipelineHistoryVO;
 import seecoder.devcloud.web.model.vo.pipeline.PipelineInfoVO;
 import seecoder.devcloud.web.service.pipeline.PipelineService;
 
-import javax.ws.rs.GET;
-import javax.ws.rs.PUT;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -69,7 +68,7 @@ public class PipelineController {
     @ApiOperation(value = "依据模板创建一个流水线配置", httpMethod = "POST")
     @ApiImplicitParam(name = "pipelineCreateVO", value = "流水线创建配置信息",dataType = "object",paramType = "body")
     @PostMapping
-    public Response createPipelineConfig(@RequestBody PipelineCreateVO pipelineCreateVO){
+    public Response createPipelineConfig(@RequestBody @Validated PipelineCreateVO pipelineCreateVO){
         pipelineService.createPipelineConfig(pipelineCreateVO);
         return Response.buildSuccess();
     }
@@ -100,4 +99,10 @@ public class PipelineController {
         return Response.buildSuccess();
     }
 
+    @ApiOperation(value = "获取可用的pipeline模板名字", httpMethod = "GET")
+    @GetMapping("/templates")
+    public Response getPipelineTemplateNames(){
+        //todo 实现
+        return Response.buildSuccess(Collections.emptyList());
+    }
 }

+ 5 - 6
web/src/main/java/seecoder/devcloud/web/controller/project/ProjectController.java

@@ -5,10 +5,9 @@ import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
-import seecoder.devcloud.web.model.po.project.Project;
-import seecoder.devcloud.web.service.project.ProjectService;
 import seecoder.devcloud.web.model.vo.Response;
 import seecoder.devcloud.web.model.vo.project.ProjectVO;
+import seecoder.devcloud.web.service.project.ProjectService;
 
 import java.util.List;
 
@@ -27,7 +26,7 @@ public class ProjectController {
 
     @ApiOperation(value = "根据group获取Project列表", httpMethod = "GET")
     @GetMapping("/listByGroup/{groupId}")
-    @ApiImplicitParam(value = "groupId",dataType ="int", paramType = "path")
+    @ApiImplicitParam(name = "groupId",dataType ="int", paramType = "path")
     public Response<List<ProjectVO>> listProjectsByGroupId(@PathVariable("groupId")int groupId){
         return Response.buildSuccess(projectService.listProjectsByGroupId(groupId));
     }
@@ -41,21 +40,21 @@ public class ProjectController {
 
     @ApiOperation(value = "根据projectId获取Project", httpMethod = "GET")
     @GetMapping("/{projectId}")
-    @ApiImplicitParam(value = "projectId",dataType ="int", paramType = "path")
+    @ApiImplicitParam(name = "projectId",dataType ="int", paramType = "path")
     public Response<ProjectVO> getProjectById(@PathVariable("projectId")int projectId){
         return Response.buildSuccess(projectService.getProjectById(projectId));
     }
 
     @ApiOperation(value = "创建项目,传入的参数中不必带有效的projectId字段,返回一个创建后的结果,注入id", httpMethod = "POST")
     @PostMapping("/create")
-    @ApiImplicitParam(value = "project",dataType = "object", paramType = "body")
+    @ApiImplicitParam(name = "project",dataType = "object", paramType = "body")
     public Response<ProjectVO> createProject(@RequestBody ProjectVO project){
         return Response.buildSuccess(projectService.createProject(project));
     }
 
     @ApiOperation(value = "根据projectId删除项目", httpMethod = "DELETE")
     @DeleteMapping("/delete/{projectId}")
-    @ApiImplicitParam(value = "projectId",dataType ="int", paramType = "path")
+    @ApiImplicitParam(name = "projectId",dataType ="int", paramType = "path")
     public Response deleteProject(@PathVariable("projectId")int projectId){
         projectService.deleteProject(projectId);
         return Response.buildSuccess();

+ 58 - 0
web/src/main/java/seecoder/devcloud/web/controller/user/GroupController.java

@@ -0,0 +1,58 @@
+package seecoder.devcloud.web.controller.user;
+
+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.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import seecoder.devcloud.web.model.vo.Response;
+import seecoder.devcloud.web.service.user.GroupService;
+
+import javax.validation.constraints.Pattern;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/18
+ * @description:
+ */
+@RestController
+@RequestMapping("/groups")
+@Api(tags = "组 api")
+public class GroupController {
+
+    private final GroupService groupService;
+
+    @Autowired
+    public GroupController(GroupService groupService) {
+        this.groupService = groupService;
+    }
+
+    @ApiOperation(value = "创建组", httpMethod = "POST")
+    @ApiImplicitParam(name = "userId",dataType ="string", paramType = "param")
+    @PostMapping()
+    public Response createGroup(@RequestParam("name")
+                                    @Validated
+                                    @Pattern(regexp = "^\\w{3,20}$", message = "组名称只能为长度为3-20且由数字、26个英文字母或者下划线组成的字符串")
+                                            String name){
+        groupService.createGroup(name);
+        return Response.buildSuccess();
+    }
+
+    @ApiOperation(value = "添加组成员", httpMethod = "POST")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "invitedUserId",dataType ="int", paramType = "param"),
+            @ApiImplicitParam(name = "groupId",dataType ="int", paramType = "param")
+    })
+
+    @PostMapping("/members")
+    public Response addMember(@RequestParam("invitedUserId") Integer invitedUserId,
+                              @RequestParam("groupId") Integer groupId){
+        groupService.addMember(invitedUserId, groupId);
+        return Response.buildSuccess();
+    }
+}

+ 1 - 13
web/src/main/java/seecoder/devcloud/web/dao/user/GroupMapper.java

@@ -16,7 +16,7 @@ import seecoder.devcloud.web.model.po.user.Group;
 public interface GroupMapper {
 
     /**
-     * id并非由此后端生成,而是gitlab创建后,将gitlab groupid填入
+     * group id并非由此后端生成,而是gitlab创建后,将gitlab groupid填入
      */
     @InsertProvider(type = GeneralInsertUpdateSqlProvider.class, method = "insert")
     int insert(Group group,String... ignoredCols);
@@ -30,16 +30,4 @@ public interface GroupMapper {
     @Select("select * from `group` where name = #{name}")
     Group findGroupByName(String name);
 
-    @Select("select *, id as group_id from `group` where id = #{id}")
-    @Result(column = "group_id", property = "members", many = @Many(select = "seecoder.devcloud.web.dao.user.GroupMemberMapper.selectUsersByGroupId"))
-    Group findWithMembersById(Integer id);
-
-    @Deprecated
-    Group findGroupByShareLink(String shareLink);
-
-
-
-
-
-
 }

+ 20 - 3
web/src/main/java/seecoder/devcloud/web/infrastructure/GlobalExceptionHandler.java

@@ -1,16 +1,17 @@
 package seecoder.devcloud.web.infrastructure;
 
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.apache.http.HttpStatus;
+import org.springframework.validation.BindException;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.bind.annotation.RestControllerAdvice;
-import seecoder.devcloud.common.exceptions.AccessDeniedException;
-import seecoder.devcloud.common.exceptions.ConflictException;
 import seecoder.devcloud.common.exceptions.ServiceException;
 import seecoder.devcloud.web.infrastructure.security.TokenExpiredException;
 import seecoder.devcloud.web.model.vo.Response;
 
+import javax.validation.ConstraintViolationException;
+
 /**
  * @author PuHong Weng
  * @date 2021/3/5
@@ -20,6 +21,22 @@ import seecoder.devcloud.web.model.vo.Response;
 @Slf4j
 public class GlobalExceptionHandler {
 
+    //***************************validation参数异常的捕获**************
+
+    @ExceptionHandler(value = BindException.class)
+    @ResponseBody
+    public Response handleResourceBindException(BindException e) {
+        return Response.buildFailure(HttpStatus.SC_BAD_REQUEST, e.getMessage());
+    }
+
+    @ExceptionHandler(value = ConstraintViolationException.class)
+    @ResponseBody
+    public Response handleResourceConstraintViolationException(ConstraintViolationException e) {
+        return Response.buildFailure(HttpStatus.SC_BAD_REQUEST, e.getMessage());
+    }
+
+    //***************************业务异常的捕获**************
+
     @ExceptionHandler(ServiceException.class)
     @ResponseBody
     public Response serviceExceptionHandler(ServiceException e){

+ 21 - 0
web/src/main/java/seecoder/devcloud/web/infrastructure/ValidationExceptionHandler.java

@@ -0,0 +1,21 @@
+package seecoder.devcloud.web.infrastructure;
+
+import org.springframework.validation.BindException;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import seecoder.devcloud.web.model.vo.Response;
+
+import javax.validation.ConstraintViolationException;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/18
+ * @description:
+ */
+@ControllerAdvice
+public class ValidationExceptionHandler {
+
+
+
+}

+ 0 - 1
web/src/main/java/seecoder/devcloud/web/infrastructure/security/JwtAuthenticationTokenFilter.java

@@ -70,7 +70,6 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
                             .buildDetails(httpServletRequest));
                     SecurityContextHolder.getContext().setAuthentication(authentication);
                 } else {
-                    //todo test token
                     PrintWriter out = null ;
                     try{
                         httpServletResponse.setCharacterEncoding("UTF-8");

+ 1 - 27
web/src/main/java/seecoder/devcloud/web/model/po/user/Group.java

@@ -1,15 +1,10 @@
 package seecoder.devcloud.web.model.po.user;
 
 
-import lombok.Builder;
-import lombok.Data;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
-import seecoder.devcloud.web.model.enums.GroupType;
-
-import java.util.List;
 
 /**
  * Description:
@@ -25,32 +20,11 @@ import java.util.List;
 public class Group {
 
     /**
-     * id并非由此后端生成,而是gitlab创建后,将gitlab groupid填入
+     * id并非由此后端生成,而是gitlab创建后,将gitlab group id填入
      */
     private Integer id;
 
-    /**
-     * 来源于gitlab
-     */
-    private Integer namespace;
-    /**
-     * 小组类型
-     */
-    private GroupType type;
-
-    /**
-     * 小组的加组链接
-     */
-    private String shareLink;
-
-    /**
-     * 组名
-     */
     private String name;
 
-    /**
-     * 小组成员
-     */
-    private List<User> members;
 
 }

+ 2 - 1
web/src/main/java/seecoder/devcloud/web/model/vo/pipeline/PipelineCreateVO.java

@@ -3,7 +3,7 @@ package seecoder.devcloud.web.model.vo.pipeline;
 import io.swagger.annotations.ApiModel;
 import lombok.Data;
 
-import javax.validation.Valid;
+import javax.validation.constraints.Pattern;
 
 /**
  * @author PuHong Weng
@@ -18,6 +18,7 @@ public class PipelineCreateVO {
 
     private Integer pipelineId;
 
+    @Pattern(regexp = "^\\w{3,20}$", message = "流水线名只能为长度为3-20且由数字、26个英文字母或者下划线组成的字符串")
     private String name;
 
     private String templateName;

+ 0 - 9
web/src/main/java/seecoder/devcloud/web/model/vo/user/GroupVO.java

@@ -5,9 +5,6 @@ import lombok.Data;
 import lombok.NoArgsConstructor;
 import seecoder.devcloud.web.model.po.user.Group;
 
-import java.util.List;
-import java.util.stream.Collectors;
-
 /**
  * @EnumName GroupVO
  * @PackageName com.moekr.moocoder.logic.Serializer
@@ -22,16 +19,10 @@ import java.util.stream.Collectors;
 public class GroupVO {
     private Integer id;
     private String name;
-    private String code;
-    private List<UserVO> members;
 
     public GroupVO(Group group) {
         this.id=group.getId();
         this.name=group.getName();
-        this.code=group.getShareLink();
-        this.members=group.getMembers().stream()
-                .map(UserVO::new)
-                .collect(Collectors.toList());
     }
 
 }

+ 0 - 49
web/src/main/java/seecoder/devcloud/web/model/vo/user/RegisterVO.java

@@ -1,49 +0,0 @@
-package seecoder.devcloud.web.model.vo.user;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.springframework.web.bind.annotation.PostMapping;
-
-import javax.validation.constraints.Email;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Pattern;
-
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class RegisterVO {
-	//@Email(message = "用户名也要填邮箱名称!")
-	@NotNull(groups = {PostMapping.class},message = "请填写用户名!")
-	private String username="default";
-	@Email(message = "邮箱格式不正确!")
-//	@NotNull(message = "请填写邮箱!")
-	@JsonIgnore
-	private String email;
-	@Pattern(groups = {PostMapping.class},regexp = "[0-9a-zA-Z_]{8,16}", message = "密码只能包含大小写字母、数字和下划线,且必须为8-16位!")
-	@NotNull(groups = {PostMapping.class},message = "请填写密码!")
-	private String password;
-	@Pattern(regexp = "^\\w+${4,23}", message = "昵称只能包含大小写字母、数字和下划线,且必须为4-23位!")
-	private String nickname="nickname";
-
-	public RegisterVO(@Email(message = "邮箱格式不正确!") @NotNull(message = "请填写邮箱!") String username, @Pattern(regexp = "[0-9a-zA-Z_]{8,16}", message = "密码只能包含大小写字母、数字和下划线,且必须为8-16位!") @NotNull(message = "请填写密码!") String password, String nickname) {
-		this.email = username;
-		this.username=buildUsername(username);
-		this.password = password;
-		this.nickname = nickname;
-	}
-	public void buildUsername(){
-		this.username=buildUsername(this.email);
-	}
-	public static String buildUsername(@Email(groups = {PostMapping.class},message = "邮箱格式不正确!") @NotNull(groups = {PostMapping.class},message = "请填写用户名!")String email){
-		return email.replace("@","_").replaceAll("\\.","_");
-	}
-
-	public void setUsername(String username) {
-		this.email = username;
-		this.username=buildUsername(username);
-	}
-}

+ 20 - 5
web/src/main/java/seecoder/devcloud/web/service/impl/project/ProjectServiceImpl.java

@@ -1,22 +1,32 @@
 package seecoder.devcloud.web.service.impl.project;
 
+import com.nju.edu.gitlab.SeecoderGitlabApi;
+import com.nju.edu.gitlab.SeecoderGitlabException;
+import com.nju.edu.gitlab.dto.project.VisibilityForm;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import seecoder.devcloud.common.exceptions.ServiceException;
 import seecoder.devcloud.web.dao.project.ProjectMapper;
 import seecoder.devcloud.web.model.po.project.Project;
-import seecoder.devcloud.web.service.project.ProjectService;
-import seecoder.devcloud.web.model.vo.Response;
 import seecoder.devcloud.web.model.vo.project.ProjectVO;
+import seecoder.devcloud.web.service.project.ProjectService;
 
 import java.util.List;
 import java.util.stream.Collectors;
 
 @Service
 public class ProjectServiceImpl implements ProjectService {
-    @Autowired
-    ProjectMapper projectMapper;
 
+    private final ProjectMapper projectMapper;
+
+    private final SeecoderGitlabApi seecoderGitlabApi;
+
+    @Autowired
+    public ProjectServiceImpl(ProjectMapper projectMapper, SeecoderGitlabApi seecoderGitlabApi) {
+        this.projectMapper = projectMapper;
+        this.seecoderGitlabApi = seecoderGitlabApi;
+    }
 
     @Override
     public List<ProjectVO> listProjectsByGroupId(int groupId) {
@@ -41,8 +51,13 @@ public class ProjectServiceImpl implements ProjectService {
     public ProjectVO createProject(ProjectVO projectVO) {
         Project project = new Project();
         BeanUtils.copyProperties(projectVO,project);
-
+        try {
+            seecoderGitlabApi.createProject(projectVO.getName(), VisibilityForm.PRIVATE);
+        } catch (SeecoderGitlabException e) {
+            throw new ServiceException("Error: 创建项目是时发生异常[" + e.getMessage() + "]");
+        }
         projectMapper.insertProject(project);
+
         // TODO:在对应的gitlab仓库中注册WEBHOOK
         return new ProjectVO(project);
 

+ 38 - 45
web/src/main/java/seecoder/devcloud/web/service/impl/user/GroupServiceImpl.java

@@ -1,29 +1,25 @@
 package seecoder.devcloud.web.service.impl.user;
 
 
+import com.nju.edu.gitlab.SeecoderGitlabApi;
+import com.nju.edu.gitlab.SeecoderGitlabException;
+import com.nju.edu.gitlab.dto.member.AccessLevelForm;
+import com.nju.edu.gitlab.vo.GitlabGroup;
 import lombok.extern.slf4j.Slf4j;
-import org.gitlab4j.api.GitLabApiException;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
-import seecoder.devcloud.api.gitlab.GitlabApi;
-import seecoder.devcloud.api.gitlab.model.GitlabGroup;
 import seecoder.devcloud.common.exceptions.EntityNotFoundException;
 import seecoder.devcloud.common.exceptions.ServiceException;
 import seecoder.devcloud.web.dao.user.GroupMapper;
 import seecoder.devcloud.web.dao.user.GroupMemberMapper;
-import seecoder.devcloud.web.model.enums.GroupType;
 import seecoder.devcloud.web.model.po.user.Group;
 import seecoder.devcloud.web.model.po.user.User;
-import seecoder.devcloud.web.service.user.GroupService;
 import seecoder.devcloud.web.model.vo.user.GroupVO;
+import seecoder.devcloud.web.service.user.GroupService;
 import seecoder.devcloud.web.service.user.UserService;
 
-import java.util.ArrayList;
 import java.util.List;
-import java.util.UUID;
 
 
 @Service
@@ -31,78 +27,75 @@ import java.util.UUID;
 public class GroupServiceImpl implements GroupService {
     private final GroupMapper groupMapper;
     private final GroupMemberMapper groupMemberMapper;
-    private final GitlabApi gitlabApi;
+
+    private final SeecoderGitlabApi seecoderGitlabApi;
+
+    private final String GROUP_NAME_PREFIX = "DEVCLOUD_";
 
     @Autowired
-    public GroupServiceImpl(GroupMapper groupMapper, GroupMemberMapper groupMemberMapper, GitlabApi gitlabApi) {
+    public GroupServiceImpl(GroupMapper groupMapper, GroupMemberMapper groupMemberMapper, SeecoderGitlabApi seecoderGitlabApi) {
         this.groupMapper = groupMapper;
         this.groupMemberMapper = groupMemberMapper;
-        this.gitlabApi = gitlabApi;
+        this.seecoderGitlabApi = seecoderGitlabApi;
     }
 
     @Override
     @Transactional
-    public GroupVO createGroup(String name, Integer userId) throws ServiceException {
+    public GroupVO createGroup(String name) throws ServiceException {
         if (groupMapper.findGroupByName(name) != null){
             throw new ServiceException("您创建的小组名字已被使用!");
         }
         User user = UserService.loginUser();
-        List<User> members = new ArrayList<>();
-        members.add(user);
-        GitlabGroup gitGroup;
+        GitlabGroup gitlabGroup = null;
         try {
-            gitGroup = gitlabApi.createGroup(name);
-            gitlabApi.addMemberToGroup(gitGroup.getId(), user.getId());
-        } catch (GitLabApiException e) {
-            log.error(e.getMessage(), e);
-            throw new RuntimeException("创建Group时发生异常[" + e.getMessage() + "]");
+            gitlabGroup = seecoderGitlabApi.createGroup(GROUP_NAME_PREFIX + name);
+            seecoderGitlabApi.addMember(gitlabGroup.getGroupId(), user.getId(), AccessLevelForm.MASTER);
+        } catch (SeecoderGitlabException e) {
+            throw new ServiceException("Error: 创建Group时发生异常[" + e.getMessage() + "]");
         }
         Group group = Group.builder()
-                .id(gitGroup.getId())
+                .id(gitlabGroup.getGroupId())
                 .name(name)
-                .namespace(gitGroup.getNamespace())
-                .shareLink(UUID.randomUUID().toString().replace("-", ""))
-                .type(GroupType.GROUP)
-                .members(members)
                 .build();
-        groupMapper.insert(group, "members");
-        groupMemberMapper.insert(gitGroup.getId(), userId);
+        groupMapper.insert(group);
+        groupMemberMapper.insert(gitlabGroup.getGroupId(), user.getId());
         return new GroupVO(group);
     }
 
 
     @Override
     //@Transactional
-    public GroupVO addMember(Integer userId, Integer invitedUserId, Integer groupId) throws EntityNotFoundException {
+    public void addMember(Integer invitedUserId, Integer groupId) throws EntityNotFoundException {
+        //当前登陆的用户id
+        int userId = UserService.loginUser().getId();
+
+        //只有在组内的用户才能邀请
         List<Integer> userIds = groupMemberMapper.selectUserIdsByGroupId(groupId);
         if (!userIds.contains(userId)) {
-            throw new EntityNotFoundException("小组邀请发生错误,用户没有权限!");
+            throw new EntityNotFoundException("Error: 小组邀请发生错误,用户没有权限!");
         }
         if (userIds.contains(invitedUserId)) {
-            throw new RuntimeException("邀请的用户已经加入小组!");
+            throw new RuntimeException("Error: 邀请的用户已经加入小组!");
         }
         try {
-            gitlabApi.addMemberToGroup(groupId, invitedUserId);
-        } catch (GitLabApiException e) {
-            log.error(e.getMessage(), e);
-            throw new RuntimeException("将成员加入Group时发生异常[" + e.getMessage() + "]");
+            seecoderGitlabApi.addMember(groupId, invitedUserId, AccessLevelForm.MASTER);
+        } catch (SeecoderGitlabException e) {
+            throw new ServiceException("Error: 将成员加入Group时发生异常[" + e.getMessage() + "]");
         }
         groupMemberMapper.insert(groupId, invitedUserId);
-        Group group = groupMapper.findWithMembersById(groupId);
-        return new GroupVO(group);
+        //Group group = groupMapper.findWithMembersById(groupId);
     }
 
     @Override
     public void quitGroup(Integer groupId, Integer userId) throws ServiceException {
 
-        try {
-            gitlabApi.quitGroup(groupId,userId);
-        } catch (GitLabApiException e) {
-            log.error(e.getMessage(), e);
-            throw new ServiceException(e.getMessage());
-        }
-        groupMemberMapper.delete(groupId,userId);
-
+//        try {
+//            gitlabApi.quitGroup(groupId,userId);
+//        } catch (GitLabApiException e) {
+//            log.error(e.getMessage(), e);
+//            throw new ServiceException(e.getMessage());
+//        }
+//        groupMemberMapper.delete(groupId,userId);
     }
 }
 

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

@@ -33,7 +33,9 @@ public interface ProjectService {
 
     /**
      * 删除项目,懒删除
+     * todo 目前统一代码服务没有提供对应接口,此方法过期,待统一代码服务api更新后再补回
      */
+    @Deprecated
     void deleteProject(int projectId);
 
 }

+ 9 - 2
web/src/main/java/seecoder/devcloud/web/service/user/GroupService.java

@@ -18,9 +18,16 @@ import seecoder.devcloud.web.model.vo.user.GroupVO;
 @Service
 public interface GroupService {
 
-    GroupVO createGroup(String name,  Integer userId) throws ServiceException;
+    /**
+     * 创建组,组的名字前面会加上 GROUP_NAME_PREFIX = "DEVCLOUD_" 的前缀
+     */
+    GroupVO createGroup(String name) throws ServiceException;
 
-    GroupVO addMember(Integer userId, Integer invitedUserId, Integer groupId)  throws EntityNotFoundException;
+    void addMember(Integer invitedUserId, Integer groupId)  throws EntityNotFoundException;
 
+    /**
+     * todo 目前统一代码服务没有提供对应接口,此方法过期,待统一代码服务api更新后再补回
+     */
+    @Deprecated
     void quitGroup(Integer groupId, Integer userId) throws ServiceException;
 }

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

@@ -10,7 +10,7 @@ public interface UserService {
     UserVO getLoginUser();
 
     /**
-     * 用于内部获取登🦌用户PO
+     * 用于内部获取登用户PO
      */
     static User loginUser(){
         return (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

+ 1 - 4
web/src/main/resources/SQLscripts/group.sql

@@ -2,9 +2,6 @@ create table if not exists devcloud.`group`
 (
     id         int                      not null
         primary key,
-    name       varchar(23) charset utf8 not null,
-    namespace  int                      not null,
-    share_link varchar(63)              not null,
-    type       varchar(15) charset utf8 null
+    name       varchar(23) charset utf8 not null
 );
 

+ 0 - 3
web/src/main/resources/SQLscripts/group_member.sql

@@ -4,8 +4,5 @@ create table if not exists devcloud.group_member
     user_id  int not null,
     constraint group_member_group_id_fk
         foreign key (group_id) references devcloud.`group` (id)
-            on delete cascade,
-    constraint group_member_user_id_fk
-        foreign key (user_id) references devcloud.user (id)
             on delete cascade
 );

Некоторые файлы не были показаны из-за большого количества измененных файлов