Bladeren bron

Merge branch 'platform-dev' of http://47.100.18.120:3000/SEEC/SEEC-II-Demo into platform-dev

raledong 7 jaren geleden
bovenliggende
commit
0809c79380

+ 64 - 4
src/main/java/nju/seec/SEECdemo/logic/api/k8s/LimitRangeApi.java

@@ -1,11 +1,71 @@
 package nju.seec.SEECdemo.logic.api.k8s;
 
+import io.kubernetes.client.models.V1LimitRange;
+import io.kubernetes.client.models.V1LimitRangeList;
+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.LimitRange;
+
+import java.util.List;
+import java.util.Map;
+
 
-/**
- * author: rale
- * createdAt: 12/26/18
- */
 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
+     *
+     * @param namespace 命名空间名称需要唯一
+     * @param name      LimitRange的资源名称
+     */
+    void deleteLimitRange(String namespace, String name) throws K8sApiException;
+
+    /**
+     * 获取命名空间内的LimitRange列表
+     *
+     * @param namespace 命名空间名称需要唯一
+     */
+    List<V1LimitRange> getLimitRangeList(String namespace) throws K8sApiException;
+
+    /**
+     * 获取命名空间内的指定名称的LimitRange
+     *
+     * @param namespace 命名空间名称需要唯一
+     * @param name      LimitRange的资源名称
+     */
+    V1LimitRange 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;
+
+
+
+
 }
+

+ 37 - 7
src/main/java/nju/seec/SEECdemo/logic/api/k8s/SecretApi.java

@@ -3,6 +3,7 @@ package nju.seec.SEECdemo.logic.api.k8s;
 import com.google.protobuf.Api;
 import io.kubernetes.client.ApiException;
 import io.kubernetes.client.models.V1Secret;
+import nju.seec.SEECdemo.logic.api.k8s.exception.K8sApiException;
 import nju.seec.SEECdemo.logic.api.k8s.vo.ApiResult;
 
 import javax.xml.transform.Result;
@@ -12,38 +13,60 @@ import java.util.Map;
 public interface SecretApi {
 
     /**
-     * 创建通用密钥,如数据库的用户名,密码
+     * 创建通用密钥,如数据库的用户名,密码,默认type为Opaque
      * @param namespace
      * @param name
      * @param data
      * @return ApiResult
      */
-    ApiResult createGenericSecret(String namespace, String name, Map<String, byte[]> data);
+    V1Secret createGenericSecret(String namespace, String name, Map<String, byte[]> data) throws K8sApiException;
 
     /**
-     * 创建通用密钥,如数据库的用户名,密码
+     * 创建通用密钥,自己定义Secret的type,如Service Account、Opaque、kubernetes.io/dockerconfigjson.
      * @param namespace
      * @param name
      * @param data
      * @param type
      * @return ApiResult
      */
-    ApiResult createGenericSecret(String namespace, String name, Map<String, byte[]> data, String type);
+    V1Secret createGenericSecret(String namespace, String name, Map<String, byte[]> data, String type) throws K8sApiException;
 
     /**
      * 在namespace下生成私有仓库server的密钥
      * 密钥名称将自动生成
+     * @param namespace
+     * @param server
+     * @param user
+     * @param password
+     */
+    V1Secret createPrivateRegistrySecret(String namespace, String server, String user, String password) throws K8sApiException;
+
+
+    /**
+     * 在namespace下生成私有仓库server的密钥
+     * 密钥名称自己指定
+     * @param namespace
+     * @param name
      * @param server
      * @param user
      * @param password
      */
-    ApiResult createPrivateRegistrySecret(String namespace, String server, String user, String password);
+    V1Secret createPrivateRegistrySecret(String namespace, String name, String server, String user, String password) throws K8sApiException;
 
     /**
      * 获取指定namespace下的Secret列表
      * @param namespace
      */
-    ApiResult getSecretList(String namespace);
+    List<V1Secret> getSecretList(String namespace) throws K8sApiException;
+
+    /**
+     * 获取指定namespace下的指定type的Secret列表
+     *
+     * @param namespace
+     * @param type
+     */
+    List<V1Secret> getSecretListByType(String namespace, String type) throws K8sApiException;
+
 
     /**
      * 获取指定namespace下的密钥
@@ -51,6 +74,13 @@ public interface SecretApi {
      * @param namespace
      * @param name
      */
-    ApiResult getSecret(String namespace, String name);
+    V1Secret getSecretByName(String namespace, String name) throws K8sApiException;
+
+    /**
+     * 删除指定namespace下指定名字的Secret
+     * @param namespace
+     * @param name
+     */
+    void deleteSecretByName(String namespace, String name) throws K8sApiException;
 
 }

