瀏覽代碼

Refactor Ingress Api 修复创建失败和删除异常问题

raledong 7 年之前
父節點
當前提交
f0059633cf

+ 18 - 1
src/main/java/nju/seec/SEECdemo/logic/api/k8s/IngressApi.java

@@ -1,5 +1,6 @@
 package nju.seec.SEECdemo.logic.api.k8s;
 
+import nju.seec.SEECdemo.logic.api.k8s.dto.IngressDTO;
 import nju.seec.SEECdemo.logic.api.k8s.vo.ApiResult;
 
 /**
@@ -8,5 +9,21 @@ import nju.seec.SEECdemo.logic.api.k8s.vo.ApiResult;
  */
 public interface IngressApi {
 
-    ApiResult<String> create(String namespace, String name, String path, String serviceName, int port);
+    void create(IngressDTO ingressDTO);
+
+    /**
+     * 若命名空间不存在或者Ingress不存在,抛出K8sApiException
+     * @param namespace
+     * @param name
+     * @throws nju.seec.SEECdemo.logic.api.k8s.exception.K8sApiException 当K8s系统执行操作出现系统异常时,会抛出系统异常
+     */
+    void delete(String namespace, String name);
+
+    /**
+     * 若命名空间不存在或者资源不存在,不会执行任何操作,也不会抛出异常
+     * @param namespace
+     * @param name
+     * @throws nju.seec.SEECdemo.logic.api.k8s.exception.K8sApiException 当K8s系统执行操作出现系统异常时,会抛出系统异常
+     */
+    void deleteIfExists(String namespace, String name);
 }

+ 92 - 0
src/main/java/nju/seec/SEECdemo/logic/api/k8s/dto/IngressDTO.java

@@ -0,0 +1,92 @@
+package nju.seec.SEECdemo.logic.api.k8s.dto;
+
+import io.kubernetes.client.custom.IntOrString;
+import io.kubernetes.client.models.*;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * author: rale
+ * createdAt: 1/5/19
+ */
+@Data
+@NoArgsConstructor
+public class IngressDTO {
+    public static final String API_VERSION = "extensions/v1beta1";
+
+    private static final String KIND = "Ingress";
+
+    private String namespace;
+
+    private String name;
+
+    private String path;
+
+    private String httpHost;
+
+    /*Ingress能暴露HTTP和HTTPS协议口,目前暂不支持HTTPS协议*/
+    private Set<IngressDetailDTO> httpRules = new HashSet<>();
+
+
+    @Data
+    @NoArgsConstructor
+    public static class IngressDetailDTO{
+
+        private String path;
+
+        private String serviceName;
+
+        private int port;
+    }
+
+
+    public V1beta1Ingress toV1beta1Ingress(){
+        V1beta1IngressSpec v1beta1IngressSpec = new V1beta1IngressSpecBuilder()
+                .withRules(toV1beta1IngressRule())
+                .build();
+        V1beta1Ingress v1beta1Ingress = new V1beta1IngressBuilder()
+                .withApiVersion(API_VERSION)
+                .withKind(KIND)
+                .withMetadata(this.toV1ObjectMeta())
+                .withSpec(v1beta1IngressSpec)
+                .build();
+        return v1beta1Ingress;
+    }
+
+    private V1ObjectMeta toV1ObjectMeta() {
+        return new V1ObjectMetaBuilder()
+                .withName(name)
+                .withNamespace(namespace)
+                .addToAnnotations("nginx.ingress.kubernetes.io/rewrite-target", "/")
+                .build();
+    }
+
+    private V1beta1HTTPIngressRuleValue toV1beta1HTTPIngressRuleValue() {
+        List<V1beta1HTTPIngressPath> paths = httpRules.stream().map(rule -> {
+                    V1beta1HTTPIngressPath v1beta1HTTPIngressPath = new V1beta1HTTPIngressPath();
+                    v1beta1HTTPIngressPath.setPath(rule.getPath());
+                    V1beta1IngressBackend v1beta1IngressBackend = new V1beta1IngressBackend();
+                    v1beta1IngressBackend.setServiceName(rule.getServiceName());
+                    v1beta1IngressBackend.setServicePort(new IntOrString(rule.getPort()));
+
+                    v1beta1HTTPIngressPath.setBackend(v1beta1IngressBackend);
+                    return v1beta1HTTPIngressPath;
+        }).collect(Collectors.toList());
+
+        return new V1beta1HTTPIngressRuleValueBuilder()
+                .withPaths(paths)
+                .build();
+    }
+
+    private V1beta1IngressRule toV1beta1IngressRule() {
+        return new V1beta1IngressRuleBuilder()
+                .withHost(httpHost)
+                .withHttp(toV1beta1HTTPIngressRuleValue())
+                .build();
+    }
+}

