ソースを参照

test: k8s 创建各功能测试

同时规范了 pipeline包的异常抛出
370774330@qq.com 5 年 前
コミット
653a5b676c

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

@@ -53,5 +53,5 @@ public class K8sConstants {
 
     public final static String SERVICE_SUFFIX = "-service";
 
-    public final static String INGRESS_SUFFIX = "-suffix";
+    public final static String INGRESS_SUFFIX = "-ingress";
 }

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

@@ -50,4 +50,12 @@ public class Context {
      * 整个构建流程的记录, 每一个模块的各种运行信息(正常运行的结果,异常信息)都应该写入这里
      */
     private String result;
+
+    public void appendSuccessResult(String msg){
+        result = result + "Success: " + msg + "\n";
+    }
+
+    public void appendErrorResult(String msg, Exception e){
+        result = result + "Error: " + msg +"[" + e.getMessage() +"]" + "\n";
+    }
 }

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

@@ -12,6 +12,10 @@ public class PipelineException extends Exception{
     public static final String GIT_CLONE_ERROR = "从仓库拉取代码发生错误";
     public static final String DOCKERFILE_CREATE_ERROR = "创建dockerfile文件错误";
     public static final String IMAGE_BUILD_ERROR = "构建镜像构建推送到仓库错误";
+    public static final String INGRESS_CREATE_ERROR = "K8S ingress 创建错误";
+    public static final String SERVICE_CREATE_ERROR = "K8S service 创建错误";
+    public static final String DEPLOYMENT_CREATE_ERROR = "K8S deployment 创建错误";
+    public static final String NAMESPACE_CREATE_ERROR = "K8S namespace 创建错误";
     private int code;
     private String msg;
 

+ 5 - 6
core/src/main/java/seecoder/devcloud/core/pipeline/handler/DockerImageBuildHandler.java

@@ -59,8 +59,7 @@ public class DockerImageBuildHandler extends AbstractHandler {
             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);
+            context.appendErrorResult(PipelineException.GIT_CLONE_ERROR,e);
             throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE, PipelineException.GIT_CLONE_ERROR,e);
         }
         //2. 帮助学生创建dockerfile文件
@@ -73,8 +72,7 @@ public class DockerImageBuildHandler extends AbstractHandler {
             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);
+            context.appendErrorResult(PipelineException.DOCKERFILE_CREATE_ERROR,e);
             throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE, PipelineException.DOCKERFILE_CREATE_ERROR,e);
         }
 
@@ -97,13 +95,14 @@ public class DockerImageBuildHandler extends AbstractHandler {
                 }
             });
         } catch (Exception e) {
-            String error = "Error: 构建镜像推送到仓库错误, " + e.getMessage() + "\n";
-            context.setResult(context.getResult() + error);
+            context.appendErrorResult(PipelineException.IMAGE_BUILD_ERROR,e);
             throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE, PipelineException.IMAGE_BUILD_ERROR ,e);
         }
         //4. 将镜像名字加入context
         context.getConfigs().put("imageName", imageName);
         context.getConfigs().put("imageTag", imageTag);
+
+        context.appendSuccessResult("Success: DockerImageBuild");
     }
 }
 

+ 7 - 8
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 org.apache.http.HttpStatus;
 import seecoder.devcloud.api.ApplicationProperties;
 import seecoder.devcloud.api.k8s.DeploymentApi;
 import seecoder.devcloud.api.k8s.K8sConstants;
@@ -9,14 +10,12 @@ import seecoder.devcloud.api.k8s.exception.K8sApiException;
 import seecoder.devcloud.api.k8s.model.Container;
 import seecoder.devcloud.api.k8s.model.ContainerPort;
 import seecoder.devcloud.api.k8s.model.Deployment;
-import seecoder.devcloud.api.k8s.util.SecretTypeEnum;
 import seecoder.devcloud.api.k8s.vo.SecretVO;
 import seecoder.devcloud.common.util.SpringUtil;
 import seecoder.devcloud.core.pipeline.Context;
+import seecoder.devcloud.core.pipeline.PipelineException;
 
 import java.util.Collections;
