Added Deployment Files 84/3584/1
authorabhijit_onap <abhijit.das.gupta@huawei.com>
Thu, 18 Jun 2020 08:52:52 +0000 (14:22 +0530)
committerabhijit_onap <abhijit.das.gupta@huawei.com>
Thu, 18 Jun 2020 08:52:52 +0000 (14:22 +0530)
Deployment via YAML declarative files.

Deployment Objects supported
1. Pod
2. Service

Signed-off-by: abhijit_onap <abhijit.das.gupta@huawei.com>
Change-Id: I3eee468139779095a9d641bb14c195023a3926c7

12 files changed:
blueprints/common/eliot-ui/be/src/eliotk8sclient/pom.xml
blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/AppException.java [new file with mode: 0644]
blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/common/AppConstants.java [new file with mode: 0644]
blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/controller/AppDeployController.java [new file with mode: 0755]
blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/deploy/GenericDeploy.java [new file with mode: 0644]
blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/deploy/GenericDeployFactory.java [new file with mode: 0644]
blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/deploy/kubernetes/DeployFactory.java [new file with mode: 0644]
blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/deploy/kubernetes/IDeploy.java [new file with mode: 0644]
blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/deploy/kubernetes/KubernetesDeploy.java [new file with mode: 0644]
blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/deploy/kubernetes/PodServiceDeploy.java [new file with mode: 0644]
blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/service/AppService.java [new file with mode: 0644]
blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/service/AppServiceHandler.java [new file with mode: 0644]

index e33a861..e16d977 100644 (file)
@@ -15,9 +15,9 @@
        <description>eliot backend code for kubernetes client</description>
 
        <properties>
-               <java.version>1.8</java.version>
+               <java.version>11</java.version>
+               <maven.test.skip>true</maven.test.skip>
        </properties>
-
        <dependencies>
                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <version>5.0.0</version>
                        <scope>compile</scope>
                </dependency>
-
-       </dependencies>
+        <dependency>
+            <groupId>com.fasterxml.jackson.dataformat</groupId>
+            <artifactId>jackson-dataformat-yaml</artifactId>
+            <version>2.10.3</version>
+        </dependency>
+               <dependency>
+                       <groupId>org.apache.logging.log4j</groupId>
+                       <artifactId>log4j-core</artifactId>
+                       <version>2.13.2</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.logging.log4j</groupId>
+                       <artifactId>log4j-api</artifactId>
+                       <version>2.13.2</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.bitbucket.b_c</groupId>
+                       <artifactId>jose4j</artifactId>
+                       <version>0.4.4</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.logging.log4j</groupId>
+                       <artifactId>log4j-slf4j-impl</artifactId>
+                       <version>2.13.2</version>
+               </dependency>
+               <dependency>
+                       <groupId>com.fasterxml.jackson.dataformat</groupId>
+                       <artifactId>jackson-dataformat-yaml</artifactId>
+                       <version>2.9.9</version>
+               </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpcore</artifactId>
+            <version>4.4.13</version>
+        </dependency>
+    </dependencies>
 
        <build>
                <plugins>
