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
<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>
--- /dev/null
+/*
+ * 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);
+ }
+}
+
--- /dev/null
+/*
+ * 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 = ":";
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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();
+ }
+
+}
--- /dev/null
+/*
+ * 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();
+ }
+
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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());
+ }
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+
+
+
+}
--- /dev/null
+/*
+ * 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);
+ }
+}