Bläddra i källkod

Merge branch 'platform-dev'

raledong 7 år sedan
förälder
incheckning
a3f2a96504
23 ändrade filer med 572 tillägg och 198 borttagningar
  1. 0 27
      src/main/java/nju/seec/SEECdemo/config/WebSocketConfig.java
  2. 15 0
      src/main/java/nju/seec/SEECdemo/logic/api/k8s/DeploymentApi.java
  3. 0 36
      src/main/java/nju/seec/SEECdemo/logic/api/k8s/LimitRangeApi.java
  4. 17 0
      src/main/java/nju/seec/SEECdemo/logic/api/k8s/WatchApi.java
  5. 2 3
      src/main/java/nju/seec/SEECdemo/logic/api/k8s/exception/K8sApiException.java
  6. 29 0
      src/main/java/nju/seec/SEECdemo/logic/api/k8s/impl/DeploymentApiImpl.java
  7. 33 49
      src/main/java/nju/seec/SEECdemo/logic/api/k8s/impl/LimitRangeApiImpl.java
  8. 3 3
      src/main/java/nju/seec/SEECdemo/logic/api/k8s/impl/LogApiImpl.java
  9. 75 0
      src/main/java/nju/seec/SEECdemo/logic/api/k8s/impl/WatchApiImpl.java
  10. 4 0
      src/main/java/nju/seec/SEECdemo/logic/api/k8s/model/Container.java
  11. 12 6
      src/main/java/nju/seec/SEECdemo/logic/api/k8s/model/CpuQuantity.java
  12. 13 0
      src/main/java/nju/seec/SEECdemo/logic/api/k8s/model/Deployment.java
  13. 33 0
      src/main/java/nju/seec/SEECdemo/logic/api/k8s/model/DeploymentStatus.java
  14. 53 0
      src/main/java/nju/seec/SEECdemo/logic/api/k8s/model/HttpGetAction.java
  15. 43 37
      src/main/java/nju/seec/SEECdemo/logic/api/k8s/model/LimitRange.java
  16. 61 0
      src/main/java/nju/seec/SEECdemo/logic/api/k8s/model/Probe.java
  17. 10 6
      src/main/java/nju/seec/SEECdemo/logic/api/k8s/model/StorageQuantity.java
  18. 41 1
      src/main/java/nju/seec/SEECdemo/logic/api/k8s/util/BeanAnnouncement.java
  19. 11 9
      src/main/java/nju/seec/SEECdemo/logic/service/impl/ProjectServiceImpl.java
  20. 91 12
      src/test/java/nju/seec/SEECdemo/service/api/DeploymentApiImplTest.java
  21. 0 8
      src/test/java/nju/seec/SEECdemo/service/api/LimitRangeTest.java
  22. 1 1
      src/test/java/nju/seec/SEECdemo/service/api/SecretApiImplTest.java
  23. 25 0
      src/test/java/nju/seec/SEECdemo/service/api/WatchApiImplTest.java

+ 0 - 27
src/main/java/nju/seec/SEECdemo/config/WebSocketConfig.java

@@ -1,27 +0,0 @@
-package nju.seec.SEECdemo.config;
-
-import org.springframework.context.annotation.Configuration;
-import org.springframework.messaging.simp.config.MessageBrokerRegistry;
-import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
-import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
-import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
-
-/**
- * author: rale
- * createdAt: 1/12/19
- */
-@Configuration
-@EnableWebSocketMessageBroker
-public class WebSocketConfig  implements WebSocketMessageBrokerConfigurer {
-
-    @Override
-    public void configureMessageBroker(MessageBrokerRegistry config) {
-        config.enableSimpleBroker("/topic");
-        config.setApplicationDestinationPrefixes("/app");
-    }
-
-    @Override
-    public void registerStompEndpoints(StompEndpointRegistry registry) {
-        registry.addEndpoint("/ws").withSockJS();
-    }
-}

+ 15 - 0
src/main/java/nju/seec/SEECdemo/logic/api/k8s/DeploymentApi.java

@@ -1,6 +1,7 @@
 package nju.seec.SEECdemo.logic.api.k8s;
 
 import nju.seec.SEECdemo.logic.api.k8s.model.Deployment;
+import nju.seec.SEECdemo.logic.api.k8s.model.DeploymentStatus;
 
 /**
  * author: rale
@@ -53,4 +54,18 @@ public interface DeploymentApi {
      */
     boolean exists(String namespace, String name);
 
+    /**
+     * 根据命名空间和名称查找Deployment
+     * @param namespace
+     * @param name
+     * @return 如果Deployment不存在,则返回null
+     */
+    Deployment get(String namespace, String name);
+
+    /**
+     * 查询deployment的状态
+     * @return 如果该deployment不存在,则返回null
+     * @throws nju.seec.SEECdemo.logic.api.k8s.exception.K8sApiException SYSTEM_ERROR 系统异常
+     */
+    DeploymentStatus getStatus(String namespace, String name);
 }

+ 0 - 36
src/main/java/nju/seec/SEECdemo/logic/api/k8s/LimitRangeApi.java

@@ -11,26 +11,6 @@ import java.util.Map;
 
 public interface LimitRangeApi {
 
-    /**
-     * 传入参数转换为V1LimitRange对象
-     *
-     * @param namespace 命名空间名称需要唯一
-     * @param name      LimitRange的资源名称
-     * @param _default  默认资源配额,存放资源名称和配额的键值对,String : cpu or memory (optional)
-     * @param defaultRequest 默认资源请求配额 (optional)
-     * @param max 最大资源配额 (optional)
-     * @param min 最小资源配额 (optional)
-     * note: 如果不需要optional的参数可传入null
-     */
-    V1LimitRange toLimitRange(String namespace, String name, Map<String, Integer> _default, Map<String, Integer> defaultRequest, Map<String, Integer> max, Map<String, Integer> min);
-
-    /**
-     * 传入参数转换为V1LimitRange对象
-     * @param namespace 命名空间名称需要唯一
-     * @param body      配置好的V1LimitRange,可由toLimitRange()获得
-     */
-    V1LimitRange createLimitRange(String namespace, V1LimitRange body) throws K8sApiException;
-
     /**
      * 创建LimitRange
      *
@@ -62,16 +42,6 @@ public interface LimitRangeApi {
      */
     LimitRange getLimitRangeByName(String namespace, String name) throws K8sApiException;
 
-    /**
-     * 更新命名空间内的指定名称的LimitRange
-     *
-     * @param namespace 命名空间名称需要唯一
-     * @param name      LimitRange的资源名称
-     * @param body
-     */
-    V1LimitRange updateLimitRange(String namespace, String name, V1LimitRange body) throws K8sApiException;
-
-
     /**
      * 更新命名空间内的指定名称的LimitRange
      *
@@ -81,11 +51,5 @@ public interface LimitRangeApi {
      */
     LimitRange updateLimitRange(String namespace, String name, LimitRange body) throws K8sApiException;
 
-
-
-
-
-
-
 }
 

