Structural changes
Added values.yaml
Added namespace
Change-Id: I5ec9af0833ce5c51d735eacb6ce81775b0e578f3
diff --git a/rapp-manager/src/main/java/org/oransc/rappmanager/controller/AppController.java b/rapp-manager/src/main/java/org/oransc/rappmanager/controller/AppController.java
index 56809fe..3bdc4a4 100644
--- a/rapp-manager/src/main/java/org/oransc/rappmanager/controller/AppController.java
+++ b/rapp-manager/src/main/java/org/oransc/rappmanager/controller/AppController.java
@@ -18,6 +18,9 @@
package org.oransc.rappmanager.controller;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
@@ -25,15 +28,10 @@
import java.io.IOException;
-import javax.validation.Valid;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-
import org.oransc.rappmanager.exception.ServiceException;
import org.oransc.rappmanager.service.App;
import org.oransc.rappmanager.service.AppList;
import org.oransc.rappmanager.service.AppService;
-import org.oransc.rappmanager.service.ChartService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
@@ -49,74 +47,70 @@
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-
@RestController("rAppController")
@RequestMapping("rms")
-@Api(tags = { "rapp" })
+@Api(tags = {"rapp"})
public class AppController {
@Autowired
private AppService appService;
@Autowired
- private ChartService chartService;
private static Gson gson = new GsonBuilder().create();
@GetMapping(path = "/apps", produces = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation(value = "Return all Apps")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "rApp List") })
+ @ApiResponses(value = {@ApiResponse(code = 200, message = "rApp List")})
public ResponseEntity<AppList> getAllApps() throws ServiceException {
return new ResponseEntity<>(appService.getAllApps(), HttpStatus.OK);
}
- @GetMapping(path = "/apps/{name}", produces = MediaType.APPLICATION_JSON_VALUE)
- @ApiOperation(value = "Return a App")
- @ApiResponses(value = { @ApiResponse(code = 200, message = "rApp") })
- public ResponseEntity<App> getApp(@PathVariable("name") String name) throws ServiceException {
- return new ResponseEntity<>(appService.getApp(name), HttpStatus.OK);
- }
-
- @PostMapping(path = "/install", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
+ @PostMapping(
+ path = "/install",
+ consumes = MediaType.APPLICATION_JSON_VALUE,
+ produces = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation(value = "Install the rApp")
- @ApiResponses(value = { @ApiResponse(code = 201, message = "rApp Installed") })
+ @ApiResponses(value = {@ApiResponse(code = 201, message = "rApp Installed")})
public ResponseEntity<Object> installApp(@RequestBody InstallationInfo info) throws ServiceException {
- App app = App.builder().name(info.getName()).namespace(info.getNamespace()).version(info.getVersion()).build();
+ App app = appService.getApp(info.getName(), info.getVersion());
appService.installApp(app);
return new ResponseEntity<>(HttpStatus.CREATED);
}
@DeleteMapping(path = "/install/{name}/{version}", produces = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation(value = "Uninstall the App")
- @ApiResponses(value = { @ApiResponse(code = 201, message = "rApp Uninstalled") })
+ @ApiResponses(value = {@ApiResponse(code = 201, message = "rApp Uninstalled")})
public ResponseEntity<Object> deleteApp( //
- @PathVariable("name") String name, //
- @PathVariable("version") String version) throws ServiceException {
- App app = appService.getApp(name);
+ @PathVariable("name") String name, //
+ @PathVariable("version") String version) throws ServiceException {
+ App app = appService.getApp(name, version);
appService.uninstallApp(app);
- return new ResponseEntity<>(HttpStatus.OK);
+ return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
- @PostMapping(path = "/apps", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
+ @PostMapping(
+ path = "/apps",
+ consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
+ produces = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation(value = "Onboard the Chart")
- @ApiResponses(value = { @ApiResponse(code = 201, message = "Chart Onboarded") })
+ @ApiResponses(value = {@ApiResponse(code = 201, message = "Chart Onboarded")})
public ResponseEntity<String> onboardChart( //
- @RequestPart("chart") MultipartFile chartFile, //
- @RequestPart("values") MultipartFile overrideFile, //
- @RequestParam("info") String infoJson) throws ServiceException, IOException {
+ @RequestPart("chart") MultipartFile chartFile, //
+ @RequestPart("values") MultipartFile overrideFile, //
+ @RequestParam("info") String infoJson) throws ServiceException, IOException {
AppInfo info = gson.fromJson(infoJson, AppInfo.class);
appService.saveApp(info, chartFile, overrideFile);
return new ResponseEntity<>(HttpStatus.OK);
}
- @DeleteMapping(path = "/charts/{name}/{version}")
- @ApiOperation(value = "Delete the Chart")
- @ApiResponses(value = { @ApiResponse(code = 204, message = "Chart Deleted") })
+ @DeleteMapping(path = "/apps/{name}/{version}")
+ @ApiOperation(value = "Delete the app")
+ @ApiResponses(value = {@ApiResponse(code = 204, message = "Chart Deleted")})
public ResponseEntity<Object> deleteChart(@PathVariable("name") String name,
- @PathVariable("version") String version) throws ServiceException {
- chartService.deleteChart(name, version);
+ @PathVariable("version") String version) throws ServiceException {
+ App app = appService.getApp(name, version);
+ appService.deleteApp(app);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
diff --git a/rapp-manager/src/main/java/org/oransc/rappmanager/controller/AppInfo.java b/rapp-manager/src/main/java/org/oransc/rappmanager/controller/AppInfo.java
new file mode 100644
index 0000000..c097899
--- /dev/null
+++ b/rapp-manager/src/main/java/org/oransc/rappmanager/controller/AppInfo.java
@@ -0,0 +1,48 @@
+/*-
+ * ========================LICENSE_START=================================
+ * Copyright (C) 2021 Nordix Foundation. All rights reserved.
+ * ======================================================================
+ * 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.
+ * ========================LICENSE_END===================================
+ */
+
+package org.oransc.rappmanager.controller;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.gson.annotations.SerializedName;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Builder;
+import lombok.Getter;
+
+import org.immutables.gson.Gson;
+
+@Schema(name = "application-information", description = "Application information")
+@Getter
+@Builder
+@JsonInclude(Include.NON_NULL)
+@Gson.TypeAdapters
+public class AppInfo {
+
+ @Schema(name = "name", description = "name", required = true)
+ @JsonProperty(value = "name", required = true)
+ @SerializedName("name")
+ private final String name;
+
+ private final String version;
+
+ private final String namespace; // kube
+
+}
diff --git a/rapp-manager/src/main/java/org/oransc/rappmanager/controller/InstallationInfo.java b/rapp-manager/src/main/java/org/oransc/rappmanager/controller/InstallationInfo.java
new file mode 100644
index 0000000..e8013f6
--- /dev/null
+++ b/rapp-manager/src/main/java/org/oransc/rappmanager/controller/InstallationInfo.java
@@ -0,0 +1,36 @@
+/*-
+ * ========================LICENSE_START=================================
+ * Copyright (C) 2021 Nordix Foundation. All rights reserved.
+ * ======================================================================
+ * 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.
+ * ========================LICENSE_END===================================
+ */
+
+package org.oransc.rappmanager.controller;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Builder;
+import lombok.Getter;
+
+import org.immutables.gson.Gson;
+
+@Getter
+@Builder
+@Schema(name = "installation_information", description = "Information for one installation")
+@Gson.TypeAdapters
+public class InstallationInfo {
+
+ private final String name;
+ private final String version;
+
+}
diff --git a/rapp-manager/src/main/java/org/oransc/rappmanager/helm/HelmClient.java b/rapp-manager/src/main/java/org/oransc/rappmanager/helm/HelmClient.java
index 51c046b..025122b 100644
--- a/rapp-manager/src/main/java/org/oransc/rappmanager/helm/HelmClient.java
+++ b/rapp-manager/src/main/java/org/oransc/rappmanager/helm/HelmClient.java
@@ -49,6 +49,13 @@
executeCommand(builder);
}
+ protected String getOverrideFileName(App app) {
+ Path appPath = getAppPath(app);
+ File file = new File(appPath.toFile(), "values.yaml");
+ return file.getAbsolutePath();
+
+ }
+
protected String getChartFileName(App app) {
return getChartFile(app).getAbsolutePath();
}
diff --git a/rapp-manager/src/main/java/org/oransc/rappmanager/service/App.java b/rapp-manager/src/main/java/org/oransc/rappmanager/service/App.java
index c827b39..11b4529 100644
--- a/rapp-manager/src/main/java/org/oransc/rappmanager/service/App.java
+++ b/rapp-manager/src/main/java/org/oransc/rappmanager/service/App.java
@@ -27,16 +27,9 @@
@Builder
public class App {
- private String name = "";
- private String version = "";
+ private String name;
+ private String version;
- private String namespace = ""; // kube
+ private String namespace; // kube
- /**
- * private Status status; // how to determine the status of the app. Which
- * kubernetes object will tell me //that the app is running? It can have pod or
- * deployment or jobs, statefulset. //Easy way is to get meta-data of the app
- *
- * public enum Status { RUNNING, ERROR, }
- **/
}
diff --git a/rapp-manager/src/main/java/org/oransc/rappmanager/service/AppService.java b/rapp-manager/src/main/java/org/oransc/rappmanager/service/AppService.java
index b2c6ada..2f16455 100644
--- a/rapp-manager/src/main/java/org/oransc/rappmanager/service/AppService.java
+++ b/rapp-manager/src/main/java/org/oransc/rappmanager/service/AppService.java
@@ -18,21 +18,22 @@
package org.oransc.rappmanager.service;
-import java.io.File;
import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
+import java.lang.invoke.MethodHandles;
import org.oransc.rappmanager.configuration.ApplicationConfig;
import org.oransc.rappmanager.controller.AppInfo;
import org.oransc.rappmanager.exception.ServiceException;
import org.oransc.rappmanager.helm.HelmClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
@Service
public class AppService {
+ private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@Autowired
private AppStore appStore;
@@ -49,16 +50,17 @@
return AppList.builder().apps(appStore.getAllApp()).build();
}
- public App getApp(String name) throws ServiceException {
- return appStore.getApp(name);
+ public App getApp(String name, String version) throws ServiceException {
+ return appStore.getApp(name, version);
}
- public void saveApp(AppInfo appInfo, MultipartFile chartFile, MultipartFile overrideFile) throws IOException {
- Path appPath = getAppPath(appInfo);
- Files.createDirectories(appPath);
+ public App saveApp(AppInfo appInfo, MultipartFile chartFile, MultipartFile overrideFile)
+ throws IOException, ServiceException {
+ return appStore.saveApp(appInfo, chartFile, overrideFile);
+ }
- chartFile.transferTo(new File(appPath.toFile(), "chart.tgz"));
- overrideFile.transferTo(new File(appPath.toFile(), "values.yaml"));
+ public void deleteApp(App app) {
+ appStore.deleteApp(app);
}
public void installApp(App app) throws ServiceException {
@@ -66,22 +68,11 @@
// Call the kubernetes api to create namespace
// Validate the override file
helmClient.installApp(app);
- appStore.addApp(app);
-
}
public void uninstallApp(App app) throws ServiceException {
// call the kubernetes api to delete objects (helm call)
helmClient.uninstallApp(app);
- appStore.deleteApp(app.getName());
- }
-
- private Path getAppPath(AppInfo chart) {
- return Path.of(getDatabaseDirectory(), chart.getName(), chart.getVersion());
- }
-
- private String getDatabaseDirectory() {
- return appConfig.getVardataDirectory() + "/database";
}
}
diff --git a/rapp-manager/src/main/java/org/oransc/rappmanager/service/AppStore.java b/rapp-manager/src/main/java/org/oransc/rappmanager/service/AppStore.java
index c74440a..6422b30 100644
--- a/rapp-manager/src/main/java/org/oransc/rappmanager/service/AppStore.java
+++ b/rapp-manager/src/main/java/org/oransc/rappmanager/service/AppStore.java
@@ -18,33 +18,61 @@
package org.oransc.rappmanager.service;
+import java.io.File;
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.oransc.rappmanager.configuration.ApplicationConfig;
+import org.oransc.rappmanager.controller.AppInfo;
import org.oransc.rappmanager.exception.ServiceException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
+import org.springframework.util.FileSystemUtils;
+import org.springframework.web.multipart.MultipartFile;
@Component
public class AppStore {
+ private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
/**
* The appStore map contains app name as key & App as value
*/
- private Map<String, App> appStore = new HashMap<>();
+ private Map<String, App> appMap = new HashMap<>();
- public synchronized void addApp(App app) throws ServiceException {
+ @Autowired
+ ApplicationConfig appConfig;
- if (!appStore.containsKey(app.getName())) {
- appStore.put(app.getName(), app);
- } else {
+ public synchronized App saveApp(AppInfo appInfo, MultipartFile chartFile, MultipartFile overrideFile)
+ throws IOException, ServiceException {
+ if (appMap.containsKey(key(appInfo.getName(), appInfo.getVersion()))) {
throw new ServiceException("App Already Exist");
}
+ Path appPath = getAppPath(appInfo.getName(), appInfo.getVersion());
+ Files.createDirectories(appPath);
+
+ chartFile.transferTo(new File(appPath.toFile(), "chart.tgz"));
+ overrideFile.transferTo(new File(appPath.toFile(), "values.yaml"));
+
+ App app = App.builder() //
+ .name(appInfo.getName()) //
+ .version(appInfo.getVersion()) //
+ .namespace(appInfo.getNamespace()) //
+ .build();
+
+ appMap.put(key(app), app);
+ return app;
}
- public synchronized App getApp(String name) throws ServiceException {
- App app = appStore.get(name);
+ public synchronized App getApp(String name, String version) throws ServiceException {
+ App app = appMap.get(key(name, version));
if (app == null) {
throw new ServiceException("App not found: " + name);
}
@@ -52,10 +80,43 @@
}
public synchronized List<App> getAllApp() {
- return new ArrayList<App>(appStore.values());
+ return new ArrayList<>(appMap.values());
}
- public synchronized void deleteApp(String name) {
- appStore.remove(name);
+ public synchronized void deleteApp(App app) {
+ try {
+ Path appPath = getAppPath(app.getName(), app.getVersion());
+ FileSystemUtils.deleteRecursively(appPath);
+ } catch (IOException e) {
+ logger.warn("Could not delete app database : {}", e.getMessage());
+ }
+
+ appMap.remove(key(app));
}
+
+ public synchronized void reset() {
+ try {
+ FileSystemUtils.deleteRecursively(Path.of(this.appConfig.getVardataDirectory()));
+ } catch (IOException e) {
+ logger.warn("Could not delete database : {}", e.getMessage());
+ }
+ appMap.clear();
+ }
+
+ private Path getAppPath(String appName, String appVersion) {
+ return Path.of(getDatabaseDirectory(), appName, appVersion);
+ }
+
+ private String getDatabaseDirectory() {
+ return appConfig.getVardataDirectory() + "/database";
+ }
+
+ private String key(App app) {
+ return key(app.getName(), app.getVersion());
+ }
+
+ private String key(String appName, String appVersion) {
+ return appName + "_" + appVersion;
+ }
+
}
diff --git a/rapp-manager/src/main/java/org/oransc/rappmanager/service/ChartService.java b/rapp-manager/src/main/java/org/oransc/rappmanager/service/ChartService.java
deleted file mode 100644
index 3730acf..0000000
--- a/rapp-manager/src/main/java/org/oransc/rappmanager/service/ChartService.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*-
- * ========================LICENSE_START=================================
- * Copyright (C) 2021 Nordix Foundation. All rights reserved.
- * ======================================================================
- * 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.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.rappmanager.service;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Type;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Map;
-
-import org.oransc.rappmanager.client.AsyncRestClient;
-import org.oransc.rappmanager.client.AsyncRestClientFactory;
-import org.oransc.rappmanager.configuration.ApplicationConfig;
-import org.oransc.rappmanager.controller.AppInfo;
-import org.oransc.rappmanager.exception.ServiceException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Service;
-import org.springframework.web.multipart.MultipartFile;
-
-// Need to support multiple Chart registry. So add an interface and use it based on the registry choice.
-@Service
-public class ChartService {
-
- private static final Logger logger = LoggerFactory.getLogger(ChartService.class);
-
- private final AsyncRestClient chartClient;
- private final ApplicationConfig appConfig;
-
- private static Gson gson = new GsonBuilder().serializeNulls().create();
-
- private static String basePath = "/api/charts";
-
- public ChartService(@Autowired ApplicationConfig appConfig) {
- AsyncRestClientFactory factory = new AsyncRestClientFactory(appConfig.getWebClientConfig());
- chartClient = factory.createRestClientNoHttpProxy(appConfig.getChartApi());
- this.appConfig = appConfig;
- }
-
- public Map<String, AppInfo[]> getCharts() throws ServiceException {
- ResponseEntity<String> rsp = chartClient.getForEntity(basePath).block();
- if (rsp.getStatusCodeValue() != 200) {
- throw new ServiceException("Error Getting Charts");
- }
- logger.debug("Sucessfully fetched the charts");
- return parseChart(rsp.getBody());
- }
-
- public AppInfo[] getChart(String name) throws ServiceException {
- ResponseEntity<String> rsp = chartClient.getForEntity(basePath + "/" + name).block();
- if (!rsp.getStatusCode().is2xxSuccessful()) {
- throw new ServiceException("Error Getting Chart " + name);
- }
- logger.debug("Sucessfully fetched the chart");
- return gson.fromJson(rsp.getBody(), AppInfo[].class);
- }
-
- public void saveChart(AppInfo chart, MultipartFile chartFile, MultipartFile overrideFile) throws IOException {
- Path appPath = getAppPath(chart);
- Files.createDirectories(appPath);
-
- chartFile.transferTo(new File(appPath.toFile(), "chart.tgz"));
- overrideFile.transferTo(new File(appPath.toFile(), "values.yaml"));
- }
-
- private Path getAppPath(AppInfo chart) {
- return Path.of(getDatabaseDirectory(), chart.getName(), chart.getVersion());
- }
-
- private String getDatabaseDirectory() {
- return appConfig.getVardataDirectory() + "/database";
- }
-
- public void deleteChart(String name, String version) throws ServiceException {
- ResponseEntity<String> rsp = chartClient.deleteForEntity(basePath + "/" + name + "/" + version).block();
- if (!rsp.getStatusCode().is2xxSuccessful()) {
- throw new ServiceException("Error in deleting Chart " + name);
- }
- logger.debug("Sucessfully deleted the chart");
- }
-
- private Map<String, AppInfo[]> parseChart(String json) {
- Type mapType = new TypeToken<Map<String, AppInfo[]>>() {
- }.getType();
- return gson.fromJson(json, mapType);
- }
-
-}
diff --git a/rapp-manager/src/test/java/org/oransc/rappmanager/controller/ChartControllerTest.java b/rapp-manager/src/test/java/org/oransc/rappmanager/controller/Microk8sTest.java
similarity index 64%
rename from rapp-manager/src/test/java/org/oransc/rappmanager/controller/ChartControllerTest.java
rename to rapp-manager/src/test/java/org/oransc/rappmanager/controller/Microk8sTest.java
index 46c28fc..e5a8c29 100644
--- a/rapp-manager/src/test/java/org/oransc/rappmanager/controller/ChartControllerTest.java
+++ b/rapp-manager/src/test/java/org/oransc/rappmanager/controller/Microk8sTest.java
@@ -7,13 +7,9 @@
import com.google.gson.GsonBuilder;
import java.io.File;
-import java.io.IOException;
import java.lang.invoke.MethodHandles;
-import java.nio.file.Path;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import org.junit.Test;
import org.junit.jupiter.api.AfterEach;
@@ -26,8 +22,10 @@
import org.oransc.rappmanager.configuration.ApplicationConfig;
import org.oransc.rappmanager.configuration.ImmutableWebClientConfig;
import org.oransc.rappmanager.configuration.WebClientConfig;
+import org.oransc.rappmanager.exception.ServiceException;
import org.oransc.rappmanager.helm.HelmClient;
import org.oransc.rappmanager.service.App;
+import org.oransc.rappmanager.service.AppStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -47,8 +45,6 @@
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit4.SpringRunner;
-import org.springframework.test.web.servlet.MockMvc;
-import org.springframework.util.FileSystemUtils;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.BodyInserters.MultipartInserter;
@@ -56,25 +52,27 @@
@RunWith(SpringRunner.class)
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
-@TestPropertySource(properties = { //
+@TestPropertySource(
+ properties = { //
"server.ssl.key-store=./config/keystore.jks", //
"app.webclient.trust-store=./config/truststore.jks", //
"app.vardata-directory=./target" //
-})
-public class ChartControllerTest {
+ })
+public class Microk8sTest {
private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static Gson gson = new GsonBuilder().serializeNulls().create();
+ private final static String APP_NAME = "test-application";
+ private final static String VERSION = "1.0.0";
+ private final static String NAMESPACE = "test-application-namespace";
@LocalServerPort
private int port;
@Autowired
- private MockMvc mvc;
-
- @Autowired
ApplicationConfig applicationConfig;
- private Map<String, AppInfo[]> charts = new HashMap<>();
+ @Autowired
+ AppStore appStore;
static class Microk8sHelmClient extends HelmClient {
public Microk8sHelmClient(@Autowired ApplicationConfig appConfig) {
@@ -84,8 +82,10 @@
@Override
public ProcessBuilder prepareInstallCommand(App app) {
List<String> helmArguments = Arrays.asList("microk8s.helm", //
- "install", getChartFileName(app), //
- "--name", releaseName(app));
+ "install", getChartFileName(app), //
+ "--name", releaseName(app), //
+ "--namespace", app.getNamespace(), //
+ "--values", getOverrideFileName(app));
ProcessBuilder processBuilder = new ProcessBuilder();
return processBuilder.command(helmArguments);
@@ -118,45 +118,52 @@
@BeforeEach
@AfterEach
void reset() {
- try {
- FileSystemUtils.deleteRecursively(Path.of(this.applicationConfig.getVardataDirectory()));
- } catch (IOException e) {
- logger.warn("Could not delete database : {}", e.getMessage());
- }
+ appStore.reset();
}
@Test
- public void testPostApp_InstallApp_DeleteApp() {
+ public void testPostApp_InstallApp_DeleteApp() throws ServiceException {
+ onboardApp();
+ App app = appStore.getApp(APP_NAME, VERSION);
+ assertThat(app.getNamespace()).isEqualTo(NAMESPACE);
- AsyncRestClient client = restClient();
- {
- // onboard APP
- String url = "/rms/apps";
- AppInfo appInfo = AppInfo.builder().name("test-application").version("1.0.0").build();
+ installApp();
- File chartFile = new File(getClass().getClassLoader().getResource("testchart-0.1.0.tgz").getFile());
- File overrideFile = new File(getClass().getClassLoader().getResource("testValues.yaml").getFile());
- MultipartInserter body = createPostAppBody(chartFile, appInfo, overrideFile);
- ResponseEntity<String> e = client.postForEntity(url, body, MediaType.MULTIPART_FORM_DATA).block();
+ uninstallApp();
- assertThat(e.getStatusCode()).isEqualTo(HttpStatus.OK);
- }
- {
- // Install App
- InstallationInfo app = InstallationInfo.builder().name("test-application").version("1.0.0")
- .namespace("test-application-namespace").build();
- String body = gson.toJson(app);
- String url = "/rms/install";
- ResponseEntity<String> e = client.postForEntity(url, body).block();
- assertThat(e.getStatusCode()).isEqualTo(HttpStatus.CREATED);
- }
- {
- // Uninstall App
- String url = "/rms/install/test-application/1.0.0";
- ResponseEntity<String> e = client.deleteForEntity(url).block();
- assertThat(e.getStatusCode()).isEqualTo(HttpStatus.OK);
- }
+ deleteApp();
+ }
+ private void onboardApp() {
+ String url = "/rms/apps";
+ AppInfo appInfo = AppInfo.builder().name(APP_NAME).version(VERSION).namespace(NAMESPACE).build();
+
+ File chartFile = new File(getClass().getClassLoader().getResource("testchart-0.1.0.tgz").getFile());
+ File overrideFile = new File(getClass().getClassLoader().getResource("testValues.yaml").getFile());
+ MultipartInserter body = createPostAppBody(chartFile, appInfo, overrideFile);
+ ResponseEntity<String> e = restClient().postForEntity(url, body, MediaType.MULTIPART_FORM_DATA).block();
+
+ assertThat(e.getStatusCode()).isEqualTo(HttpStatus.OK);
+ }
+
+ private void installApp() {
+ InstallationInfo app = InstallationInfo.builder().name(APP_NAME).version(VERSION).build();
+ String body = gson.toJson(app);
+ String url = "/rms/install";
+ ResponseEntity<String> e = restClient().postForEntity(url, body).block();
+ assertThat(e.getStatusCode()).isEqualTo(HttpStatus.CREATED);
+ }
+
+ private void uninstallApp() {
+ String url = "/rms/install/" + APP_NAME + "/" + VERSION;
+ ResponseEntity<String> e = restClient().deleteForEntity(url).block();
+ assertThat(e.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
+ }
+
+ private void deleteApp() {
+ String url = "/rms/apps/" + APP_NAME + "/" + VERSION;
+ ResponseEntity<String> e = restClient().deleteForEntity(url).block();
+ assertThat(e.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
}
private MultipartInserter createPostAppBody(File chartFile, AppInfo appInfo, File overrideFile) {
@@ -170,15 +177,15 @@
private AsyncRestClient restClient(String baseUrl, boolean useTrustValidation) {
WebClientConfig config = this.applicationConfig.getWebClientConfig();
config = ImmutableWebClientConfig.builder() //
- .keyStoreType(config.keyStoreType()) //
- .keyStorePassword(config.keyStorePassword()) //
- .keyStore(config.keyStore()) //
- .keyPassword(config.keyPassword()) //
- .isTrustStoreUsed(useTrustValidation) //
- .trustStore(config.trustStore()) //
- .trustStorePassword(config.trustStorePassword()) //
- .httpProxyConfig(config.httpProxyConfig()) //
- .build();
+ .keyStoreType(config.keyStoreType()) //
+ .keyStorePassword(config.keyStorePassword()) //
+ .keyStore(config.keyStore()) //
+ .keyPassword(config.keyPassword()) //
+ .isTrustStoreUsed(useTrustValidation) //
+ .trustStore(config.trustStore()) //
+ .trustStorePassword(config.trustStorePassword()) //
+ .httpProxyConfig(config.httpProxyConfig()) //
+ .build();
AsyncRestClientFactory f = new AsyncRestClientFactory(config);
return f.createRestClientNoHttpProxy(baseUrl);