Add submodule for it/dev repository to access its OpenAPI spec.
Add xapp onboarder controller and basic tests.
Bump version to 2.1.0.
Change-Id: I14975e6765bffc15a9e3738ceb6aaa4c8a35c9f1
Issue-ID: OAM-108
Signed-off-by: Lott, Christopher (cl778h) <cl778h@att.com>
[submodule "dashboard/e2-mgr-client/ric-plt-e2mgr"]
path = dashboard/e2-mgr-client/ric-plt-e2mgr
url = ../../ric-plt/e2mgr
+[submodule "dashboard/xapp-obrd-client/it-dev"]
+ path = dashboard/xapp-obrd-client/it-dev
+ url = ../../it/dev
<parent>
<groupId>org.o-ran-sc.portal.ric-dashboard</groupId>
<artifactId>ric-dash-parent</artifactId>
- <version>2.0.3-SNAPSHOT</version>
+ <version>2.1.0-SNAPSHOT</version>
</parent>
<!-- This groupId will NOT allow deployment in LF -->
<groupId>org.o-ran-sc.ric-plt.appmgr.client</groupId>
<parent>
<groupId>org.o-ran-sc.portal.ric-dashboard</groupId>
<artifactId>ric-dash-parent</artifactId>
- <version>2.0.3-SNAPSHOT</version>
+ <version>2.1.0-SNAPSHOT</version>
</parent>
<!-- This groupId will NOT allow deployment in LF -->
<groupId>org.o-ran-sc.ric-plt.e2mgr.client</groupId>
<artifactId>ric-dash-parent</artifactId>
<name>RIC Dashboard Project</name>
<packaging>pom</packaging>
- <version>2.0.3-SNAPSHOT</version>
+ <version>2.1.0-SNAPSHOT</version>
<properties>
<java.version>11</java.version>
<!-- Properties for the license-maven-plugin in child POMs -->
<modules>
<module>app-mgr-client</module>
<module>e2-mgr-client</module>
+ <module>xapp-obrd-client</module>
<module>webapp-frontend</module>
<module>webapp-backend</module>
</modules>
<parent>
<groupId>org.o-ran-sc.portal.ric-dashboard</groupId>
<artifactId>ric-dash-parent</artifactId>
- <version>2.0.3-SNAPSHOT</version>
+ <version>2.1.0-SNAPSHOT</version>
</parent>
<!-- reuse parent groupId -->
<artifactId>ric-dash-be</artifactId>
<artifactId>e2-mgr-client</artifactId>
<version>4.4.4-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.o-ran-sc.it-dev.xapp-onboarder.client</groupId>
+ <artifactId>xapp-obrd-client</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.onap.portal.sdk</groupId>
<artifactId>epsdk-fw</artifactId>
import org.oransc.ric.portal.dashboard.controller.AppManagerController;
import org.oransc.ric.portal.dashboard.controller.E2ManagerController;
import org.oransc.ric.portal.dashboard.controller.SimpleErrorController;
+import org.oransc.ric.portal.dashboard.controller.XappOnboarderController;
import org.oransc.ric.portal.dashboard.portalapi.PortalAuthManager;
import org.oransc.ric.portal.dashboard.portalapi.PortalAuthenticationFilter;
import org.slf4j.Logger;
E2ManagerController.CONTROLLER_PATH + "/" + DashboardConstants.RIC_INSTANCE_KEY + "/*/"
+ E2ManagerController.HEALTH_METHOD, //
E2ManagerController.CONTROLLER_PATH + "/" + DashboardConstants.VERSION_METHOD, //
+ XappOnboarderController.CONTROLLER_PATH + "/" + DashboardConstants.VERSION_METHOD, //
+ XappOnboarderController.CONTROLLER_PATH + "/" + DashboardConstants.RIC_INSTANCE_KEY + "/*/"
+ + XappOnboarderController.HEALTH_METHOD, //
SimpleErrorController.ERROR_PATH };
@Override
--- /dev/null
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2020 AT&T Intellectual Property
+ * %%
+ * 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.config;
+
+import java.lang.invoke.MethodHandles;
+
+import org.oransc.itdev.xapponboarder.client.api.ChartsApi;
+import org.oransc.itdev.xapponboarder.client.api.HealthApi;
+import org.oransc.itdev.xapponboarder.client.api.OnboardApi;
+import org.oransc.itdev.xapponboarder.client.invoker.ApiClient;
+import org.oransc.ric.portal.dashboard.model.RicInstance;
+import org.oransc.ric.portal.dashboard.model.RicRegionList;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.DefaultUriBuilderFactory;
+
+/**
+ * The OpenAPI generated API client code using Spring RestTemplate is not thread
+ * safe according to https://github.com/swagger-api/swagger-codegen/issues/9222
+ *
+ * As a workaround this builder creates a new client at every request. If this
+ * proves to be too slow then clients could be cached for each thread.
+ */
+public class XappOnboarderApiBuilder {
+
+ private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ private final String urlSuffix;
+ private final RicRegionList instanceConfig;
+
+ public XappOnboarderApiBuilder(final RicRegionList instanceConfig, final String urlSuffix) {
+ logger.debug("ctor: suffix {}", urlSuffix);
+ this.instanceConfig = instanceConfig;
+ this.urlSuffix = urlSuffix;
+ }
+
+ private ApiClient apiClient(String instanceKey) {
+ RicInstance instance = instanceConfig.getInstance(instanceKey);
+ String url = new DefaultUriBuilderFactory(instance.getPltUrlPrefix().trim()).builder()
+ .path(this.urlSuffix.trim()).build().normalize().toString();
+ logger.debug("apiClient URL {}", url);
+ return new ApiClient(new RestTemplate()).setBasePath(url);
+ }
+
+ public HealthApi getHealthApi(String instanceKey) {
+ return new HealthApi(apiClient(instanceKey));
+ }
+
+ public ChartsApi getChartsApi(String instanceKey) {
+ return new ChartsApi(apiClient(instanceKey));
+ }
+
+ public OnboardApi getOnboardApi(String instanceKey) {
+ return new OnboardApi(apiClient(instanceKey));
+ }
+
+}
--- /dev/null
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2020 AT&T Intellectual Property
+ * %%
+ * 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.config;
+
+import java.lang.invoke.MethodHandles;
+
+import org.oransc.ric.portal.dashboard.model.RicRegionList;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+/**
+ * Creates an Xapp onboarder client builder as a bean to be managed by the
+ * Spring container.
+ */
+@Configuration
+@Profile("!test")
+public class XappOnboarderConfiguration {
+
+ private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ // Populated by the autowired constructor
+ private final String urlSuffix;
+ private final RicRegionList instanceConfig;
+
+ @Autowired
+ public XappOnboarderConfiguration(@Value("${xappobrd.url.suffix}") final String urlSuffix,
+ final RicRegionList instanceConfig) {
+ logger.debug("ctor: URL suffix {}", urlSuffix);
+ this.urlSuffix = urlSuffix;
+ this.instanceConfig = instanceConfig;
+ }
+
+ @Bean
+ // The bean (method) name must be globally unique
+ public XappOnboarderApiBuilder xappOnboarderApiBuilder() {
+ return new XappOnboarderApiBuilder(instanceConfig, urlSuffix);
+ }
+
+}
--- /dev/null
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2020 AT&T Intellectual Property
+ * %%
+ * 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.controller;
+
+import java.lang.invoke.MethodHandles;
+
+import org.oransc.itdev.xapponboarder.client.api.HealthApi;
+import org.oransc.itdev.xapponboarder.client.model.Descriptor;
+import org.oransc.itdev.xapponboarder.client.model.DescriptorRemote;
+import org.oransc.itdev.xapponboarder.client.model.Status;
+import org.oransc.ric.portal.dashboard.DashboardApplication;
+import org.oransc.ric.portal.dashboard.DashboardConstants;
+import org.oransc.ric.portal.dashboard.config.XappOnboarderApiBuilder;
+import org.oransc.ric.portal.dashboard.model.SuccessTransport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.annotation.Secured;
+import org.springframework.util.Assert;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import io.swagger.annotations.ApiOperation;
+
+/**
+ * Proxies calls from the front end to the Xapp Onboarder API.
+ *
+ * If a method throws RestClientResponseException, it is handled by a method in
+ * {@link CustomResponseEntityExceptionHandler} which returns status 502. All
+ * other exceptions are handled by Spring which returns status 500.
+ */
+@Configuration
+@RestController
+@RequestMapping(value = XappOnboarderController.CONTROLLER_PATH, produces = MediaType.APPLICATION_JSON_VALUE)
+public class XappOnboarderController {
+
+ private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ // Publish paths in constants for tests
+ public static final String CONTROLLER_PATH = DashboardConstants.ENDPOINT_PREFIX + "/xappobrd";
+ // Dashboard only
+ public static final String HEALTH_METHOD = "health";
+ public static final String CHARTS_METHOD = "charts";
+ public static final String ONBOARD_METHOD = "onboard";
+ public static final String ONBOARD_DOWNLOAD_METHOD = "onboard/download";
+ // Path component, not a method nor a path parameter
+ public static final String VALUESYAML = "values.yaml";
+ // Path parameters
+ public static final String XAPPNAME_PP = "xapp";
+ public static final String VERSION_PP = "ver";
+
+ // Populated by the autowired constructor
+ private final XappOnboarderApiBuilder xappOnboarderApiBuilder;
+
+ @Autowired
+ public XappOnboarderController(final XappOnboarderApiBuilder xappOnboarderApiBuilder) {
+ Assert.notNull(xappOnboarderApiBuilder, "builder must not be null");
+ this.xappOnboarderApiBuilder = xappOnboarderApiBuilder;
+ if (logger.isDebugEnabled())
+ logger.debug("ctor: configured with builder type {}", xappOnboarderApiBuilder.getClass().getName());
+ }
+
+ @ApiOperation(value = "Gets the xapp onboarder client library MANIFEST.MF property Implementation-Version.", response = SuccessTransport.class)
+ @GetMapping(DashboardConstants.VERSION_METHOD)
+ // No role required
+ public SuccessTransport getClientVersion() {
+ return new SuccessTransport(200, DashboardApplication.getImplementationVersion(HealthApi.class));
+ }
+
+ @ApiOperation(value = "Gets the health from the xapp onboarder, expressed as the response code.")
+ @GetMapping(DashboardConstants.RIC_INSTANCE_KEY + "/{" + DashboardConstants.RIC_INSTANCE_KEY + "}/" + HEALTH_METHOD)
+ // No role required
+ public ResponseEntity<Status> getHealthCheck(
+ @PathVariable(DashboardConstants.RIC_INSTANCE_KEY) String instanceKey) {
+ logger.debug("getHealthCheck instance {}", instanceKey);
+ HealthApi api = xappOnboarderApiBuilder.getHealthApi(instanceKey);
+ Status status = api.getHealthCheck();
+ return ResponseEntity.status(api.getApiClient().getStatusCode().value()).body(status);
+ }
+
+ @ApiOperation(value = "Gets the helm charts.", response = String.class)
+ @GetMapping(DashboardConstants.RIC_INSTANCE_KEY + "/{" + DashboardConstants.RIC_INSTANCE_KEY + "}/" + CHARTS_METHOD)
+ @Secured({ DashboardConstants.ROLE_ADMIN, DashboardConstants.ROLE_STANDARD })
+ public Object getCharts(@PathVariable(DashboardConstants.RIC_INSTANCE_KEY) String instanceKey) {
+ logger.debug("getCharts instance {}", instanceKey);
+ return xappOnboarderApiBuilder.getChartsApi(instanceKey).getChartsList();
+ }
+
+ @ApiOperation(value = "Gets the helm chart for the specified xApp and version.", response = String.class)
+ @GetMapping(DashboardConstants.RIC_INSTANCE_KEY + "/{" + DashboardConstants.RIC_INSTANCE_KEY + "}/" + CHARTS_METHOD
+ + "/" + XAPPNAME_PP + "/{" + XAPPNAME_PP + "}/" + VERSION_PP + "/{" + VERSION_PP + "}")
+ @Secured({ DashboardConstants.ROLE_ADMIN, DashboardConstants.ROLE_STANDARD })
+ public Object getChart(@PathVariable(DashboardConstants.RIC_INSTANCE_KEY) String instanceKey,
+ @PathVariable(XAPPNAME_PP) String xappName, @PathVariable(VERSION_PP) String version) {
+ logger.debug("getChart instance {} xapp {} ver {}", instanceKey, xappName, version);
+ return xappOnboarderApiBuilder.getChartsApi(instanceKey).getChartsFetcher(xappName, version);
+ }
+
+ @ApiOperation(value = "Gets the values yaml for the specified xApp and version.", response = String.class)
+ @GetMapping(DashboardConstants.RIC_INSTANCE_KEY + "/{" + DashboardConstants.RIC_INSTANCE_KEY + "}/" + CHARTS_METHOD
+ + "/" + XAPPNAME_PP + "/{" + XAPPNAME_PP + "}/" + VERSION_PP + "/{" + VERSION_PP + "}/" + VALUESYAML)
+ @Secured({ DashboardConstants.ROLE_ADMIN, DashboardConstants.ROLE_STANDARD })
+ public Object getValues(@PathVariable(DashboardConstants.RIC_INSTANCE_KEY) String instanceKey,
+ @PathVariable(XAPPNAME_PP) String xappName, @PathVariable(VERSION_PP) String version) {
+ logger.debug("getValues instance {} xapp {} ver {}", instanceKey, xappName, version);
+ return xappOnboarderApiBuilder.getChartsApi(instanceKey).getValuesYamlFetcher(xappName, version);
+ }
+
+ @ApiOperation(value = "Onboard xApp using the xApp descriptor and schema in the request body.", response = Status.class)
+ @PostMapping(DashboardConstants.RIC_INSTANCE_KEY + "/{" + DashboardConstants.RIC_INSTANCE_KEY + "}/"
+ + ONBOARD_METHOD)
+ @Secured({ DashboardConstants.ROLE_ADMIN })
+ public Status onboardXapp(@PathVariable(DashboardConstants.RIC_INSTANCE_KEY) String instanceKey, //
+ @Validated @RequestBody Descriptor appDescriptor) {
+ logger.debug("onboardxApp instance {} descriptor {}", instanceKey, appDescriptor);
+ return xappOnboarderApiBuilder.getOnboardApi(instanceKey).postOnboardxApps(appDescriptor);
+ }
+
+ @ApiOperation(value = "Onboard xApp after downloading the xApp descriptor and schema from the URLs.", response = Status.class)
+ @PostMapping(DashboardConstants.RIC_INSTANCE_KEY + "/{" + DashboardConstants.RIC_INSTANCE_KEY + "}/"
+ + ONBOARD_DOWNLOAD_METHOD)
+ @Secured({ DashboardConstants.ROLE_ADMIN })
+ public Status onboardRemoteXapp(@PathVariable(DashboardConstants.RIC_INSTANCE_KEY) String instanceKey, //
+ @Validated @RequestBody DescriptorRemote appDescriptor) {
+ logger.debug("onboardRemoteXapp instance {} descriptor {}", instanceKey, appDescriptor);
+ return xappOnboarderApiBuilder.getOnboardApi(instanceKey).postOnboardxAppsDownload(appDescriptor);
+ }
+
+}
# uses pltUrlPrefix
suffix: /e2mgr/v1
+# Xapp Onboarder
+xappobrd:
+ url:
+ # uses pltUrlPrefix
+ suffix: /xappobrd/api/v1
+
# Kubernetes API via https://github.com/nokia/caas-ingress
caasingress:
# Set insecure=true to disable SSL certificate and hostname checking
--- /dev/null
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2020 AT&T Intellectual Property
+ * %%
+ * 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.config;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+
+import org.oransc.itdev.xapponboarder.client.api.ChartsApi;
+import org.oransc.itdev.xapponboarder.client.api.HealthApi;
+import org.oransc.itdev.xapponboarder.client.api.OnboardApi;
+import org.oransc.itdev.xapponboarder.client.invoker.ApiClient;
+import org.oransc.itdev.xapponboarder.client.model.Descriptor;
+import org.oransc.itdev.xapponboarder.client.model.DescriptorRemote;
+import org.oransc.itdev.xapponboarder.client.model.Status;
+import org.oransc.ric.portal.dashboard.TestUtils;
+import org.oransc.ric.portal.dashboard.model.RicRegionList;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.http.HttpStatus;
+
+/**
+ * Creates a mock implementation of the Xapp Onboarder client API.
+ */
+@Configuration
+@Profile("test")
+public class XappOnboarderMockConfiguration {
+
+ private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ // Simulate remote method delay for UI testing
+ private int delayMs;
+
+ // Autowire all the properties required by the real class
+ // (even tho not used here) as a test of the properties.
+ @Autowired
+ public XappOnboarderMockConfiguration(@Value("${xappobrd.url.suffix}") final String urlSuffix, //
+ final RicRegionList instanceConfig, //
+ @Value("${mock.config.delay:0}") int delayMs) {
+ logger.info("ctor: configured with suffix {}, instances {}, delay {}", urlSuffix, instanceConfig, delayMs);
+ this.delayMs = delayMs;
+ }
+
+ private ApiClient apiClient() {
+ ApiClient mockClient = mock(ApiClient.class);
+ when(mockClient.getStatusCode()).thenReturn(HttpStatus.OK);
+ return mockClient;
+ }
+
+ private HealthApi healthApi() {
+ ApiClient apiClient = apiClient();
+ HealthApi mockApi = mock(HealthApi.class);
+ when(mockApi.getApiClient()).thenReturn(apiClient);
+ doAnswer(i -> {
+ return new Status().status("OK");
+ }).when(mockApi).getHealthCheck();
+ return mockApi;
+ }
+
+ private ChartsApi chartsApi() throws IOException {
+ final String sampleChartListJson = TestUtils.readDataFromPath("sample-chart-list.json");
+ final String sampleChartYaml = TestUtils.readDataFromPath("sample-chart.yaml");
+ final String sampleValuesYaml = TestUtils.readDataFromPath("sample-values.yaml");
+ ApiClient apiClient = apiClient();
+ ChartsApi mockApi = mock(ChartsApi.class);
+ when(mockApi.getApiClient()).thenReturn(apiClient);
+ doAnswer(inv -> {
+ if (delayMs > 0) {
+ logger.debug("getChartsList sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ }
+ return sampleChartListJson;
+ }).when(mockApi).getChartsList();
+ doAnswer(inv -> {
+ if (delayMs > 0) {
+ logger.debug("getChartsFetcher sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ }
+ return sampleChartYaml;
+ }).when(mockApi).getChartsFetcher(any(String.class), any(String.class));
+ doAnswer(inv -> {
+ if (delayMs > 0) {
+ logger.debug("getValuesYamlFetcher sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ }
+ return sampleValuesYaml;
+ }).when(mockApi).getValuesYamlFetcher(any(String.class), any(String.class));
+ return mockApi;
+ }
+
+ private OnboardApi onboardApi() {
+ ApiClient apiClient = apiClient();
+ OnboardApi mockApi = mock(OnboardApi.class);
+ when(mockApi.getApiClient()).thenReturn(apiClient);
+ doAnswer(inv -> {
+ if (delayMs > 0) {
+ logger.debug("postOnboardxApps sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ }
+ return new Status().status("OK");
+ }).when(mockApi).postOnboardxApps(any(Descriptor.class));
+ doAnswer(inv -> {
+ if (delayMs > 0) {
+ logger.debug("postOnboardxAppsDownload sleeping {}", delayMs);
+ Thread.sleep(delayMs);
+ }
+ return new Status().status("OK");
+ }).when(mockApi).postOnboardxAppsDownload(any(DescriptorRemote.class));
+ return mockApi;
+ }
+
+ @Bean
+ // Must use the same name as the non-mock configuration
+ public XappOnboarderApiBuilder xappOnboarderApiBuilder() throws IOException {
+ final XappOnboarderApiBuilder mockBuilder = mock(XappOnboarderApiBuilder.class);
+ final HealthApi mockHealthApi = healthApi();
+ when(mockBuilder.getHealthApi(any(String.class))).thenReturn(mockHealthApi);
+ final ChartsApi mockChartsApi = chartsApi();
+ when(mockBuilder.getChartsApi(any(String.class))).thenReturn(mockChartsApi);
+ final OnboardApi mockOnboardApi = onboardApi();
+ when(mockBuilder.getOnboardApi(any(String.class))).thenReturn(mockOnboardApi);
+ return mockBuilder;
+ }
+
+}
--- /dev/null
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2020 AT&T Intellectual Property
+ * %%
+ * 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.config.test;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.oransc.itdev.xapponboarder.client.api.ChartsApi;
+import org.oransc.itdev.xapponboarder.client.api.HealthApi;
+import org.oransc.ric.portal.dashboard.config.RICInstanceMockConfiguration;
+import org.oransc.ric.portal.dashboard.config.XappOnboarderApiBuilder;
+
+public class XappOnboarderConfigTest extends AbstractConfigTest {
+
+ @Test
+ public void builderTest() {
+ XappOnboarderApiBuilder builder = new XappOnboarderApiBuilder(instanceConfig, "suffix");
+ HealthApi healthApi = builder.getHealthApi(RICInstanceMockConfiguration.INSTANCE_KEY_1);
+ Assertions.assertNotNull(healthApi);
+ ChartsApi chartsApi = builder.getChartsApi(RICInstanceMockConfiguration.INSTANCE_KEY_1);
+ Assertions.assertNotNull(chartsApi);
+ }
+
+}
--- /dev/null
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2020 AT&T Intellectual Property
+ * %%
+ * 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.controller;
+
+import java.lang.invoke.MethodHandles;
+import java.net.URI;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.oransc.itdev.xapponboarder.client.model.Config;
+import org.oransc.itdev.xapponboarder.client.model.Descriptor;
+import org.oransc.itdev.xapponboarder.client.model.DescriptorRemote;
+import org.oransc.itdev.xapponboarder.client.model.Status;
+import org.oransc.ric.portal.dashboard.DashboardConstants;
+import org.oransc.ric.portal.dashboard.config.RICInstanceMockConfiguration;
+import org.oransc.ric.portal.dashboard.model.SuccessTransport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+
+public class XappOnboarderControllerTest extends AbstractControllerTest {
+
+ private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ @Test
+ public void versionTest() {
+ URI uri = buildUri(null, XappOnboarderController.CONTROLLER_PATH, DashboardConstants.VERSION_METHOD);
+ logger.info("Invoking {}", uri);
+ SuccessTransport st = restTemplate.getForObject(uri, SuccessTransport.class);
+ Assertions.assertFalse(st.getData().toString().isEmpty());
+ }
+
+ @Test
+ public void healthTest() {
+ URI uri = buildUri(null, XappOnboarderController.CONTROLLER_PATH, DashboardConstants.RIC_INSTANCE_KEY,
+ RICInstanceMockConfiguration.INSTANCE_KEY_1, XappOnboarderController.HEALTH_METHOD);
+ logger.info("Invoking {}", uri);
+ ResponseEntity<Void> voidResponse = restTemplate.getForEntity(uri, Void.class);
+ Assertions.assertTrue(voidResponse.getStatusCode().is2xxSuccessful());
+ }
+
+ @Test
+ public void getAllChartsTest() {
+ URI uri = buildUri(null, XappOnboarderController.CONTROLLER_PATH, DashboardConstants.RIC_INSTANCE_KEY,
+ RICInstanceMockConfiguration.INSTANCE_KEY_1, XappOnboarderController.CHARTS_METHOD);
+ logger.info("Invoking {}", uri);
+ ResponseEntity<String> response = testRestTemplateStandardRole().exchange(uri, HttpMethod.GET, null,
+ new ParameterizedTypeReference<String>() {
+ });
+ Assertions.assertFalse(response.getBody().isEmpty());
+ }
+
+ @Test
+ public void getOneChartTest() {
+ URI uri = buildUri(null, XappOnboarderController.CONTROLLER_PATH, DashboardConstants.RIC_INSTANCE_KEY,
+ RICInstanceMockConfiguration.INSTANCE_KEY_1, XappOnboarderController.CHARTS_METHOD,
+ XappOnboarderController.XAPPNAME_PP, "xapp", XappOnboarderController.VERSION_PP, "v1");
+ logger.info("Invoking {}", uri);
+ ResponseEntity<String> response = testRestTemplateStandardRole().exchange(uri, HttpMethod.GET, null,
+ new ParameterizedTypeReference<String>() {
+ });
+ Assertions.assertFalse(response.getBody().isEmpty());
+ }
+
+ @Test
+ public void getOneValuesTest() {
+ URI uri = buildUri(null, XappOnboarderController.CONTROLLER_PATH, DashboardConstants.RIC_INSTANCE_KEY,
+ RICInstanceMockConfiguration.INSTANCE_KEY_1, XappOnboarderController.CHARTS_METHOD,
+ XappOnboarderController.XAPPNAME_PP, "xapp", XappOnboarderController.VERSION_PP, "v1",
+ XappOnboarderController.VALUESYAML);
+ logger.info("Invoking {}", uri);
+ ResponseEntity<String> response = testRestTemplateStandardRole().exchange(uri, HttpMethod.GET, null,
+ new ParameterizedTypeReference<String>() {
+ });
+ Assertions.assertFalse(response.getBody().isEmpty());
+ }
+
+ @Test
+ public void onboardXappByBodyTest() {
+ URI uri = buildUri(null, XappOnboarderController.CONTROLLER_PATH, DashboardConstants.RIC_INSTANCE_KEY,
+ RICInstanceMockConfiguration.INSTANCE_KEY_1, XappOnboarderController.ONBOARD_METHOD);
+ logger.info("Invoking {}", uri);
+ Config configFileJson = new Config().xappName("name").version("1.0.0");
+ Descriptor descr = new Descriptor().configFileJson(configFileJson).controlsSchemaJson("{}");
+ Status status = testRestTemplateAdminRole().postForObject(uri, descr, Status.class);
+ Assertions.assertNotNull(status);
+ Assertions.assertNotNull(status.getStatus());
+ }
+
+ @Test
+ public void onboardXappByUrlTest() {
+ URI uri = buildUri(null, XappOnboarderController.CONTROLLER_PATH, DashboardConstants.RIC_INSTANCE_KEY,
+ RICInstanceMockConfiguration.INSTANCE_KEY_1, XappOnboarderController.ONBOARD_DOWNLOAD_METHOD);
+ logger.info("Invoking {}", uri);
+ DescriptorRemote descr = new DescriptorRemote().configFileJsonUrl("url1").configFileJsonUrl("url2");
+ Status status = testRestTemplateAdminRole().postForObject(uri, descr, Status.class);
+ Assertions.assertNotNull(status);
+ Assertions.assertNotNull(status.getStatus());
+ }
+
+}
--- /dev/null
+{
+ "anr": [
+ {
+ "name": "anr",
+ "version": "1.0.0",
+ "description": "Standard xApp Helm Chart",
+ "apiVersion": "v1",
+ "appVersion": "1.0",
+ "urls": [
+ "charts/anr-1.0.0.tgz"
+ ],
+ "created": "2020-06-15T14:57:25.238326423Z",
+ "digest": "d83cf464479e59999917b67305db04480c6c573b1812b8095547705d9e2ce2a1"
+ }
+ ],
+ "mcxapp": [
+ {
+ "name": "mcxapp",
+ "version": "1.0.7",
+ "description": "Standard xApp Helm Chart",
+ "apiVersion": "v1",
+ "appVersion": "1.0",
+ "urls": [
+ "charts/mcxapp-1.0.7.tgz"
+ ],
+ "created": "2020-06-15T14:59:25.734253163Z",
+ "digest": "06a0a194238b505b83e95b2d2637b26335a799f60fe3d04fde0450f98d67a782"
+ }
+ ]
+}
--- /dev/null
+################################################################################
+# Copyright (c) 2019 AT&T Intellectual Property. #
+# #
+# 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. #
+################################################################################
+apiVersion: v1
+appVersion: "1.0"
+description: Standard xApp Helm Chart
+name: xapp-std
+version: 0.0.1
--- /dev/null
+################################################################################
+# Copyright (c) 2019 AT&T Intellectual Property. #
+# #
+# 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. #
+################################################################################'
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+
+# Location of the xApp config files injected from the xApp descriptor
+appconfig:
+ path: /opt/ric/config
+
+# Number of replica
+replicaCount: 1
+
+# Image pulling policy
+image_pull_policy: IfNotPresent
+
+# Environment variables that will be injected
+appenv: {}
+
+# Liveness probe definition. If empty, liveness probe will be disabled
+livenessProbe: {}
+
+# Readiness probe definition. If empty, readiness probe will be disabled
+readinessProbe: {}
+
+# Instance name. If empty, chart name will be used
+name: {}
+
+# Full instance name. If empty, full name will be constructed from name
+fullname: {}
+############### The following are from the xApp descriptor ###############
+
+
+
"integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
"dev": true
},
+ "bindings": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+ "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "file-uri-to-path": "1.0.0"
+ }
+ },
"blob": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
"schema-utils": "^2.6.5"
}
},
+ "file-uri-to-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+ "dev": true,
+ "optional": true
+ },
"fileset": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz",
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
"dev": true
},
+ "nan": {
+ "version": "2.14.1",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz",
+ "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==",
+ "dev": true,
+ "optional": true
+ },
"nanomatch": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
"integrity": "sha512-zEKehHdCK8E/k4Y0HepprGdYBHr2AOsaq4QpeqoCyUElOOC5M3qi3ZEHV1VF54I7heBQktswwXe5UyWduJ0Xeg=="
},
"ngx-toastr": {
- "version": "12.0.0",
- "resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-12.0.0.tgz",
- "integrity": "sha512-J0mvGXH9cLlP3acoLJcuYhsQcL+EOAtkS1Y5tFKzrw2TYqY2HNffMVPvK+KP1LDJHiIgRpYg3ZELw1raAl0R/A=="
+ "version": "12.1.0",
+ "resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-12.1.0.tgz",
+ "integrity": "sha512-rytCRBhvuudj614Kfj9GoIVQDrFuLvHSMP1YrMwTmR1SNkNJZOpGKmaSDCCBrNDkSrGouzMWBlFbl1UDBBsiqw==",
+ "requires": {
+ "tslib": "^1.10.0"
+ }
},
"nice-try": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1"
+ }
}
}
},
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1"
+ }
},
"is-absolute-url": {
"version": "3.0.3",
<parent>
<groupId>org.o-ran-sc.portal.ric-dashboard</groupId>
<artifactId>ric-dash-parent</artifactId>
- <version>2.0.3-SNAPSHOT</version>
+ <version>2.1.0-SNAPSHOT</version>
</parent>
<!-- reuse parent groupId -->
<artifactId>ric-dash-fe</artifactId>
--- /dev/null
+# Xapp Onboarder Client Generator
+
+This project generates a REST client library from the OpenAPI specification
+file obtained from the it/dev xapp_onboarder project, available here as a git
+submodule with a pinned version, and packages it in a jar.
+
+## Eclipse and STS Users
+
+The source folder should be generated automatically by the Swagger Codegen maven
+plugin and should also appear on the build path in Eclipse/STS, but if not,
+follow these steps:
+
+1. Generate the code using maven:
+ mvn install
+2. Add this folder to the project build path:
+ target/generated-sources/swagger/src/main/java
+
+## License
+
+Copyright (C) 2020 AT&T Intellectual Property & Nokia. 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.
--- /dev/null
+Subproject commit 9945133851dad8f533adcc331b33aca451b0decc
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--<![CDATA[
+========================LICENSE_START=================================
+O-RAN-SC
+%%
+Copyright (C) 2020 AT&T Intellectual Property
+%%
+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===================================
+]]>-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.o-ran-sc.portal.ric-dashboard</groupId>
+ <artifactId>ric-dash-parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ </parent>
+ <!-- This groupId will NOT allow deployment in LF -->
+ <groupId>org.o-ran-sc.it-dev.xapp-onboarder.client</groupId>
+ <artifactId>xapp-obrd-client</artifactId>
+ <name>RIC Xapp Onboarder Client</name>
+ <!-- Update to match submodule tag -->
+ <version>1.0.0-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.itdev.xapponboarder.client</client.base.package.name>
+ </properties>
+ <!-- Successful compilation requires generated code dependencies -->
+ <dependencies>
+ <!-- Required for Java 9 and later -->
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.swagger.core.v3</groupId>
+ <artifactId>swagger-annotations</artifactId>
+ <version>2.0.8</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ </dependency>
+ <!-- HTTP client: Spring RestTemplate -->
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ </dependency>
+ <!-- JSON processing: jackson -->
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.jaxrs</groupId>
+ <artifactId>jackson-jaxrs-json-provider</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.datatype</groupId>
+ <artifactId>jackson-datatype-jsr310</artifactId>
+ </dependency>
+ <!-- test dependencies -->
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <!-- This 2019 version is required for OpenAPI 3 -->
+ <groupId>io.swagger.codegen.v3</groupId>
+ <artifactId>swagger-codegen-maven-plugin</artifactId>
+ <version>3.0.8</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ <configuration>
+ <inputSpec>${project.basedir}/it-dev/xapp_onboarder/xapp_onboarder/xapp-onboarder-api.yaml</inputSpec>
+ <language>java</language>
+ <configOptions>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>${project.artifactId}</artifactId>
+ <artifactVersion>${project.version}</artifactVersion>
+ <library>resttemplate</library>
+ <java8>true</java8>
+ <dateLibrary>java8</dateLibrary>
+ <licenseName>Apache 2.0</licenseName>
+ <licenseUrl>https://www.apache.org/licenses/LICENSE-2.0</licenseUrl>
+ </configOptions>
+ <packageName>${client.base.package.name}</packageName>
+ <modelPackage>${client.base.package.name}.model</modelPackage>
+ <apiPackage>${client.base.package.name}.api</apiPackage>
+ <invokerPackage>${client.base.package.name}.invoker</invokerPackage>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <!-- add build information to manifest. Java provides access to the implementation
+ version for a package, so cram the build number into there. -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <!-- version>2.5</version> -->
+ <configuration>
+ <archive>
+ <manifest>
+ <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+ </manifest>
+ <manifestEntries>
+ <Implementation-Version>${project.version}-b${build.number}</Implementation-Version>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </plugin>
+ <!-- Add generated source folder to Eclipse build path -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <!-- version>1.7</version> -->
+ <executions>
+ <execution>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>add-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>target/generated-sources/swagger/src/main/java</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <!--This plugin's configuration is used to store Eclipse m2e settings
+ only. It has no influence on the Maven build itself. -->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>io.swagger</groupId>
+ <artifactId>swagger-codegen-maven-plugin</artifactId>
+ <versionRange>[1.0,)</versionRange>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore />
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
--- /dev/null
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2020 AT&T Intellectual Property
+ * %%
+ * 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.xappobrd.client.test;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.oransc.itdev.xapponboarder.client.api.HealthApi;
+import org.oransc.itdev.xapponboarder.client.invoker.ApiClient;
+import org.springframework.web.client.RestClientException;
+
+/**
+ * Demonstrates use of the generated xapp onboarder client.
+ *
+ * The get fails because no server is available.
+ */
+public class XappOnboarderClientTest {
+
+ @Test
+ public void demo() {
+ ApiClient apiClient = new ApiClient();
+ apiClient.setBasePath("http://localhost:30099/");
+ HealthApi healthApi = new HealthApi(apiClient);
+ try {
+ healthApi.getHealthCheck();
+ System.out.println("getHealthCheck answered: " + apiClient.getStatusCode().toString());
+ Assertions.assertTrue(apiClient.getStatusCode().is2xxSuccessful());
+ } catch (RestClientException e) {
+ System.err.println("getHealthCheck failed: " + e.toString());
+ }
+ }
+}
``appmgr.url.suffix``
-Application Manager URL suffix. Default is ``/ric/v1``.
+Application Manager URL suffix. Default is ``/appmgr/ric/v1``.
``caasingress.aux.url.suffix``
``e2mgr.url.suffix``
-E2 Manager URL suffix. Default is ``/v1``.
+E2 Manager URL suffix. Default is ``/e2mgr/v1``.
``portalapi.appname``
Path of file that stores user details. Default is
``dashboard-users.json``.
+``xappobrd.url.suffix``
+
+Xapp Onboarder URL suffix. Default is ``/xapporbd/api/v1``.
Key Properties
^^^^^^^^^^^^^^
RIC Dashboard Release Notes
===========================
+Version 2.1.0, 8 Jun 2020
+--------------------------
+* Add Xapp Onboarder client to backend (`OAM-108 <https://jira.o-ran-sc.org/browse/OAM-108>`_)
+
Version 2.0.3, 3 Jun 2020
--------------------------
* Validate request bodies in backend REST controller methods