+ 17 - 0
src/main/java/nju/seec/SEECdemo/logic/api/k8s/WatchApi.java

@@ -0,0 +1,17 @@
+package nju.seec.SEECdemo.logic.api.k8s;
+
+/**
+ * author: rale
+ * createdAt: 1/13/19
+ */
+public interface WatchApi {
+
+    /**
+     * 会监听deployment的状态
+     * 超时时间十分钟
+     */
+    void watchDeployment();
+
+    void watchPod();
+
+}

+ 2 - 3
src/main/java/nju/seec/SEECdemo/logic/api/k8s/exception/K8sApiException.java

@@ -7,12 +7,11 @@ import java.util.HashMap;
 import java.util.Map;
 
 @Data
-@NoArgsConstructor
 public class K8sApiException extends RuntimeException{
 
-    private int code;
+    private final int code;
 
-    private String description;
+    private final String description;
 
     public static final Map<Integer, String> codeMap = new HashMap<>();
 

+ 29 - 0
src/main/java/nju/seec/SEECdemo/logic/api/k8s/impl/DeploymentApiImpl.java

@@ -8,6 +8,7 @@ import io.kubernetes.client.models.*;
 import nju.seec.SEECdemo.logic.api.k8s.DeploymentApi;
 import nju.seec.SEECdemo.logic.api.k8s.model.Deployment;
 import nju.seec.SEECdemo.logic.api.k8s.exception.K8sApiException;
+import nju.seec.SEECdemo.logic.api.k8s.model.DeploymentStatus;
 import nju.seec.SEECdemo.util.LoggerUtil;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -139,6 +140,34 @@ public class DeploymentApiImpl implements DeploymentApi{
         return false;
     }
 
+    @Override
+    public Deployment get(String namespace, String name) {
+        try{
+            V1Deployment v1Deployment = appsV1Api.readNamespacedDeployment(
+                    name,
+                    namespace,
+                    PRETTY_FORMAT,
+                    false,
+                    false);
+            return v1Deployment == null ? null : new Deployment(v1Deployment);
+        } catch (ApiException e) {
+            if (e.getCode() != K8sApiException.NOT_FOUND) {
+                LoggerUtil.error(logger, e, "查询Deployment异常,namespace={}, name={}", namespace, name);
+                throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+            }
+        } catch (Exception e) {
+            LoggerUtil.error(logger, e, "查询Deployment异常, namespace={}, name={}", namespace, name);
+            throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+        }
+        return null;
+    }
+
+    @Override
+    public DeploymentStatus getStatus(String namespace, String name) {
+        Deployment deployment = this.get(namespace, name);
+        return deployment == null ? null : deployment.getStatus();
+    }
+
     private void deleteDeployment(String namespace, String name) throws ApiException{
         V1DeleteOptions v1DeleteOptions = new V1DeleteOptionsBuilder()
                 .withApiVersion(Deployment.API_VERSION)

+ 33 - 49
src/main/java/nju/seec/SEECdemo/logic/api/k8s/impl/LimitRangeApiImpl.java

@@ -10,6 +10,7 @@ import nju.seec.SEECdemo.logic.api.k8s.LimitRangeApi;
 import nju.seec.SEECdemo.logic.api.k8s.exception.K8sApiException;
 import nju.seec.SEECdemo.logic.api.k8s.model.LimitRange;
 import nju.seec.SEECdemo.logic.api.k8s.vo.LimitRangeVO;
+import nju.seec.SEECdemo.util.LoggerUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -17,6 +18,8 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
+import static nju.seec.SEECdemo.util.Constants.PRETTY_FORMAT;
+
 
 @Service
 public class LimitRangeApiImpl implements LimitRangeApi {
@@ -25,51 +28,18 @@ public class LimitRangeApiImpl implements LimitRangeApi {
     private CoreV1Api coreV1Api;
 
     @Override
-    public V1LimitRange toLimitRange(String namespace, String name, Map<String, Integer> _default, Map<String, Integer> defaultRequest, Map<String, Integer> max, Map<String, Integer> min) {
-        LimitRangeVO limitRangeVO = new LimitRangeVO();
-        limitRangeVO.setName(name);
-        limitRangeVO.setNamespace(namespace);
-        limitRangeVO.set_default(_default);
-        limitRangeVO.setDefault_request(defaultRequest);
-        limitRangeVO.setMax(max);
-        limitRangeVO.setMin(min);
-        return limitRangeVO.toV1LimitRange();
-    }
-
-    @Override
-    public V1LimitRange createLimitRange(String namespace, V1LimitRange body) throws K8sApiException {
-
-        try {
-            return coreV1Api.createNamespacedLimitRange(namespace, body, "OK");
-        } catch (ApiException e) {
-            //namespace NotFound 404
-            //Already Exist 409
-            //422 if default value greater than max value, or min value greater than defaultRequest value
-            switch (e.getCode()) {
-                case K8sApiException.NOT_FOUND:
-                    throw new K8sApiException(K8sApiException.NOT_FOUND);
-                case K8sApiException.ALREADY_EXIST:
-                    throw new K8sApiException(K8sApiException.ALREADY_EXIST);
-                case K8sApiException.INVALID_VALUE:
-                    throw new K8sApiException(K8sApiException.INVALID_VALUE);
-                default:
-                    throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
-            }
-        }
-    }
-
-    @Override
-    public LimitRange createLimitRange(String namespace, LimitRange limitRange) throws K8sApiException {
-        V1LimitRange v1LimitRange =  createLimitRange(namespace, limitRange.toV1LimitRange());
-        return limitRange;
+    public LimitRange createLimitRange(String namespace, LimitRange limitRange) {
+        V1LimitRange v1LimitRange =  limitRange.toV1LimitRange();
+        v1LimitRange = createLimitRange(namespace, v1LimitRange);
+        return v1LimitRange == null ? null : new LimitRange(v1LimitRange);
     }
 
     @Override
-    public void deleteLimitRange(String namespace, String name) throws K8sApiException {
+    public void deleteLimitRange(String namespace, String name) {
         V1DeleteOptions body = new V1DeleteOptions();
         try {
             //暂时没有用到deleteNamespacedSecret()中的其他参数。
-            V1Status v1Status = coreV1Api.deleteNamespacedLimitRange(name, namespace, body, "", 5, false, "");
+            V1Status v1Status = coreV1Api.deleteNamespacedLimitRange(name, namespace, body, PRETTY_FORMAT, 5, false, "");
         } catch (ApiException e) {
             if (e.getCode() == K8sApiException.NOT_FOUND) {
                 throw new K8sApiException(K8sApiException.NOT_FOUND);
@@ -80,7 +50,7 @@ public class LimitRangeApiImpl implements LimitRangeApi {
     }
 
     @Override
-    public List<LimitRange> getLimitRangeList(String namespace) throws K8sApiException {
+    public List<LimitRange> getLimitRangeList(String namespace) {
         try {
             V1LimitRangeList limitRangeList = coreV1Api.listNamespacedLimitRange(namespace, "OK", "", "", false, "", 5, "", 5, false);
             List<V1LimitRange> itemList = limitRangeList.getItems();
@@ -89,7 +59,7 @@ public class LimitRangeApiImpl implements LimitRangeApi {
             } else {
                 List<LimitRange> result = new ArrayList<>();
                 for (V1LimitRange v1LimitRange : itemList)
-                    result.add(LimitRange.toLimitRange(v1LimitRange));
+                    result.add(new LimitRange(v1LimitRange));
                 return result;
             }
         } catch (ApiException e) {
@@ -99,7 +69,7 @@ public class LimitRangeApiImpl implements LimitRangeApi {
     }
 
     @Override
-    public LimitRange getLimitRangeByName(String namespace, String name) throws K8sApiException {
+    public LimitRange getLimitRangeByName(String namespace, String name) {
         List<LimitRange> list = getLimitRangeList(namespace);
         for (LimitRange limitRange : list) {
             if (limitRange.getName().equals(name)) {
@@ -109,18 +79,32 @@ public class LimitRangeApiImpl implements LimitRangeApi {
         throw new K8sApiException(K8sApiException.NOT_FOUND);
     }
 
-    @Override
-    public V1LimitRange updateLimitRange(String namespace, String name, V1LimitRange body) throws K8sApiException {
-        //暂时没研究清楚Api参数,该方法实现为删除并重新创建
-        deleteLimitRange(namespace, name);
-        return createLimitRange(namespace, body);
-    }
 
     @Override
-    public LimitRange updateLimitRange(String namespace, String name, LimitRange body) throws K8sApiException {
+    public LimitRange updateLimitRange(String namespace, String name, LimitRange body) {
         deleteLimitRange(namespace, name);
         return createLimitRange(namespace, body);
     }
 
 
+    private V1LimitRange createLimitRange(String namespace, V1LimitRange body) {
+
+        try {
+            return coreV1Api.createNamespacedLimitRange(namespace, body, PRETTY_FORMAT);
+        } catch (ApiException e) {
+            //namespace NotFound 404
+            //Already Exist 409
+            //422 if default value greater than max value, or min value greater than defaultRequest value
+            switch (e.getCode()) {
+                case K8sApiException.NOT_FOUND:
+                    throw new K8sApiException(K8sApiException.NOT_FOUND);
+                case K8sApiException.ALREADY_EXIST:
+                    throw new K8sApiException(K8sApiException.ALREADY_EXIST);
+                case K8sApiException.INVALID_VALUE:
+                    throw new K8sApiException(K8sApiException.INVALID_VALUE);
+                default:
+                    throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+            }
+        }
+    }
 }

+ 3 - 3
src/main/java/nju/seec/SEECdemo/logic/api/k8s/impl/LogApiImpl.java

@@ -35,8 +35,8 @@ public class LogApiImpl implements LogApi{
         PodLogs logs = new PodLogs();
         InputStream inputStream = logs.streamNamespacedPodLog(pod);
 
-        byte[] data = ByteStreams.toByteArray(inputStream);
-        System.out.print(data.length);
-//        ByteStreams.copy(inputStream, System.out);
+//        byte[] data = ByteStreams.toByteArray(inputStream);
+//        System.out.print(data.length);
+        ByteStreams.copy(inputStream, System.out);
     }
 }

+ 75 - 0
src/main/java/nju/seec/SEECdemo/logic/api/k8s/impl/WatchApiImpl.java

@@ -0,0 +1,75 @@
+package nju.seec.SEECdemo.logic.api.k8s.impl;
+
+import com.google.common.reflect.TypeToken;
+import io.kubernetes.client.ApiClient;
+import io.kubernetes.client.ApiException;
+import io.kubernetes.client.apis.AppsV1Api;
+import io.kubernetes.client.apis.CoreV1Api;
+import io.kubernetes.client.models.V1Deployment;
+import io.kubernetes.client.models.V1Pod;
+import io.kubernetes.client.util.Watch;
+import nju.seec.SEECdemo.logic.api.k8s.WatchApi;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+
+import static nju.seec.SEECdemo.util.Constants.PRETTY_FORMAT;
+
+/**
+ * author: rale
+ * createdAt: 1/13/19
+ */
+@Service
+public class WatchApiImpl implements WatchApi{
+
+    private ApiClient watchApiClient;
+
+    private AppsV1Api watchAppsV1Api;
+
+    @Autowired
+    public WatchApiImpl(ApiClient watchApiClient, AppsV1Api watchAppsV1Api) {
+        this.watchApiClient = watchApiClient;
+        this.watchAppsV1Api = watchAppsV1Api;
+    }
+    @Override
+//    @Async("taskExecutor")
+    public void watchDeployment() {
+        try {
+            Watch<V1Deployment> watch = Watch.createWatch(
+                    watchApiClient,
+                    watchAppsV1Api.listNamespacedDeploymentCall(
+                            "demo2",
+                            PRETTY_FORMAT,
+                            null,
+                            null,
+                            null,
+                            "demo.seec.nju.cn/app=test",
+                            null,
+                            null,
+                            null,
+                            true,
+                            null,
+                            null ),
+                    new TypeToken<Watch.Response<V1Deployment>>(){}.getType()
+
+            );
+            watch.forEach(response -> {
+                System.out.printf("%s pod : %s %s%n", response.type, response.object.getMetadata().getName(), response.object.getStatus());
+                try {
+                    watch.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            });
+        } catch (ApiException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void watchPod() {
+
+    }
+}

+ 4 - 0
src/main/java/nju/seec/SEECdemo/logic/api/k8s/model/Container.java

@@ -45,6 +45,8 @@ public class Container {
     /* 环境变量 */
     private Map<String, String> env = new HashMap<>();
 
+    /* 探测容器是否就绪 */
+    private Probe readinessProbe;
 
     public Container(V1Container v1Container) {
         this.name = v1Container.getName();
@@ -56,11 +58,13 @@ public class Container {
             this.env = v1Container.getEnv().stream().collect(Collectors.toMap(V1EnvVar::getName, V1EnvVar::getValue));
         }
     }
+
     public V1Container toV1Container(){
         return new V1ContainerBuilder()
                 .withName(name)
                 .withImage(image)
                 .withImagePullPolicy(IMAGE_PULL_POLICY)
+                .withReadinessProbe(readinessProbe == null ? null : readinessProbe.toV1Probe())
                 .withArgs(args)
                 .withCommand(command)
                 .withPorts(ports.stream().map(ContainerPort::toV1ContainerPort).collect(Collectors.toList()))

+ 12 - 6
src/main/java/nju/seec/SEECdemo/logic/api/k8s/model/CpuQuantity.java

@@ -2,19 +2,20 @@ package nju.seec.SEECdemo.logic.api.k8s.model;
 
 import io.kubernetes.client.custom.Quantity;
 import lombok.Data;
+import lombok.Getter;
 import lombok.NoArgsConstructor;
 
 /**
  * CPU配额数量,默认单位为m,即CPU时间
  */
-@Data
-@NoArgsConstructor
+@Getter
 public class CpuQuantity {
 
-    private Quantity quantity;
+    private final Quantity quantity;
 
-    private Unit unit = Unit.Mi;
+    private final Unit unit;
 
+    private static final Unit DEFAULT_UNIT = Unit.Mi;
     //Cpu=0
     public static final CpuQuantity EMPTY = new CpuQuantity(0);
     //Cpu的默认分配额度
@@ -36,17 +37,21 @@ public class CpuQuantity {
     }
 
 
+
     public CpuQuantity(int quantity){
-        this.quantity = Quantity.fromString(quantity + unit.getCode());
+        this.quantity = Quantity.fromString(quantity + DEFAULT_UNIT.getCode());
+        this.unit = DEFAULT_UNIT;
     }
 
     public CpuQuantity(long quantity) {
-        this.quantity = Quantity.fromString(quantity + unit.getCode());
+        this.quantity = Quantity.fromString(quantity + DEFAULT_UNIT.getCode());
+        this.unit = DEFAULT_UNIT;
     }
 
 
     public CpuQuantity(Quantity quantity) {
         this.quantity = quantity;
+        this.unit = DEFAULT_UNIT;
     }
 
     public Quantity toQuantity(){
@@ -65,4 +70,5 @@ public class CpuQuantity {
         }
     }
 
+
 }

+ 13 - 0
src/main/java/nju/seec/SEECdemo/logic/api/k8s/model/Deployment.java

@@ -3,7 +3,9 @@ package nju.seec.SEECdemo.logic.api.k8s.model;
 import io.kubernetes.client.models.*;
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import lombok.Setter;
 import org.hibernate.validator.constraints.Range;
+import org.springframework.data.annotation.ReadOnlyProperty;
 
 import javax.validation.constraints.NotEmpty;
 import java.util.*;
@@ -24,6 +26,7 @@ public class Deployment {
     @NotEmpty
     private String name;
 
+    @NotEmpty
     private String namespace;
 
     private List<Container> containers = new ArrayList<>();
@@ -37,12 +40,22 @@ public class Deployment {
 
     private Map<String, String> annotations = new HashMap<>();
 
+    @ReadOnlyProperty
+    private DeploymentStatus status;
+
     public Deployment(V1Deployment v1Deployment) {
         this.name = v1Deployment.getMetadata().getName();
         this.namespace = v1Deployment.getMetadata().getNamespace();
         this.containers = v1Deployment.getSpec().getTemplate().getSpec().getContainers()
                 .stream().map(Container::new).collect(Collectors.toList());
+        this.imagePullSecrets = v1Deployment.getSpec().getTemplate().getSpec().getImagePullSecrets()
+                .stream().map(V1LocalObjectReference::getName).collect(Collectors.toList());
+        this.replicas = v1Deployment.getSpec().getReplicas();
+        this.labels = v1Deployment.getMetadata().getLabels();
+        this.annotations = v1Deployment.getMetadata().getAnnotations();
+        this.status = new DeploymentStatus(v1Deployment.getStatus());
     }
+
     public V1Deployment toV1Deployment(){
         return new V1DeploymentBuilder()
                 .withApiVersion(API_VERSION)

+ 33 - 0
src/main/java/nju/seec/SEECdemo/logic/api/k8s/model/DeploymentStatus.java

@@ -0,0 +1,33 @@
+package nju.seec.SEECdemo.logic.api.k8s.model;
+
+import io.kubernetes.client.models.V1DeploymentStatus;
+import lombok.Data;
+
+/**
+ * author: rale
+ * createdAt: 1/16/19
+ */
+@Data
+public class DeploymentStatus {
+
+    /**
+     * 当前为就绪状态的容器
+     */
+    private int readyReplicas;
+
+    /**
+     * 当前不可用的容器
+     */
+    private int unavailableReplicas;
+
+    /**
+     * 当前为最新版本的容器
+     */
+    private int updatedReplicas;
+
+    public DeploymentStatus(V1DeploymentStatus deploymentStatus) {
+        this.readyReplicas = deploymentStatus.getReadyReplicas() == null ? 0 : deploymentStatus.getReadyReplicas();
+        this.unavailableReplicas = deploymentStatus.getUnavailableReplicas() == null ? 0 : deploymentStatus.getUnavailableReplicas();
+        this.updatedReplicas = deploymentStatus.getUpdatedReplicas() == null ? 0 : deploymentStatus.getUpdatedReplicas();
+    }
+}

+ 53 - 0
src/main/java/nju/seec/SEECdemo/logic/api/k8s/model/HttpGetAction.java

@@ -0,0 +1,53 @@
+package nju.seec.SEECdemo.logic.api.k8s.model;
+
+import io.kubernetes.client.custom.IntOrString;
+import io.kubernetes.client.models.V1HTTPGetAction;
+import io.kubernetes.client.models.V1HTTPGetActionBuilder;
+import io.kubernetes.client.models.V1HTTPHeader;
+import io.kubernetes.client.models.V1HTTPHeaderBuilder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * author: rale
+ * createdAt: 1/13/19
+ *  封装HTTP get请求
+ */
+@Data
+@NoArgsConstructor
+public class HttpGetAction {
+
+    /*默认值为容器的host名称,即容器名称*/
+    private String host;
+
+    private Map<String, String> httpHeaders = Collections.EMPTY_MAP;
+
+    private String path;
+
+    private int port;
+
+    public HttpGetAction(V1HTTPGetAction v1HTTPGetAction) {
+        this.host = v1HTTPGetAction.getHost();
+        if (v1HTTPGetAction.getHttpHeaders() != null) {
+            httpHeaders = v1HTTPGetAction.getHttpHeaders().stream().collect(Collectors.toMap(V1HTTPHeader::getName, V1HTTPHeader::getValue));
+        }
+        this.path = v1HTTPGetAction.getPath();
+        this.port = v1HTTPGetAction.getPort().getIntValue();
+    }
+
+    public V1HTTPGetAction toV1HTTPGetAction() {
+        return new V1HTTPGetActionBuilder()
+                .withHost(host)
+                .withHttpHeaders(
+                        httpHeaders.entrySet().stream()
+                                .map(entry -> new V1HTTPHeaderBuilder().withName(entry.getKey()).withValue(entry.getValue()).build())
+                                .collect(Collectors.toList()))
+                .withPath(path)
+                .withPort(new IntOrString(port))
+                .build();
+    }
+}

+ 43 - 37
src/main/java/nju/seec/SEECdemo/logic/api/k8s/model/LimitRange.java

@@ -17,6 +17,12 @@ import static nju.seec.SEECdemo.util.Constants.NAME_PATTERN;
 @Data
 @NoArgsConstructor
 public class LimitRange {
+
+    private static final String API_VERSION = "v1";
+    private static final String KIND = "LimitRange";
+    private static final String CPU_KEY = "cpu";
+    private static final String MEMORY_KEY = "memory";
+
     @NotNull
     private String namespace;
 
@@ -24,89 +30,89 @@ public class LimitRange {
     @Pattern(regexp = NAME_PATTERN)
     private String name;
 
-    private CpuQuantity default_cpu;
-    private StorageQuantity default_memory;
-    private CpuQuantity default_request_cpu;
-    private StorageQuantity default_request_memory;
-    private CpuQuantity max_cpu;
-    private StorageQuantity max_memory;
-    private CpuQuantity min_cpu;
-    private StorageQuantity min_memory;
+    private CpuQuantity defaultCPU;
+    private StorageQuantity defaultMemory;
+    private CpuQuantity defaultRequestCPU;
+    private StorageQuantity defaultRequestMemory;
+    private CpuQuantity maxCpu;
+    private StorageQuantity maxMemory;
+    private CpuQuantity minCpu;
+    private StorageQuantity minMemory;
 
 
     private String type = "Container";
 
-    public static LimitRange toLimitRange(V1LimitRange v1LimitRange) {
+    public LimitRange(V1LimitRange v1LimitRange) {
         LimitRange limitRange = new LimitRange();
         V1LimitRangeItem v1LimitRangeItem = v1LimitRange.getSpec().getLimits().get(0);
         limitRange.setName(v1LimitRange.getMetadata().getName());
         limitRange.setNamespace(v1LimitRange.getMetadata().getNamespace());
         limitRange.setType(v1LimitRangeItem.getType());
         limitRange.setValues(v1LimitRangeItem);
-        return limitRange;
     }
 
+
     public V1LimitRange toV1LimitRange() {
         return new V1LimitRangeBuilder()
-                .withApiVersion("v1")
-                .withKind("LimitRangeVO")
+                .withApiVersion(API_VERSION)
+                .withKind(KIND)
                 .withMetadata(this.toV1ObjectMeta())
                 .withSpec(this.toV1LimitRangeSpec())
                 .build();
     }
 
-    public V1ObjectMeta toV1ObjectMeta() {
+    private V1ObjectMeta toV1ObjectMeta() {
         return new V1ObjectMetaBuilder()
                 .withNamespace(namespace)
                 .withName(name)
                 .build();
     }
 
-    public V1LimitRangeSpec toV1LimitRangeSpec() {
+    private V1LimitRangeSpec toV1LimitRangeSpec() {
         return new V1LimitRangeSpec().addLimitsItem(this.toV1LimitRangeItem());
     }
 
-    public V1LimitRangeItem toV1LimitRangeItem() {
+    private V1LimitRangeItem toV1LimitRangeItem() {
 
         V1LimitRangeItem v1LimitRangeItem = new V1LimitRangeItem();
-        if (!getItemValue(default_cpu, default_memory).isEmpty())
-            v1LimitRangeItem.setDefault(getItemValue(default_cpu, default_memory));
-        if (!getItemValue(default_request_cpu, default_request_memory).isEmpty())
-            v1LimitRangeItem.setDefaultRequest(getItemValue(default_request_cpu, default_request_memory));
-        if (!getItemValue(max_cpu, max_memory).isEmpty())
-            v1LimitRangeItem.setMax(getItemValue(max_cpu, max_memory));
-        if (!getItemValue(min_cpu, min_memory).isEmpty())
-            v1LimitRangeItem.setMin(getItemValue(min_cpu, min_memory));
+        if (!getItemValue(defaultCPU, defaultMemory).isEmpty())
+            v1LimitRangeItem.setDefault(getItemValue(defaultCPU, defaultMemory));
+        if (!getItemValue(defaultRequestCPU, defaultRequestMemory).isEmpty())
+            v1LimitRangeItem.setDefaultRequest(getItemValue(defaultRequestCPU, defaultRequestMemory));
+        if (!getItemValue(maxCpu, maxMemory).isEmpty())
+            v1LimitRangeItem.setMax(getItemValue(maxCpu, maxMemory));
+        if (!getItemValue(minCpu, minMemory).isEmpty())
+            v1LimitRangeItem.setMin(getItemValue(minCpu, minMemory));
         v1LimitRangeItem.setType(type);
         return v1LimitRangeItem;
     }
 
 
-    public Map<String, Quantity> getItemValue(CpuQuantity cpu_value, StorageQuantity memory_value) {
+    private Map<String, Quantity> getItemValue(CpuQuantity cpuValue, StorageQuantity memoryValue) {
         Map<String, Quantity> itemValue = new HashMap<>();
-        if (cpu_value != null) {
-            itemValue.put("cpu", cpu_value.toQuantity());
+        if (cpuValue != null) {
+            itemValue.put(CPU_KEY, cpuValue.toQuantity());
         }
-        if (memory_value != null) {
-            itemValue.put("memory", memory_value.toQuantity());
+        if (memoryValue != null) {
+            itemValue.put(MEMORY_KEY, memoryValue.toQuantity());
         }
         return itemValue;
     }
 
 
-    public void setValues(V1LimitRangeItem v1LimitRangeItem) {
+    private void setValues(V1LimitRangeItem v1LimitRangeItem) {
         Map<String, Quantity> _default = v1LimitRangeItem.getDefault();
         Map<String, Quantity> default_request = v1LimitRangeItem.getDefaultRequest();
         Map<String, Quantity> max = v1LimitRangeItem.getMax();
         Map<String, Quantity> min = v1LimitRangeItem.getMin();
-        setDefault_cpu(CpuQuantity.getCpuQuantity(_default.getOrDefault("cpu", null)));
-        setDefault_memory(StorageQuantity.getStorageQuantity(_default.getOrDefault("memory", null)));
-        setDefault_request_cpu(CpuQuantity.getCpuQuantity(default_request.getOrDefault("cpu", null)));
-        setDefault_request_memory(StorageQuantity.getStorageQuantity(default_request.getOrDefault("memory", null)));
-        setMax_cpu(CpuQuantity.getCpuQuantity(max.getOrDefault("cpu", null)));
-        setMax_memory(StorageQuantity.getStorageQuantity(max.getOrDefault("memory", null)));
-        setMin_cpu(CpuQuantity.getCpuQuantity(min.getOrDefault("cpu", null)));
-        setMin_memory(StorageQuantity.getStorageQuantity(min.getOrDefault("memory", null)));
+        setDefaultCPU(CpuQuantity.getCpuQuantity(_default.getOrDefault(CPU_KEY, null)));
+        setDefaultMemory(StorageQuantity.getStorageQuantity(_default.getOrDefault(MEMORY_KEY, null)));
+        setDefaultRequestCPU(CpuQuantity.getCpuQuantity(default_request.getOrDefault(CPU_KEY, null)));
+        setDefaultRequestMemory(StorageQuantity.getStorageQuantity(default_request.getOrDefault(MEMORY_KEY, null)));
+        setMaxCpu(CpuQuantity.getCpuQuantity(max.getOrDefault(CPU_KEY, null)));
+        setMaxMemory(StorageQuantity.getStorageQuantity(max.getOrDefault(MEMORY_KEY, null)));
+        setMinCpu(CpuQuantity.getCpuQuantity(min.getOrDefault(CPU_KEY, null)));
+        setMinMemory(StorageQuantity.getStorageQuantity(min.getOrDefault(MEMORY_KEY, null)));
     }
 
 }

+ 61 - 0
src/main/java/nju/seec/SEECdemo/logic/api/k8s/model/Probe.java

@@ -0,0 +1,61 @@
+package nju.seec.SEECdemo.logic.api.k8s.model;
+
+import io.kubernetes.client.models.V1Probe;
+import io.kubernetes.client.models.V1ProbeBuilder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * author: rale
+ * createdAt: 1/12/19
+ */
+@Data
+@NoArgsConstructor
+public class Probe {
+
+    private static final int DEFAULT_INITIAL_DELAY_SECONDS = 0;
+    private static final int DEFAULT_PERIOD_SECONDS = 10;
+    private static final int DEFAULT_SUCCESS_THRESHOLD = 1;
+    private static final int DEFAULT_FAILURE_THRESHOLD = 3;
+    private static final int DEFAULT_TIMEOUT_SECONDS = 1;
+
+    /* 容器启动后等待多少秒后执行Probe */
+    private int initialDelaySeconds = DEFAULT_INITIAL_DELAY_SECONDS;
+
+    /* 每隔多少秒执行Probe */
+    private int periodSeconds = DEFAULT_PERIOD_SECONDS;
+
+    /* Probe执行成功多少次方可认为探测成功 */
+    private int successThreshold  = DEFAULT_SUCCESS_THRESHOLD;
+
+    /* Probe执行失败多少次访客认为探测失败 */
+    private int failureThreshold = DEFAULT_FAILURE_THRESHOLD;
+
+    /* 超时时间 */
+    private int timeoutSeconds = DEFAULT_TIMEOUT_SECONDS;
+
+    private HttpGetAction httpGetAction;
+
+    public Probe(V1Probe v1Probe) {
+        this.initialDelaySeconds = v1Probe.getInitialDelaySeconds();
+        this.periodSeconds = v1Probe.getPeriodSeconds();
+        this.successThreshold = v1Probe.getSuccessThreshold();
+        this.failureThreshold = v1Probe.getFailureThreshold();
+        this.timeoutSeconds = v1Probe.getTimeoutSeconds();
+        this.httpGetAction = v1Probe.getHttpGet() == null ? null : new HttpGetAction(v1Probe.getHttpGet());
+    }
+
+    public V1Probe toV1Probe() {
+        V1Probe v1Probe = new V1Probe();
+        v1Probe.setInitialDelaySeconds(initialDelaySeconds);
+        v1Probe.setPeriodSeconds(periodSeconds);
+        v1Probe.setSuccessThreshold(successThreshold);
+        v1Probe.setFailureThreshold(failureThreshold);
+        v1Probe.setTimeoutSeconds(timeoutSeconds);
+        if (httpGetAction != null) {
+            v1Probe.setHttpGet(httpGetAction.toV1HTTPGetAction());
+        }
+        return v1Probe;
+    }
+
+}

+ 10 - 6
src/main/java/nju/seec/SEECdemo/logic/api/k8s/model/StorageQuantity.java

@@ -2,20 +2,22 @@ package nju.seec.SEECdemo.logic.api.k8s.model;
 
 import io.kubernetes.client.custom.Quantity;
 import lombok.Data;
+import lombok.Getter;
 import lombok.NoArgsConstructor;
 
 /**
  * 存储配额的单位,默认为MB
  * 可选的为KB,MB,GB
  */
-@Data
-@NoArgsConstructor
+@Getter
 public class StorageQuantity {
 
-    private Quantity quantity;
+    private final Quantity quantity;
 
     //存储的默认单位为MB
-    private Unit unit = Unit.MB;
+    private final Unit unit;
+
+    private static final Unit DEFAULT_UNIT = Unit.MB;
 
     //存储空间为0
     public static final StorageQuantity EMPTY = new StorageQuantity(0);
@@ -41,16 +43,18 @@ public class StorageQuantity {
     }
 
     public StorageQuantity(int quantity){
-        this.quantity = Quantity.fromString(quantity + unit.getCode());
+        this.quantity = Quantity.fromString(quantity + DEFAULT_UNIT.getCode());
+        this.unit = DEFAULT_UNIT;
     }
 
     public StorageQuantity(int quantity, Unit unit) {
-        this(quantity);
+        this.quantity = Quantity.fromString(quantity + DEFAULT_UNIT.getCode());
         this.unit = unit;
     }
 
     public StorageQuantity(Quantity quantity) {
         this.quantity = quantity;
+        this.unit = DEFAULT_UNIT;
     }
 
     public Quantity toQuantity(){

+ 41 - 1
src/main/java/nju/seec/SEECdemo/logic/api/k8s/util/BeanAnnouncement.java

@@ -13,9 +13,13 @@ import org.springframework.context.annotation.Bean;
 import org.springframework.stereotype.Component;
 import nju.seec.SEECdemo.util.ApplicationProperties.K8s;
 
+import java.util.concurrent.TimeUnit;
+
 @Component
 public class BeanAnnouncement {
 
+    private final ApiClient apiClient;
+
     private final CoreV1Api coreV1Api;
 
     private final AppsV1Api appsV1Api;
@@ -24,18 +28,38 @@ public class BeanAnnouncement {
 
     private final Exec exec;
 
+    /**
+     * http读取的超时时间设置为7分钟
+     */
+    private final ApiClient watchApiClient;
+
+    private final CoreV1Api watchCoreV1Api;
+
+    private final AppsV1Api watchAppsV1Api;
+
     @Autowired
     public BeanAnnouncement(ApplicationProperties applicationProperties) {
         K8s k8s = applicationProperties.getK8s();
         String apiServer = k8s.getApiServer();
         String token = k8s.getToken();
 
-        ApiClient apiClient = Config.fromToken(apiServer, token);
+        this.apiClient = Config.fromToken(apiServer, token);
         Configuration.setDefaultApiClient(apiClient);
         this.coreV1Api = new CoreV1Api();
         this.appsV1Api = new AppsV1Api();
         this.extensionsV1beta1Api = new ExtensionsV1beta1Api();
         this.exec = new Exec();
+
+
+        this.watchApiClient = Config.fromToken(apiServer, token);
+        this.watchApiClient.getHttpClient().setReadTimeout(10, TimeUnit.MINUTES);
+        this.watchCoreV1Api = new CoreV1Api(watchApiClient);
+        this.watchAppsV1Api = new AppsV1Api(watchApiClient);
+    }
+
+    @Bean
+    public ApiClient apiClient() {
+        return apiClient;
     }
 
     @Bean
@@ -58,4 +82,20 @@ public class BeanAnnouncement {
         return exec;
     }
 
+
+    @Bean
+    public ApiClient watchApiClient() {
+        return watchApiClient;
+    }
+
+    @Bean
+    public CoreV1Api watchCoreV1Api() {
+        return watchCoreV1Api;
+    }
+
+    @Bean
+    public AppsV1Api watchAppsV1Api() {
+        return watchAppsV1Api;
+    }
+
 }

+ 11 - 9
src/main/java/nju/seec/SEECdemo/logic/service/impl/ProjectServiceImpl.java

@@ -6,6 +6,7 @@ import nju.seec.SEECdemo.logic.api.k8s.LimitRangeApi;
 import nju.seec.SEECdemo.logic.api.k8s.NamespaceApi;
 import nju.seec.SEECdemo.logic.api.k8s.ResourceQuotaApi;
 import nju.seec.SEECdemo.logic.api.k8s.SecretApi;
+import nju.seec.SEECdemo.logic.api.k8s.model.LimitRange;
 import nju.seec.SEECdemo.logic.api.k8s.model.Namespace;
 import nju.seec.SEECdemo.logic.api.k8s.model.ResourceQuota;
 import nju.seec.SEECdemo.logic.service.DBService;
@@ -79,8 +80,8 @@ public class ProjectServiceImpl implements ProjectService{
             resourceQuotaApi.create(resourceQuota);
 
             //创建项目资源默认配额
-            V1LimitRange v1LimitRange = buildLimitRange(projectName, seecIITemplate.getDefaultResourceConfig());
-            limitRangeApi.createLimitRange(projectName, v1LimitRange);
+            LimitRange limitRange = buildLimitRange(projectName, seecIITemplate.getDefaultResourceConfig());
+            limitRangeApi.createLimitRange(projectName, limitRange);
 
             //创建项目同名数据库
             DBDetailVO dbDetailVO = dbService.createSchemaAndUserForProject(projectName);
@@ -146,12 +147,13 @@ public class ProjectServiceImpl implements ProjectService{
         return resourceQuota;
     }
 
-    private V1LimitRange buildLimitRange(String projectName, ResourceConfig resourceConfig) {
-        //配置应用的默认配额
-        Map<String, Integer> defaultValue = new HashMap<>();
-        defaultValue.put("cpu", 50);
-        defaultValue.put("memory", 500);
-        V1LimitRange v1LimitRange = limitRangeApi.toLimitRange(projectName, projectName, defaultValue, defaultValue, null, null);
-        return v1LimitRange;
+    private LimitRange buildLimitRange(String projectName, ResourceConfig resourceConfig) {
+        LimitRange limitRange = new LimitRange();
+        limitRange.setDefaultCPU(resourceConfig.getDefaultCPU());
+        limitRange.setDefaultMemory(resourceConfig.getDefaultMemory());
+        limitRange.setDefaultRequestCPU(resourceConfig.getDefaultCPU());
+        limitRange.setMaxCpu(resourceConfig.getMaxCPU());
+        limitRange.setMaxMemory(resourceConfig.getMaxMemory());
+        return limitRange;
     }
 }

+ 91 - 12
src/test/java/nju/seec/SEECdemo/service/api/DeploymentApiImplTest.java

@@ -1,9 +1,16 @@
 package nju.seec.SEECdemo.service.api;
 
+import com.google.common.reflect.TypeToken;
+import io.kubernetes.client.ApiClient;
+import io.kubernetes.client.ApiException;
+import io.kubernetes.client.apis.AppsV1Api;
+import io.kubernetes.client.apis.CoreV1Api;
+import io.kubernetes.client.models.V1Deployment;
+import io.kubernetes.client.models.V1Namespace;
+import io.kubernetes.client.models.V1Pod;
+import io.kubernetes.client.util.Watch;
 import nju.seec.SEECdemo.logic.api.k8s.DeploymentApi;
-import nju.seec.SEECdemo.logic.api.k8s.model.Container;
-import nju.seec.SEECdemo.logic.api.k8s.model.ContainerPort;
-import nju.seec.SEECdemo.logic.api.k8s.model.Deployment;
+import nju.seec.SEECdemo.logic.api.k8s.model.*;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -11,9 +18,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.junit4.SpringRunner;
 
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
+import java.net.SocketTimeoutException;
+import java.util.*;
 
 import static nju.seec.SEECdemo.util.Constants.APPLICATION_LABEL;
 
@@ -25,6 +31,17 @@ public class DeploymentApiImplTest {
     private DeploymentApi deploymentApi;
 
     private Deployment deployment;
+
+    @Autowired
+    private ApiClient watchApiClient;
+
+    @Autowired
+    private CoreV1Api coreV1Api;
+
+    @Autowired
+    private AppsV1Api appsV1Api;
+
+    @Autowired
     @Before
     public void before() {
         deployment = new Deployment();
@@ -34,14 +51,35 @@ public class DeploymentApiImplTest {
 
         Container container = new Container();
         container.setName("container");
-        container.setImage("10.1.1.243:18082/container_demo:1.0");
-        ContainerPort containerPort = new ContainerPort();
-        containerPort.setPort(8081);
-        containerPort.setProtocol("TCP");
+        container.setImage("10.1.1.243:18082/container_demo:3.0");
+        ContainerPort service = new ContainerPort();
+        service.setName("service");
+        service.setPort(8081);
+        service.setProtocol("TCP");
         Set<ContainerPort> ports = new HashSet<>();
-        ports.add(containerPort);
+        ports.add(service);
+
+        ContainerPort health = new ContainerPort();
+        health.setName("health");
+        health.setPort(9090);
+        health.setProtocol("TCP");
+        ports.add(health);
         container.setPorts(ports);
 
+        Map<String, String> env = new HashMap<>();
+        env.put("DB_USERNAME", "root");
+        env.put("DB_URL", "mysql.group25.svc.cluster.local:3306");
+        env.put("DB_SCHEMA", "container_demo");
+        env.put("DB_PASSWORD", "password");
+        container.setEnv(env);
+
+        Probe probe = new Probe();
+        HttpGetAction httpGetAction = new HttpGetAction();
+        httpGetAction.setPath("/actuator/health");
+        httpGetAction.setPort(9090);
+        probe.setHttpGetAction(httpGetAction);
+        container.setReadinessProbe(probe);
+
         deployment.setLabels(Collections.singletonMap(APPLICATION_LABEL, "test"));
         deployment.setImagePullSecrets(Collections.singletonList("docker-registry-secret"));
 
@@ -54,12 +92,32 @@ public class DeploymentApiImplTest {
         deploymentApi.deleteIfExist("demo2", "test");
 
         deploymentApi.createSync(deployment);
+
+//        try {
+//            Watch<V1Pod> watch = Watch.createWatch(watchApiClient,
+//                    new CoreV1Api(watchApiClient).listNamespacedPodCall("demo2", null, null, null, null, "demo.seec.nju.cn/app=test", null, null, null, true, null, null ),
+//                    new TypeToken<Watch.Response<V1Pod>>(){}.getType());
+//            watch.forEach(response -> {
+//                System.out.printf("%s pod : %s %s%n", response.type, response.object.getMetadata().getName(), response.object.getStatus());
+//            });
+//        } catch (ApiException e) {
+//            System.out.println(e.getResponseBody());
+//        } catch (Exception e) {
+//            System.out.println(e);
+//        }
+
+
     }
 
     @Test
     public void testCreateAsync() {
         deploymentApi.deleteIfExist("demo2", "test");
         deploymentApi.createAsync(deployment);
+        try {
+            Thread.sleep(60000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
     }
 
     @Test
@@ -68,11 +126,32 @@ public class DeploymentApiImplTest {
 
     @Test
     public void testDelete() {
-        deploymentApi.delete("demo", "test");
+        deploymentApi.delete("demo2", "test");
     }
 
     @Test
     public void testDeleteIfExist() {
         deploymentApi.deleteIfExist("demo", "test");
     }
+
+    @Test
+    public void testGet(){
+        Deployment deployment = deploymentApi.get("demo2", "test");
+        System.out.println(deployment);
+    }
+
+    @Test
+    public void testGetStatus() {
+        for (int i = 0 ; i<100 ; i++) {
+            DeploymentStatus status = deploymentApi.getStatus("demo2", "test");
+            System.out.println(status);
+            try {
+                Thread.sleep(10000);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+
+        }
+    }
+
 }

+ 0 - 8
src/test/java/nju/seec/SEECdemo/service/api/LimitRangeTest.java

@@ -133,12 +133,6 @@ public class LimitRangeTest {
         Map<String, Integer> min1 = new HashMap<>();
         min1.put("cpu", 50);
         min1.put("memory", 512);
-        V1LimitRange body = limitRangeApi.toLimitRange(namespace, name, _default, defaultrequest, max1, min1);
-        try {
-            limitRangeApi.updateLimitRange(namespace, name, body);
-        } catch (K8sApiException e) {
-            e.printStackTrace();
-        }
     }
 
     @Test
@@ -146,7 +140,5 @@ public class LimitRangeTest {
         Map<String, Integer> _default = new HashMap<>();
         _default.put("cpu", 100);
         _default.put("memory", 1024);
-        V1LimitRange v1LimitRange = limitRangeApi.toLimitRange("demo", "demo", _default, _default, null, null);
-        limitRangeApi.createLimitRange("demo", v1LimitRange);
     }
 }

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

@@ -128,7 +128,7 @@ public class SecretApiImplTest {
 
     @Test
     public void testGetSecretByType() {
-        List<SecretVO> v1Secret = secretApi.getSecretListByType("demo", SecretTypeEnum.REGISTRY);
+        List<SecretVO> v1Secret = secretApi.getSecretListByType("demo", SecretTypeEnum.Generic);
         v1Secret.stream().forEach((v1Secret1 -> {
             v1Secret1.getData().values().forEach((stringEntry -> {
                 System.out.println(stringEntry);

+ 25 - 0
src/test/java/nju/seec/SEECdemo/service/api/WatchApiImplTest.java

@@ -0,0 +1,25 @@
+package nju.seec.SEECdemo.service.api;
+
+import nju.seec.SEECdemo.logic.api.k8s.WatchApi;
+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;
+
+/**
+ * author: rale
+ * createdAt: 1/13/19
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class WatchApiImplTest {
+
+    @Autowired
+    private WatchApi watchApi;
+
+    @Test
+    public void testWatchDeployment() {
+        watchApi.watchDeployment();
+    }
+}