Upgrade App Manager to version 0.1.5 97/397/4
authorLott, Christopher (cl778h) <cl778h@att.com>
Fri, 21 Jun 2019 13:12:45 +0000 (09:12 -0400)
committerLott, Christopher (cl778h) <cl778h@att.com>
Fri, 21 Jun 2019 15:19:23 +0000 (11:19 -0400)
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) <cl778h@att.com>
28 files changed:
a1-med-client/pom.xml
anr-xapp-client/pom.xml
app-mgr-client/.gitignore [moved from xapp-mgr-client/.gitignore with 100% similarity]
app-mgr-client/README.md [moved from xapp-mgr-client/README.md with 91% similarity]
app-mgr-client/pom.xml [moved from xapp-mgr-client/pom.xml with 96% similarity]
app-mgr-client/src/main/resources/xapp_manager_rest_api_v0_1_5.yaml [moved from xapp-mgr-client/src/main/resources/xapp_manager_rest_api_v0_1_4.yaml with 95% similarity]
app-mgr-client/src/test/java/org/oransc/ric/portal/dashboard/appmgr/client/test/AppManagerClientTest.java [moved from xapp-mgr-client/src/test/java/org/oransc/ric/portal/dashboard/xappmgr/client/test/XappManagerClientTest.java with 80% similarity]
docs/release-notes.rst
e2-mgr-client/pom.xml
pom.xml
webapp-backend/pom.xml
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/AppManagerConfiguration.java [moved from webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerConfiguration.java with 88% similarity]
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/AppManagerMockConfiguration.java [moved from webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerMockConfiguration.java with 76% similarity]
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AppManagerController.java [moved from webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/XappManagerController.java with 80% similarity]
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/model/AppTransport.java [new file with mode: 0644]
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/model/DashboardDeployableXapps.java [new file with mode: 0644]
webapp-frontend/src/app/app.module.ts
webapp-frontend/src/app/catalog/catalog.component.css
webapp-frontend/src/app/catalog/catalog.component.html
webapp-frontend/src/app/catalog/catalog.component.spec.ts
webapp-frontend/src/app/catalog/catalog.component.ts
webapp-frontend/src/app/catalog/catalog.datasource.ts
webapp-frontend/src/app/control/control.component.html
webapp-frontend/src/app/control/control.component.ts
webapp-frontend/src/app/control/control.datasource.ts
webapp-frontend/src/app/interfaces/app-mgr.types.ts [moved from webapp-frontend/src/app/interfaces/xapp-mgr.types.ts with 89% similarity]
webapp-frontend/src/app/services/app-mgr/app-mgr.service.spec.ts [moved from webapp-frontend/src/app/services/xapp-mgr/xapp-mgr.service.spec.ts with 86% similarity]
webapp-frontend/src/app/services/app-mgr/app-mgr.service.ts [moved from webapp-frontend/src/app/services/xapp-mgr/xapp-mgr.service.ts with 76% similarity]

index 974abcc..ba55b69 100644 (file)
@@ -28,7 +28,7 @@ limitations under the License.
                <version>1.0.4-SNAPSHOT</version>
        </parent>
        <!-- This groupId will NOT allow deployment in LF -->
-       <groupId>org.o-ran-sc.ric.a1med.client</groupId>
+       <groupId>org.o-ran-sc.ric.plt.a1med.client</groupId>
        <artifactId>a1-med-client</artifactId>
        <name>RIC A1 Mediator client</name>
        <version>0.4.0-SNAPSHOT</version>
index f0f66bb..2cf9533 100644 (file)
@@ -28,7 +28,7 @@ limitations under the License.
                <version>1.0.4-SNAPSHOT</version>
        </parent>
        <!-- This groupId will NOT allow deployment in LF -->
-       <groupId>org.o-ran-sc.ric.anrxapp.client</groupId>
+       <groupId>org.o-ran-sc.ric.xapp.anr.client</groupId>
        <artifactId>anr-xapp-client</artifactId>
        <name>RIC ANR xApp client</name>
        <version>0.0.8-SNAPSHOT</version>
similarity index 91%
rename from xapp-mgr-client/README.md
rename to app-mgr-client/README.md
index d6eda84..35d8941 100644 (file)
@@ -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
 
similarity index 96%
rename from xapp-mgr-client/pom.xml
rename to app-mgr-client/pom.xml
index 86639f4..0cd496a 100644 (file)
@@ -28,17 +28,17 @@ limitations under the License.
                <version>1.0.4-SNAPSHOT</version>
        </parent>
        <!-- This groupId will NOT allow deployment in LF -->