+ 0 - 3
src/main/java/nju/seec/SEECdemo/logic/api/k8s/dto/NamespaceDTO.java

@@ -50,13 +50,10 @@ public class NamespaceDTO {
                 .withLabels(labels)
                 .withAnnotations(annotations)
                 .build();
-        V1NamespaceSpec v1NamespaceSpec = new V1NamespaceSpecBuilder()
-                .build();
         V1Namespace v1Namespace = new V1NamespaceBuilder()
                 .withApiVersion(VERSION)
                 .withKind(KIND)
                 .withMetadata(v1ObjectMeta)
-                .withSpec(v1NamespaceSpec)
                 .build();
         return v1Namespace;
 

+ 59 - 42
src/main/java/nju/seec/SEECdemo/logic/api/k8s/impl/IngressApiImpl.java

@@ -9,12 +9,19 @@ import io.kubernetes.client.models.*;
 import io.kubernetes.client.proto.V1beta1Apps;
 import io.kubernetes.client.proto.V1beta1Extensions;
 import nju.seec.SEECdemo.logic.api.k8s.IngressApi;
+import nju.seec.SEECdemo.logic.api.k8s.dto.IngressDTO;
+import nju.seec.SEECdemo.logic.api.k8s.exception.K8sApiException;
 import nju.seec.SEECdemo.logic.api.k8s.vo.ApiResult;
+import nju.seec.SEECdemo.logic.api.k8s.vo.Namespace;
+import nju.seec.SEECdemo.util.ApplicationProperties;
 import nju.seec.SEECdemo.util.LoggerUtil;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import static nju.seec.SEECdemo.util.Constants.FOREGROUND_PROPAGATION_POLICY;
+import static nju.seec.SEECdemo.util.Constants.PRETTY_FORMAT;
+
 /**
  * author: rale
  * createdAt: 12/24/18
@@ -23,54 +30,64 @@ import org.springframework.stereotype.Service;
 public class IngressApiImpl implements IngressApi{
     private static final Logger logger = LoggerUtil.getLogger(IngressApi.class);
     @Autowired
-    private ExtensionsV1beta1Api extensionsV1beta1Api;
+    private final ExtensionsV1beta1Api extensionsV1beta1Api;
 
-    //@todo fix bug
-    @Override
-    public ApiResult<String> create(String namespace, String name, String path, String serviceName, int port) {
-        V1ObjectMeta v1ObjectMeta = new V1ObjectMetaBuilder()
-                .withName(name)
-                .withNamespace(namespace)
-                .build();
+    @Autowired
+    public IngressApiImpl(ApplicationProperties applicationProperties, ExtensionsV1beta1Api extensionsV1beta1Api){
+        this.extensionsV1beta1Api = extensionsV1beta1Api;
+    }
 
-        V1beta1HTTPIngressPath v1beta1HTTPIngressPath = new V1beta1HTTPIngressPathBuilder()
-                .withPath(path)
-                .withBackend(new V1beta1IngressBackendBuilder()
-                        .withServiceName(serviceName)
-                        .withServicePort(new IntOrString(port))
-                        .build())
-                .build();
-        V1beta1HTTPIngressRuleValue v1beta1HTTPIngressRuleValue = new V1beta1HTTPIngressRuleValueBuilder()
-                .addToPaths(v1beta1HTTPIngressPath)
-                 .build();
-        V1beta1IngressRule v1beta1IngressRule = new V1beta1IngressRuleBuilder()
-                .withHost("deernowl.cn")
-                .withHttp(v1beta1HTTPIngressRuleValue)
-                .build();
-        V1beta1IngressSpec v1beta1IngressSpec = new V1beta1IngressSpecBuilder()
-                .withRules(v1beta1IngressRule)
-                .build();
-        V1beta1Ingress v1beta1Ingress = new V1beta1IngressBuilder()
-                .withApiVersion("extensions/v1beta1")
-                .withKind("Ingress")
-                .withMetadata(v1ObjectMeta)
-                .withSpec(v1beta1IngressSpec)
-                .build();
+    @Override
+    public void create(IngressDTO ingressDTO) {
+        V1beta1Ingress v1beta1Ingress = ingressDTO.toV1beta1Ingress();
 
         try {
-            extensionsV1beta1Api.createNamespacedIngress(namespace, v1beta1Ingress, "pretty");
+            extensionsV1beta1Api.createNamespacedIngress(ingressDTO.getNamespace(), v1beta1Ingress, PRETTY_FORMAT);
         } catch (ApiException e) {
-            LoggerUtil.error(logger, e, "ingress 创建失败,v1BetaIngress={}, response={}", v1beta1Ingress, e.getResponseBody());
-            ApiResult<String> apiResult = new ApiResult<>();
-            apiResult.setSuccess(false);
-            apiResult.setErrorCode(e.getCode());
-            apiResult.setErrorDescription(e.getMessage());
-            return apiResult;
+            LoggerUtil.error(logger, e, "ingress 创建失败,ingressDTO={}, response={}", ingressDTO, e.getResponseBody());
+            throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
         }
-        ApiResult<String> result = new ApiResult<>();
-        result.setSuccess(true);
-        result.setValue("deernowl.cn" + path);
-        return result;
     }
 
+    /**
+     * @see IngressApi#delete(String, String)
+     * @param namespace
+     * @param name
+     */
+    @Override
+    public void delete(String namespace, String name) {
+        //@todo 判断是否存在
+        V1DeleteOptions v1DeleteOptions = new V1DeleteOptionsBuilder()
+                .withApiVersion(IngressDTO.API_VERSION)
+                .withPropagationPolicy(FOREGROUND_PROPAGATION_POLICY)
+                .build();
+        try {
+            extensionsV1beta1Api.deleteNamespacedIngress(name, namespace, v1DeleteOptions, PRETTY_FORMAT, null, null, FOREGROUND_PROPAGATION_POLICY);;
+        }catch (ApiException e) {
+            LoggerUtil.error(logger, e, "ingress 删除失败,name={}, namespace={}, response={}", name, namespace, e.getResponseBody());
+            throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+        }catch (Exception e) {
+            //K8s swagger 异常, 无需进行处理
+        }
+    }
+
+    /**
+     * @see IngressApi#deleteIfExists(String, String)
+     * @param namespace
+     * @param name
+     */
+    @Override
+    public void deleteIfExists(String namespace, String name) {
+        V1DeleteOptions v1DeleteOptions = new V1DeleteOptionsBuilder()
+                .withApiVersion(IngressDTO.API_VERSION)
+                .withPropagationPolicy(FOREGROUND_PROPAGATION_POLICY)
+                .build();
+        try {
+            extensionsV1beta1Api.deleteNamespacedIngress(name, namespace, v1DeleteOptions, PRETTY_FORMAT, null, null, FOREGROUND_PROPAGATION_POLICY);;
+        }catch (ApiException e) {
+            LoggerUtil.error(logger, e, "ingress 删除失败,name={}, namespace={}, response={}", name, namespace, e.getResponseBody());
+        }catch (Exception e) {
+            //K8s Swagger 异常, 无需进行处理
+        }
+    }
 }

