Pārlūkot izejas kodu

k8s API配置 开发了创建Namespace的方法

raledong 7 gadi atpakaļ
vecāks
revīzija
05489bb98f

+ 4 - 5
config.yml

@@ -31,8 +31,7 @@ moocoder:
     type: local
     properties:
       location: ./problem
-
-kubernetes:
-  external-ip:
-    k8s2: 10.10.241.0/24
-    k8s3: 10.10.242.0/24
+  k8s:
+    api-server: https://10.1.1.198:6443
+    token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi10b2tlbi0yZ2o5NSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJhZG1pbiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjRjZGQ0MGFlLTA1OWItMTFlOS1hMTIwLTAyMDA2MTI3MDAwNSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTphZG1pbiJ9.LwQ-LQlA_yhtndGLpveRfs0ZFFW971P1tchzJZP81s1vz0msb0q6dLJmcsCHaYhHWZ58_DCc0e7suGmUFEeMZcJL-sj3js1Cp5WNdnyz99Y3vZ-krHvNHGoc42jOrNUeO27Kb7uTDCmmKcCJSQ9gw8s2ie--7Z_kPAKVjhqr9nHtfrmmuIqFgwbIBQrNyJLMxaXs6tsCS4YWBuIQK1aOPWsijJNXA8W1acQ7p95P3tBGYMq17AaOEdeK8m76CIWeIt1mzRmjAhWQ--06J2-zw1Xq62ogjQLnjZuS8Tq7G_wLeoAVo9llR72FNDBXuJo-eSdVKBrFP6-Q-nCaWcQkCw
+    ingress-host: deernowl.cn

+ 14 - 0
pom.xml

@@ -131,6 +131,20 @@
 			<artifactId>junit</artifactId>
 			<scope>test</scope>
 		</dependency>
+
+		<!--k8s java client Dependencies-->
+		<dependency>
+			<groupId>io.kubernetes</groupId>
+			<artifactId>client-java</artifactId>
+			<version>3.0.0</version>
+			<scope>compile</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>io.fabric8</groupId>
+			<artifactId>kubernetes-client</artifactId>
+			<version>3.1.12</version>
+		</dependency>
 	</dependencies>
 
 	<build>

+ 14 - 0
src/main/java/nju/seec/SEECdemo/logic/api/k8s/NamespaceApi.java

@@ -0,0 +1,14 @@
+package nju.seec.SEECdemo.logic.api.k8s;
+
+import io.kubernetes.client.models.V1Namespace;
+import nju.seec.SEECdemo.logic.api.k8s.vo.ApiResult;
+import nju.seec.SEECdemo.logic.api.k8s.vo.Namespace;
+
+/**
+ * author: rale
+ * createdAt: 12/22/18
+ */
+public interface NamespaceApi {
+
+    ApiResult<Void> create(Namespace namespace);
+}

+ 43 - 0
src/main/java/nju/seec/SEECdemo/logic/api/k8s/impl/NamespaceApiImpl.java

@@ -0,0 +1,43 @@
+package nju.seec.SEECdemo.logic.api.k8s.impl;
+
+import io.kubernetes.client.ApiException;
+import io.kubernetes.client.apis.CoreV1Api;
+import io.kubernetes.client.models.V1Namespace;
+import nju.seec.SEECdemo.logic.api.k8s.NamespaceApi;
+import nju.seec.SEECdemo.logic.api.k8s.vo.ApiResult;
+import nju.seec.SEECdemo.logic.api.k8s.vo.Namespace;
+import nju.seec.SEECdemo.util.LoggerUtil;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import nju.seec.SEECdemo.logic.api.k8s.vo.ApiResult;
+
+/**
+ * author: rale
+ * createdAt: 12/22/18
+ */
+@Service
+public class NamespaceApiImpl implements NamespaceApi{
+
+    private Logger logger = LoggerUtil.getLogger(NamespaceApi.class);
+    @Autowired
+    private CoreV1Api coreV1Api;
+
+    @Override
+    public ApiResult<Void> create(Namespace namespace) {
+        V1Namespace v1Namespace = namespace.toV1Namespace();
+        try {
+            coreV1Api.createNamespace(v1Namespace, "true");
+        } catch (ApiException e) {
+            LoggerUtil.error(logger, e, "Namespace创建失败,namespace={}, v1Namespace={}", namespace, v1Namespace);
+            ApiResult<Void> result = new ApiResult<>();
+            result.setSuccess(false);
+            result.setErrorCode(e.getCode());
+            return result;
+        }
+        ApiResult<Void> result = new ApiResult<>();
+        result.setSuccess(true);
+        return result;
+    }
+
+}