-       <groupId>org.o-ran-sc.ric.xappmgr.client</groupId>
-       <artifactId>xapp-mgr-client</artifactId>
-       <name>RIC xApp Manager client</name>
-       <version>0.1.4-SNAPSHOT</version>
+       <groupId>org.o-ran-sc.ric.plt.appmgr.client</groupId>
+       <artifactId>app-mgr-client</artifactId>
+       <name>RIC App Manager client</name>
+       <version>0.1.5-SNAPSHOT</version>
        <properties>
                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
                <!-- Jenkins invokes maven with -Dbuild.number=.. -->
                <build.number>0</build.number>
                <!-- same as groupId BUT without hyphens -->
-               <client.base.package.name>org.oransc.ric.xappmgr.client</client.base.package.name>
+               <client.base.package.name>org.oransc.ric.plt.appmgr.client</client.base.package.name>
        </properties>
        <!-- Successful compilation requires generated code dependencies -->
        <dependencies>
@@ -104,7 +104,7 @@ limitations under the License.
                                                        <goal>generate</goal>
                                                </goals>
                                                <configuration>
-                                                       <inputSpec>${project.basedir}/src/main/resources/xapp_manager_rest_api_v0_1_4.yaml</inputSpec>
+                                                       <inputSpec>${project.basedir}/src/main/resources/xapp_manager_rest_api_v0_1_5.yaml</inputSpec>
                                                        <language>java</language>
                                                        <configOptions>
                                                                <groupId>${project.groupId}</groupId>
@@ -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'
  * 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)
index f87c161..c1d2e00 100644 (file)
@@ -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
 --------------------------
index 335f3cc..c54a641 100644 (file)
@@ -28,7 +28,7 @@ limitations under the License.
                <version>1.0.4-SNAPSHOT</version>
        </parent>
        <!-- This groupId will NOT allow deployment in LF -->
-       <groupId>org.o-ran-sc.ric.e2mgr.client</groupId>
+       <groupId>org.o-ran-sc.ric.plt.e2mgr.client</groupId>
        <artifactId>e2-mgr-client</artifactId>
        <name>RIC E2 Manager client</name>
        <version>20190620-SNAPSHOT</version>
diff --git a/pom.xml b/pom.xml
index 4e6feaf..a2f192f 100644 (file)
--- 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">
        <modelVersion>4.0.0</modelVersion>
        <parent>
+               <!-- this group Id must match LF gerrit repository -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>2.1.4.RELEASE</version>
@@ -45,8 +46,8 @@ limitations under the License.
        <modules>
                <module>a1-med-client</module>
                <module>anr-xapp-client</module>
+               <module>app-mgr-client</module>
                <module>e2-mgr-client</module>
-               <module>xapp-mgr-client</module>
                <module>webapp-frontend</module>
                <module>webapp-backend</module>
        </modules>
index fac2743..f426920 100644 (file)
@@ -36,26 +36,28 @@ limitations under the License.
                <build.number>0</build.number>
        </properties>
        <dependencies>
+               <!-- xApps -->
                <dependency>
-                       <groupId>org.o-ran-sc.ric.a1med.client</groupId>
+                       <groupId>org.o-ran-sc.ric.xapp.anr.client</groupId>
+                       <artifactId>anr-xapp-client</artifactId>
+                       <version>0.0.8-SNAPSHOT</version>
+               </dependency>
+               <!-- Platform components -->
+               <dependency>
+                       <groupId>org.o-ran-sc.ric.plt.a1med.client</groupId>
                        <artifactId>a1-med-client</artifactId>
                        <version>0.4.0-SNAPSHOT</version>
                </dependency>
                <dependency>
-                       <groupId>org.o-ran-sc.ric.anrxapp.client</groupId>
-                       <artifactId>anr-xapp-client</artifactId>
-                       <version>0.0.8-SNAPSHOT</version>
+                       <groupId>org.o-ran-sc.ric.plt.appmgr.client</groupId>
+                       <artifactId>app-mgr-client</artifactId>
+                       <version>0.1.5-SNAPSHOT</version>
                </dependency>
                <dependency>
-                       <groupId>org.o-ran-sc.ric.e2mgr.client</groupId>
+                       <groupId>org.o-ran-sc.ric.plt.e2mgr.client</groupId>
                        <artifactId>e2-mgr-client</artifactId>
                        <version>20190620-SNAPSHOT</version>
                </dependency>
-               <dependency>
-                       <groupId>org.o-ran-sc.ric.xappmgr.client</groupId>
-                       <artifactId>xapp-mgr-client</artifactId>
-                       <version>0.1.4-SNAPSHOT</version>
-               </dependency>
                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-web</artifactId>
