diff options
11 files changed, 251 insertions, 33 deletions
diff --git a/docs/openapi/components.yml b/docs/openapi/components.yml index 05f1ac06..3d8aa2cf 100644 --- a/docs/openapi/components.yml +++ b/docs/openapi/components.yml @@ -43,6 +43,21 @@ components: type: string example: system-001 + ModuleSet: + type: object + properties: + schemas: + type: array + items: + type: object + properties: + moduleName: + type: string + revision: + type: string + namespace: + type: string + OperationalRequest: type: object properties: diff --git a/docs/openapi/openapi.yml b/docs/openapi/openapi.yml index a4a238c4..114c521e 100644 --- a/docs/openapi/openapi.yml +++ b/docs/openapi/openapi.yml @@ -51,22 +51,16 @@ paths: content: application/json: schema: - type: string + $ref: 'components.yml#/components/schemas/ModuleSet' example: { - 'schemas': { - 'schema': [ - { - 'identifier': 'example-identifier', - 'version': 'example-version', - 'format': 'example-format', - 'namespace': 'example:namespace', - 'location': [ - 'example-location' - ] - } - ] - } - } + "schemas": [ + { + "moduleName": "example-identifier", + "revision": "example-version", + "namespace": "example-namespace" + } + ] + } '400': $ref: 'components.yml#/components/responses/BadRequest' '401': diff --git a/src/main/java/org/onap/cps/ncmp/dmi/model/ModuleSchemaList.java b/src/main/java/org/onap/cps/ncmp/dmi/model/ModuleSchemaList.java new file mode 100644 index 00000000..1e7dcb0a --- /dev/null +++ b/src/main/java/org/onap/cps/ncmp/dmi/model/ModuleSchemaList.java @@ -0,0 +1,36 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.dmi.model; + +import java.util.List; +import lombok.Getter; +import lombok.Setter; + +/** + * ModuleSchemaList. + */ +@Getter +@Setter +public class ModuleSchemaList { + + private List<ModuleSchemaProperties> schema; + +} diff --git a/src/main/java/org/onap/cps/ncmp/dmi/model/ModuleSchemaProperties.java b/src/main/java/org/onap/cps/ncmp/dmi/model/ModuleSchemaProperties.java new file mode 100644 index 00000000..507758ad --- /dev/null +++ b/src/main/java/org/onap/cps/ncmp/dmi/model/ModuleSchemaProperties.java @@ -0,0 +1,40 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.dmi.model; + +import java.util.List; +import lombok.Getter; +import lombok.Setter; + +/** + * ModuleSchemaProperties. + */ +@Getter +@Setter +public class ModuleSchemaProperties { + + private String identifier; + private String version; + private String format; + private String namespace; + private List<String> location; + +} diff --git a/src/main/java/org/onap/cps/ncmp/dmi/model/ModuleSchemas.java b/src/main/java/org/onap/cps/ncmp/dmi/model/ModuleSchemas.java new file mode 100644 index 00000000..1794dedf --- /dev/null +++ b/src/main/java/org/onap/cps/ncmp/dmi/model/ModuleSchemas.java @@ -0,0 +1,34 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.dmi.model; + +import lombok.Getter; +import lombok.Setter; + +/** + * ModuleSchemas. + */ +@Getter +@Setter +public class ModuleSchemas { + + private ModuleSchemaList schemas; +} diff --git a/src/main/java/org/onap/cps/ncmp/dmi/rest/controller/DmiRestController.java b/src/main/java/org/onap/cps/ncmp/dmi/rest/controller/DmiRestController.java index 969e08d3..3d49b78e 100644 --- a/src/main/java/org/onap/cps/ncmp/dmi/rest/controller/DmiRestController.java +++ b/src/main/java/org/onap/cps/ncmp/dmi/rest/controller/DmiRestController.java @@ -28,6 +28,7 @@ import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.dmi.model.CmHandles; import org.onap.cps.ncmp.dmi.model.ModuleReference; import org.onap.cps.ncmp.dmi.model.ModuleRequestParent; +import org.onap.cps.ncmp.dmi.model.ModuleSet; import org.onap.cps.ncmp.dmi.model.OperationalRequest; import org.onap.cps.ncmp.dmi.rest.api.DmiPluginApi; import org.onap.cps.ncmp.dmi.rest.api.DmiPluginInternalApi; @@ -52,10 +53,9 @@ public class DmiRestController implements DmiPluginApi, DmiPluginInternalApi { } @Override - public ResponseEntity<String> getModulesForCmHandle(final String cmHandle) { - - final String modulesListAsJson = dmiService.getModulesForCmHandle(cmHandle); - return new ResponseEntity<>(modulesListAsJson, HttpStatus.OK); + public ResponseEntity<ModuleSet> getModulesForCmHandle(final String cmHandle) { + final var moduleSet = dmiService.getModulesForCmHandle(cmHandle); + return new ResponseEntity<ModuleSet>(moduleSet, HttpStatus.OK); } @Override @@ -118,6 +118,7 @@ public class DmiRestController implements DmiPluginApi, DmiPluginInternalApi { private List<ModuleReference> convertRestObjectToJavaApiObject(final ModuleRequestParent moduleRequestParent) { return objectMapper - .convertValue(moduleRequestParent.getData().getModules(), new TypeReference<List<ModuleReference>>() {}); + .convertValue(moduleRequestParent.getData().getModules(), new TypeReference<List<ModuleReference>>() { + }); } }
\ No newline at end of file diff --git a/src/main/java/org/onap/cps/ncmp/dmi/service/DmiService.java b/src/main/java/org/onap/cps/ncmp/dmi/service/DmiService.java index 528eb641..a7c94349 100644 --- a/src/main/java/org/onap/cps/ncmp/dmi/service/DmiService.java +++ b/src/main/java/org/onap/cps/ncmp/dmi/service/DmiService.java @@ -25,6 +25,7 @@ import java.util.Map; import javax.validation.constraints.NotNull; import org.onap.cps.ncmp.dmi.exception.DmiException; import org.onap.cps.ncmp.dmi.model.ModuleReference; +import org.onap.cps.ncmp.dmi.model.ModuleSet; /** * Interface for handling Dmi plugin Data. @@ -38,7 +39,7 @@ public interface DmiService { * @return {@code String} returns all modules * @throws DmiException can throw dmi exception */ - String getModulesForCmHandle(String cmHandle) throws DmiException; + ModuleSet getModulesForCmHandle(String cmHandle) throws DmiException; /** * This method used to register the given {@code CmHandles} diff --git a/src/main/java/org/onap/cps/ncmp/dmi/service/DmiServiceImpl.java b/src/main/java/org/onap/cps/ncmp/dmi/service/DmiServiceImpl.java index 32c8526c..94bd97d7 100644 --- a/src/main/java/org/onap/cps/ncmp/dmi/service/DmiServiceImpl.java +++ b/src/main/java/org/onap/cps/ncmp/dmi/service/DmiServiceImpl.java @@ -39,6 +39,10 @@ import org.onap.cps.ncmp.dmi.exception.ResourceDataNotFound; import org.onap.cps.ncmp.dmi.model.CmHandleOperation; import org.onap.cps.ncmp.dmi.model.CreatedCmHandle; import org.onap.cps.ncmp.dmi.model.ModuleReference; +import org.onap.cps.ncmp.dmi.model.ModuleSchemaProperties; +import org.onap.cps.ncmp.dmi.model.ModuleSchemas; +import org.onap.cps.ncmp.dmi.model.ModuleSet; +import org.onap.cps.ncmp.dmi.model.ModuleSetSchemas; import org.onap.cps.ncmp.dmi.service.client.NcmpRestClient; import org.onap.cps.ncmp.dmi.service.operation.SdncOperations; import org.springframework.http.HttpStatus; @@ -73,14 +77,15 @@ public class DmiServiceImpl implements DmiService { } @Override - public String getModulesForCmHandle(final String cmHandle) throws DmiException { + public ModuleSet getModulesForCmHandle(final String cmHandle) throws DmiException { final ResponseEntity<String> responseEntity = sdncOperations.getModulesFromNode(cmHandle); if (responseEntity.getStatusCode() == HttpStatus.OK) { final String responseBody = responseEntity.getBody(); if (StringUtils.isEmpty(responseBody)) { throw new ModulesNotFoundException(cmHandle, "SDNC returned no modules for given cm-handle."); } - return responseBody; + final ModuleSet moduleSet = createModuleSchema(responseBody); + return moduleSet; } else { throw new DmiException("SDNC is not able to process request.", "response code : " + responseEntity.getStatusCode() + " message : " + responseEntity.getBody()); @@ -129,6 +134,36 @@ public class DmiServiceImpl implements DmiService { } } + private ModuleSet createModuleSchema(final String responseBody) { + final var moduleSchemas = convertModulesToNodeSchema(responseBody); + final List<ModuleSetSchemas> moduleSetSchemas = new ArrayList<>(); + for (final ModuleSchemaProperties schemaProperties : moduleSchemas.getSchemas().getSchema()) { + moduleSetSchemas.add(convertModulesToModuleSchemas(schemaProperties)); + } + final var moduleSet = new ModuleSet(); + moduleSet.setSchemas(moduleSetSchemas); + return moduleSet; + } + + private ModuleSetSchemas convertModulesToModuleSchemas(final ModuleSchemaProperties moduleSchemaProperties) { + final var moduleSetSchemas = new ModuleSetSchemas(); + moduleSetSchemas.setModuleName(moduleSchemaProperties.getIdentifier()); + moduleSetSchemas.setNamespace(moduleSchemaProperties.getNamespace()); + moduleSetSchemas.setRevision(moduleSchemaProperties.getVersion()); + return moduleSetSchemas; + } + + private ModuleSchemas convertModulesToNodeSchema(final String modulesListAsJson) { + try { + return objectMapper.readValue(modulesListAsJson, ModuleSchemas.class); + } catch (final JsonProcessingException e) { + log.error("JSON exception occurred when converting the following modules to node schema " + + "{}", modulesListAsJson); + throw new DmiException("Unable to process JSON.", + "JSON exception occurred when mapping modules.", e); + } + } + @Override public Object getResourceDataOperationalForCmHandle(final @NotNull String cmHandle, final @NotNull String resourceIdentifier, diff --git a/src/test/groovy/org/onap/cps/ncmp/dmi/rest/controller/DmiRestControllerSpec.groovy b/src/test/groovy/org/onap/cps/ncmp/dmi/rest/controller/DmiRestControllerSpec.groovy index 0c8ae3fc..f24f65a8 100644 --- a/src/test/groovy/org/onap/cps/ncmp/dmi/rest/controller/DmiRestControllerSpec.groovy +++ b/src/test/groovy/org/onap/cps/ncmp/dmi/rest/controller/DmiRestControllerSpec.groovy @@ -20,11 +20,19 @@ package org.onap.cps.ncmp.dmi.rest.controller + +import com.fasterxml.jackson.databind.ObjectMapper import org.onap.cps.ncmp.dmi.TestUtils import org.onap.cps.ncmp.dmi.exception.DmiException import org.onap.cps.ncmp.dmi.exception.ModuleResourceNotFoundException import org.onap.cps.ncmp.dmi.exception.ModulesNotFoundException + import org.onap.cps.ncmp.dmi.model.ModuleReference +import org.onap.cps.ncmp.dmi.model.ModuleSchemaList +import org.onap.cps.ncmp.dmi.model.ModuleSchemaProperties +import org.onap.cps.ncmp.dmi.model.ModuleSchemas +import org.onap.cps.ncmp.dmi.model.ModuleSet +import org.onap.cps.ncmp.dmi.model.ModuleSetSchemas import org.onap.cps.ncmp.dmi.service.DmiService import org.spockframework.spring.SpringBean import org.springframework.beans.factory.annotation.Autowired @@ -47,6 +55,9 @@ class DmiRestControllerSpec extends Specification { @SpringBean DmiService mockDmiService = Mock() + @SpringBean + ObjectMapper mockObjectMapper = Spy() + @Autowired private MockMvc mvc @@ -57,8 +68,14 @@ class DmiRestControllerSpec extends Specification { given: 'REST endpoint for getting all modules' def getModuleUrl = "$basePathV1/ch/node1/modules" and: 'get modules for cm-handle returns a json' - def someJson = 'some-json' - mockDmiService.getModulesForCmHandle('node1') >> someJson + def moduleSetSchema = new ModuleSetSchemas() + moduleSetSchema.namespace('some-namespace') + moduleSetSchema.moduleName('some-moduleName') + moduleSetSchema.revision('some-revision') + def moduleSetSchemasList = [moduleSetSchema] as List<ModuleSetSchemas> + def moduleSet = new ModuleSet() + moduleSet.schemas(moduleSetSchemasList) + mockDmiService.getModulesForCmHandle('node1') >> moduleSet when: 'post is being called' def response = mvc.perform(post(getModuleUrl) .contentType(MediaType.APPLICATION_JSON)) @@ -66,7 +83,21 @@ class DmiRestControllerSpec extends Specification { then: 'status is OK' response.status == HttpStatus.OK.value() and: 'the response content matches the result from the DMI service' - response.getContentAsString() == someJson + response.getContentAsString() == '{"schemas":[{"moduleName":"some-moduleName","revision":"some-revision","namespace":"some-namespace"}]}' + } + + def 'Get all modules for given cm handle with invalid json.'() { + given: 'REST endpoint for getting all modules' + def getModuleUrl = "$basePathV1/ch/node1/modules" + and: 'get modules for cmHandle throws an exception' + mockObjectMapper.readValue(_ as String, _ as ModuleSchemaList) >> { throw Mock(DmiException.class) } + mockDmiService.getModulesForCmHandle('node1') >> 'some-value' + when: 'post is being called' + def response = mvc.perform(post(getModuleUrl) + .contentType(MediaType.APPLICATION_JSON)) + .andReturn().response + then: 'the status is as expected' + response.status == HttpStatus.INTERNAL_SERVER_ERROR.value() } def 'Get all modules for given cm handle with exception handling of #scenario.'() { @@ -75,16 +106,16 @@ class DmiRestControllerSpec extends Specification { and: 'get modules for cm-handle throws #exceptionClass' mockDmiService.getModulesForCmHandle('node1') >> { throw Mock(exceptionClass) } when: 'post is invoked' - def response = mvc.perform(post(getModuleUrl) + def response = mvc.perform( post(getModuleUrl) .contentType(MediaType.APPLICATION_JSON)) .andReturn().response then: 'response status is #expectedResponse' response.status == expectedResponse where: 'the scenario is #scenario' - scenario | exceptionClass || expectedResponse - 'dmi service exception' | DmiException.class || HttpStatus.INTERNAL_SERVER_ERROR.value() - 'no modules found' | ModulesNotFoundException.class || HttpStatus.NOT_FOUND.value() - 'any other runtime exception' | RuntimeException.class || HttpStatus.INTERNAL_SERVER_ERROR.value() + scenario | exceptionClass || expectedResponse + 'dmi service exception' | DmiException.class || HttpStatus.INTERNAL_SERVER_ERROR.value() + 'no modules found' | ModulesNotFoundException.class || HttpStatus.NOT_FOUND.value() + 'any other runtime exception' | RuntimeException.class || HttpStatus.INTERNAL_SERVER_ERROR.value() } def 'Register given list of cm handles.'() { diff --git a/src/test/groovy/org/onap/cps/ncmp/dmi/service/DmiServiceImplSpec.groovy b/src/test/groovy/org/onap/cps/ncmp/dmi/service/DmiServiceImplSpec.groovy index da8ff6b8..e456d411 100644 --- a/src/test/groovy/org/onap/cps/ncmp/dmi/service/DmiServiceImplSpec.groovy +++ b/src/test/groovy/org/onap/cps/ncmp/dmi/service/DmiServiceImplSpec.groovy @@ -22,6 +22,7 @@ package org.onap.cps.ncmp.dmi.service import com.fasterxml.jackson.core.JsonProcessingException import com.fasterxml.jackson.databind.ObjectMapper +import org.onap.cps.ncmp.dmi.TestUtils import org.onap.cps.ncmp.dmi.config.DmiPluginConfig import org.onap.cps.ncmp.dmi.exception.CmHandleRegistrationException import org.onap.cps.ncmp.dmi.exception.DmiException @@ -29,6 +30,8 @@ import org.onap.cps.ncmp.dmi.exception.ModuleResourceNotFoundException import org.onap.cps.ncmp.dmi.exception.ModulesNotFoundException import org.onap.cps.ncmp.dmi.exception.ResourceDataNotFound import org.onap.cps.ncmp.dmi.model.ModuleReference +import org.onap.cps.ncmp.dmi.model.ModuleSchemaList +import org.onap.cps.ncmp.dmi.model.ModuleSchemas import org.onap.cps.ncmp.dmi.service.client.NcmpRestClient import org.onap.cps.ncmp.dmi.service.operation.SdncOperations import org.springframework.http.HttpStatus @@ -49,12 +52,25 @@ class DmiServiceImplSpec extends Specification { given: 'cm handle id' def cmHandle = 'node1' and: 'request operation returns OK' - def body = 'body' + def body = TestUtils.getResourceFileContent('ModuleSchema.json') mockSdncOperations.getModulesFromNode(cmHandle) >> new ResponseEntity<String>(body, HttpStatus.OK) when: 'get modules for cm-handle is called' def result = objectUnderTest.getModulesForCmHandle(cmHandle) then: 'result is equal to the response from the SDNC service' - result == body + result.toString().contains('moduleName: example-identifier') + result.toString().contains('revision: example-version') + } + + def 'Call get modules for cm-handle with invalid json.'() { + given: 'cm handle id' + def cmHandle = 'node1' + and: 'request operation returns invalid json' + def body = TestUtils.getResourceFileContent('ModuleSchema.json') + mockSdncOperations.getModulesFromNode(cmHandle) >> new ResponseEntity<String>('invalid json', HttpStatus.OK) + when: 'get modules for cm-handle is called' + def result = objectUnderTest.getModulesForCmHandle(cmHandle) + then: 'a dmi exception is thrown' + thrown(DmiException) } def 'Call get modules for cm-handle and SDNC returns "bad request" status.'() { diff --git a/src/test/resources/ModuleSchema.json b/src/test/resources/ModuleSchema.json new file mode 100644 index 00000000..07a0a037 --- /dev/null +++ b/src/test/resources/ModuleSchema.json @@ -0,0 +1,15 @@ +{ + "schemas": { + "schema": [ + { + "identifier": "example-identifier", + "version": "example-version", + "format": "example-format", + "namespace": "example:namespace", + "location": [ + "example-location" + ] + } + ] + } +}
\ No newline at end of file |