diff --git a/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/AppException.java b/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/AppException.java
new file mode 100644 (file)
index 0000000..e0a85a4
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2020 Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.eliot.eliotbe.eliotk8sclient;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ResponseStatus(HttpStatus.CONFLICT)
+public class AppException extends RuntimeException {
+
+    private static final long serialVersionUID = 1333309258952411164L;
+
+    public AppException(String msg) {
+        super(msg);
+    }
+}
+
diff --git a/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/common/AppConstants.java b/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/common/AppConstants.java
new file mode 100644 (file)
index 0000000..e5478e9
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2020 Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.eliot.eliotbe.eliotk8sclient.common;
+
+public class AppConstants {
+
+    public static final String EMPTY_STRING = "";
+
+    public static final String POD_NAME = "name";
+
+    public static final String POD_NAME_SPACE = "namespace";
+
+    public static final String POD_STATUS = "status";
+
+    public static final String SERVICE_NAME = "name";
+
+    public static final String SERVICE_NAME_SPACE = "namespace";
+
+    public static final String CONTAINERS = "containers";
+
+    public static final String PODS = "pods";
+
+    public static final String NAMEANDNAMESPACE = "|!";
+
+    public static final String K8SPOD = "|~";
+
+    public static final String POD_TYPE = "|`";
+
+    public static final String KIND = "kind";
+    //public static final String APP_PACKAGE_EXTENSION = ".csar";
+
+    public static final long MAX_PACKAGE_SIZE = 10485760;
+
+    public static final long MAX_CONFIG_SIZE = 5242880;
+
+    public static final int MAX_PACKAGE_DIR_SIZE = 16;
+
+    public static final int MAX_FILE_PATH_LENGTH = 2048;
+
+    public static final String HTTPS = "https://";
+
+    public static final String COLON = ":";
+}
diff --git a/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/controller/AppDeployController.java b/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/controller/AppDeployController.java
new file mode 100755 (executable)
index 0000000..7e3721b
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2020 Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.eliot.eliotbe.eliotk8sclient.controller;
+
+import com.eliot.eliotbe.eliotk8sclient.service.AppServiceHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.validation.constraints.Pattern;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+@Validated
+@RestController
+public class AppDeployController {
+
+    public static final Logger logger = LoggerFactory.getLogger(AppDeployController.class);
+
+    public static final String HOST_IP_REGEXP
+        = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$";
+    public static final String APP_INSTANCE_ID_REGEXP
+            = "([a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}){1}";
+    public static final String TENENT_ID_REGEXP = "[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}";
+    public static final String WORKLOAD_ID_REGEXP = "^.{1,1024}$";
+    public static final String QUERY_REGEXP = "^.{1,512}$";
+    @Autowired
+    private AppServiceHandler appServiceHandler;
+
+    /**
+     * Upload Deployment YAML file.
+     * @param file file
+     * @return
+     */
+    @RequestMapping(path = "/upload",
+        method = RequestMethod.POST,produces = MediaType.APPLICATION_JSON_VALUE)
+    public ResponseEntity<Map<String, String>> uploadAppDeployment(
+            @RequestParam("file") MultipartFile file) throws IOException {
+        logger.info("Deployment Upload File");
+        return appServiceHandler.uploadDeployment(file);
+    }
+}
diff --git a/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/deploy/GenericDeploy.java b/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/deploy/GenericDeploy.java
new file mode 100644 (file)
index 0000000..8886e3e
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2020 Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.eliot.eliotbe.eliotk8sclient.deploy;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.List;
+
+public abstract class GenericDeploy {
+
+    protected void search(final String pattern, final File folder, List<String> result) {
+        File[] files = folder.listFiles();
+        if (null != files) {
+            for (final File f : files) {
+                if (f.isDirectory()) {
+                    search(pattern, f, result);
+                }
+                handleFile(f, pattern, result);
+            }
+        }
+    }
+
+    private void handleFile(File f, String pattern, List<String> result) {
+        if (f.isFile() && f.getName().matches(pattern)) {
+            try {
+                result.add(f.getCanonicalPath());
+            } catch (IOException e) {
+                return;
+            }
+        }
+    }
+
+    public abstract String deploy(String packagepath);
+}
diff --git a/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/deploy/GenericDeployFactory.java b/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/deploy/GenericDeployFactory.java
new file mode 100644 (file)
index 0000000..df29165
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2020 Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.eliot.eliotbe.eliotk8sclient.deploy;
+
+
+import com.eliot.eliotbe.eliotk8sclient.deploy.kubernetes.KubernetesDeploy;
+
+public class GenericDeployFactory {
+
+    /**
+     * create ubernetesDeploy.
+     *
+     * @param deploymentType deploymentType
+     * @return
+     */
+    public static GenericDeploy create(String deploymentType) {
+        return new KubernetesDeploy();
+    }
+
+}
diff --git a/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/deploy/kubernetes/DeployFactory.java b/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/deploy/kubernetes/DeployFactory.java
new file mode 100644 (file)
index 0000000..dc5625a
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2020 Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.eliot.eliotbe.eliotk8sclient.deploy.kubernetes;
+
+import java.nio.file.Path;
+
+public class DeployFactory {
+
+    public static IDeploy create() {
+        return new com.eliot.eliotbe.eliotk8sclient.deploy.kubernetes.PodServiceDeploy();
+    }
+
+}
diff --git a/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/deploy/kubernetes/IDeploy.java b/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/deploy/kubernetes/IDeploy.java
new file mode 100644 (file)
index 0000000..63c246f
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2020 Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.eliot.eliotbe.eliotk8sclient.deploy.kubernetes;
+
+public interface IDeploy {
+
+    String deploy(String dstYamlFilePath);
+}
diff --git a/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/deploy/kubernetes/KubernetesDeploy.java b/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/deploy/kubernetes/KubernetesDeploy.java
new file mode 100644 (file)
index 0000000..73df718
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2020 Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.eliot.eliotbe.eliotk8sclient.deploy.kubernetes;
+
+import com.eliot.eliotbe.eliotk8sclient.deploy.GenericDeploy;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+import io.kubernetes.client.models.*;
+import io.kubernetes.client.util.Yaml;
+import org.jose4j.json.internal.json_simple.JSONObject;
+import org.jose4j.json.internal.json_simple.parser.JSONParser;
+import org.jose4j.json.internal.json_simple.parser.ParseException;
+import com.eliot.eliotbe.eliotk8sclient.common.AppConstants;
+import com.eliot.eliotbe.eliotk8sclient.deploy.GenericDeploy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.StringUtils;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.*;
+
+public class KubernetesDeploy extends GenericDeploy {
+    private static final Logger logger = LoggerFactory.getLogger(KubernetesDeploy.class);
+
+    private static final Map<String,Class<?>> kindClassMap = new HashMap<String, Class<?>>() {
+        private static final long serialVersionUID = 3033314593899228898L;
+        {
+            put("Pod",V1Pod.class);
+            put("Deployment",V1Deployment.class);
+            put("PersistentVolume",V1PersistentVolume.class);
+            put("PersistentVolumeClaim",V1PersistentVolumeClaim.class);
+            put("Service",V1Service.class);
+        }
+    };
+    /**
+     * deploy.
+     * @param packagepath packagepath
+     * @return
+     */
+    public String deploy(String dstYamlFilePath) {
+        //String dstYamlFilePath = findDeploymentYamlPath(packagepath);
+        if (StringUtils.isEmpty(dstYamlFilePath)) {
+            logger.error("not found deploy yaml file.");
+            return AppConstants.EMPTY_STRING;
+        }
+        String yamlContent = readYamlFile(dstYamlFilePath);
+        String yamlStr = null;
+        try {
+            logger.info("before kube config installation ");
+            yamlStr = deployByYaml(yamlContent,dstYamlFilePath);
+        } catch (IOException e) {
+            logger.error("invoke method deployYaml fail : {}",e.getMessage());
+            return AppConstants.EMPTY_STRING;
+        }
+        return yamlStr;
+    }
+
+     private String findDeploymentYamlPath(String packagepath) {
+        List<String> result = new ArrayList<>();
+        search(".*\\.yaml", new File(packagepath), result);
+        String dstYamlFilePath = null;
+        for (String path : result) {
+            if (path.contains("Deployment")) {
+                dstYamlFilePath = path;
+            }
+        }
+        return dstYamlFilePath;
+    }
+
+    protected String readYamlFile(String pathname) {
+        File file = new File(pathname);
+        StringBuilder fileContents = new StringBuilder((int) file.length());
+        Scanner scanner;
+        try {
+            scanner = new Scanner(file, "UTF-8");
+        } catch (FileNotFoundException e) {
+            logger.error("read yaml file fail : {}",e.getMessage());
+            return "";
+        }
+
+        String lineSeparator = System.getProperty("line.separator");
+        try {
+            while (scanner.hasNextLine()) {
+                fileContents.append(scanner.nextLine() + lineSeparator);
+            }
+            return fileContents.toString();
+        } finally {
+            scanner.close();
+        }
+    }
+
+    protected void addModelMap(String apiVersion, String kind) {
+        if (kindClassMap.containsKey(kind)) {
+            Yaml.addModelMap(apiVersion, kind, kindClassMap.get(kind));
+            logger.info("after addModelMap for {}",kindClassMap.get(kind).getName());
+            return;
+        }
+        logger.error("not found kind : {}",kind);
+    }
+
+    private String deployByYaml(String yamlContent, String dstYamlFilePath) throws IOException {
+        logger.info("Inside updateDeploymentYaml to install pod and service");
+        ObjectMapper yamlReader = new ObjectMapper(new YAMLFactory());
+        for (String ret : yamlContent.split("---")) {
+            if (StringUtils.isEmpty(ret)) {
+                continue;
+            }
+            Object obj = yamlReader.readValue(ret, Object.class);
+            String data = new ObjectMapper().writeValueAsString(obj);
+            try {
+                JSONObject json = (JSONObject) new JSONParser().parse(data);
+                if (json.get("kind") == null) {
+                    continue;
+                }
+                String kind = json.get("kind").toString();
+                String apiVersion = json.get("apiVersion").toString();
+                addModelMap(apiVersion,kind);
+            } catch (ParseException e) {
+                logger.error("parse data fail : {}",e.getMessage());
+            }
+        }
+        IDeploy deployment = DeployFactory.create();
+        return deployment.deploy(dstYamlFilePath);
+    }
+}
diff --git a/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/deploy/kubernetes/PodServiceDeploy.java b/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/deploy/kubernetes/PodServiceDeploy.java
new file mode 100644 (file)
index 0000000..fbe9fec
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2020 Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.eliot.eliotbe.eliotk8sclient.deploy.kubernetes;
+
+import com.google.gson.Gson;
+import io.kubernetes.client.ApiException;
+import io.kubernetes.client.apis.CoreV1Api;
+import io.kubernetes.client.models.V1Pod;
+import io.kubernetes.client.models.V1Service;
+import io.kubernetes.client.util.Yaml;
+import com.eliot.eliotbe.eliotk8sclient.common.AppConstants;
+import com.eliot.eliotbe.eliotk8sclient.AppException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+class PodServiceDeploy implements IDeploy {
+    private static final Logger logger = LoggerFactory.getLogger(com.eliot.eliotbe.eliotk8sclient.deploy.kubernetes.PodServiceDeploy.class);
+
+    private static final Gson gson = new Gson();
+     /**
+     * KubernetesDeployment constructor.
+     */
+    public PodServiceDeploy() {
+
+    }
+
+    /**
+     * create namespace pod.
+     * @param dstYamlFilePath dstYamlFilePath
+     * @return
+     */
+    @Override
+    public String deploy(String dstYamlFilePath) {
+        String nameSpace = "";
+        logger.info("-------------Kubernetes Deployment via YAML------------");
+        List<Object> list;
+        try {
+            list = Yaml.loadAll(new File(dstYamlFilePath));
+        } catch (IOException e) {
+            logger.error("load yaml file fail : {}",e.getMessage());
+            return AppConstants.EMPTY_STRING;
+        }
+
+        for (Object object : list) {
+            String type = object.getClass().getSimpleName();
+            switch (type) {
+                case "V1Pod":
+                    nameSpace = handlePodCreateRequest(object);
+                    break;
+                case "V1Service":
+                    nameSpace = handleServiceCreateRequest(object);
+                    break;
+                default:
+                    break;
+            }
+        }
+        logger.info("response with both pod and service: {}",nameSpace);
+        return nameSpace;
+    }
+
+    private String handleServiceCreateRequest(Object object) {
+        logger.info("SERVICE create request");
+        CoreV1Api v1service = new CoreV1Api();
+        V1Service serviceResult;
+        try {
+            serviceResult = v1service
+                .createNamespacedService("default", (V1Service) object, null, null, null);
+            logger.info("After createNamespacedService call with result: {}", serviceResult);
+            StringBuilder nameSpace = new StringBuilder("").append(Objects.requireNonNull(serviceResult.getMetadata())
+                .getName()).append(AppConstants.NAMEANDNAMESPACE).append(serviceResult.getMetadata()
+                .getNamespace()).append(AppConstants.POD_TYPE).append("Service").append(AppConstants.K8SPOD);
+            return nameSpace.toString();
+        } catch (ApiException e) {
+            throw new AppException(e.getMessage());
+        }
+    }
+
+    private String handlePodCreateRequest(Object object) {
+        logger.info("POD create request");
+        CoreV1Api v1pod = new CoreV1Api();
+        V1Pod createResult;
+        try {
+            createResult = v1pod.createNamespacedPod("default", (V1Pod) object, null, null, null);
+            logger.info("After createNamespacedPod call with result: {}", createResult);
+            StringBuilder nameSpace = new StringBuilder("").append(Objects.requireNonNull(createResult.getMetadata())
+                .getName()).append(AppConstants.NAMEANDNAMESPACE).append(createResult.getMetadata().getNamespace())
+                .append(AppConstants.POD_TYPE).append("Pod").append(AppConstants.K8SPOD);
+            return nameSpace.toString();
+        } catch (ApiException e) {
+            throw new AppException(e.getMessage());
+        }
+    }
+}
diff --git a/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/service/AppService.java b/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/service/AppService.java
new file mode 100644 (file)
index 0000000..c0f6b00
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2020 Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.eliot.eliotbe.eliotk8sclient.service;
+
+import com.eliot.eliotbe.eliotk8sclient.deploy.GenericDeployFactory;
+import com.google.gson.Gson;
+import io.kubernetes.client.ApiException;
+import io.kubernetes.client.apis.CoreV1Api;
+import io.kubernetes.client.models.V1PodList;
+import org.apache.tomcat.util.http.fileupload.FileUtils;
+import org.apache.tomcat.util.http.fileupload.IOUtils;
+import com.eliot.eliotbe.eliotk8sclient.AppException;
+import com.eliot.eliotbe.eliotk8sclient.common.AppConstants;
+import com.eliot.eliotbe.eliotk8sclient.deploy.GenericDeploy;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+import org.apache.http.ParseException;
+
+import java.io.File;
+//import org.apache.http.ParseException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.security.SecureRandom;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+
+@Component
+public class AppService {
+    private static final Logger logger = LoggerFactory.getLogger(AppService.class);
+
+    private static final  Gson gson = new Gson();
+
+/*    @Value("${DEPLOY_TYPE}")
+    private String deploymentType;*/
+
+    //@Value("${PACKAGE_BASE_PATH}")
+    private String packageBasePath = "/home/root1/eliot/deploy";
+
+    public String instantiateApplication(String deploymentPathWithFile) {
+/*        AppLcmUtils.setDefaultApiClient(k8sConfig);
+        String packageDir = getPackageDirName(AppConstants.MAX_PACKAGE_DIR_SIZE);
+        String packagePath = extractZipFile(file,packageDir);
+        if (packagePath.isEmpty()) {
+            logger.error("extract zip file fail");
+            return AppConstants.EMPTY_STRING;
+        }*/
+        try {
+            logger.info("Deployment Begin...");
+            GenericDeploy deploy = GenericDeployFactory.create("kubernetes");
+            return deploy.deploy(deploymentPathWithFile);
+        } catch (AppException | ParseException e) {
+            throw new AppException(e.getMessage());
+        }
+/*        finally {
+            if (!packagePath.isEmpty()) {
+                File appPackage = new File(packagePath);
+                if (appPackage.exists()) {
+                    try {
+                        FileUtils.cleanDirectory(appPackage);
+                        FileUtils.deleteDirectory(appPackage);
+                    } catch (IOException e) {
+                        logger.error("failed to delete application package : {}",e.getMessage());
+                    }
+                }
+            }
+        }*/
+    }
+    /**
+     * Returns storage base path.
+     *
+     * @return base path
+     */
+    public String getPackageBasePath() {
+        File file = new File(packageBasePath);
+        if (file.exists()) {
+            logger.info("Inside File Exists");
+            return packageBasePath + '/';
+        }
+        boolean isMk = file.mkdir();
+        if (!isMk) {
+            logger.info("Directory Create");
+            return AppConstants.EMPTY_STRING;
+        }
+        return packageBasePath + '/';
+    }
+
+
+    /**
+     * Generate application package directory name.
+     *
+     * @param size directory name size
+     * @return directory name
+     */
+    private String getPackageDirName(int size) {
+        final String allowed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+        SecureRandom sr = new SecureRandom();
+        StringBuilder sb = new StringBuilder(size);
+        for (int i = 0; i < size; i++) {
+            sb.append(allowed.charAt(sr.nextInt(allowed.length())));
+        }
+        return sb.toString();
+    }
+
+
+
+}
diff --git a/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/service/AppServiceHandler.java b/blueprints/common/eliot-ui/be/src/eliotk8sclient/src/main/java/com/eliot/eliotbe/eliotk8sclient/service/AppServiceHandler.java
new file mode 100644 (file)
index 0000000..406f064
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2020 Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.eliot.eliotbe.eliotk8sclient.service;
+
+
+import org.apache.tomcat.util.http.fileupload.FileUploadException;
+import com.eliot.eliotbe.eliotk8sclient.AppException;
+import com.eliot.eliotbe.eliotk8sclient.common.AppConstants;
+import org.apache.tomcat.util.http.fileupload.FileUtils;
+import org.joda.time.LocalDate;
+import org.joda.time.LocalDateTime;
+import org.joda.time.LocalTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.lang.System;
+import java.io.File;
+@Component
+public class AppServiceHandler {
+
+    public static final Logger logger = LoggerFactory.getLogger(AppServiceHandler.class);
+
+    @Autowired
+    private AppService appService;
+
+    /**
+     * Upload deployment file.
+     * @param file file
+     * @return
+     */
+    public ResponseEntity<Map<String, String>> uploadDeployment(MultipartFile file)
+            throws IOException {
+        try {
+            validateFile(file, AppConstants.MAX_CONFIG_SIZE, "");
+        } catch (FileUploadException | NullPointerException e) {
+            Map<String, String> response = new HashMap<>();
+            response.put("error",e.getMessage());
+            return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
+        }
+
+        String destination = appService.getPackageBasePath() + LocalDate.now().toString()
+                + LocalTime.now().getMillisOfSecond() +"/";
+        File destinationfile = new File(destination);
+/*        if (file.exists()) {
+            FileUtils.cleanDirectory(file);
+            FileUtils.deleteDirectory(file);
+        }*/
+        boolean isMk = destinationfile.mkdir();
+        if (!isMk) {
+            logger.info("package directory creation failed");
+        }
+
+        logger.info("destination path is set");
+
+        String deploymentPathWithFile = null;
+
+        deploymentPathWithFile = storeDeployFile(destination,file);
+
+        appService.instantiateApplication(deploymentPathWithFile);
+
+        Map<String, String> response = new HashMap<>();
+        response.put("Application Deployed","OK");
+        return new ResponseEntity<>(response, HttpStatus.OK);
+    }
+
+    private boolean checkK8sConfigFile(Path k8sConfig) {
+        if (!k8sConfig.toFile().isFile() || !k8sConfig.toFile().exists()) {
+            logger.error("Config file does not exist...");
+            return false;
+        }
+        return true;
+    }
+
+    private String storeDeployFile(String basePath, MultipartFile file) throws IOException {
+        // Get the file and save it somewhere
+        byte[] bytes = file.getBytes();
+
+        //String packageDir = getPackageDirName(AppConstants.MAX_PACKAGE_DIR_SIZE);
+        Path path = Paths.get(basePath + file.getOriginalFilename());
+       // Path path = Paths.get("~/");
+        Files.write(path, bytes);
+        String deploymentFilePath;
+        return deploymentFilePath = basePath+ file.getOriginalFilename();
+    }
+
+    private Path loadK8sConfigFilePath(String basePath) {
+        return Paths.get(basePath + "");
+    }
+
+/*    private String getPackageDirName(int size) {
+        final String allowed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+        SecureRandom sr = new SecureRandom();
+        StringBuilder sb = new StringBuilder(size);
+        for (int i = 0; i < size; i++) {
+            sb.append(allowed.charAt(sr.nextInt(allowed.length())));
+        }
+        return sb.toString();
+    }*/
+
+    /**
+     * Validate MultipartFile.
+     *
+     * @param file file
+     * @param fileSize  file size for validation
+     * @param extension file extension
+     * @throws FileUploadException on exception throws
+     */
+    public void validateFile(MultipartFile file, long fileSize, String extension) throws FileUploadException {
+        if (file == null) {
+            throw new FileUploadException("file is null");
+        }
+
+        if (file.isEmpty()) {
+            throw new FileUploadException("file is empty");
+        } else if (!extension.isEmpty()
+            && null != file.getOriginalFilename() && !file.getOriginalFilename().endsWith(extension)) {
+            throw new FileUploadException("package format not supported");
+        } else if (file.getSize() > fileSize) {
+            throw new FileUploadException("file size not in the limit");
+        }
+    }
+    private ResponseEntity<Map<String, String>> createErrorResponse(String error) {
+        Map<String, String> response = new HashMap<>();
+        response.put("error", error);
+        response.put("status", HttpStatus.INTERNAL_SERVER_ERROR.toString());
+        return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
+    }
+}