-import java.util.List;
-import java.util.stream.Collectors;
 
 /**
  * @author PuHong Weng
@@ -38,7 +37,7 @@ public class K8sDeploymentHandler extends AbstractHandler {
 
     private final static String DEFAULT_IMAGE_PULL_SECRET_NAME = "seecoder-devcloud-image-pull-secret";
 
-    public K8sDeploymentHandler(ApplicationProperties applicationProperties) {
+    public K8sDeploymentHandler() {
         this.applicationProperties = SpringUtil.getBean(ApplicationProperties.class);
         secretApi = SpringUtil.getBean(SecretApi.class);
         deploymentApi = SpringUtil.getBean(DeploymentApi.class);
@@ -51,9 +50,9 @@ public class K8sDeploymentHandler extends AbstractHandler {
      * @param context
      */
     @Override
-    public void process(Context context) {
+    public void process(Context context) throws PipelineException {
         //配置初始化
-        String imageName = context.getConfigs().getOrDefault("imageName", "");
+        String imageName = context.getConfigs().get("imageName");
         int port = Integer.parseInt(context.getConfigs().getOrDefault("port", "8000"));
         int replicas = Integer.parseInt(context.getConfigs().getOrDefault("replicas", "1"));
         String namespace = context.getNamespace();
@@ -92,7 +91,7 @@ public class K8sDeploymentHandler extends AbstractHandler {
                     applicationProperties.getDocker().getRegistryPassword()
             );
         }
-        deployment.setImagePullSecrets(Collections.singletonList(secretVO.getName()));
+        deployment.setImagePullSecrets(Collections.singletonList(DEFAULT_IMAGE_PULL_SECRET_NAME));
 
         try {
             deploymentApi.create(deployment);
@@ -102,7 +101,7 @@ public class K8sDeploymentHandler extends AbstractHandler {
                 deploymentApi.update(deployment);
                 log.info("deployment更新成功");
             } else {
-                throw e;
+                throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE,PipelineException.DEPLOYMENT_CREATE_ERROR,e);
             }
         }
     }

+ 21 - 7
core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sIngressHandler.java

@@ -1,21 +1,24 @@
 package seecoder.devcloud.core.pipeline.handler;
 
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpStatus;
 import seecoder.devcloud.api.ApplicationProperties;
 import seecoder.devcloud.api.k8s.IngressApi;
 import seecoder.devcloud.api.k8s.K8sConstants;
+import seecoder.devcloud.api.k8s.exception.K8sApiException;
 import seecoder.devcloud.api.k8s.model.Ingress;
 import seecoder.devcloud.common.util.SpringUtil;
 import seecoder.devcloud.core.pipeline.Context;
+import seecoder.devcloud.core.pipeline.PipelineException;
 
 import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
 
 /**
  * @author PuHong Weng
  * @date 2021/1/18
  * @description:
  */
