From 80f26bbeef6caea8f9946e8a0e1a5e0319dacc38 Mon Sep 17 00:00:00 2001 From: "Lott, Christopher (cl778h)" Date: Fri, 21 Jun 2019 09:12:45 -0400 Subject: [PATCH] Upgrade App Manager to version 0.1.5 This adds a method to list the deployable (available) apps. Extended backend to proxy to the new App Manager method. Revised the frontend catalog interface, service and screen to call the new backend method. Renamed from "xapp-manager" to "app-manager" to be consistent with that project's naming conventions. Change-Id: I6216ea09d8e316f00f2df5a73f3a64f89aaf8a54 Signed-off-by: Lott, Christopher (cl778h) --- a1-med-client/pom.xml | 2 +- anr-xapp-client/pom.xml | 2 +- {xapp-mgr-client => app-mgr-client}/.gitignore | 0 {xapp-mgr-client => app-mgr-client}/README.md | 4 +- {xapp-mgr-client => app-mgr-client}/pom.xml | 12 ++-- .../resources/xapp_manager_rest_api_v0_1_5.yaml | 32 +++++++++-- .../appmgr/client/test/AppManagerClientTest.java | 16 +++--- docs/release-notes.rst | 1 + e2-mgr-client/pom.xml | 2 +- pom.xml | 3 +- webapp-backend/pom.xml | 22 ++++---- ...iguration.java => AppManagerConfiguration.java} | 10 ++-- ...ation.java => AppManagerMockConfiguration.java} | 44 ++++++++------- ...erController.java => AppManagerController.java} | 52 +++++++++++------ .../ric/portal/dashboard/model/AppTransport.java | 66 ++++++++++++++++++++++ .../dashboard/model/DashboardDeployableXapps.java | 31 ++++++++++ webapp-frontend/src/app/app.module.ts | 4 +- .../src/app/catalog/catalog.component.css | 1 - .../src/app/catalog/catalog.component.html | 9 +-- .../src/app/catalog/catalog.component.spec.ts | 4 +- .../src/app/catalog/catalog.component.ts | 26 ++++----- .../src/app/catalog/catalog.datasource.ts | 35 ++++++------ .../src/app/control/control.component.html | 2 +- .../src/app/control/control.component.ts | 10 ++-- .../src/app/control/control.datasource.ts | 44 +++++++-------- .../{xapp-mgr.types.ts => app-mgr.types.ts} | 9 ++- .../app-mgr.service.spec.ts} | 6 +- .../app-mgr.service.ts} | 15 +++-- 28 files changed, 305 insertions(+), 159 deletions(-) rename {xapp-mgr-client => app-mgr-client}/.gitignore (100%) rename {xapp-mgr-client => app-mgr-client}/README.md (91%) rename {xapp-mgr-client => app-mgr-client}/pom.xml (96%) rename xapp-mgr-client/src/main/resources/xapp_manager_rest_api_v0_1_4.yaml => app-mgr-client/src/main/resources/xapp_manager_rest_api_v0_1_5.yaml (95%) rename xapp-mgr-client/src/test/java/org/oransc/ric/portal/dashboard/xappmgr/client/test/XappManagerClientTest.java => app-mgr-client/src/test/java/org/oransc/ric/portal/dashboard/appmgr/client/test/AppManagerClientTest.java (80%) rename webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/{XappManagerConfiguration.java => AppManagerConfiguration.java} (88%) rename webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/{XappManagerMockConfiguration.java => AppManagerMockConfiguration.java} (76%) rename webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/{XappManagerController.java => AppManagerController.java} (80%) create mode 100644 webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/model/AppTransport.java create mode 100644 webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/model/DashboardDeployableXapps.java rename webapp-frontend/src/app/interfaces/{xapp-mgr.types.ts => app-mgr.types.ts} (89%) rename webapp-frontend/src/app/services/{xapp-mgr/xapp-mgr.service.spec.ts => app-mgr/app-mgr.service.spec.ts} (86%) rename webapp-frontend/src/app/services/{xapp-mgr/xapp-mgr.service.ts => app-mgr/app-mgr.service.ts} (76%) diff --git a/a1-med-client/pom.xml b/a1-med-client/pom.xml index 974abccd..ba55b693 100644 --- a/a1-med-client/pom.xml +++ b/a1-med-client/pom.xml @@ -28,7 +28,7 @@ limitations under the License. 1.0.4-SNAPSHOT - org.o-ran-sc.ric.a1med.client + org.o-ran-sc.ric.plt.a1med.client a1-med-client RIC A1 Mediator client 0.4.0-SNAPSHOT diff --git a/anr-xapp-client/pom.xml b/anr-xapp-client/pom.xml index f0f66bbe..2cf95338 100644 --- a/anr-xapp-client/pom.xml +++ b/anr-xapp-client/pom.xml @@ -28,7 +28,7 @@ limitations under the License. 1.0.4-SNAPSHOT - org.o-ran-sc.ric.anrxapp.client + org.o-ran-sc.ric.xapp.anr.client anr-xapp-client RIC ANR xApp client 0.0.8-SNAPSHOT diff --git a/xapp-mgr-client/.gitignore b/app-mgr-client/.gitignore similarity index 100% rename from xapp-mgr-client/.gitignore rename to app-mgr-client/.gitignore diff --git a/xapp-mgr-client/README.md b/app-mgr-client/README.md similarity index 91% rename from xapp-mgr-client/README.md rename to app-mgr-client/README.md index d6eda84f..35d89417 100644 --- a/xapp-mgr-client/README.md +++ b/app-mgr-client/README.md @@ -1,7 +1,7 @@ -# XApp Manager Client Generator +# App Manager Client Generator This projects generates a REST client library from the Swagger specification -file stored here and packages it in a jar. +file stored in src/main/resources and packages it in a jar. ## Eclipse and STS Users diff --git a/xapp-mgr-client/pom.xml b/app-mgr-client/pom.xml similarity index 96% rename from xapp-mgr-client/pom.xml rename to app-mgr-client/pom.xml index 86639f48..0cd496a3 100644 --- a/xapp-mgr-client/pom.xml +++ b/app-mgr-client/pom.xml @@ -28,17 +28,17 @@ limitations under the License. 1.0.4-SNAPSHOT - org.o-ran-sc.ric.xappmgr.client - xapp-mgr-client - RIC xApp Manager client - 0.1.4-SNAPSHOT + org.o-ran-sc.ric.plt.appmgr.client + app-mgr-client + RIC App Manager client + 0.1.5-SNAPSHOT UTF-8 UTF-8 0 - org.oransc.ric.xappmgr.client + org.oransc.ric.plt.appmgr.client @@ -104,7 +104,7 @@ limitations under the License. generate - ${project.basedir}/src/main/resources/xapp_manager_rest_api_v0_1_4.yaml + ${project.basedir}/src/main/resources/xapp_manager_rest_api_v0_1_5.yaml java ${project.groupId} diff --git a/xapp-mgr-client/src/main/resources/xapp_manager_rest_api_v0_1_4.yaml b/app-mgr-client/src/main/resources/xapp_manager_rest_api_v0_1_5.yaml similarity index 95% rename from xapp-mgr-client/src/main/resources/xapp_manager_rest_api_v0_1_4.yaml rename to app-mgr-client/src/main/resources/xapp_manager_rest_api_v0_1_5.yaml index 7d316ce6..eb893594 100644 --- a/xapp-mgr-client/src/main/resources/xapp_manager_rest_api_v0_1_4.yaml +++ b/app-mgr-client/src/main/resources/xapp_manager_rest_api_v0_1_5.yaml @@ -1,8 +1,8 @@ # ========================LICENSE_START================================= # O-RAN-SC -# %% +# # Copyright (C) 2019 AT&T Intellectual Property and Nokia -# %% +# # 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 @@ -18,7 +18,7 @@ swagger: '2.0' info: description: This is a draft API for RIC appmgr - version: 0.1.4 + version: 0.1.5 title: RIC appmgr license: name: Apache 2.0 @@ -111,7 +111,22 @@ paths: '200': description: successful query of xApps schema: - $ref: '#/definitions/AllXapps' + $ref: '#/definitions/AllDeployedXapps' + '500': + description: Internal error + '/xapps/list': + get: + summary: Returns the list of all deployable xapps + tags: + - xapp + operationId: listAllXapps + produces: + - application/json + responses: + '200': + description: successful list of deployable xApps + schema: + $ref: '#/definitions/AllDeployableXapps' '500': description: Internal error '/xapps/{xAppName}': @@ -382,7 +397,12 @@ paths: '400': description: Invalid subscription supplied definitions: - AllXapps: + AllDeployableXapps: + type: array + items: + type: string + example: "xapp-dummy" + AllDeployedXapps: type: array items: $ref: '#/definitions/Xapp' @@ -573,4 +593,4 @@ definitions: - deleted - updated xApps: - $ref: '#/definitions/AllXapps' + $ref: '#/definitions/AllDeployedXapps' diff --git a/xapp-mgr-client/src/test/java/org/oransc/ric/portal/dashboard/xappmgr/client/test/XappManagerClientTest.java b/app-mgr-client/src/test/java/org/oransc/ric/portal/dashboard/appmgr/client/test/AppManagerClientTest.java similarity index 80% rename from xapp-mgr-client/src/test/java/org/oransc/ric/portal/dashboard/xappmgr/client/test/XappManagerClientTest.java rename to app-mgr-client/src/test/java/org/oransc/ric/portal/dashboard/appmgr/client/test/AppManagerClientTest.java index 13daf050..a52d8315 100644 --- a/xapp-mgr-client/src/test/java/org/oransc/ric/portal/dashboard/xappmgr/client/test/XappManagerClientTest.java +++ b/app-mgr-client/src/test/java/org/oransc/ric/portal/dashboard/appmgr/client/test/AppManagerClientTest.java @@ -17,14 +17,14 @@ * limitations under the License. * ========================LICENSE_END=================================== */ -package org.oransc.ric.portal.dashboard.xappmgr.client.test; +package org.oransc.ric.portal.dashboard.appmgr.client.test; import org.junit.jupiter.api.Test; -import org.oransc.ric.xappmgr.client.api.HealthApi; -import org.oransc.ric.xappmgr.client.api.XappApi; -import org.oransc.ric.xappmgr.client.invoker.ApiClient; -import org.oransc.ric.xappmgr.client.model.AllXapps; -import org.oransc.ric.xappmgr.client.model.Xapp; +import org.oransc.ric.plt.appmgr.client.api.HealthApi; +import org.oransc.ric.plt.appmgr.client.api.XappApi; +import org.oransc.ric.plt.appmgr.client.invoker.ApiClient; +import org.oransc.ric.plt.appmgr.client.model.AllDeployedXapps; +import org.oransc.ric.plt.appmgr.client.model.Xapp; import org.springframework.web.client.RestClientException; /** @@ -32,7 +32,7 @@ import org.springframework.web.client.RestClientException; * * The test fails because no server is available. */ -public class XappManagerClientTest { +public class AppManagerClientTest { @Test public void demo() { @@ -47,7 +47,7 @@ public class XappManagerClientTest { } try { XappApi xappApi = new XappApi(apiClient); - AllXapps allXapps = xappApi.getAllXapps(); + AllDeployedXapps allXapps = xappApi.getAllXapps(); System.out.println("getAllXapps answered: " + apiClient.getStatusCode().toString()); System.out.println("xApp count: " + allXapps.size()); for (Xapp x : allXapps) diff --git a/docs/release-notes.rst b/docs/release-notes.rst index f87c161c..c1d2e00c 100644 --- a/docs/release-notes.rst +++ b/docs/release-notes.rst @@ -38,6 +38,7 @@ Version 1.0.4, 21 June 2019 * Extend Xapp Controller with config endpoints * Add build number to dashboard version string * Move mock admin screen user data to backend +* Update App manager client to spec version 0.1.5 Version 1.0.3, 28 May 2019 -------------------------- diff --git a/e2-mgr-client/pom.xml b/e2-mgr-client/pom.xml index 335f3ccb..c54a641c 100644 --- a/e2-mgr-client/pom.xml +++ b/e2-mgr-client/pom.xml @@ -28,7 +28,7 @@ limitations under the License. 1.0.4-SNAPSHOT - org.o-ran-sc.ric.e2mgr.client + org.o-ran-sc.ric.plt.e2mgr.client e2-mgr-client RIC E2 Manager client 20190620-SNAPSHOT diff --git a/pom.xml b/pom.xml index 4e6feaf7..a2f192f5 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,7 @@ limitations under the License. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 + org.springframework.boot spring-boot-starter-parent 2.1.4.RELEASE @@ -45,8 +46,8 @@ limitations under the License. a1-med-client anr-xapp-client + app-mgr-client e2-mgr-client - xapp-mgr-client webapp-frontend webapp-backend diff --git a/webapp-backend/pom.xml b/webapp-backend/pom.xml index fac2743a..f4269209 100644 --- a/webapp-backend/pom.xml +++ b/webapp-backend/pom.xml @@ -36,26 +36,28 @@ limitations under the License. 0 + - org.o-ran-sc.ric.a1med.client + org.o-ran-sc.ric.xapp.anr.client + anr-xapp-client + 0.0.8-SNAPSHOT + + + + org.o-ran-sc.ric.plt.a1med.client a1-med-client 0.4.0-SNAPSHOT - org.o-ran-sc.ric.anrxapp.client - anr-xapp-client - 0.0.8-SNAPSHOT + org.o-ran-sc.ric.plt.appmgr.client + app-mgr-client + 0.1.5-SNAPSHOT - org.o-ran-sc.ric.e2mgr.client + org.o-ran-sc.ric.plt.e2mgr.client e2-mgr-client 20190620-SNAPSHOT - - org.o-ran-sc.ric.xappmgr.client - xapp-mgr-client - 0.1.4-SNAPSHOT - org.springframework.boot spring-boot-starter-web diff --git a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerConfiguration.java b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/AppManagerConfiguration.java similarity index 88% rename from webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerConfiguration.java rename to webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/AppManagerConfiguration.java index 1b699de6..f2ffca6c 100644 --- a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerConfiguration.java +++ b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/AppManagerConfiguration.java @@ -23,9 +23,9 @@ import java.lang.invoke.MethodHandles; import java.net.MalformedURLException; import java.net.URL; -import org.oransc.ric.xappmgr.client.api.HealthApi; -import org.oransc.ric.xappmgr.client.api.XappApi; -import org.oransc.ric.xappmgr.client.invoker.ApiClient; +import org.oransc.ric.plt.appmgr.client.api.HealthApi; +import org.oransc.ric.plt.appmgr.client.api.XappApi; +import org.oransc.ric.plt.appmgr.client.invoker.ApiClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -41,7 +41,7 @@ import org.springframework.web.client.RestTemplate; */ @Configuration @Profile("!mock") -public class XappManagerConfiguration { +public class AppManagerConfiguration { private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); @@ -49,7 +49,7 @@ public class XappManagerConfiguration { private final String xappMgrUrl; @Autowired - public XappManagerConfiguration(@Value("${xappmgr.url}") final String url) throws MalformedURLException { + public AppManagerConfiguration(@Value("${xappmgr.url}") final String url) throws MalformedURLException { logger.info("Configuring xApp Manager at base URL {}", url); new URL(url); this.xappMgrUrl = url; diff --git a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerMockConfiguration.java b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/AppManagerMockConfiguration.java similarity index 76% rename from webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerMockConfiguration.java rename to webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/AppManagerMockConfiguration.java index 8c0ff14d..10517e88 100644 --- a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerMockConfiguration.java +++ b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/AppManagerMockConfiguration.java @@ -26,19 +26,20 @@ import static org.mockito.Mockito.when; import java.lang.invoke.MethodHandles; -import org.oransc.ric.xappmgr.client.api.HealthApi; -import org.oransc.ric.xappmgr.client.api.XappApi; -import org.oransc.ric.xappmgr.client.invoker.ApiClient; -import org.oransc.ric.xappmgr.client.model.AllXappConfig; -import org.oransc.ric.xappmgr.client.model.AllXapps; -import org.oransc.ric.xappmgr.client.model.ConfigMetadata; -import org.oransc.ric.xappmgr.client.model.SubscriptionRequest; -import org.oransc.ric.xappmgr.client.model.SubscriptionResponse; -import org.oransc.ric.xappmgr.client.model.XAppConfig; -import org.oransc.ric.xappmgr.client.model.XAppInfo; -import org.oransc.ric.xappmgr.client.model.Xapp; -import org.oransc.ric.xappmgr.client.model.Xapp.StatusEnum; -import org.oransc.ric.xappmgr.client.model.XappInstance; +import org.oransc.ric.plt.appmgr.client.api.HealthApi; +import org.oransc.ric.plt.appmgr.client.api.XappApi; +import org.oransc.ric.plt.appmgr.client.invoker.ApiClient; +import org.oransc.ric.plt.appmgr.client.model.AllDeployableXapps; +import org.oransc.ric.plt.appmgr.client.model.AllDeployedXapps; +import org.oransc.ric.plt.appmgr.client.model.AllXappConfig; +import org.oransc.ric.plt.appmgr.client.model.ConfigMetadata; +import org.oransc.ric.plt.appmgr.client.model.SubscriptionRequest; +import org.oransc.ric.plt.appmgr.client.model.SubscriptionResponse; +import org.oransc.ric.plt.appmgr.client.model.XAppConfig; +import org.oransc.ric.plt.appmgr.client.model.XAppInfo; +import org.oransc.ric.plt.appmgr.client.model.Xapp; +import org.oransc.ric.plt.appmgr.client.model.Xapp.StatusEnum; +import org.oransc.ric.plt.appmgr.client.model.XappInstance; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Bean; @@ -52,28 +53,31 @@ import org.springframework.http.HttpStatus; */ @Profile("mock") @Configuration -public class XappManagerMockConfiguration { +public class AppManagerMockConfiguration { private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - private final AllXapps allXapps; + private final AllDeployableXapps availXapps; + private final AllDeployedXapps deployedXapps; private final AllXappConfig allXappConfigs; - public XappManagerMockConfiguration() { + public AppManagerMockConfiguration() { logger.info("Configuring mock xApp Manager"); final String[] appNames = { "AdmissionControl", "Automatic Neighbor Relation", "Dual Connectivity" }; final String configJson = " { \"config\" : \"example\" }"; final String descriptorJson = " { \"descriptor\" : \"example\" }"; allXappConfigs = new AllXappConfig(); - allXapps = new AllXapps(); + availXapps = new AllDeployableXapps(); + deployedXapps = new AllDeployedXapps(); for (String n : appNames) { ConfigMetadata metadata = new ConfigMetadata().configName("config-" + n).name(n).namespace("namespace"); XAppConfig config = new XAppConfig().config(configJson).descriptor(descriptorJson).metadata(metadata); allXappConfigs.add(config); + availXapps.add(n); Xapp xapp = new Xapp().name(n).version("version").status(StatusEnum.UNKNOWN); xapp.addInstancesItem(new XappInstance().name("abcd-1234").ip("1.2.3.4").port(200) .status(XappInstance.StatusEnum.RUNNING)); - allXapps.add(xapp); + deployedXapps.add(xapp); } } @@ -114,7 +118,9 @@ public class XappManagerMockConfiguration { when(mockApi.deployXapp(any(XAppInfo.class))).thenReturn(new Xapp()); - when(mockApi.getAllXapps()).thenReturn(allXapps); + when(mockApi.listAllXapps()).thenReturn(availXapps); + + when(mockApi.getAllXapps()).thenReturn(deployedXapps); Xapp xappByName = new Xapp().name("name").status(StatusEnum.UNKNOWN).version("v1"); when(mockApi.getXappByName(any(String.class))).thenReturn(xappByName); diff --git a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/XappManagerController.java b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AppManagerController.java similarity index 80% rename from webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/XappManagerController.java rename to webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AppManagerController.java index 057d8c48..e8ad8a92 100644 --- a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/XappManagerController.java +++ b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AppManagerController.java @@ -23,17 +23,20 @@ import java.lang.invoke.MethodHandles; import javax.servlet.http.HttpServletResponse; +import org.oransc.ric.plt.appmgr.client.api.HealthApi; +import org.oransc.ric.plt.appmgr.client.api.XappApi; +import org.oransc.ric.plt.appmgr.client.model.AllDeployableXapps; +import org.oransc.ric.plt.appmgr.client.model.AllDeployedXapps; +import org.oransc.ric.plt.appmgr.client.model.AllXappConfig; +import org.oransc.ric.plt.appmgr.client.model.ConfigMetadata; +import org.oransc.ric.plt.appmgr.client.model.XAppConfig; +import org.oransc.ric.plt.appmgr.client.model.XAppInfo; +import org.oransc.ric.plt.appmgr.client.model.Xapp; import org.oransc.ric.portal.dashboard.DashboardApplication; import org.oransc.ric.portal.dashboard.DashboardConstants; +import org.oransc.ric.portal.dashboard.model.AppTransport; +import org.oransc.ric.portal.dashboard.model.DashboardDeployableXapps; import org.oransc.ric.portal.dashboard.model.SuccessTransport; -import org.oransc.ric.xappmgr.client.api.HealthApi; -import org.oransc.ric.xappmgr.client.api.XappApi; -import org.oransc.ric.xappmgr.client.model.AllXappConfig; -import org.oransc.ric.xappmgr.client.model.AllXapps; -import org.oransc.ric.xappmgr.client.model.ConfigMetadata; -import org.oransc.ric.xappmgr.client.model.XAppConfig; -import org.oransc.ric.xappmgr.client.model.XAppInfo; -import org.oransc.ric.xappmgr.client.model.Xapp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -51,14 +54,14 @@ import org.springframework.web.client.HttpStatusCodeException; import io.swagger.annotations.ApiOperation; /** - * Proxies calls from the front end to the xApp Manager API. All methods answer + * Proxies calls from the front end to the App Manager API. All methods answer * 502 on failure:
HTTP server received an invalid response from a * server it consulted when acting as a proxy or gateway.
*/ @Configuration @RestController -@RequestMapping(value = DashboardConstants.ENDPOINT_PREFIX + "/xappmgr", produces = MediaType.APPLICATION_JSON_VALUE) -public class XappManagerController { +@RequestMapping(value = DashboardConstants.ENDPOINT_PREFIX + "/appmgr", produces = MediaType.APPLICATION_JSON_VALUE) +public class AppManagerController { private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); @@ -67,7 +70,7 @@ public class XappManagerController { private final XappApi xappApi; @Autowired - public XappManagerController(final HealthApi healthApi, final XappApi xappApi) { + public AppManagerController(final HealthApi healthApi, final XappApi xappApi) { Assert.notNull(healthApi, "health API must not be null"); Assert.notNull(xappApi, "xapp API must not be null"); this.healthApi = healthApi; @@ -161,14 +164,31 @@ public class XappManagerController { } } - @ApiOperation(value = "Returns the status of all xapps.", response = AllXapps.class) + @ApiOperation(value = "Returns a list of deployable xapps.", response = DashboardDeployableXapps.class) + @RequestMapping(value = "/xapps/list", method = RequestMethod.GET) + public Object getAvailableXapps() { + logger.debug("getAvailableXapps"); + try { + AllDeployableXapps appNames = xappApi.listAllXapps(); + // Answer a collection of structure instead of string + DashboardDeployableXapps apps = new DashboardDeployableXapps(); + for (String n : appNames) + apps.add(new AppTransport(n)); + return apps; + } catch (HttpStatusCodeException ex) { + logger.error("getAvailableXapps failed: {}", ex.toString()); + return ResponseEntity.status(HttpServletResponse.SC_BAD_GATEWAY).body(ex.getResponseBodyAsString()); + } + } + + @ApiOperation(value = "Returns the status of all deployed xapps.", response = AllDeployedXapps.class) @RequestMapping(value = "/xapps", method = RequestMethod.GET) - public Object getAllXapps() { - logger.debug("getAllXapps"); + public Object getDeployedXapps() { + logger.debug("getDeployedXapps"); try { return xappApi.getAllXapps(); } catch (HttpStatusCodeException ex) { - logger.error("getAllXapps failed: {}", ex.toString()); + logger.error("getDeployedXapps failed: {}", ex.toString()); return ResponseEntity.status(HttpServletResponse.SC_BAD_GATEWAY).body(ex.getResponseBodyAsString()); } } diff --git a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/model/AppTransport.java b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/model/AppTransport.java new file mode 100644 index 00000000..f4312cab --- /dev/null +++ b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/model/AppTransport.java @@ -0,0 +1,66 @@ +/*- + * ========================LICENSE_START================================= + * O-RAN-SC + * %% + * Copyright (C) 2019 AT&T Intellectual Property and Nokia + * %% + * 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.ric.portal.dashboard.model; + +/** + * Trivial model to transport available application from the App manager. I + * expect that system will soon add additional attributes. This allows coding to + * a structure rather than a scalar. + */ +public class AppTransport implements IDashboardResponse { + + private String name; + private String version; + + /** + * Builds an empty object. + */ + public AppTransport() { + // no-arg constructor + } + + /** + * Builds an object with the specified value. + * + * @param s + * value to transport. + */ + public AppTransport(String s) { + this.name = s; + } + + public String getName() { + return name; + } + + public void setName(String s) { + this.name = s; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + +} diff --git a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/model/DashboardDeployableXapps.java b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/model/DashboardDeployableXapps.java new file mode 100644 index 00000000..6cca83a0 --- /dev/null +++ b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/model/DashboardDeployableXapps.java @@ -0,0 +1,31 @@ +/*- + * ========================LICENSE_START================================= + * O-RAN-SC + * %% + * Copyright (C) 2019 AT&T Intellectual Property and Nokia + * %% + * 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.ric.portal.dashboard.model; + +import java.util.ArrayList; + +/** + * Replaces AllDeployableXapps, which only wraps String. + */ +public class DashboardDeployableXapps extends ArrayList { + + private static final long serialVersionUID = -928428052502491021L; + +} diff --git a/webapp-frontend/src/app/app.module.ts b/webapp-frontend/src/app/app.module.ts index 5d8a611b..35a2fa93 100644 --- a/webapp-frontend/src/app/app.module.ts +++ b/webapp-frontend/src/app/app.module.ts @@ -40,7 +40,7 @@ import { AppComponent } from './app.component'; import { LoginComponent } from './login/login.component'; import { CatalogComponent } from './catalog/catalog.component'; import { UiService } from './services/ui/ui.service'; -import { XappMgrService } from './services/xapp-mgr/xapp-mgr.service'; +import { AppMgrService } from './services/app-mgr/app-mgr.service'; import { DashboardService } from './services/dashboard/dashboard.service'; import { E2ManagerService } from './services/e2-mgr/e2-mgr.service'; import { SidenavListComponent } from './navigation/sidenav-list/sidenav-list.component'; @@ -144,7 +144,7 @@ import { AcXappComponent } from './ac-xapp/ac-xapp.component'; ], providers: [ UiService, - XappMgrService, + AppMgrService, DashboardService, E2ManagerService, ErrorDialogService diff --git a/webapp-frontend/src/app/catalog/catalog.component.css b/webapp-frontend/src/app/catalog/catalog.component.css index 91510bb9..abcff4f9 100644 --- a/webapp-frontend/src/app/catalog/catalog.component.css +++ b/webapp-frontend/src/app/catalog/catalog.component.css @@ -49,4 +49,3 @@ .catalog-button-row button{ margin-right: 5px; } - diff --git a/webapp-frontend/src/app/catalog/catalog.component.html b/webapp-frontend/src/app/catalog/catalog.component.html index 2277bb7f..db27f2c1 100644 --- a/webapp-frontend/src/app/catalog/catalog.component.html +++ b/webapp-frontend/src/app/catalog/catalog.component.html @@ -25,20 +25,15 @@ - xApp Name + App Name {{element.name}} - xApp version + Version {{element.version}} - - Status - {{element.status}} - - Action diff --git a/webapp-frontend/src/app/catalog/catalog.component.spec.ts b/webapp-frontend/src/app/catalog/catalog.component.spec.ts index 4bd360d0..037b653a 100644 --- a/webapp-frontend/src/app/catalog/catalog.component.spec.ts +++ b/webapp-frontend/src/app/catalog/catalog.component.spec.ts @@ -7,9 +7,9 @@ * 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. diff --git a/webapp-frontend/src/app/catalog/catalog.component.ts b/webapp-frontend/src/app/catalog/catalog.component.ts index 04b83805..a2e3cd1d 100644 --- a/webapp-frontend/src/app/catalog/catalog.component.ts +++ b/webapp-frontend/src/app/catalog/catalog.component.ts @@ -7,9 +7,9 @@ * 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. @@ -20,7 +20,7 @@ import { Component, OnInit, ViewChild } from '@angular/core'; import { MatSort } from '@angular/material/sort'; import { ErrorDialogService } from '../services/ui/error-dialog.service'; -import { XappMgrService } from '../services/xapp-mgr/xapp-mgr.service'; +import { AppMgrService } from '../services/app-mgr/app-mgr.service'; import { ConfirmDialogService } from './../services/ui/confirm-dialog.service'; import { NotificationService } from './../services/ui/notification.service'; import { CatalogDataSource } from './catalog.datasource'; @@ -30,40 +30,40 @@ import { CatalogDataSource } from './catalog.datasource'; templateUrl: './catalog.component.html', styleUrls: ['./catalog.component.css'], }) -export class CatalogComponent implements OnInit{ +export class CatalogComponent implements OnInit { - displayedColumns: string[] = ['name', 'version', 'status', 'action']; + displayedColumns: string[] = ['name', 'version', 'action']; dataSource: CatalogDataSource; @ViewChild(MatSort) sort: MatSort; constructor( - private xappMgrSvc: XappMgrService, + private appMgrSvc: AppMgrService, private confirmDialogService: ConfirmDialogService, private errorService: ErrorDialogService, private notification: NotificationService) { } ngOnInit() { - this.dataSource = new CatalogDataSource(this.xappMgrSvc, this.sort ); + this.dataSource = new CatalogDataSource(this.appMgrSvc, this.sort ); this.dataSource.loadTable(); } onConfigurexApp(name: string): void { - const aboutError = 'Not implemented yet'; + const aboutError = 'Configure not implemented (yet)'; this.errorService.displayError(aboutError); } onDeployxApp(name: string): void { - this.confirmDialogService.openConfirmDialog('Are you sure you want to deploy this xApp?') + this.confirmDialogService.openConfirmDialog('Deploy application ' + name + '?') .afterClosed().subscribe(res => { if (res) { - this.xappMgrSvc.deployXapp(name).subscribe( + this.appMgrSvc.deployXapp(name).subscribe( response => { switch (response.status) { case 200: - this.notification.success('xApp deploy succeeded!'); + this.notification.success('Deploy succeeded!'); break; default: - this.notification.warn('xApp deploy failed.'); + this.notification.warn('Deploy failed.'); } } ); @@ -71,4 +71,4 @@ export class CatalogComponent implements OnInit{ }); } -} \ No newline at end of file +} diff --git a/webapp-frontend/src/app/catalog/catalog.datasource.ts b/webapp-frontend/src/app/catalog/catalog.datasource.ts index f6ae32d4..e47abfde 100644 --- a/webapp-frontend/src/app/catalog/catalog.datasource.ts +++ b/webapp-frontend/src/app/catalog/catalog.datasource.ts @@ -25,32 +25,32 @@ import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import { Observable } from 'rxjs/Observable'; import { of } from 'rxjs/observable/of'; import { catchError, finalize, map } from 'rxjs/operators'; -import { XMXapp } from '../interfaces/xapp-mgr.types'; -import { XappMgrService } from '../services/xapp-mgr/xapp-mgr.service'; +import { AppMgrService } from '../services/app-mgr/app-mgr.service'; +import { XMDeployableApp } from '../interfaces/app-mgr.types'; -export class CatalogDataSource extends DataSource { +export class CatalogDataSource extends DataSource { - private xAppsSubject = new BehaviorSubject([]); + private xAppsSubject = new BehaviorSubject([]); private loadingSubject = new BehaviorSubject(false); public loading$ = this.loadingSubject.asObservable(); - constructor(private xappMgrSvc: XappMgrService, private sort: MatSort ) { + constructor(private appMgrSvc: AppMgrService, private sort: MatSort) { super(); - }; + } loadTable() { this.loadingSubject.next(true); - this.xappMgrSvc.getAll() + this.appMgrSvc.getDeployable() .pipe( catchError(() => of([])), finalize(() => this.loadingSubject.next(false)) ) - .subscribe(xApps => this.xAppsSubject.next(xApps) ) + .subscribe(xApps => this.xAppsSubject.next(xApps)); } - connect(collectionViewer: CollectionViewer): Observable { + connect(collectionViewer: CollectionViewer): Observable { const dataMutations = [ this.xAppsSubject.asObservable(), this.sort.sortChange @@ -65,24 +65,23 @@ export class CatalogDataSource extends DataSource { this.loadingSubject.complete(); } - private getSortedData(data: XMXapp[]) { + private getSortedData(data: XMDeployableApp[]) { if (!this.sort.active || this.sort.direction === '') { return data; } - - return data.sort((a, b) => { + return data.sort((a: XMDeployableApp, b: XMDeployableApp) => { const isAsc = this.sort.direction === 'asc'; switch (this.sort.active) { - case 'name': return compare(a.name, b.name, isAsc); - case 'version': return compare(a.version, b.version, isAsc); - case 'status': return compare(a.status, b.status, isAsc); + case 'name': return this.compare(a.name, b.name, isAsc); + case 'version': return this.compare(a.version, b.version, isAsc); default: return 0; } }); } -} -function compare(a, b, isAsc) { - return (a < b ? -1 : 1) * (isAsc ? 1 : -1); + private compare(a: string, b: string, isAsc: boolean) { + return (a < b ? -1 : 1) * (isAsc ? 1 : -1); + } + } diff --git a/webapp-frontend/src/app/control/control.component.html b/webapp-frontend/src/app/control/control.component.html index 700efd9c..cb41f199 100644 --- a/webapp-frontend/src/app/control/control.component.html +++ b/webapp-frontend/src/app/control/control.component.html @@ -25,7 +25,7 @@
- xApp Name + App Name {{element.xapp}} diff --git a/webapp-frontend/src/app/control/control.component.ts b/webapp-frontend/src/app/control/control.component.ts index 88359469..4059d276 100644 --- a/webapp-frontend/src/app/control/control.component.ts +++ b/webapp-frontend/src/app/control/control.component.ts @@ -20,8 +20,8 @@ import { Component, OnInit, ViewChild } from '@angular/core'; import { MatSort } from '@angular/material/sort'; import { Router } from '@angular/router'; -import { XappControlRow } from '../interfaces/xapp-mgr.types'; -import { XappMgrService } from '../services/xapp-mgr/xapp-mgr.service'; +import { XappControlRow } from '../interfaces/app-mgr.types'; +import { AppMgrService } from '../services/app-mgr/app-mgr.service'; import { ConfirmDialogService } from './../services/ui/confirm-dialog.service'; import { ErrorDialogService } from './../services/ui/error-dialog.service'; import { NotificationService } from './../services/ui/notification.service'; @@ -41,14 +41,14 @@ export class ControlComponent implements OnInit { @ViewChild(MatSort) sort: MatSort; constructor( - private xappMgrSvc: XappMgrService, + private appMgrSvc: AppMgrService, private router: Router, private confirmDialogService: ConfirmDialogService, private errorDialogService: ErrorDialogService, private notification: NotificationService) { } ngOnInit() { - this.dataSource = new ControlDataSource(this.xappMgrSvc, this.sort); + this.dataSource = new ControlDataSource(this.appMgrSvc, this.sort); this.dataSource.loadTable(); } @@ -68,7 +68,7 @@ export class ControlComponent implements OnInit { this.confirmDialogService.openConfirmDialog('Are you sure you want to undeploy xApp ' + app.xapp + '?') .afterClosed().subscribe(res => { if (res) { - this.xappMgrSvc.undeployXapp(app.xapp).subscribe( + this.appMgrSvc.undeployXapp(app.xapp).subscribe( response => { this.dataSource.loadTable(); switch (response.status) { diff --git a/webapp-frontend/src/app/control/control.datasource.ts b/webapp-frontend/src/app/control/control.datasource.ts index 60f8563e..41d7ba41 100644 --- a/webapp-frontend/src/app/control/control.datasource.ts +++ b/webapp-frontend/src/app/control/control.datasource.ts @@ -25,8 +25,8 @@ import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import { Observable } from 'rxjs/Observable'; import { of } from 'rxjs/observable/of'; import { catchError, finalize, map } from 'rxjs/operators'; -import { XappControlRow, XMXapp, XMXappInstance } from '../interfaces/xapp-mgr.types'; -import { XappMgrService } from '../services/xapp-mgr/xapp-mgr.service'; +import { XappControlRow, XMDeployedApp, XMXappInstance } from '../interfaces/app-mgr.types'; +import { AppMgrService } from '../services/app-mgr/app-mgr.service'; export class ControlDataSource extends DataSource { @@ -45,18 +45,18 @@ export class ControlDataSource extends DataSource { txMessages: [], }; - constructor(private xappMgrSvc: XappMgrService, private sort: MatSort) { + constructor(private appMgrSvc: AppMgrService, private sort: MatSort) { super(); - }; + } loadTable() { this.loadingSubject.next(true); - this.xappMgrSvc.getAll() + this.appMgrSvc.getDeployed() .pipe( catchError(() => of([])), finalize(() => this.loadingSubject.next(false)) ) - .subscribe(xApps => this.xAppInstancesSubject.next(this.getInstance(xApps))) + .subscribe(xApps => this.xAppInstancesSubject.next(this.flatten(xApps))); } connect(collectionViewer: CollectionViewer): Observable { @@ -74,24 +74,22 @@ export class ControlDataSource extends DataSource { this.loadingSubject.complete(); } - getInstance(allxappdata: XMXapp[]) { + private flatten(allxappdata: XMDeployedApp[]) { const xAppInstances: XappControlRow[] = []; - for (const xappindex in allxappdata) { - const instancelist = allxappdata[xappindex].instances; - if (!instancelist) { - var instance: XappControlRow = { - xapp: allxappdata[xappindex].name, + for (const xapp of allxappdata) { + if (!xapp.instances) { + const row: XappControlRow = { + xapp: xapp.name, instance: this.emptyInstances - } - xAppInstances.push(instance); - } - else { - for (const instanceindex in instancelist) { - var instance: XappControlRow = { - xapp: allxappdata[xappindex].name, - instance: instancelist[instanceindex] - } - xAppInstances.push(instance); + }; + xAppInstances.push(row); + } else { + for (const ins of xapp.instances) { + const row: XappControlRow = { + xapp: xapp.name, + instance: ins + }; + xAppInstances.push(row); } } } @@ -119,4 +117,4 @@ export class ControlDataSource extends DataSource { function compare(a, b, isAsc) { return (a < b ? -1 : 1) * (isAsc ? 1 : -1); -} \ No newline at end of file +} diff --git a/webapp-frontend/src/app/interfaces/xapp-mgr.types.ts b/webapp-frontend/src/app/interfaces/app-mgr.types.ts similarity index 89% rename from webapp-frontend/src/app/interfaces/xapp-mgr.types.ts rename to webapp-frontend/src/app/interfaces/app-mgr.types.ts index 1c3cc388..5acaf047 100644 --- a/webapp-frontend/src/app/interfaces/xapp-mgr.types.ts +++ b/webapp-frontend/src/app/interfaces/app-mgr.types.ts @@ -18,7 +18,7 @@ * ========================LICENSE_END=================================== */ -// Models of data used by the xApp Manager +// Models of data used by the App Manager export interface XMSubscription { eventType: string; @@ -41,7 +41,12 @@ export interface XMXappInstance { txMessages: Array; } -export interface XMXapp { +export interface XMDeployableApp { + name: string; + version: string; +} + +export interface XMDeployedApp { name: string; status: string; version: string; diff --git a/webapp-frontend/src/app/services/xapp-mgr/xapp-mgr.service.spec.ts b/webapp-frontend/src/app/services/app-mgr/app-mgr.service.spec.ts similarity index 86% rename from webapp-frontend/src/app/services/xapp-mgr/xapp-mgr.service.spec.ts rename to webapp-frontend/src/app/services/app-mgr/app-mgr.service.spec.ts index c62fd8b4..7698f5a8 100644 --- a/webapp-frontend/src/app/services/xapp-mgr/xapp-mgr.service.spec.ts +++ b/webapp-frontend/src/app/services/app-mgr/app-mgr.service.spec.ts @@ -19,13 +19,13 @@ */ import { TestBed } from '@angular/core/testing'; -import { XappMgrService } from './xapp-mgr.service'; +import { AppMgrService } from './app-mgr.service'; -describe('XappMgrService', () => { +describe('AppMgrService', () => { beforeEach(() => TestBed.configureTestingModule({})); it('should be created', () => { - const service: XappMgrService = TestBed.get(XappMgrService); + const service: AppMgrService = TestBed.get(AppMgrService); expect(service).toBeTruthy(); }); }); diff --git a/webapp-frontend/src/app/services/xapp-mgr/xapp-mgr.service.ts b/webapp-frontend/src/app/services/app-mgr/app-mgr.service.ts similarity index 76% rename from webapp-frontend/src/app/services/xapp-mgr/xapp-mgr.service.ts rename to webapp-frontend/src/app/services/app-mgr/app-mgr.service.ts index 48132d22..428bbe3e 100644 --- a/webapp-frontend/src/app/services/xapp-mgr/xapp-mgr.service.ts +++ b/webapp-frontend/src/app/services/app-mgr/app-mgr.service.ts @@ -20,20 +20,23 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; -import { XMXappInfo, XMXapp} from '../../interfaces/xapp-mgr.types'; - +import { XMXappInfo, XMDeployableApp, XMDeployedApp } from '../../interfaces/app-mgr.types'; @Injectable() -export class XappMgrService { +export class AppMgrService { constructor(private httpClient: HttpClient) { // injects to variable httpClient } - private basePath = 'api/xappmgr/xapps'; + private basePath = 'api/appmgr/xapps'; + + getDeployable(): Observable { + return this.httpClient.get(this.basePath + '/list'); + } - getAll(): Observable{ - return this.httpClient.get(this.basePath) + getDeployed(): Observable { + return this.httpClient.get(this.basePath); } deployXapp(name: string) { -- 2.16.6