+ 7 - 1
src/main/java/nju/seec/SEECdemo/logic/api/k8s/exception/K8sApiException.java

@@ -18,7 +18,11 @@ public class K8sApiException extends RuntimeException{
 
     public static final int NAMESPACE_NOT_EXIST = 400;
     public static final int DEPLOYMENT_NOT_EXIST = 401;
+    public static final int NOT_FOUND = 404;
     public static final int RESOURCE_QUOTA_NOT_EXIST = 402;
+    public static final int ALREADY_EXIST = 409;
+    //LimitRange的参数配置:default值不大于max的值,default request的值不小于min的值
+    public static final int INVALID_VALUE = 422;
 
     public static final int NAMESPACE_ALREADY_EXIST = 500;
     public static final int RESOURCE_QUOTA_ALREADY_EXIST = 501;
@@ -35,8 +39,10 @@ public class K8sApiException extends RuntimeException{
     static {
         codeMap.put(NAMESPACE_NOT_EXIST, "命名空间不存在");
         codeMap.put(DEPLOYMENT_NOT_EXIST, "部署不存在");
+        codeMap.put(NOT_FOUND, "资源不存在");
         codeMap.put(RESOURCE_QUOTA_NOT_EXIST, "资源限额不存在");
-
+        codeMap.put(ALREADY_EXIST, "资源已存在");
+        codeMap.put(INVALID_VALUE, "参数设置无效");
         codeMap.put(NAMESPACE_ALREADY_EXIST, "命名空间已经存在");
         codeMap.put(RESOURCE_QUOTA_ALREADY_EXIST, "资源限额已经存在");
 

+ 108 - 0
src/main/java/nju/seec/SEECdemo/logic/api/k8s/impl/LimitRangeApiImpl.java

@@ -0,0 +1,108 @@
+package nju.seec.SEECdemo.logic.api.k8s.impl;
+
+import io.kubernetes.client.ApiException;
+import io.kubernetes.client.apis.CoreV1Api;
+import io.kubernetes.client.models.V1DeleteOptions;
+import io.kubernetes.client.models.V1LimitRange;
+import io.kubernetes.client.models.V1LimitRangeList;
+import io.kubernetes.client.models.V1Status;
+import nju.seec.SEECdemo.logic.api.k8s.LimitRangeApi;
+import nju.seec.SEECdemo.logic.api.k8s.exception.K8sApiException;
+import nju.seec.SEECdemo.logic.api.k8s.vo.LimitRange;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+
+@Service
+public class LimitRangeApiImpl implements LimitRangeApi {
+
+    @Autowired
+    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) {
+        LimitRange limitRange = new LimitRange();
+        limitRange.setName(name);
+        limitRange.setNamespace(namespace);
+        limitRange.set_default(_default);
+        limitRange.setDefault_request(defaultRequest);
+        limitRange.setMax(max);
+        limitRange.setMin(min);
+        return limitRange.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 void deleteLimitRange(String namespace, String name) throws K8sApiException {
+        V1DeleteOptions body = new V1DeleteOptions();
+        try {
+            //暂时没有用到deleteNamespacedSecret()中的其他参数。
+            V1Status v1Status = coreV1Api.deleteNamespacedLimitRange(name, namespace, body, "", 5, false, "");
+        } catch (ApiException e) {
+            if (e.getCode() == K8sApiException.NOT_FOUND) {
+                throw new K8sApiException(K8sApiException.NOT_FOUND);
+            } else {
+                throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+            }
+        }
+    }
+
+    @Override
+    public List<V1LimitRange> getLimitRangeList(String namespace) throws K8sApiException {
+        try {
+            V1LimitRangeList limitRangeList = coreV1Api.listNamespacedLimitRange(namespace, "OK", "", "", false, "", 5, "", 5, false);
+            List<V1LimitRange> result = limitRangeList.getItems();
+            if (result.isEmpty()) {
+                throw new K8sApiException(K8sApiException.NOT_FOUND);
+            } else {
+                return result;
+            }
+        } catch (ApiException e) {
+            //如果namespace不存在也不会抛出异常,会返回一个空的list
+            throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+        }
+
+    }
+
+    @Override
+    public V1LimitRange getLimitRangeByName(String namespace, String name) throws K8sApiException {
+        List<V1LimitRange> list = getLimitRangeList(namespace);
+        for (V1LimitRange limitRange : list) {
+            if (limitRange.getMetadata().getName().equals(name)) {
+                return limitRange;
+            }
+        }
+        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);
+    }
+}

+ 65 - 38
src/main/java/nju/seec/SEECdemo/logic/api/k8s/impl/SecretApiImpl.java

@@ -4,11 +4,10 @@ package nju.seec.SEECdemo.logic.api.k8s.impl;
 import com.google.protobuf.Api;
 import io.kubernetes.client.ApiException;
 import io.kubernetes.client.apis.CoreV1Api;
-import io.kubernetes.client.models.V1ObjectMeta;
-import io.kubernetes.client.models.V1Secret;
-import io.kubernetes.client.models.V1SecretList;
+import io.kubernetes.client.models.*;
 import nju.seec.SEECdemo.logic.api.k8s.DeploymentApi;
 import nju.seec.SEECdemo.logic.api.k8s.SecretApi;
+import nju.seec.SEECdemo.logic.api.k8s.exception.K8sApiException;
 import nju.seec.SEECdemo.logic.api.k8s.vo.ApiResult;
 import nju.seec.SEECdemo.util.LoggerUtil;
 import org.slf4j.Logger;
@@ -30,13 +29,13 @@ public class SecretApiImpl implements SecretApi {
     private CoreV1Api coreV1Api;
 
     @Override
-    public ApiResult createGenericSecret(String namespace, String name, Map<String, byte[]> data) {
+    public V1Secret createGenericSecret(String namespace, String name, Map<String, byte[]> data) throws K8sApiException {
         String type = "Opaque";
         return createGenericSecret(namespace, name, data, type);
     }
 
     @Override
-    public ApiResult createGenericSecret(String namespace, String name, Map<String, byte[]> data, String type) {
+    public V1Secret createGenericSecret(String namespace, String name, Map<String, byte[]> data, String type) throws K8sApiException {
 
         //Secret默认创建的Type为Opaque,base64编码格式的Secret,用来储存密码、密钥等。
 
@@ -51,20 +50,30 @@ public class SecretApiImpl implements SecretApi {
         v1Secret.setType(type);
 
         try {
-            V1Secret createdSecret = coreV1Api.createNamespacedSecret("mjj-test", v1Secret, "OK");
-            return new ApiResult<V1Secret>(createdSecret);
+            return coreV1Api.createNamespacedSecret("mjj-test", v1Secret, "OK");
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "Secret创建失败, Secret={}, response={}", v1Secret, e.getResponseBody());
-            ApiResult<Void> result = new ApiResult<>();
-            result.setSuccess(false);
-            result.setErrorCode(e.getCode());
-            return result;
+            switch (e.getCode()) {
+                case K8sApiException.NAMESPACE_NOT_EXIST:
+                    throw new K8sApiException(K8sApiException.NAMESPACE_NOT_EXIST);
+                case K8sApiException.ALREADY_EXIST:
+                    throw new K8sApiException(K8sApiException.ALREADY_EXIST);
+                default:
+                    throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+            }
         }
     }
 
     @Override
-    public ApiResult createPrivateRegistrySecret(String namespace, String server, String user, String password) {
+    public V1Secret createPrivateRegistrySecret(String namespace, String server, String user, String password) throws K8sApiException {
+        //dockerSecret 统一的名称
+        String name = "docker-registry-secret";
+        return createPrivateRegistrySecret(namespace, name, server, user, password);
 
+    }
+
+    @Override
+    public V1Secret createPrivateRegistrySecret(String namespace, String name, String server, String user, String password) throws K8sApiException {
         Map<String, byte[]> data = new HashMap<>();
 
         String dockerConfigJson =
@@ -74,46 +83,64 @@ public class SecretApiImpl implements SecretApi {
         data.put(".dockerconfigjson", dockerConfigJson.getBytes());
 
         //dockerSecret 统一的名称
-        String name = "docker-registry-secret";
-
-        String tpye = "kubernetes.io/dockerconfigjson";
 
-        return createGenericSecret(namespace, name, data, tpye);
+        String type = "kubernetes.io/dockerconfigjson";
 
+        return createGenericSecret(namespace, name, data, type);
     }
 
     @Override
-    public ApiResult getSecretList(String namespace) {
+    public List<V1Secret> getSecretList(String namespace) throws K8sApiException {
         try {
             V1SecretList v1SecretList = coreV1Api.listNamespacedSecret(namespace, "OK", "", "",false, "", 200, "", 10, false);
-            List<V1Secret> secretList = v1SecretList.getItems();
-            return new ApiResult<List<V1Secret>>(secretList);
+            return v1SecretList.getItems();
         } catch (ApiException e) {
             LoggerUtil.error(logger, e, "Secret列表获取失败, response={}", e.getResponseBody());
-            ApiResult<Void> result = new ApiResult<>();
-            result.setSuccess(false);
-            result.setErrorCode(e.getCode());
-            return result;
+            if (e.getCode() == K8sApiException.NAMESPACE_NOT_EXIST) {
+                throw new K8sApiException(K8sApiException.NAMESPACE_NOT_EXIST);
+            } else {
+                throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
+            }
+        }
+    }
+
+    @Override
+    public List<V1Secret> getSecretListByType(String namespace, String type) throws K8sApiException {
+        List<V1Secret> secretList = getSecretList(namespace);
+        List<V1Secret> resultList = new ArrayList<>();
+        for (V1Secret secret : secretList) {
+            String secretType = secret.getType();
+            if (type.equals(secretType)) {
+                resultList.add(secret);
+            }
         }
+        return resultList;
     }
 
     @Override
-    public ApiResult getSecret(String namespace, String name) {
-        ApiResult apiResult = getSecretList(namespace);
-        if (apiResult.getErrorCode() != 0) {
-            return apiResult;
-        } else {
-            List<V1Secret> secretList = (List<V1Secret>) apiResult.getValue();
-            for (V1Secret secret : secretList) {
-                V1ObjectMeta meta = secret.getMetadata();
-                if (meta.getName().equals(name)) {
-                    return new ApiResult<V1Secret>(secret);
-                }
+    public V1Secret getSecretByName(String namespace, String name) throws K8sApiException {
+        List<V1Secret> secretList = getSecretList(namespace);
+        for (V1Secret secret : secretList) {
+            V1ObjectMeta meta = secret.getMetadata();
+            if (meta.getName().equals(name)) {
+                return secret;
+            }
+        }
+        throw new K8sApiException(K8sApiException.NOT_FOUND);
+    }
+
+    @Override
+    public void deleteSecretByName(String namespace, String name) throws K8sApiException {
+        V1DeleteOptions body = new V1DeleteOptions();
+        try {
+            //暂时没有用到deleteNamespacedSecret()中的其他参数。
+            V1Status v1Status = coreV1Api.deleteNamespacedSecret(name, namespace, body, "", 5, false, "");
+        } catch (ApiException e) {
+            if (e.getCode() == K8sApiException.NOT_FOUND) {
+                throw new K8sApiException(K8sApiException.NOT_FOUND);
+            } else {
+                throw K8sApiException.K8s_SYSTEM_ERROR_EXCEPTION;
             }
-            ApiResult<Void> result = new ApiResult<>();
-            result.setSuccess(false);
-            result.setErrorCode(ApiResult.NOT_EXIST);
-            return result;
         }
     }
 }

+ 82 - 0
src/main/java/nju/seec/SEECdemo/logic/api/k8s/vo/LimitRange.java

@@ -0,0 +1,82 @@
+package nju.seec.SEECdemo.logic.api.k8s.vo;
+
+import io.kubernetes.client.custom.Quantity;
+import io.kubernetes.client.models.*;
+import jnr.ffi.annotations.In;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import java.util.HashMap;
+import java.util.Map;
+
+import static nju.seec.SEECdemo.util.Constants.NAME_PATTERN;
+
+/**
+ * author: mjj
+ * createdAt: 2018/12/30
+ * description:
+ */
+
+@Data
+@NoArgsConstructor
+public class LimitRange {
+
+    @NotNull
+    private String namespace;
+
+    @NotNull
+    @Pattern(regexp = NAME_PATTERN)
+    private String name;
+
+    private Map<String, Integer> _default;
+    private Map<String, Integer> default_request;
+    private Map<String, Integer> max;
+    private Map<String, Integer> min;
+    private String type = "Container";
+
+
+
+    public V1LimitRange toV1LimitRange() {
+        return new V1LimitRangeBuilder()
+                .withApiVersion("v1")
+                .withKind("LimitRange")
+                .withMetadata(this.toV1ObjectMeta())
+                .withSpec(this.toV1LimitRangeSpec())
+                .build();
+    }
+
+    public V1ObjectMeta toV1ObjectMeta() {
+        return new V1ObjectMetaBuilder()
+                .withNamespace(namespace)
+                .withName(name)
+                .build();
+    }
+
+    public V1LimitRangeSpec toV1LimitRangeSpec() {
+        return new V1LimitRangeSpec().addLimitsItem(this.toV1LimitRangeItem());
+    }
+
+    public V1LimitRangeItem toV1LimitRangeItem() {
+        V1LimitRangeItem v1LimitRangeItem = new V1LimitRangeItem();
+        if (_default != null) v1LimitRangeItem.setDefault(exchange(_default));
+        if (default_request != null) v1LimitRangeItem.setDefaultRequest(exchange(default_request));
+        if (max != null) v1LimitRangeItem.setMax(exchange(max));
+        if (min != null) v1LimitRangeItem.setMin(exchange(min));
+        v1LimitRangeItem.setType(type);
+        return v1LimitRangeItem;
+    }
+
+    public Map<String, Quantity> exchange(Map<String, Integer> setting) {
+        Map<String, Quantity> result = new HashMap<>();
+        for (Map.Entry<String, Integer> entry : setting.entrySet()) {
+            if (entry.getKey().equals("cpu")) {
+                result.put(entry.getKey(), new CpuQuantity(entry.getValue()).toQuantity());
+            } else if (entry.getKey().equals("memory")) {
+                result.put(entry.getKey(), new StorageQuantity(entry.getValue()).toQuantity());
+            }
+        }
+        return result;
+    }
+}

+ 1 - 1
src/main/java/nju/seec/SEECdemo/logic/api/k8s/vo/StorageQuantity.java

@@ -43,7 +43,7 @@ public class StorageQuantity {
     }
 
     public Quantity toQuantity(){
-        return new Quantity(quantity, Quantity.Format.DECIMAL_EXPONENT);
+        return new Quantity(quantity, Quantity.Format.DECIMAL_SI);
     }