+ 22 - 0
src/main/java/nju/seec/SEECdemo/logic/api/k8s/vo/ApiResult.java

@@ -0,0 +1,22 @@
+package nju.seec.SEECdemo.logic.api.k8s.vo;
+
+import lombok.Data;
+import org.springframework.data.annotation.ReadOnlyProperty;
+
+/**
+ * author: rale
+ * createdAt: 12/23/18
+ */
+
+@Data
+public class ApiResult<T> {
+
+    @ReadOnlyProperty
+    private boolean success;
+
+    private int errorCode;
+
+    private T value;
+
+    public static final int CONFLICT = 409;//命名冲突
+}

+ 30 - 0
src/main/java/nju/seec/SEECdemo/logic/api/k8s/vo/Constants.java

@@ -0,0 +1,30 @@
+package nju.seec.SEECdemo.logic.api.k8s.vo;
+
+public abstract class Constants {
+
+	//标签域名前缀
+	private static final String LABEL_PREFIX = "nju.seec.SEECdemo";
+	//课程前缀
+	static final String TYPE_LABEL = LABEL_PREFIX + "/type";
+
+	static final String DESCRIPTION_LABEL = LABEL_PREFIX + "/description";
+	// 用户namespace的label
+	static final String USERSPACE_LABEL = LABEL_PREFIX +"/userspace";
+	// pod的label
+	static final String SELECTOR_LABEL = LABEL_PREFIX + "/app";
+	// 非对外service的label
+	static final String INTERNAL_LABEL = LABEL_PREFIX + "/internal";
+	// 对外service的label
+	static final String EXTERNAL_LABEL = LABEL_PREFIX + "/external";
+	// 持久卷访问模式
+	static final String STORAGE_ACCESS_MODE = "ReadWriteMany";
+	// 持久卷存储类型
+	static final String STORAGE_CLASS = "glusterfs";
+
+	static final String RESOURCE_STORAGE = "storage";
+
+	static final String NAME_PATTERN = "^[0-9a-zA-Z-]{8,}$";
+
+	static final String NAMESPACE_API_VERSION = "v1";
+
+}

+ 66 - 0
src/main/java/nju/seec/SEECdemo/logic/api/k8s/vo/Namespace.java

@@ -0,0 +1,66 @@
+package nju.seec.SEECdemo.logic.api.k8s.vo;
+
+import io.kubernetes.client.models.*;
+import lombok.Data;
+import lombok.ToString;
+import org.springframework.util.CollectionUtils;
+
+import javax.validation.constraints.NotNull;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * author: rale
+ * createdAt: 12/22/18
+ */
+@ToString
+@Data
+public class Namespace {
+
+    private static final String VERSION = "v1";
+
+    private static final String KIND = "Namespace";
+
+    @NotNull
+    private String name;
+
+    private String description;
+
+    @NotNull
+    private String type;
+
+    public V1Namespace toV1Namespace(){
+        V1ObjectMeta v1ObjectMeta = new V1ObjectMetaBuilder()
+                .withName(name)
+                .withLabels(Collections.singletonMap(Constants.TYPE_LABEL, type))
+                .addToAnnotations(Constants.DESCRIPTION_LABEL, description == null ? name : description)
+                .build();
+        V1NamespaceSpec v1NamespaceSpec = new V1NamespaceSpecBuilder()
+                .build();
+        V1Namespace v1Namespace = new V1NamespaceBuilder()
+                .withApiVersion(VERSION)
+                .withKind(KIND)
+                .withMetadata(v1ObjectMeta)
+                .withSpec(v1NamespaceSpec)
+                .build();
+        return v1Namespace;
+
+    }
+
+    public Namespace fromV1Namespace(V1Namespace v1Namespace) {
+        Namespace namespace = new Namespace();
+        V1ObjectMeta v1ObjectMeta = v1Namespace.getMetadata();
+        if (v1ObjectMeta != null) {
+            namespace.setName(v1Namespace.getMetadata().getName());
+            Map<String, String> annotations = v1ObjectMeta.getAnnotations();
+            if (!CollectionUtils.isEmpty(annotations)) {
+                namespace.setDescription(annotations.get(Constants.DESCRIPTION_LABEL));
+            }
+            Map<String, String> labels = v1ObjectMeta.getLabels();
+            if (!CollectionUtils.isEmpty(labels)) {
+                namespace.setType(labels.get(Constants.TYPE_LABEL));
+            }
+        }
+        return namespace;
+    }
+}