@@ -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;
@@ -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);
@@ -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: <blockquote>HTTP server received an invalid response from a
  * server it consulted when acting as a proxy or gateway.</blockquote>
  */
 @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 (file)
index 0000000..f4312ca
--- /dev/null
@@ -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 (file)
index 0000000..6cca83a
--- /dev/null
@@ -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<AppTransport> {
+
+       private static final long serialVersionUID = -928428052502491021L;
+
+}
index 5d8a611..35a2fa9 100644 (file)
@@ -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
index 2277bb7..db27f2c 100644 (file)
   <table mat-table [dataSource]="dataSource" matSort class="catalog-table mat-elevation-z8">
 
     <ng-container matColumnDef="name">
-      <mat-header-cell *matHeaderCellDef mat-sort-header> xApp Name </mat-header-cell>
+      <mat-header-cell *matHeaderCellDef mat-sort-header> App Name </mat-header-cell>
       <mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
     </ng-container>
 
     <ng-container matColumnDef="version">
-      <mat-header-cell *matHeaderCellDef mat-sort-header> xApp version </mat-header-cell>
+      <mat-header-cell *matHeaderCellDef mat-sort-header> Version </mat-header-cell>
       <mat-cell *matCellDef="let element"> {{element.version}} </mat-cell>
     </ng-container>
 
-    <ng-container matColumnDef="status">
-      <mat-header-cell *matHeaderCellDef mat-sort-header> Status </mat-header-cell>
-      <mat-cell *matCellDef="let element"> {{element.status}} </mat-cell>
-    </ng-container>
-
     <ng-container matColumnDef="action">
       <mat-header-cell *matHeaderCellDef> Action </mat-header-cell>
       <mat-cell *matCellDef="let element">
index 4bd360d..037b653 100644 (file)
@@ -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.
index 04b8380..a2e3cd1 100644 (file)
@@ -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
+}
index f6ae32d..e47abfd 100644 (file)
@@ -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<XMXapp> {
+export class CatalogDataSource extends DataSource<XMDeployableApp> {
 
-  private xAppsSubject = new BehaviorSubject<XMXapp[]>([]);
+  private xAppsSubject = new BehaviorSubject<XMDeployableApp[]>([]);
 
   private loadingSubject = new BehaviorSubject<boolean>(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<XMXapp[]> {
+  connect(collectionViewer: CollectionViewer): Observable<XMDeployableApp[]> {
     const dataMutations = [
       this.xAppsSubject.asObservable(),
       this.sort.sortChange
@@ -65,24 +65,23 @@ export class CatalogDataSource extends DataSource<XMXapp> {
     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);
+  }
+
 }
 
index 700efd9..cb41f19 100644 (file)
@@ -25,7 +25,7 @@
   <table mat-table [dataSource]="dataSource" matSort multiTemplateDataRows class="control-table mat-elevation-z8">
 
     <ng-container matColumnDef="xapp">
-      <mat-header-cell *matHeaderCellDef mat-sort-header> xApp Name </mat-header-cell>
+      <mat-header-cell *matHeaderCellDef mat-sort-header> App Name </mat-header-cell>
       <mat-cell *matCellDef="let element"> {{element.xapp}} </mat-cell>
     </ng-container>
 
index 8835946..4059d27 100644 (file)
@@ -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) {
index 60f8563..41d7ba4 100644 (file)
@@ -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<XappControlRow> {
 
@@ -45,18 +45,18 @@ export class ControlDataSource extends DataSource<XappControlRow> {
       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<XappControlRow[]> {
@@ -74,24 +74,22 @@ export class ControlDataSource extends DataSource<XappControlRow> {
     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<XappControlRow> {
 
 function compare(a, b, isAsc) {
   return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
-}
\ No newline at end of file
+}
@@ -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<string>;
 }
 
-export interface XMXapp {
+export interface XMDeployableApp {
+  name: string;
+  version: string;
+}
+
+export interface XMDeployedApp {
   name: string;
   status: string;
   version: string;
  */
 
 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();
   });
 });
 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<XMDeployableApp[]> {
+    return this.httpClient.get<XMDeployableApp[]>(this.basePath + '/list');
+  }
 
-  getAll(): Observable<XMXapp[]>{
-    return this.httpClient.get<XMXapp[]>(this.basePath)
+  getDeployed(): Observable<XMDeployedApp[]> {
+    return this.httpClient.get<XMDeployedApp[]>(this.basePath);
   }
 
   deployXapp(name: string) {