+ 4 - 4
src/main/java/nju/seec/SEECdemo/logic/api/k8s/util/SecretTypeEnum.java

@@ -31,10 +31,10 @@ public enum SecretTypeEnum {
     }
 
     public static SecretTypeEnum getByValue(String value) {
-        switch (value) {
-            case "Opaque": return Generic;
-            case "kubernetes.io/dockerconfigjson" : return REGISTRY;
-            case "Service Account" : return SERVICE_ACCOUNT;
+        for (SecretTypeEnum secretTypeEnum : SecretTypeEnum.values()){
+            if (StringUtils.equals(secretTypeEnum.getValue(), value)) {
+                return secretTypeEnum;
+            }
         }
         return null;
     }

+ 23 - 1
src/test/java/nju/seec/SEECdemo/service/api/IngressApiImplTest.java

@@ -3,12 +3,17 @@ package nju.seec.SEECdemo.service.api;
 import io.kubernetes.client.models.V1Secret;
 import io.kubernetes.client.models.V1SecretBuilder;
 import nju.seec.SEECdemo.logic.api.k8s.IngressApi;
+import nju.seec.SEECdemo.logic.api.k8s.dto.IngressDTO;
+import nju.seec.SEECdemo.logic.api.k8s.dto.IngressDTO.IngressDetailDTO;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.junit4.SpringRunner;
 
+import java.util.HashSet;
+import java.util.Set;
+
 /**
  * author: rale
  * createdAt: 12/24/18
@@ -22,6 +27,23 @@ public class IngressApiImplTest {
 
     @Test
     public void testCreate(){
-        ingressApi.create("group24", "test", "/", "test", 80);
+        IngressDTO ingressDTO = new IngressDTO();
+        ingressDTO.setName("test");
+        ingressDTO.setNamespace("demo");
+        ingressDTO.setHttpHost("deernowl.cn");
+        IngressDetailDTO ingressDetailDTO = new IngressDetailDTO();
+        ingressDetailDTO.setPath("/demo/test");
+        ingressDetailDTO.setPort(8081);
+        ingressDetailDTO.setServiceName("test");
+        Set<IngressDetailDTO> details = new HashSet<>();
+        details.add(ingressDetailDTO);
+        ingressDTO.setHttpRules(details);
+        ingressApi.create(ingressDTO);
+
+    }
+
+    @Test
+    public void testDelete() {
+        ingressApi.delete("group24", "test-ingress");
     }
 }