+ 13 - 0
src/main/java/nju/seec/SEECdemo/util/ApplicationProperties.java

@@ -32,6 +32,8 @@ public class ApplicationProperties {
 	private Mail mail = new Mail();
 	@Valid
 	private Storage storage = new Storage();
+	@Valid
+	private K8s k8s = new K8s();
 
 	@Data
 	public static class Gitlab {
@@ -85,4 +87,15 @@ public class ApplicationProperties {
 		private String type = "local";
 		private Map<String, String> properties = new HashMap<>();
 	}
+
+	@Data
+	public static class K8s{
+		@URL
+		@NotEmpty
+		private String apiServer;
+		@NotEmpty
+		private String token;
+		@NotEmpty
+		private String ingressHost;
+	}
 }

+ 37 - 0
src/main/java/nju/seec/SEECdemo/util/LoggerUtil.java

@@ -0,0 +1,37 @@
+package nju.seec.SEECdemo.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * author: rale
+ * createdAt: 12/22/18
+ * 日志工具
+ */
+public class LoggerUtil {
+
+    public static Logger getLogger(Class<?> className){
+        return LoggerFactory.getLogger(className);
+    }
+
+    public static void info(Logger logger, String info, Object... parameters){
+        logger.info(info, parameters);
+    }
+
+    public static void warn(Logger logger, String info, Object... parameters){
+        logger.warn(info, parameters);
+    }
+
+    public static void  error(Logger logger, String info, Object... parameters) {
+        logger.error(info, parameters);
+    }
+
+    public static void error(Logger logger, Exception e, String info, Object... parameters) {
+        logger.error("", e);
+        logger.error(info, parameters);
+    }
+
+    public static void debug(Logger logger, String info, Object... parameters) {
+        logger.debug(info, parameters);
+    }
+}

+ 45 - 0
src/main/resources/application-backup.yml

@@ -0,0 +1,45 @@
+spring:
+  jpa:
+    hibernate:
+      ddl-auto: update
+      naming:
+        implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
+        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
+  mail:
+    properties:
+      mail:
+        smtp:
+          auth: true
+          starttls:
+            enable: true
+            required: true
+  resources:
+    chain:
+      strategy:
+        content:
+          enabled: true
+          paths:
+            - /moocoder-frontend/**
+            - /js/**
+            - /css/**
+  servlet:
+    multipart:
+      max-file-size: 16MB
+      max-request-size: 16MB
+server:
+  tomcat:
+    remote-ip-header: X-Forwarded-For
+    protocol-header: X-Forwarded-Proto
+  servlet:
+    session:
+      persistent: true
+      store-dir: ${java.io.tmpdir}/moocoder-session
+      timeout: 1d
+  use-forward-headers: true
+management:
+  endpoints:
+    web:
+      base-path: /api/actuator
+  endpoint:
+    shutdown:
+      enabled: true

+ 74 - 0
src/main/resources/application-dev.yml

@@ -0,0 +1,74 @@
+spring:
+  datasource:
+    url: jdbc:mysql://10.1.1.198:13306/seec2?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false
+    username: root
+    password: NJU67software
+  jpa:
+    hibernate:
+      ddl-auto: update
+      naming:
+        implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
+        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
+    database-platform: org.hibernate.dialect.MySQL57InnoDBDialect
+  mail:
+    properties:
+      mail:
+        smtp:
+          auth: true
+          starttls:
+            enable: true
+            required: true
+  resources:
+    chain:
+      strategy:
+        content:
+          enabled: true
+          paths:
+            - /moocoder-frontend/**
+            - /js/**
+            - /css/**
+  servlet:
+    multipart:
+      max-file-size: 16MB
+      max-request-size: 16MB
+server:
+  tomcat:
+    remote-ip-header: X-Forwarded-For
+    protocol-header: X-Forwarded-Proto
+  servlet:
+    session:
+      persistent: true
+      store-dir: ${java.io.tmpdir}/moocoder-session
+      timeout: 1d
+  use-forward-headers: true
+management:
+  endpoints:
+    web:
+      base-path: /api/actuator
+  endpoint:
+    shutdown:
+      enabled: true
+
+moocoder:
+  secret: 1qaz2wsx
+  gitlab:
+    host: http://10.1.1.172:8081
+    git-proxy: http://10.1.1.172:8081
+    username: root
+    token: 1hXhC2YLkuAb9iaykqWi
+  jenkins:
+    host: http://10.1.1.243:8082
+    username: root
+    token: 113cb5bd4a6fea342892a08c8d2e07dc68
+  docker:
+    nexus: 10.1.1.243:10082
+  mail:
+    from: noreply@moocoder.cn
+  storage:
+    type: local
+    properties:
+      location: ./problem
+  k8s:
+    api-server: https://10.1.1.198:6443
+    token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi10b2tlbi0yZ2o5NSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJhZG1pbiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjRjZGQ0MGFlLTA1OWItMTFlOS1hMTIwLTAyMDA2MTI3MDAwNSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTphZG1pbiJ9.LwQ-LQlA_yhtndGLpveRfs0ZFFW971P1tchzJZP81s1vz0msb0q6dLJmcsCHaYhHWZ58_DCc0e7suGmUFEeMZcJL-sj3js1Cp5WNdnyz99Y3vZ-krHvNHGoc42jOrNUeO27Kb7uTDCmmKcCJSQ9gw8s2ie--7Z_kPAKVjhqr9nHtfrmmuIqFgwbIBQrNyJLMxaXs6tsCS4YWBuIQK1aOPWsijJNXA8W1acQ7p95P3tBGYMq17AaOEdeK8m76CIWeIt1mzRmjAhWQ--06J2-zw1Xq62ogjQLnjZuS8Tq7G_wLeoAVo9llR72FNDBXuJo-eSdVKBrFP6-Q-nCaWcQkCw
+    ingress-host: deernowl.cn

+ 45 - 0
src/main/resources/application-test.yml

@@ -0,0 +1,45 @@
+spring:
+  jpa:
+    hibernate:
+      ddl-auto: update
+      naming:
+        implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
+        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
+  mail:
+    properties:
+      mail:
+        smtp:
+          auth: true
+          starttls:
+            enable: true
+            required: true
+  resources:
+    chain:
+      strategy:
+        content:
+          enabled: true
+          paths:
+            - /moocoder-frontend/**
+            - /js/**
+            - /css/**
+  servlet:
+    multipart:
+      max-file-size: 16MB
+      max-request-size: 16MB
+server:
+  tomcat:
+    remote-ip-header: X-Forwarded-For
+    protocol-header: X-Forwarded-Proto
+  servlet:
+    session:
+      persistent: true
+      store-dir: ${java.io.tmpdir}/moocoder-session
+      timeout: 1d
+  use-forward-headers: true
+management:
+  endpoints:
+    web:
+      base-path: /api/actuator
+  endpoint:
+    shutdown:
+      enabled: true

+ 2 - 44
src/main/resources/application.yml

@@ -1,45 +1,3 @@
 spring:
-  jpa:
-    hibernate:
-      ddl-auto: update
-      naming:
-        implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
-        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
-  mail:
-    properties:
-      mail:
-        smtp:
-          auth: true
-          starttls:
-            enable: true
-            required: true
-  resources:
-    chain:
-      strategy:
-        content:
-          enabled: true
-          paths:
-            - /moocoder-frontend/**
-            - /js/**
-            - /css/**
-  servlet:
-    multipart:
-      max-file-size: 16MB
-      max-request-size: 16MB
-server:
-  tomcat:
-    remote-ip-header: X-Forwarded-For
-    protocol-header: X-Forwarded-Proto
-  servlet:
-    session:
-      persistent: true
-      store-dir: ${java.io.tmpdir}/moocoder-session
-      timeout: 1d
-  use-forward-headers: true
-management:
-  endpoints:
-    web:
-      base-path: /api/actuator
-  endpoint:
-    shutdown:
-      enabled: true
+  profiles:
+    active: dev

+ 30 - 0
src/test/java/nju/seec/SEECdemo/service/api/NamespaceApiImplTest.java

@@ -0,0 +1,30 @@
+package nju.seec.SEECdemo.service.api;
+
+import nju.seec.SEECdemo.logic.api.k8s.NamespaceApi;
+import nju.seec.SEECdemo.logic.api.k8s.vo.Namespace;
+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: 12/22/18
+ */
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class NamespaceApiImplTest {
+
+    @Autowired
+    private NamespaceApi namespaceApi;
+
+    @Test
+    public void testCreate() {
+        Namespace namespace = new Namespace();
+        namespace.setName("group21");
+        namespace.setDescription("这是软工二的大作业");
+        namespaceApi.create(namespace);
+    }
+}