From 78fb8f4c474afd642751ab70e7609a6a5c2e221d Mon Sep 17 00:00:00 2001 From: PatrikBuhr Date: Tue, 26 Jan 2021 13:11:48 +0100 Subject: [PATCH] Uplift from master Needed du to EIS API changes Signed-off-by: PatrikBuhr Issue-ID: NONRTRIC-385 Change-Id: I694eebfe5a59d46923ffea860880acfe5dc81165 --- ...ocker-release-portal-nonrtric-controlpanel.yaml | 2 +- docs/release-notes.rst | 22 +++ pom.xml | 121 ++++++++-------- webapp-backend/pom.xml | 38 +++--- .../controller/EnrichmentController.java | 39 +++--- .../controlpanel/eiproducerapi/EiProducerApi.java | 11 +- .../eiproducerapi/EiProducerApiImpl.java | 28 +++- .../model/ProducerRegistrationInfo.java | 64 +++++++++ .../controlpanel/model/ProducerStatusInfo.java | 45 ++++++ .../controlpanel/util/JsonArrayHandler.java | 24 ++++ .../portal/nonrtric/controlpanel/RestApiTest.java | 23 +--- .../eiproducerapi/EiProducerApiImplTest.java | 61 +++++---- .../EnrichmentControllerMockConfiguration.java | 81 ++++++----- webapp-frontend/pom.xml | 152 ++++++++++----------- 14 files changed, 443 insertions(+), 268 deletions(-) create mode 100644 webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/model/ProducerRegistrationInfo.java create mode 100644 webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/model/ProducerStatusInfo.java create mode 100644 webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/util/JsonArrayHandler.java diff --git a/.releases/docker-release-portal-nonrtric-controlpanel.yaml b/.releases/docker-release-portal-nonrtric-controlpanel.yaml index 39ec485..3fb32b4 100644 --- a/.releases/docker-release-portal-nonrtric-controlpanel.yaml +++ b/.releases/docker-release-portal-nonrtric-controlpanel.yaml @@ -7,4 +7,4 @@ project: portal ref: 9d99a37374c9266f3d11ff0a19c2d068571159ba containers: - name: nonrtric-controlpanel - version: 2.1.0 + version: 2.1.1 diff --git a/docs/release-notes.rst b/docs/release-notes.rst index 7e1c490..79b4876 100644 --- a/docs/release-notes.rst +++ b/docs/release-notes.rst @@ -30,6 +30,9 @@ Version history | 2020-12-03 | 2.1.0 | Henrik Andersson | Cherry Release | | | | | | +------------+----------+------------------+----------------+ +| 2021-01-26 | 2.1.1 | Patrik Buhr | Cherry Release | +| | | | maintenance | ++------------+----------+------------------+----------------+ Release Data ============ @@ -72,4 +75,23 @@ Cherry | | | +-----------------------------+----------------------------------------------------------------+ +Cherry +------ ++-----------------------------+----------------------------------------------------------------+ +| **Project** | Non-RT RIC Control Panel | +| | | ++-----------------------------+----------------------------------------------------------------+ +| **Repo/commit-ID** | nonrtric-controlpanel/e79f1251a9bd970816de91c8272025d6264154bd | +| | | ++-----------------------------+----------------------------------------------------------------+ +| **Release designation** | Cherry | +| | | ++-----------------------------+----------------------------------------------------------------+ +| **Release date** | 2021-01-26 | +| | | ++-----------------------------+----------------------------------------------------------------+ +| **Purpose of the delivery** | Updated API to the Enrichment Controller Service | +| | | ++-----------------------------+----------------------------------------------------------------+ + Fully supported in Firefox and Chrome. Minor issues in Safari. Not supported in Microsoft Edge and IE. diff --git a/pom.xml b/pom.xml index 520f46f..f19f20d 100644 --- a/pom.xml +++ b/pom.xml @@ -22,64 +22,65 @@ limitations under the License. - 4.0.0 - - - org.springframework.boot - spring-boot-starter-parent - 2.3.4.RELEASE - - - org.o-ran-sc.portal.nonrtric.controlpanel - nonrtric-controlpanel-parent - Non-RT RIC Control Panel project - pom - 2.1.0-SNAPSHOT - - 11 + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 2.3.4.RELEASE + + + + org.o-ran-sc.portal.nonrtric.controlpanel + nonrtric-controlpanel-parent + Non-RT RIC Control Panel project + pom + 2.1.1-SNAPSHOT + + 11 3.7.0.1746 - - - webapp-frontend - webapp-backend - - - - - org.apache.maven.plugins - maven-compiler-plugin - - ${java.version} - ${java.version} - - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - - jar - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - - org.sonarsource.scanner.maven - sonar-maven-plugin - ${sonar-maven-plugin.version} - - - - + + + webapp-frontend + webapp-backend + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + + org.sonarsource.scanner.maven + sonar-maven-plugin + ${sonar-maven-plugin.version} + + + + \ No newline at end of file diff --git a/webapp-backend/pom.xml b/webapp-backend/pom.xml index e8c65e4..6541331 100644 --- a/webapp-backend/pom.xml +++ b/webapp-backend/pom.xml @@ -27,7 +27,7 @@ limitations under the License. org.o-ran-sc.portal.nonrtric.controlpanel nonrtric-controlpanel-parent - 2.1.0-SNAPSHOT + 2.1.1-SNAPSHOT nonrtric-controlpanel-be Non-RT RIC Control Panel Webapp backend @@ -153,23 +153,23 @@ limitations under the License. - - org.codehaus.mojo - build-helper-maven-plugin - - - add-source - generate-sources - - add-source - - - - ${project.build.directory}/generated-sources/annotations/ - - - - + + org.codehaus.mojo + build-helper-maven-plugin + + + add-source + generate-sources + + add-source + + + + ${project.build.directory}/generated-sources/annotations/ + + + + org.springframework.boot @@ -325,4 +325,4 @@ limitations under the License. - + \ No newline at end of file diff --git a/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/controller/EnrichmentController.java b/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/controller/EnrichmentController.java index 57019ce..5e72dee 100644 --- a/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/controller/EnrichmentController.java +++ b/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/controller/EnrichmentController.java @@ -34,6 +34,8 @@ import org.oransc.portal.nonrtric.controlpanel.ControlPanelConstants; import org.oransc.portal.nonrtric.controlpanel.eiproducerapi.EiProducerApi; import org.oransc.portal.nonrtric.controlpanel.model.JobInfo; import org.oransc.portal.nonrtric.controlpanel.model.ProducerInfo; +import org.oransc.portal.nonrtric.controlpanel.model.ProducerRegistrationInfo; +import org.oransc.portal.nonrtric.controlpanel.model.ProducerStatusInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -59,8 +61,6 @@ public class EnrichmentController { private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - private static com.google.gson.Gson gson = new GsonBuilder().create(); - // Publish paths in constants so tests are easy to write public static final String CONTROLLER_PATH = ControlPanelConstants.ENDPOINT_PREFIX + "/enrichment"; // Endpoints @@ -73,6 +73,7 @@ public class EnrichmentController { // Populated by the autowired constructor private final EiProducerApi eiProducerApi; + public static com.google.gson.Gson gson = new GsonBuilder().create(); @Autowired public EnrichmentController(final EiProducerApi eiProducerApi) { @@ -83,7 +84,7 @@ public class EnrichmentController { @ApiOperation(value = "Get the EI job definitions for one EI producer") @GetMapping(EI_JOBS) - public ResponseEntity> getEiJobs() { + public ResponseEntity getEiJobs() { logger.debug("getEiJobs"); ResponseEntity response = this.eiProducerApi.getAllEiProducerIds(); JsonArray bodyJson = JsonParser.parseString(response.getBody()).getAsJsonArray(); @@ -91,23 +92,18 @@ public class EnrichmentController { for (JsonElement producerId : bodyJson) { allJobs.addAll(getJobs(producerId)); } - return new ResponseEntity<>(allJobs, HttpStatus.OK); + return new ResponseEntity<>(gson.toJson(allJobs), HttpStatus.OK); } private List getJobs(JsonElement producerId) { - List jobs = new ArrayList<>(); - ResponseEntity jobsResponse = this.eiProducerApi.getEiJobsForOneEiProducer(producerId.getAsString()); - JsonArray jobsJson = JsonParser.parseString(jobsResponse.getBody()).getAsJsonArray(); - for (JsonElement jobJson : jobsJson) { - JobInfo jobInfo = gson.fromJson(jobJson, JobInfo.class); - jobs.add(jobInfo); - } - return jobs; + ResponseEntity> jobsResponse = + this.eiProducerApi.getEiJobsForOneEiProducer(producerId.getAsString()); + return jobsResponse.getBody(); } @ApiOperation(value = "Get EI producers") @GetMapping(EI_PRODUCERS) - public ResponseEntity> getEiProducers() { + public ResponseEntity getEiProducers() { logger.debug("getEiProducers"); ResponseEntity response = this.eiProducerApi.getAllEiProducerIds(); JsonArray bodyJson = JsonParser.parseString(response.getBody()).getAsJsonArray(); @@ -121,23 +117,22 @@ public class EnrichmentController { producers.add(producerInfo); } - return new ResponseEntity<>(producers, HttpStatus.OK); + return new ResponseEntity<>(gson.toJson(producers), HttpStatus.OK); } private String[] getSupportedTypes(JsonElement producerId) { - ResponseEntity producerResponse = this.eiProducerApi.getEiProducer(producerId.getAsString()); - JsonArray supportedTypesJson = JsonParser.parseString(producerResponse.getBody()).getAsJsonObject() - .get("supported_ei_types").getAsJsonArray(); + ResponseEntity producerResponse = + this.eiProducerApi.getEiProducer(producerId.getAsString()); List supportedTypes = new ArrayList<>(); - for (JsonElement typeJson : supportedTypesJson) { - supportedTypes.add(typeJson.getAsJsonObject().get("ei_type_identity").getAsString()); + for (String type : producerResponse.getBody().supportedTypeIds) { + supportedTypes.add(type); } return supportedTypes.toArray(new String[0]); } private String getProducerStatus(JsonElement producerId) { - ResponseEntity statusResponse = this.eiProducerApi.getEiProducerStatus(producerId.getAsString()); - return JsonParser.parseString(statusResponse.getBody()).getAsJsonObject().get("operational_state") - .getAsString(); + ResponseEntity statusResponse = + this.eiProducerApi.getEiProducerStatus(producerId.getAsString()); + return statusResponse.getBody().opState.toString(); } } diff --git a/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/eiproducerapi/EiProducerApi.java b/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/eiproducerapi/EiProducerApi.java index 943b9f9..60a3300 100644 --- a/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/eiproducerapi/EiProducerApi.java +++ b/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/eiproducerapi/EiProducerApi.java @@ -19,16 +19,21 @@ */ package org.oransc.portal.nonrtric.controlpanel.eiproducerapi; +import java.util.List; + +import org.oransc.portal.nonrtric.controlpanel.model.JobInfo; +import org.oransc.portal.nonrtric.controlpanel.model.ProducerRegistrationInfo; +import org.oransc.portal.nonrtric.controlpanel.model.ProducerStatusInfo; import org.springframework.http.ResponseEntity; public interface EiProducerApi { public ResponseEntity getAllEiProducerIds(); - public ResponseEntity getEiProducer(String eiProducerId); + public ResponseEntity getEiProducer(String eiProducerId); - public ResponseEntity getEiJobsForOneEiProducer(String eiProducerId); + public ResponseEntity> getEiJobsForOneEiProducer(String eiProducerId); - public ResponseEntity getEiProducerStatus(String eiProducerId); + public ResponseEntity getEiProducerStatus(String eiProducerId); } diff --git a/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/eiproducerapi/EiProducerApiImpl.java b/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/eiproducerapi/EiProducerApiImpl.java index 51be42a..921d586 100644 --- a/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/eiproducerapi/EiProducerApiImpl.java +++ b/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/eiproducerapi/EiProducerApiImpl.java @@ -19,12 +19,20 @@ */ package org.oransc.portal.nonrtric.controlpanel.eiproducerapi; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonSyntaxException; + import java.lang.invoke.MethodHandles; +import java.util.List; import org.json.JSONArray; import org.json.JSONObject; +import org.oransc.portal.nonrtric.controlpanel.model.JobInfo; +import org.oransc.portal.nonrtric.controlpanel.model.ProducerRegistrationInfo; +import org.oransc.portal.nonrtric.controlpanel.model.ProducerStatusInfo; import org.oransc.portal.nonrtric.controlpanel.util.AsyncRestClient; import org.oransc.portal.nonrtric.controlpanel.util.ErrorResponseHandler; +import org.oransc.portal.nonrtric.controlpanel.util.JsonArrayHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -40,6 +48,7 @@ public class EiProducerApiImpl implements EiProducerApi { private static final String STATUS = "/status"; private final AsyncRestClient webClient; + private static com.google.gson.Gson gson = new GsonBuilder().create(); @Autowired public EiProducerApiImpl( @@ -58,18 +67,25 @@ public class EiProducerApiImpl implements EiProducerApi { } @Override - public ResponseEntity getEiProducer(String eiProducerId) { - return getResponseObject(EI_PRODUCERS + "/" + eiProducerId); + public ResponseEntity getEiProducer(String eiProducerId) throws JsonSyntaxException { + ResponseEntity resp = getResponseObject(EI_PRODUCERS + "/" + eiProducerId); + ProducerRegistrationInfo info = gson.fromJson(resp.getBody(), ProducerRegistrationInfo.class); + return new ResponseEntity<>(info, resp.getStatusCode()); } @Override - public ResponseEntity getEiJobsForOneEiProducer(String eiProducerId) { - return getResponseArray(EI_PRODUCERS + "/" + eiProducerId + EI_JOBS); + public ResponseEntity> getEiJobsForOneEiProducer(String eiProducerId) + throws JsonSyntaxException, IllegalStateException { + ResponseEntity resp = getResponseArray(EI_PRODUCERS + "/" + eiProducerId + EI_JOBS); + List jobs = JsonArrayHandler.parseJsonArray(resp.getBody(), JobInfo.class); + return new ResponseEntity<>(jobs, resp.getStatusCode()); } @Override - public ResponseEntity getEiProducerStatus(String eiProducerId) { - return getResponseObject(EI_PRODUCERS + "/" + eiProducerId + STATUS); + public ResponseEntity getEiProducerStatus(String eiProducerId) throws JsonSyntaxException { + ResponseEntity resp = getResponseObject(EI_PRODUCERS + "/" + eiProducerId + STATUS); + ProducerStatusInfo status = gson.fromJson(resp.getBody(), ProducerStatusInfo.class); + return new ResponseEntity<>(status, resp.getStatusCode()); } private ResponseEntity getResponseArray(String url) { diff --git a/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/model/ProducerRegistrationInfo.java b/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/model/ProducerRegistrationInfo.java new file mode 100644 index 0000000..c6038b5 --- /dev/null +++ b/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/model/ProducerRegistrationInfo.java @@ -0,0 +1,64 @@ +/*- + * ========================LICENSE_START================================= + * O-RAN-SC + * %% + * Copyright (C) 2020 Nordix Foundation + * %% + * 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.portal.nonrtric.controlpanel.model; + +import com.google.gson.annotations.SerializedName; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.util.Collection; + +import lombok.Builder; + +import org.immutables.gson.Gson; + +@Gson.TypeAdapters +@ApiModel(value = "producer_registration_info", description = "Information for an EI producer") +@Builder +public class ProducerRegistrationInfo { + + @Gson.TypeAdapters + @ApiModel(value = "producer_ei_type_registration_info", description = "Information for an EI type") + @Builder + public static class ProducerEiTypeRegistrationInfo { + + @ApiModelProperty(value = "EI type identity", required = true) + @SerializedName("ei_type_identity") + public String eiTypeId; + + @ApiModelProperty(value = "Json schema for the job data") + @SerializedName("ei_job_data_schema") + public Object jobDataSchema; + } + + @ApiModelProperty(value = "Supported EI type IDs", required = true) + @SerializedName("supported_ei_types") + public Collection supportedTypeIds; + + @ApiModelProperty(value = "callback for EI job", required = true) + @SerializedName("ei_job_callback_url") + public String jobCallbackUrl; + + @ApiModelProperty(value = "callback for producer supervision", required = true) + @SerializedName("ei_producer_supervision_callback_url") + public String producerSupervisionCallbackUrl; +} diff --git a/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/model/ProducerStatusInfo.java b/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/model/ProducerStatusInfo.java new file mode 100644 index 0000000..53daebb --- /dev/null +++ b/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/model/ProducerStatusInfo.java @@ -0,0 +1,45 @@ +/*- + * ========================LICENSE_START================================= + * O-RAN-SC + * %% + * Copyright (C) 2019 Nordix Foundation + * %% + * 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.portal.nonrtric.controlpanel.model; + +import com.google.gson.annotations.SerializedName; + +import lombok.Builder; + +import org.immutables.gson.Gson; + +@Gson.TypeAdapters +@Builder +public class ProducerStatusInfo { + + @Gson.TypeAdapters + public enum OperationalState { + ENABLED, DISABLED + } + + @SerializedName("operational_state") + public final OperationalState opState; + + public ProducerStatusInfo(OperationalState state) { + this.opState = state; + } + +} diff --git a/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/util/JsonArrayHandler.java b/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/util/JsonArrayHandler.java new file mode 100644 index 0000000..7af2429 --- /dev/null +++ b/webapp-backend/src/main/java/org/oransc/portal/nonrtric/controlpanel/util/JsonArrayHandler.java @@ -0,0 +1,24 @@ +package org.oransc.portal.nonrtric.controlpanel.util; + +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; + +import java.util.ArrayList; +import java.util.List; + +public class JsonArrayHandler { + + public static com.google.gson.Gson gson = new GsonBuilder().create(); + + public static List parseJsonArray(String jsonString, Class clazz) { + List result = new ArrayList<>(); + JsonArray jsonArr = JsonParser.parseString(jsonString).getAsJsonArray(); + for (JsonElement jsonElement : jsonArr) { + T json = gson.fromJson(jsonElement.toString(), clazz); + result.add(json); + } + return result; + } +} diff --git a/webapp-backend/src/test/java/org/oransc/portal/nonrtric/controlpanel/RestApiTest.java b/webapp-backend/src/test/java/org/oransc/portal/nonrtric/controlpanel/RestApiTest.java index c4acad2..751b210 100644 --- a/webapp-backend/src/test/java/org/oransc/portal/nonrtric/controlpanel/RestApiTest.java +++ b/webapp-backend/src/test/java/org/oransc/portal/nonrtric/controlpanel/RestApiTest.java @@ -39,8 +39,6 @@ import java.util.stream.Collectors; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.oransc.portal.nonrtric.controlpanel.model.JobInfo; -import org.oransc.portal.nonrtric.controlpanel.model.ProducerInfo; import org.oransc.portal.nonrtric.controlpanel.util.AsyncRestClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -86,15 +84,10 @@ class RestApiTest { assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK); JsonArray jobs = JsonParser.parseString(resp.getBody()).getAsJsonArray(); - JobInfo wantedJobInfo = JobInfo.builder() // - .id("job1") // - .typeId("type1") // - .jobData(getStringFromFile("job-1.json")) // - .targetUri("http://example.com/") // - .owner("owner") // - .build(); - assertThat(jobs).hasSize(1) // - .contains(gson.toJsonTree(wantedJobInfo)); + + assertThat(jobs).hasSize(6); + assertThat(resp.getBody()).contains("job2"); + assertThat(resp.getBody()).contains("job1"); } @Test @@ -105,13 +98,7 @@ class RestApiTest { JsonArray producers = JsonParser.parseString(resp.getBody()).getAsJsonArray(); - ProducerInfo wantedProducerInfo = ProducerInfo.builder() // - .id("prod-1") // - .types(new String[] {"type1", "type2"}) // - .status("ENABLED") // - .build(); - assertThat(producers).hasSize(1) // - .contains(gson.toJsonTree(wantedProducerInfo)); + assertThat(producers).hasSize(3); } private AsyncRestClient restClient() { diff --git a/webapp-backend/src/test/java/org/oransc/portal/nonrtric/controlpanel/eiproducerapi/EiProducerApiImplTest.java b/webapp-backend/src/test/java/org/oransc/portal/nonrtric/controlpanel/eiproducerapi/EiProducerApiImplTest.java index a388d8b..298d92d 100644 --- a/webapp-backend/src/test/java/org/oransc/portal/nonrtric/controlpanel/eiproducerapi/EiProducerApiImplTest.java +++ b/webapp-backend/src/test/java/org/oransc/portal/nonrtric/controlpanel/eiproducerapi/EiProducerApiImplTest.java @@ -19,15 +19,23 @@ */ package org.oransc.portal.nonrtric.controlpanel.eiproducerapi; +import static org.junit.Assert.assertThrows; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonSyntaxException; + import java.util.Arrays; +import java.util.List; import org.junit.jupiter.api.Test; +import org.oransc.portal.nonrtric.controlpanel.model.JobInfo; +import org.oransc.portal.nonrtric.controlpanel.model.ProducerRegistrationInfo; +import org.oransc.portal.nonrtric.controlpanel.model.ProducerStatusInfo; import org.oransc.portal.nonrtric.controlpanel.util.AsyncRestClient; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -38,10 +46,7 @@ class EiProducerApiImplTest { private static final String URL_EI_PRODUCERS = "/eiproducers"; private static final String EI_PRODUCER_1 = "eiprod1"; private static final String EI_PRODUCER_2 = "eiprod2"; - private static final String EI_PRODUCER_1_INFO_VALID = - "{\"supported_ei_types\":[{\"ei_type_identity\":\"eitype1\",\"ei_job_data_schema\":{\"title\":\"eijob1\"}}]}"; - private static final String EI_PRODUCER_1_INFO_INVALID = - "{\"supported_ei_types\":[{\"ei_type_identity\":\"eitype1\",\"ei_job_data_schema\":\"title\":\"eijob1\"}}]}"; + private static final String EI_PRODUCER_1_INFO_VALID = "{\"supported_ei_types\":[]}"; private static final String URL_STATUS = "/status"; private static final String EI_PRODUCER_1_STATUS_VALID = "{\"operational_state\":\"ENABLED\"}"; private static final String EI_PRODUCER_1_STATUS_INVALID = "\"operational_state\":\"ENABLED\"}"; @@ -53,6 +58,7 @@ class EiProducerApiImplTest { AsyncRestClient restClientMock = mock(AsyncRestClient.class); EiProducerApiImpl apiUnderTest = new EiProducerApiImpl(restClientMock); + private static com.google.gson.Gson gson = new GsonBuilder().create(); private void whenGetReturnOK(String url, HttpStatus status, String body) { ResponseEntity ret = new ResponseEntity<>(body, status); @@ -86,27 +92,22 @@ class EiProducerApiImplTest { void testGetEiProducerValidJson() { whenGetReturnOK(URL_EI_PRODUCERS + "/" + EI_PRODUCER_1, HttpStatus.OK, EI_PRODUCER_1_INFO_VALID); - ResponseEntity returnedResp = apiUnderTest.getEiProducer(EI_PRODUCER_1); + ResponseEntity returnedResp = apiUnderTest.getEiProducer(EI_PRODUCER_1); assertEquals(HttpStatus.OK, returnedResp.getStatusCode()); - assertEquals(EI_PRODUCER_1_INFO_VALID, returnedResp.getBody()); + assertEquals(EI_PRODUCER_1_INFO_VALID, gson.toJson(returnedResp.getBody())); } @Test - void testGetEiProducerInvalidJson() { - whenGetReturnOK(URL_EI_PRODUCERS + "/" + EI_PRODUCER_1, HttpStatus.OK, EI_PRODUCER_1_INFO_INVALID); - - ResponseEntity returnedResp = apiUnderTest.getEiProducer(EI_PRODUCER_1); - - assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, returnedResp.getStatusCode()); - assertTrue(returnedResp.getBody().contains("JSONException")); - } - - @Test - void testGetEiJobsForOneEiProducerFailure() { + void whenGetEiJobsForOneEiProducerExceptionThrown_thenAssertionSucceeds() { whenGetReturnFailure(URL_EI_PRODUCERS + "/" + EI_PRODUCER_1 + URL_EI_JOBS, HttpStatus.NOT_FOUND, ""); - ResponseEntity returnedResp = apiUnderTest.getEiJobsForOneEiProducer(EI_PRODUCER_1); - assertEquals(HttpStatus.NOT_FOUND, returnedResp.getStatusCode()); + Exception exception = assertThrows(IllegalStateException.class, () -> { + apiUnderTest.getEiJobsForOneEiProducer(EI_PRODUCER_1); + }); + + String expectedMessage = "Not a JSON Array: null"; + String actualMessage = exception.getMessage(); + assertTrue(actualMessage.contains(expectedMessage)); } @Test @@ -115,9 +116,9 @@ class EiProducerApiImplTest { whenGetReturnOK(URL_EI_PRODUCERS + "/" + EI_PRODUCER_1 + URL_EI_JOBS, HttpStatus.OK, eiJobs); - ResponseEntity returnedResp = apiUnderTest.getEiJobsForOneEiProducer(EI_PRODUCER_1); - assertTrue(returnedResp.getBody().contains("\"ei_job_identity\":\"eijob1\"")); - assertTrue(returnedResp.getBody().contains("\"ei_job_identity\":\"eijob2\"")); + ResponseEntity> returnedResp = apiUnderTest.getEiJobsForOneEiProducer(EI_PRODUCER_1); + assertTrue(gson.toJson(returnedResp.getBody()).contains("\"ei_job_identity\":\"eijob1\"")); + assertTrue(gson.toJson(returnedResp.getBody()).contains("\"ei_job_identity\":\"eijob2\"")); assertEquals(HttpStatus.OK, returnedResp.getStatusCode()); } @@ -125,20 +126,22 @@ class EiProducerApiImplTest { void testGetEiProducerStatusValidJson() { whenGetReturnOK(URL_EI_PRODUCERS + "/" + EI_PRODUCER_1 + URL_STATUS, HttpStatus.OK, EI_PRODUCER_1_STATUS_VALID); - ResponseEntity returnedResp = apiUnderTest.getEiProducerStatus(EI_PRODUCER_1); + ResponseEntity returnedResp = apiUnderTest.getEiProducerStatus(EI_PRODUCER_1); assertEquals(HttpStatus.OK, returnedResp.getStatusCode()); - assertEquals(EI_PRODUCER_1_STATUS_VALID, returnedResp.getBody()); + assertEquals(EI_PRODUCER_1_STATUS_VALID, gson.toJson(returnedResp.getBody())); } @Test - void testGetEiProducerStatusInvalidJson() { + public void whenGetEiProducerStatusExceptionThrown_thenAssertionSucceeds() { whenGetReturnOK(URL_EI_PRODUCERS + "/" + EI_PRODUCER_1 + URL_STATUS, HttpStatus.OK, EI_PRODUCER_1_STATUS_INVALID); + Exception exception = assertThrows(JsonSyntaxException.class, () -> { + apiUnderTest.getEiProducerStatus(EI_PRODUCER_1); + }); - ResponseEntity returnedResp = apiUnderTest.getEiProducerStatus(EI_PRODUCER_1); - - assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, returnedResp.getStatusCode()); - assertTrue(returnedResp.getBody().contains("JSONException")); + String expectedMessage = "Expected BEGIN_OBJECT but was STRING"; + String actualMessage = exception.getMessage(); + assertTrue(actualMessage.contains(expectedMessage)); } } diff --git a/webapp-backend/src/test/java/org/oransc/portal/nonrtric/controlpanel/mock/EnrichmentControllerMockConfiguration.java b/webapp-backend/src/test/java/org/oransc/portal/nonrtric/controlpanel/mock/EnrichmentControllerMockConfiguration.java index c0fb4f1..decfab3 100644 --- a/webapp-backend/src/test/java/org/oransc/portal/nonrtric/controlpanel/mock/EnrichmentControllerMockConfiguration.java +++ b/webapp-backend/src/test/java/org/oransc/portal/nonrtric/controlpanel/mock/EnrichmentControllerMockConfiguration.java @@ -37,6 +37,9 @@ import java.util.stream.Collectors; import org.oransc.portal.nonrtric.controlpanel.eiproducerapi.EiProducerApi; import org.oransc.portal.nonrtric.controlpanel.model.JobInfo; +import org.oransc.portal.nonrtric.controlpanel.model.ProducerRegistrationInfo; +import org.oransc.portal.nonrtric.controlpanel.model.ProducerRegistrationInfo.ProducerEiTypeRegistrationInfo; +import org.oransc.portal.nonrtric.controlpanel.model.ProducerStatusInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.test.context.TestConfiguration; @@ -74,29 +77,29 @@ public class EnrichmentControllerMockConfiguration { } public ResponseEntity getAllEiProducers() { - EiProducers result = new EiProducers(); + List result = new ArrayList<>(); result.addAll(database.getAllEiProducers()); return new ResponseEntity<>(gson.toJson(result), HttpStatus.OK); } @Override - public ResponseEntity getEiProducer(String eiProducerId) { - EiProducer result = database.getEiProducerInstance(eiProducerId); - return new ResponseEntity<>(gson.toJson(result), HttpStatus.OK); + public ResponseEntity getEiProducer(String eiProducerId) { + ProducerRegistrationInfo result = database.getEiProducerInstance(eiProducerId); + return new ResponseEntity<>(result, HttpStatus.OK); } @Override - public ResponseEntity getEiJobsForOneEiProducer(String eiProducerId) { - EiJobs result = new EiJobs(); + public ResponseEntity> getEiJobsForOneEiProducer(String eiProducerId) { + List result = new ArrayList<>(); result.addAll(database.getAllEiJobs()); - return new ResponseEntity<>(gson.toJson(result), HttpStatus.OK); + return new ResponseEntity<>(result, HttpStatus.OK); } @Override - public ResponseEntity getEiProducerStatus(String eiProducerId) { - EiProducer result = database.getEiProducerInstance(eiProducerId); - return new ResponseEntity<>(gson.toJson(result.status()), HttpStatus.OK); + public ResponseEntity getEiProducerStatus(String eiProducerId) { + ProducerStatusInfo status = new ProducerStatusInfo(ProducerStatusInfo.OperationalState.ENABLED); + return new ResponseEntity<>(status, HttpStatus.OK); } } @@ -104,25 +107,35 @@ public class EnrichmentControllerMockConfiguration { Database() { - List supported_types = new ArrayList(); + List supported_types = new ArrayList(); - // Create EiType instance + // Create ProducerEiTypeRegistrationInfo instance String schema = getStringFromFile("ei-type-1.json"); - EiType eiType1 = getEiTypeInstance("type1", schema, Arrays.asList("prod-1")); + ProducerEiTypeRegistrationInfo eiType1 = getEiTypeInstance("type1", schema, Arrays.asList("prod-1")); supported_types.add(eiType1); - // Create EiType instance + // Create ProducerEiTypeRegistrationInfo instance schema = getStringFromFile("ei-type-2.json"); - EiType eiType2 = getEiTypeInstance("type2", schema, Arrays.asList("prod-1")); + ProducerEiTypeRegistrationInfo eiType2 = getEiTypeInstance("type2", schema, Arrays.asList("prod-1")); supported_types.add(eiType2); - // Create EiProducer instance + // Create ProducerRegistrationInfo instance putEiProducerInstance("prod-1", "http://example.com/", "http://example.com/", "http://example.com/", supported_types, new ProducerStatusInfo(ProducerStatusInfo.OperationalState.ENABLED)); + putEiProducerInstance("prod-2", "http://example.com/", "http://example.com/", "http://example.com/", + Arrays.asList(supported_types.get(0)), + new ProducerStatusInfo(ProducerStatusInfo.OperationalState.DISABLED)); + + putEiProducerInstance("3-prod", "http://example.com/", "http://example.com/", "http://example.com/", + supported_types, new ProducerStatusInfo(ProducerStatusInfo.OperationalState.ENABLED)); + // Create EiJob instance schema = getStringFromFile("job-1.json"); putEiJobInstance("type1", "job1", schema, "owner", "http://example.com/"); + + schema = getStringFromFile("job-1.json"); + putEiJobInstance("type2", "job2", schema, "owner", "http://example.com/"); } private String getStringFromFile(String path) { @@ -152,22 +165,23 @@ public class EnrichmentControllerMockConfiguration { } void putEiProducerInstance(String id, String creation_url, String deletion_url, String callback_url, - List supported_types, ProducerStatusInfo status) { - EiProducer eiProducer = ImmutableEiProducer.builder() // - .ei_producer_id(id) // - .ei_job_creation_callback_url(creation_url) // - .ei_job_deletion_callback_url(deletion_url) // - .ei_producer_supervision_callback_url(callback_url) // - .supported_ei_types(supported_types) // - .status(status).build(); // + List supported_types, ProducerStatusInfo status) { + Collection supportedTypeIds = new ArrayList<>(); + for (ProducerEiTypeRegistrationInfo i : supported_types) { + supportedTypeIds.add(i.eiTypeId); + } + ProducerRegistrationInfo eiProducer = ProducerRegistrationInfo.builder() // + .jobCallbackUrl(creation_url) // + .producerSupervisionCallbackUrl(callback_url) // + .supportedTypeIds(supportedTypeIds) // + .build(); // eiProducers.put(id, eiProducer); } - EiType getEiTypeInstance(String id, Object data, List producer_ids) { - return ImmutableEiType.builder() // - .ei_type_identity(id) // - .ei_job_data_schema(data) // - .ei_producer_ids(producer_ids) // + ProducerEiTypeRegistrationInfo getEiTypeInstance(String id, Object data, List producer_ids) { + return ProducerEiTypeRegistrationInfo.builder() // + .eiTypeId(id) // + .jobDataSchema(data) // .build(); // } @@ -179,8 +193,8 @@ public class EnrichmentControllerMockConfiguration { eiJobs.remove(id); } - EiProducer getEiProducerInstance(String id) throws RestClientException { - EiProducer i = eiProducers.get(id); + ProducerRegistrationInfo getEiProducerInstance(String id) throws RestClientException { + ProducerRegistrationInfo i = eiProducers.get(id); if (i == null) { throw new RestClientException("Producer not found: " + id); } @@ -191,16 +205,15 @@ public class EnrichmentControllerMockConfiguration { return Collections.unmodifiableCollection(eiProducers.keySet()); } - public Collection getAllEiProducers() { + public Collection getAllEiProducers() { return eiProducers.values(); } public List getAllEiJobs() { return new ArrayList<>(eiJobs.values()); - } - private Map eiProducers = new HashMap<>(); + private Map eiProducers = new HashMap<>(); private Map eiJobs = new HashMap<>(); } } diff --git a/webapp-frontend/pom.xml b/webapp-frontend/pom.xml index ea751d7..c246694 100644 --- a/webapp-frontend/pom.xml +++ b/webapp-frontend/pom.xml @@ -22,79 +22,79 @@ limitations under the License. - 4.0.0 - - org.o-ran-sc.portal.nonrtric.controlpanel - nonrtric-controlpanel-parent - 2.1.0-SNAPSHOT - - nonrtric-controlpanel-fe - Non-RT RIC Control Panel Webapp frontend - - - - com.github.eirslett - frontend-maven-plugin - 1.3 - - v10.15.3 - 6.7.0 - . - - - - install node and npm - - install-node-and-npm - - - - npm install - - npm - - - - npm run build - - npm - - - run build - - - - prod - - npm - - - run-script build - - generate-resources - - - - - org.apache.maven.plugins - maven-clean-plugin - - - - ${project.basedir} - - **/node_modules/** - dist/** - node/** - - false - - - node - - - - - - - + 4.0.0 + + org.o-ran-sc.portal.nonrtric.controlpanel + nonrtric-controlpanel-parent + 2.1.1-SNAPSHOT + + nonrtric-controlpanel-fe + Non-RT RIC Control Panel Webapp frontend + + + + com.github.eirslett + frontend-maven-plugin + 1.3 + + v10.15.3 + 6.7.0 + . + + + + install node and npm + + install-node-and-npm + + + + npm install + + npm + + + + npm run build + + npm + + + run build + + + + prod + + npm + + + run-script build + + generate-resources + + + + + org.apache.maven.plugins + maven-clean-plugin + + + + ${project.basedir} + + **/node_modules/** + dist/** + node/** + + false + + + node + + + + + + + \ No newline at end of file -- 2.16.6