+@Slf4j
 public class K8sIngressHandler extends AbstractHandler {
 
     private final ApplicationProperties applicationProperties;
@@ -30,7 +33,7 @@ public class K8sIngressHandler extends AbstractHandler {
 
 
     @Override
-    public void process(Context context) {
+    public void process(Context context) throws PipelineException {
 
         String namespace = context.getNamespace();
         String projectName = context.getProjectName();
@@ -39,18 +42,29 @@ public class K8sIngressHandler extends AbstractHandler {
         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());
+        ingressRule.setHost(namespace + applicationProperties.getK8s().getIngressHostSuffix());
         Ingress.IngressPath path = new Ingress.IngressPath();
-        path.setPath(projectName+K8sConstants.DEPLOYMENT_SUFFIX);
+        path.setPath("/" + projectName + "/");
+        path.setPort(Integer.parseInt(servicePort));
+        path.setServiceName(projectName+K8sConstants.SERVICE_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);
+        try {
+            ingressApi.create(ingress);
+            log.info("deployment创建成功");
+        } catch (K8sApiException e){
+            if (e.getCode() == K8sApiException.ALREADY_EXIST){
+                ingressApi.update(ingress);
+                log.info("deployment更新成功");
+            } else {
+                throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE,PipelineException.INGRESS_CREATE_ERROR,e);
+            }
+        }
     }
 }

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

@@ -1,12 +1,14 @@
 package seecoder.devcloud.core.pipeline.handler;
 
 import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpStatus;
 import seecoder.devcloud.api.k8s.NamespaceApi;
 import seecoder.devcloud.api.k8s.SecretApi;
 import seecoder.devcloud.api.k8s.exception.K8sApiException;
 import seecoder.devcloud.api.k8s.model.Namespace;
 import seecoder.devcloud.common.util.SpringUtil;
 import seecoder.devcloud.core.pipeline.Context;
+import seecoder.devcloud.core.pipeline.PipelineException;
 
 /**
  * @author PuHong Weng
@@ -26,7 +28,7 @@ public class K8sNamespaceHandler extends AbstractHandler {
     }
 
     @Override
-    public void process(Context context) {
+    public void process(Context context) throws PipelineException {
         Namespace namespace = new Namespace();
         namespace.setName(context.getNamespace());
 
@@ -38,7 +40,7 @@ public class K8sNamespaceHandler extends AbstractHandler {
             if (e.getCode() == K8sApiException.ALREADY_EXIST){
                 log.info("Namespace已经存在, 无需新建");
             } else{
-                throw e;
+                throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE,PipelineException.NAMESPACE_CREATE_ERROR,e);
             }
         }
 

+ 4 - 2
core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sServiceHandler.java

@@ -1,6 +1,7 @@
 package seecoder.devcloud.core.pipeline.handler;
 
 import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpStatus;
 import seecoder.devcloud.api.k8s.K8sConstants;
 import seecoder.devcloud.api.k8s.ServiceApi;
 import seecoder.devcloud.api.k8s.exception.K8sApiException;
@@ -8,6 +9,7 @@ import seecoder.devcloud.api.k8s.model.Service;
 import seecoder.devcloud.api.k8s.model.ServicePort;
 import seecoder.devcloud.common.util.SpringUtil;
 import seecoder.devcloud.core.pipeline.Context;
+import seecoder.devcloud.core.pipeline.PipelineException;
 
 import java.util.Collections;
 
@@ -27,7 +29,7 @@ public class K8sServiceHandler extends AbstractHandler {
 
 
     @Override
-    public void process(Context context){
+    public void process(Context context) throws PipelineException {
 
         //pod内容器暴露的端口
         int targetPort =  Integer.parseInt(context.getConfigs().get("port"));
@@ -53,7 +55,7 @@ public class K8sServiceHandler extends AbstractHandler {
                 serviceApi.update(service);
                 log.info("service更新成功");
             } else {
-                throw e;
+                throw new PipelineException(HttpStatus.SC_SERVICE_UNAVAILABLE,PipelineException.SERVICE_CREATE_ERROR,e);
             }
         }
     }

+ 30 - 1
core/src/test/java/seecoder/devcloud/core/CoreApplicationTests.java

@@ -8,8 +8,13 @@ import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.junit4.SpringRunner;
 import seecoder.devcloud.api.ApplicationProperties;
 import seecoder.devcloud.api.k8s.DeploymentApi;
+import seecoder.devcloud.api.k8s.IngressApi;
+import seecoder.devcloud.api.k8s.ServiceApi;
 import seecoder.devcloud.core.pipeline.Context;
+import seecoder.devcloud.core.pipeline.handler.K8sDeploymentHandler;
+import seecoder.devcloud.core.pipeline.handler.K8sIngressHandler;
 import seecoder.devcloud.core.pipeline.handler.K8sNamespaceHandler;
+import seecoder.devcloud.core.pipeline.handler.K8sServiceHandler;
 
 @RunWith(SpringRunner.class)
 @SpringBootTest
@@ -21,6 +26,12 @@ class CoreApplicationTests {
     @Autowired
     private DeploymentApi deploymentApi;
 
+    @Autowired
+    private ServiceApi serviceApi;
+
+    @Autowired
+    private IngressApi ingressApi;
+
     private Context context;
 
 
@@ -32,6 +43,9 @@ class CoreApplicationTests {
     @Test
     void k8sDeployment() {
 
+        K8sDeploymentHandler handler = new K8sDeploymentHandler();
+        context.getConfigs().put("imageName","mysql:5.7");
+        handler.process(context);
 
     }
 
@@ -44,11 +58,26 @@ class CoreApplicationTests {
     }
 
 
+    @Test
+    void k8sService() {
+        context.getConfigs().put("port","8000");
+        K8sServiceHandler k8sServiceHandler = new K8sServiceHandler();
+        k8sServiceHandler.process(context);
+    }
+
+    @Test
+    void k8sIngress() {
+        context.getConfigs().put("servicePort","8000");
+        K8sIngressHandler ingressHandler = new K8sIngressHandler();
+        ingressHandler.process(context);
+    }
+
+
     private void mockContext(){
         this.context = Context.builder()
                 .namespace("test-group")
                 .projectName("test-project")
                 .applicationProperties(applicationProperties)
-                .configs(null).build();
+                .build();
     }
 }