diff options
41 files changed, 1469 insertions, 536 deletions
diff --git a/cps-ncmp-rest/docs/openapi/components.yaml b/cps-ncmp-rest/docs/openapi/components.yaml index fd02b6e564..d82813b874 100644 --- a/cps-ncmp-rest/docs/openapi/components.yaml +++ b/cps-ncmp-rest/docs/openapi/components.yaml @@ -50,7 +50,7 @@ components: createdCmHandles: type: array items: - $ref: '#/components/schemas/RestCmHandle' + $ref: '#/components/schemas/RestInputCmHandle' updatedCmHandles: type: array example: @@ -64,14 +64,14 @@ components: update-my-property: updated-property delete-my-property: '~' items: - $ref: '#/components/schemas/RestCmHandle' + $ref: '#/components/schemas/RestInputCmHandle' removedCmHandles: type: array items: type: string example: [my-cm-handle1, my-cm-handle2, my-cm-handle3] - RestCmHandle: + RestInputCmHandle: required: - cmHandle type: object @@ -146,6 +146,23 @@ components: type: string example: my-module-revision + RestOutputCmHandle: + type: object + title: CM handle Details + properties: + cmHandle: + type: string + example: my-cm-handle1 + publicCmHandleProperties: + $ref: '#/components/schemas/CmHandlePublicProperties' + CmHandlePublicProperties: + type: array + items: + type: object + additionalProperties: + type: string + example: Book Type + examples: dataSampleRequest: summary: Sample request diff --git a/cps-ncmp-rest/docs/openapi/ncmp.yml b/cps-ncmp-rest/docs/openapi/ncmp.yml index 3a71aba804..a267fb4919 100755 --- a/cps-ncmp-rest/docs/openapi/ncmp.yml +++ b/cps-ncmp-rest/docs/openapi/ncmp.yml @@ -262,3 +262,30 @@ executeCmHandleSearch: $ref: 'components.yaml#/components/responses/Forbidden' 500: $ref: 'components.yaml#/components/responses/InternalServerError' + +retrieveCmHandleDetailsById: + get: + description: Retrieve CM handle details and properties by cm handle id + tags: + - network-cm-proxy + summary: Retrieve CM handle details + operationId: retrieveCmHandleDetailsById + parameters: + - $ref: 'components.yaml#/components/parameters/cmHandleInPath' + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: 'components.yaml#/components/schemas/RestOutputCmHandle' + 400: + $ref: 'components.yaml#/components/responses/BadRequest' + 401: + $ref: 'components.yaml#/components/responses/Unauthorized' + 403: + $ref: 'components.yaml#/components/responses/Forbidden' + 404: + $ref: 'components.yaml#/components/responses/NotFound' + 500: + $ref: 'components.yaml#/components/responses/InternalServerError'
\ No newline at end of file diff --git a/cps-ncmp-rest/docs/openapi/openapi.yml b/cps-ncmp-rest/docs/openapi/openapi.yml index 838a0d08ed..12a8318efb 100755 --- a/cps-ncmp-rest/docs/openapi/openapi.yml +++ b/cps-ncmp-rest/docs/openapi/openapi.yml @@ -36,4 +36,7 @@ paths: $ref: 'ncmp.yml#/fetchModuleReferencesByCmHandle' /v1/ch/searches: - $ref: 'ncmp.yml#/executeCmHandleSearch'
\ No newline at end of file + $ref: 'ncmp.yml#/executeCmHandleSearch' + + /v1/ch/{cm-handle}: + $ref: 'ncmp.yml#/retrieveCmHandleDetailsById'
\ No newline at end of file diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java index 419f6e9268..86f4460eaa 100755 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java +++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2021 Pantheon.tech - * Modifications (C) 2021-2022 Nordix Foundation + * Modifications Copyright (C) 2021-2022 Nordix Foundation * Modification Copyright (C) 2021 highstreet technologies GmbH * Modifications (C) 2021 Bell Canada * ================================================================================ @@ -10,6 +10,7 @@ * 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. @@ -38,15 +39,18 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.modelmapper.ModelMapper; import org.onap.cps.ncmp.api.NetworkCmProxyDataService; +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.onap.cps.ncmp.rest.api.NetworkCmProxyApi; import org.onap.cps.ncmp.rest.model.CmHandleProperties; import org.onap.cps.ncmp.rest.model.CmHandleProperty; +import org.onap.cps.ncmp.rest.model.CmHandlePublicProperties; import org.onap.cps.ncmp.rest.model.CmHandles; import org.onap.cps.ncmp.rest.model.ConditionProperties; import org.onap.cps.ncmp.rest.model.Conditions; import org.onap.cps.ncmp.rest.model.ModuleNameAsJsonObject; import org.onap.cps.ncmp.rest.model.ModuleNamesAsJsonArray; import org.onap.cps.ncmp.rest.model.ModuleReference; +import org.onap.cps.ncmp.rest.model.RestOutputCmHandle; import org.onap.cps.utils.JsonObjectMapper; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -186,6 +190,18 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { } /** + * Search for Cm Handle and Properties by Name. + * @param cmHandleId cm-handle identifier + * @return cm handle and its properties + */ + @Override + public ResponseEntity<RestOutputCmHandle> retrieveCmHandleDetailsById(final String cmHandleId) { + final NcmpServiceCmHandle ncmpServiceCmHandle = networkCmProxyDataService.getNcmpServiceCmHandle(cmHandleId); + final RestOutputCmHandle restOutputCmHandle = toRestOutputCmHandle(ncmpServiceCmHandle); + return ResponseEntity.ok(restOutputCmHandle); + } + + /** * Return module references for a cm handle. * * @param cmHandle the cm handle @@ -233,4 +249,13 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { } return cmHandleProperties; } + + private RestOutputCmHandle toRestOutputCmHandle(final NcmpServiceCmHandle ncmpServiceCmHandle) { + final RestOutputCmHandle restOutputCmHandle = new RestOutputCmHandle(); + final CmHandlePublicProperties cmHandlePublicProperties = new CmHandlePublicProperties(); + restOutputCmHandle.setCmHandle(ncmpServiceCmHandle.getCmHandleID()); + cmHandlePublicProperties.add(ncmpServiceCmHandle.getPublicProperties()); + restOutputCmHandle.setPublicCmHandleProperties(cmHandlePublicProperties); + return restOutputCmHandle; + } } diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/RestInputMapper.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/RestInputMapper.java index d38204cf1b..a1d046ece9 100644 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/RestInputMapper.java +++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/RestInputMapper.java @@ -22,13 +22,12 @@ package org.onap.cps.ncmp.rest.controller; import org.mapstruct.Mapper; import org.mapstruct.Mapping; -import org.mapstruct.Mappings; import org.mapstruct.NullValueMappingStrategy; import org.mapstruct.NullValuePropertyMappingStrategy; -import org.onap.cps.ncmp.api.models.CmHandle; import org.onap.cps.ncmp.api.models.DmiPluginRegistration; -import org.onap.cps.ncmp.rest.model.RestCmHandle; +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.onap.cps.ncmp.rest.model.RestDmiPluginRegistration; +import org.onap.cps.ncmp.rest.model.RestInputCmHandle; @Mapper(componentModel = "spring", nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT, nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT) @@ -36,11 +35,9 @@ public interface RestInputMapper { DmiPluginRegistration toDmiPluginRegistration(final RestDmiPluginRegistration restDmiPluginRegistration); - @Mappings({ - @Mapping(source = "cmHandle", target = "cmHandleID"), - @Mapping(source = "cmHandleProperties", target = "dmiProperties"), - @Mapping(source = "publicCmHandleProperties", target = "publicProperties") - }) - CmHandle toCmHandle(final RestCmHandle restCmHandle); + @Mapping(source = "cmHandle", target = "cmHandleID") + @Mapping(source = "cmHandleProperties", target = "dmiProperties") + @Mapping(source = "publicCmHandleProperties", target = "publicProperties") + NcmpServiceCmHandle toNcmpServiceCmHandle(final RestInputCmHandle restInputCmHandle); } diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandler.java index fd01096e19..5aaf1c31f0 100755 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandler.java +++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandler.java @@ -59,23 +59,13 @@ public class NetworkCmProxyRestExceptionHandler { return buildErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, exception); } - @ExceptionHandler({CpsException.class}) - public static ResponseEntity<Object> handleAnyOtherCpsExceptions(final CpsException exception) { + @ExceptionHandler({CpsException.class, ServerNcmpException.class}) + public static ResponseEntity<Object> handleAnyOtherCpsExceptions(final Exception exception) { return buildErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, exception); } - @ExceptionHandler({ServerNcmpException.class}) - public static ResponseEntity<Object> handleServerNcmpExceptions(final ServerNcmpException exception) { - return buildErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, exception); - } - - @ExceptionHandler({DmiRequestException.class}) - public static ResponseEntity<Object> handleDmiRequestExceptions(final DmiRequestException exception) { - return buildErrorResponse(HttpStatus.BAD_REQUEST, exception); - } - - @ExceptionHandler({DataValidationException.class, HttpMessageNotReadableException.class}) - public static ResponseEntity<Object> handleDataValidatedExceptions(final Exception exception) { + @ExceptionHandler({DmiRequestException.class, DataValidationException.class, HttpMessageNotReadableException.class}) + public static ResponseEntity<Object> handleDmiRequestExceptions(final Exception exception) { return buildErrorResponse(HttpStatus.BAD_REQUEST, exception); } diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy index 0c8b2227d0..c99771443a 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy @@ -22,6 +22,9 @@ package org.onap.cps.ncmp.rest.controller + +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle + import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.PATCH import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get @@ -180,6 +183,28 @@ class NetworkCmProxyControllerSpec extends Specification { response.contentAsString == '{"cmHandles":[{"cmHandleId":"some-cmhandle-id1"},{"cmHandleId":"some-cmhandle-id2"}]}' } + def 'Get Cm Handle details by Cm Handle id.' () { + given: 'an endpoint and a cm handle' + def cmHandleDetailsEndpoint = "$ncmpBasePathV1/ch/Some-Cm-Handle" + and: 'an existing ncmp service cm handle' + def cmHandleId = 'Some-Cm-Handle' + def dmiProperties = [ prop:'some DMI property' ] + def publicProperties = [ "public prop":'some public property' ] + def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleID: cmHandleId, dmiProperties: dmiProperties, publicProperties: publicProperties) + and: 'the service method is invoked with the cm handle id' + 1 * mockNetworkCmProxyDataService.getNcmpServiceCmHandle('Some-Cm-Handle') >> ncmpServiceCmHandle + when: 'the cm handle details api is invoked' + def response = mvc.perform(get(cmHandleDetailsEndpoint)).andReturn().response + then: 'the correct response is returned' + response.status == HttpStatus.OK.value() + and: 'the response returns public properties and the correct properties' + response.contentAsString.contains('publicCmHandleProperties') + response.contentAsString.contains('public prop') + response.contentAsString.contains('some public property') + and: 'the content does not contain dmi properties' + !response.contentAsString.contains("some DMI property") + } + def 'Call execute cm handle searches with unrecognized condition name.'() { given: 'an endpoint and json data' def searchesEndpoint = "$ncmpBasePathV1/ch/searches" diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/RestInputMapperSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/RestInputMapperSpec.groovy index c48a8ed360..ed938810c0 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/RestInputMapperSpec.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/RestInputMapperSpec.groovy @@ -21,8 +21,8 @@ package org.onap.cps.ncmp.rest.controller import org.mapstruct.factory.Mappers -import org.onap.cps.ncmp.rest.model.RestCmHandle import org.onap.cps.ncmp.rest.model.RestDmiPluginRegistration +import org.onap.cps.ncmp.rest.model.RestInputCmHandle import spock.lang.Specification class RestInputMapperSpec extends Specification { @@ -31,7 +31,7 @@ class RestInputMapperSpec extends Specification { def 'Convert a created REST CM Handle Input to an NCMP Service CM Handle with #scenario'() { given: 'a rest cm handle input' - def inputRestCmHandle = new RestCmHandle(cmHandle : 'example-id', cmHandleProperties: dmiProperties, + def inputRestCmHandle = new RestInputCmHandle(cmHandle : 'example-id', cmHandleProperties: dmiProperties, publicCmHandleProperties: publicProperties) def restDmiPluginRegistration = new RestDmiPluginRegistration( createdCmHandles: [inputRestCmHandle]) diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy index 306f546f32..8004328bc2 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy @@ -29,6 +29,7 @@ import org.onap.cps.ncmp.api.impl.exception.DmiRequestException import org.onap.cps.ncmp.api.impl.exception.ServerNcmpException import org.onap.cps.ncmp.rest.controller.RestInputMapper import org.onap.cps.spi.exceptions.CpsException +import org.onap.cps.spi.exceptions.DataNodeNotFoundException import org.onap.cps.spi.exceptions.DataValidationException import org.onap.cps.utils.JsonObjectMapper import org.spockframework.spring.SpringBean @@ -78,6 +79,8 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification { def errorMessage = 'some error message' @Shared def errorDetails = 'some error details' + @Shared + def dataNodeNotFoundErrorMessage = 'DataNode not found' def setup() { dataNodeBaseEndpointNcmp = "$basePathNcmp/v1" @@ -89,13 +92,14 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification { setupTestException(exception, NCMP) def response = performTestRequest(NCMP) then: 'an HTTP response is returned with correct message and details' - assertTestResponse(response, expectedErrorCode, errorMessage, expectedErrorDetails) + assertTestResponse(response, expectedErrorCode, expectedErrorMessage, expectedErrorDetails) where: - scenario | exception || expectedErrorDetails | expectedErrorCode - 'CPS' | new CpsException(errorMessage, errorDetails) || errorDetails | INTERNAL_SERVER_ERROR - 'NCMP-server' | new ServerNcmpException(errorMessage, errorDetails) || null | INTERNAL_SERVER_ERROR - 'NCMP-client' | new DmiRequestException(errorMessage, errorDetails) || null | BAD_REQUEST - 'other' | new IllegalStateException(errorMessage) || null | INTERNAL_SERVER_ERROR + scenario | exception || expectedErrorDetails | expectedErrorMessage | expectedErrorCode + 'CPS' | new CpsException(errorMessage, errorDetails) || errorDetails | errorMessage | INTERNAL_SERVER_ERROR + 'NCMP-server' | new ServerNcmpException(errorMessage, errorDetails) || null | errorMessage | INTERNAL_SERVER_ERROR + 'NCMP-client' | new DmiRequestException(errorMessage, errorDetails) || null | errorMessage | BAD_REQUEST + 'DataNode Validation' | new DataNodeNotFoundException(dataNodeNotFoundErrorMessage, errorDetails) || null | dataNodeNotFoundErrorMessage | BAD_REQUEST + 'other' | new IllegalStateException(errorMessage) || null | errorMessage | INTERNAL_SERVER_ERROR } def 'Post request with exception returns correct HTTP Status.'() { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java index 5d2ab53394..471e97e081 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java @@ -26,6 +26,7 @@ import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum import java.util.Collection; import org.onap.cps.ncmp.api.models.DmiPluginRegistration; +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.onap.cps.spi.model.ModuleReference; /* @@ -44,13 +45,13 @@ public interface NetworkCmProxyDataService { * Get resource data for data store pass-through operational * using dmi. * - * @param cmHandle cm handle + * @param cmHandleId cm handle identifier * @param resourceIdentifier resource identifier * @param acceptParamInHeader accept param * @param optionsParamInQuery options query * @return {@code Object} resource data */ - Object getResourceDataOperationalForCmHandle(String cmHandle, + Object getResourceDataOperationalForCmHandle(String cmHandleId, String resourceIdentifier, String acceptParamInHeader, String optionsParamInQuery); @@ -59,13 +60,13 @@ public interface NetworkCmProxyDataService { * Get resource data for data store pass-through running * using dmi. * - * @param cmHandle cm handle + * @param cmHandleId cm handle identifier * @param resourceIdentifier resource identifier * @param acceptParamInHeader accept param * @param optionsParamInQuery options query * @return {@code Object} resource data */ - Object getResourceDataPassThroughRunningForCmHandle(String cmHandle, + Object getResourceDataPassThroughRunningForCmHandle(String cmHandleId, String resourceIdentifier, String acceptParamInHeader, String optionsParamInQuery); @@ -73,14 +74,14 @@ public interface NetworkCmProxyDataService { /** * Write resource data for data store pass-through running * using dmi for given cm-handle. - * @param cmHandle cm handle + * @param cmHandleId cm handle identifier * @param resourceIdentifier resource identifier * @param operation required operation * @param requestBody request body to create resource * @param contentType content type in body * @return {@code Object} return data */ - Object writeResourceDataPassThroughRunningForCmHandle(String cmHandle, + Object writeResourceDataPassThroughRunningForCmHandle(String cmHandleId, String resourceIdentifier, OperationEnum operation, String requestBody, @@ -89,10 +90,10 @@ public interface NetworkCmProxyDataService { /** * Retrieve module references for the given cm handle. * - * @param cmHandle cm handle + * @param cmHandleId cm handle identifier * @return a collection of modules names and revisions */ - Collection<ModuleReference> getYangResourcesModuleReferences(String cmHandle); + Collection<ModuleReference> getYangResourcesModuleReferences(String cmHandleId); /** * Query cm handle identifiers for the given collection of module names. @@ -103,4 +104,12 @@ public interface NetworkCmProxyDataService { */ Collection<String> executeCmHandleHasAllModulesSearch(Collection<String> moduleNames); + /** + * Query cm handle details by cm handle's name. + * + * @param cmHandleId cm handle identifier + * @return a collection of cm handle details. + */ + NcmpServiceCmHandle getNcmpServiceCmHandle(String cmHandleId); + } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java index 446e45b2b8..1762e46287 100755 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java @@ -34,6 +34,7 @@ import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED; import com.fasterxml.jackson.core.JsonProcessingException; import java.util.Collection; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -47,10 +48,11 @@ import org.onap.cps.ncmp.api.impl.exception.ServerNcmpException; import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations; import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations; import org.onap.cps.ncmp.api.impl.operations.DmiOperations; -import org.onap.cps.ncmp.api.models.CmHandle; +import org.onap.cps.ncmp.api.impl.operations.YangModelCmHandleRetriever; +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandlesList; import org.onap.cps.ncmp.api.models.DmiPluginRegistration; -import org.onap.cps.ncmp.api.models.PersistenceCmHandle; -import org.onap.cps.ncmp.api.models.PersistenceCmHandlesList; +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.onap.cps.spi.exceptions.DataNodeNotFoundException; import org.onap.cps.spi.exceptions.DataValidationException; import org.onap.cps.spi.model.ModuleReference; @@ -77,6 +79,8 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService private final NetworkCmProxyDataServicePropertyHandler networkCmProxyDataServicePropertyHandler; + private final YangModelCmHandleRetriever yangModelCmHandleRetriever; + @Override public void updateDmiRegistrationAndSyncModule(final DmiPluginRegistration dmiPluginRegistration) { dmiPluginRegistration.validateDmiPluginRegistration(); @@ -97,12 +101,12 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService } @Override - public Object getResourceDataOperationalForCmHandle(final String cmHandle, + public Object getResourceDataOperationalForCmHandle(final String cmHandleId, final String resourceIdentifier, final String acceptParamInHeader, final String optionsParamInQuery) { return handleResponse(dmiDataOperations.getResourceDataFromDmi( - cmHandle, + cmHandleId, resourceIdentifier, optionsParamInQuery, acceptParamInHeader, @@ -110,12 +114,12 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService } @Override - public Object getResourceDataPassThroughRunningForCmHandle(final String cmHandle, + public Object getResourceDataPassThroughRunningForCmHandle(final String cmHandleId, final String resourceIdentifier, final String acceptParamInHeader, final String optionsParamInQuery) { return handleResponse(dmiDataOperations.getResourceDataFromDmi( - cmHandle, + cmHandleId, resourceIdentifier, optionsParamInQuery, acceptParamInHeader, @@ -123,21 +127,21 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService } @Override - public Object writeResourceDataPassThroughRunningForCmHandle(final String cmHandle, + public Object writeResourceDataPassThroughRunningForCmHandle(final String cmHandleId, final String resourceIdentifier, final OperationEnum operation, final String requestData, final String dataType) { return handleResponse( dmiDataOperations.writeResourceDataPassThroughRunningFromDmi( - cmHandle, resourceIdentifier, operation, requestData, dataType), + cmHandleId, resourceIdentifier, operation, requestData, dataType), "Not able to " + operation + " resource data."); } @Override - public Collection<ModuleReference> getYangResourcesModuleReferences(final String cmHandle) { - return cpsModuleService.getYangResourcesModuleReferences(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandle); + public Collection<ModuleReference> getYangResourcesModuleReferences(final String cmHandleId) { + return cpsModuleService.getYangResourcesModuleReferences(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId); } /** @@ -152,16 +156,56 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService } /** - * THis method registers a cm handle and intiates modules sync. + * Retrieve cm handle details for a given cm handle. + * @param cmHandleId cm handle identifier + * @return cm handle details + */ + @Override + public NcmpServiceCmHandle getNcmpServiceCmHandle(final String cmHandleId) { + final NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle(); + final YangModelCmHandle yangModelCmHandle = + yangModelCmHandleRetriever.getDmiServiceNamesAndProperties(cmHandleId); + final List<YangModelCmHandle.Property> dmiProperties = yangModelCmHandle.getDmiProperties(); + final List<YangModelCmHandle.Property> publicProperties = yangModelCmHandle.getPublicProperties(); + ncmpServiceCmHandle.setCmHandleID(yangModelCmHandle.getId()); + setDmiProperties(dmiProperties, ncmpServiceCmHandle); + setPublicProperties(publicProperties, ncmpServiceCmHandle); + return ncmpServiceCmHandle; + } + + private void setDmiProperties(final List<YangModelCmHandle.Property> dmiProperties, + final NcmpServiceCmHandle ncmpServiceCmHandle) { + final Map<String, String> dmiPropertiesMap = new LinkedHashMap<>(dmiProperties.size()); + asPropertiesMap(dmiProperties, dmiPropertiesMap); + ncmpServiceCmHandle.setDmiProperties(dmiPropertiesMap); + } + + private void setPublicProperties(final List<YangModelCmHandle.Property> publicProperties, + final NcmpServiceCmHandle ncmpServiceCmHandle) { + final Map<String, String> publicPropertiesMap = new LinkedHashMap<>(); + asPropertiesMap(publicProperties, publicPropertiesMap); + ncmpServiceCmHandle.setPublicProperties(publicPropertiesMap); + } + + private void asPropertiesMap(final List<YangModelCmHandle.Property> properties, + final Map<String, String> propertiesMap) { + for (final YangModelCmHandle.Property property: properties) { + propertiesMap.put(property.getName(), property.getValue()); + } + } + + /** + * THis method registers a cm handle and initiates modules sync. * * @param dmiPluginRegistration dmi plugin registration information. * @throws JsonProcessingException thrown if json is malformed or missing. */ public void parseAndCreateCmHandlesInDmiRegistrationAndSyncModules( final DmiPluginRegistration dmiPluginRegistration) throws JsonProcessingException { - final PersistenceCmHandlesList createdPersistenceCmHandlesList = - getUpdatedPersistenceCmHandlesList(dmiPluginRegistration, dmiPluginRegistration.getCreatedCmHandles()); - registerAndSyncNewCmHandles(createdPersistenceCmHandlesList); + final YangModelCmHandlesList createdYangModelCmHandlesList = + getUpdatedYangModelCmHandlesList(dmiPluginRegistration, + dmiPluginRegistration.getCreatedCmHandles()); + registerAndSyncNewCmHandles(createdYangModelCmHandlesList); } private static Object handleResponse(final ResponseEntity<?> responseEntity, @@ -179,29 +223,29 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService networkCmProxyDataServicePropertyHandler.updateCmHandleProperties(dmiPluginRegistration.getUpdatedCmHandles()); } - private PersistenceCmHandlesList getUpdatedPersistenceCmHandlesList( + private YangModelCmHandlesList getUpdatedYangModelCmHandlesList( final DmiPluginRegistration dmiPluginRegistration, - final List<CmHandle> updatedCmHandles) { - return PersistenceCmHandlesList.toPersistenceCmHandlesList( + final List<NcmpServiceCmHandle> updatedCmHandles) { + return YangModelCmHandlesList.toYangModelCmHandlesList( dmiPluginRegistration.getDmiPlugin(), dmiPluginRegistration.getDmiDataPlugin(), dmiPluginRegistration.getDmiModelPlugin(), updatedCmHandles); } - private void registerAndSyncNewCmHandles(final PersistenceCmHandlesList persistenceCmHandlesList) { - final String cmHandleJsonData = jsonObjectMapper.asJsonString(persistenceCmHandlesList); + private void registerAndSyncNewCmHandles(final YangModelCmHandlesList yangModelCmHandlesList) { + final String cmHandleJsonData = jsonObjectMapper.asJsonString(yangModelCmHandlesList); cpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT, cmHandleJsonData, NO_TIMESTAMP); - for (final PersistenceCmHandle persistenceCmHandle : persistenceCmHandlesList.getPersistenceCmHandles()) { - syncModulesAndCreateAnchor(persistenceCmHandle); + for (final YangModelCmHandle yangModelCmHandle : yangModelCmHandlesList.getYangModelCmHandles()) { + syncModulesAndCreateAnchor(yangModelCmHandle); } } - protected void syncModulesAndCreateAnchor(final PersistenceCmHandle persistenceCmHandle) { - syncAndCreateSchemaSet(persistenceCmHandle); - createAnchor(persistenceCmHandle); + protected void syncModulesAndCreateAnchor(final YangModelCmHandle yangModelCmHandle) { + syncAndCreateSchemaSet(yangModelCmHandle); + createAnchor(yangModelCmHandle); } private void parseAndRemoveCmHandlesInDmiRegistration(final DmiPluginRegistration dmiPluginRegistration) { @@ -225,9 +269,9 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService } } - private void syncAndCreateSchemaSet(final PersistenceCmHandle persistenceCmHandle) { + private void syncAndCreateSchemaSet(final YangModelCmHandle yangModelCmHandle) { final Collection<ModuleReference> moduleReferencesFromCmHandle = - dmiModelOperations.getModuleReferences(persistenceCmHandle); + dmiModelOperations.getModuleReferences(yangModelCmHandle); final Collection<ModuleReference> identifiedNewModuleReferencesFromCmHandle = cpsModuleService .identifyNewModuleReferences(moduleReferencesFromCmHandle); @@ -241,16 +285,16 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService if (identifiedNewModuleReferencesFromCmHandle.isEmpty()) { newModuleNameToContentMap = new HashMap<>(); } else { - newModuleNameToContentMap = dmiModelOperations.getNewYangResourcesFromDmi(persistenceCmHandle, + newModuleNameToContentMap = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, identifiedNewModuleReferencesFromCmHandle); } cpsModuleService - .createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, persistenceCmHandle.getId(), + .createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, yangModelCmHandle.getId(), newModuleNameToContentMap, existingModuleReferencesFromCmHandle); } - private void createAnchor(final PersistenceCmHandle persistenceCmHandle) { - cpsAdminService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, persistenceCmHandle.getId(), - persistenceCmHandle.getId()); + private void createAnchor(final YangModelCmHandle yangModelCmHandle) { + cpsAdminService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, yangModelCmHandle.getId(), + yangModelCmHandle.getId()); } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java index 3599213499..ca2f578f46 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java @@ -37,7 +37,7 @@ import java.util.regex.Pattern; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.CpsDataService; -import org.onap.cps.ncmp.api.models.CmHandle; +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.onap.cps.spi.FetchDescendantsOption; import org.onap.cps.spi.exceptions.DataNodeNotFoundException; import org.onap.cps.spi.model.DataNode; @@ -56,28 +56,31 @@ public class NetworkCmProxyDataServicePropertyHandler { private final CpsDataService cpsDataService; /** - * Iterates over incoming cmHandles and update the dataNodes based on the updated attributes. + * Iterates over incoming ncmpServiceCmHandles and update the dataNodes based on the updated attributes. * The attributes which are not passed will remain as is. * - * @param cmHandles collection of cmHandles + * @param ncmpServiceCmHandles collection of ncmpServiceCmHandles */ - public void updateCmHandleProperties(final Collection<CmHandle> cmHandles) throws DataNodeNotFoundException { - for (final CmHandle cmHandle : cmHandles) { + public void updateCmHandleProperties(final Collection<NcmpServiceCmHandle> ncmpServiceCmHandles) + throws DataNodeNotFoundException { + for (final NcmpServiceCmHandle ncmpServiceCmHandle : ncmpServiceCmHandles) { try { - final String cmHandleXpath = String.format(CM_HANDLE_XPATH_TEMPLATE, cmHandle.getCmHandleID()); + final String cmHandleXpath = String.format(CM_HANDLE_XPATH_TEMPLATE, + ncmpServiceCmHandle.getCmHandleID()); final DataNode existingCmHandleDataNode = cpsDataService.getDataNode(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, cmHandleXpath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); - processUpdates(existingCmHandleDataNode, cmHandle); + processUpdates(existingCmHandleDataNode, ncmpServiceCmHandle); } catch (final DataNodeNotFoundException e) { - log.error("Unable to find dataNode for cmHandleId : {} , caused by : {}", cmHandle.getCmHandleID(), + log.error("Unable to find dataNode for cmHandleId : {} , caused by : {}", + ncmpServiceCmHandle.getCmHandleID(), e.getMessage()); throw e; } } } - private void processUpdates(final DataNode existingCmHandleDataNode, final CmHandle incomingCmHandle) { + private void processUpdates(final DataNode existingCmHandleDataNode, final NcmpServiceCmHandle incomingCmHandle) { if (!incomingCmHandle.getPublicProperties().isEmpty()) { updateProperties(existingCmHandleDataNode, PUBLIC_PROPERTY, incomingCmHandle.getPublicProperties()); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java index bce3ac3847..229d4fc917 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java @@ -27,7 +27,7 @@ import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.DATA; import org.onap.cps.ncmp.api.impl.client.DmiRestClient; import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration; -import org.onap.cps.ncmp.api.models.PersistenceCmHandle; +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; import org.onap.cps.utils.JsonObjectMapper; import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity; @@ -44,7 +44,7 @@ public class DmiDataOperations extends DmiOperations { * * @param dmiRestClient {@code DmiRestClient} */ - public DmiDataOperations(final PersistenceCmHandleRetriever cmHandlePropertiesRetriever, + public DmiDataOperations(final YangModelCmHandleRetriever cmHandlePropertiesRetriever, final JsonObjectMapper jsonObjectMapper, final NcmpConfiguration.DmiProperties dmiProperties, final DmiRestClient dmiRestClient) { @@ -55,28 +55,28 @@ public class DmiDataOperations extends DmiOperations { * This method fetches the resource data from operational data store for given cm handle * identifier on given resource using dmi client. * - * @param cmHandle network resource identifier + * @param cmHandleId network resource identifier * @param resourceId resource identifier * @param optionsParamInQuery options query * @param acceptParamInHeader accept parameter * @param dataStore data store enum * @return {@code ResponseEntity} response entity */ - public ResponseEntity<Object> getResourceDataFromDmi(final String cmHandle, + public ResponseEntity<Object> getResourceDataFromDmi(final String cmHandleId, final String resourceId, final String optionsParamInQuery, final String acceptParamInHeader, final DataStoreEnum dataStore) { - final PersistenceCmHandle persistenceCmHandle = - cmHandlePropertiesRetriever.retrieveCmHandleDmiServiceNameAndDmiProperties(cmHandle); + final YangModelCmHandle yangModelCmHandle = + yangModelCmHandleRetriever.getDmiServiceNamesAndProperties(cmHandleId); final DmiRequestBody dmiRequestBody = DmiRequestBody.builder() .operation(READ) .build(); - dmiRequestBody.asDmiProperties(persistenceCmHandle.getDmiProperties()); + dmiRequestBody.asDmiProperties(yangModelCmHandle.getDmiProperties()); final String jsonBody = jsonObjectMapper.asJsonString(dmiRequestBody); final var dmiResourceDataUrl = getDmiDatastoreUrlWithOptions( - persistenceCmHandle.resolveDmiServiceName(DATA), cmHandle, resourceId, + yangModelCmHandle.resolveDmiServiceName(DATA), cmHandleId, resourceId, optionsParamInQuery, dataStore); final var httpHeaders = prepareHeader(acceptParamInHeader); return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonBody, httpHeaders); @@ -86,38 +86,38 @@ public class DmiDataOperations extends DmiOperations { * This method creates the resource data from pass-through running data store for given cm handle * identifier on given resource using dmi client. * - * @param cmHandle network resource identifier + * @param cmHandleId network resource identifier * @param resourceId resource identifier * @param operation operation enum * @param requestData the request data * @param dataType data type * @return {@code ResponseEntity} response entity */ - public ResponseEntity<Object> writeResourceDataPassThroughRunningFromDmi(final String cmHandle, + public ResponseEntity<Object> writeResourceDataPassThroughRunningFromDmi(final String cmHandleId, final String resourceId, final OperationEnum operation, final String requestData, final String dataType) { - final PersistenceCmHandle persistenceCmHandle = - cmHandlePropertiesRetriever.retrieveCmHandleDmiServiceNameAndDmiProperties(cmHandle); + final YangModelCmHandle yangModelCmHandle = + yangModelCmHandleRetriever.getDmiServiceNamesAndProperties(cmHandleId); final DmiRequestBody dmiRequestBody = DmiRequestBody.builder() .operation(operation) .data(requestData) .dataType(dataType) .build(); - dmiRequestBody.asDmiProperties(persistenceCmHandle.getDmiProperties()); + dmiRequestBody.asDmiProperties(yangModelCmHandle.getDmiProperties()); final String jsonBody = jsonObjectMapper.asJsonString(dmiRequestBody); final String dmiUrl = - getResourceInDataStoreUrl(persistenceCmHandle.resolveDmiServiceName(DATA), - cmHandle, resourceId, PASSTHROUGH_RUNNING); + getResourceInDataStoreUrl(yangModelCmHandle.resolveDmiServiceName(DATA), + cmHandleId, resourceId, PASSTHROUGH_RUNNING); return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonBody, new HttpHeaders()); } private String getResourceInDataStoreUrl(final String dmiServiceName, - final String cmHandle, + final String cmHandleId, final String resourceId, final DataStoreEnum dataStoreEnum) { - return getCmHandleUrl(dmiServiceName, cmHandle) + return getCmHandleUrl(dmiServiceName, cmHandleId) + "data" + URL_SEPARATOR + "ds" @@ -128,12 +128,12 @@ public class DmiDataOperations extends DmiOperations { } private String getDmiDatastoreUrlWithOptions(final String dmiServiceName, - final String cmHandle, + final String cmHandleId, final String resourceId, final String optionsParamInQuery, final DataStoreEnum dataStoreEnum) { final String resourceInDataStoreUrl = getResourceInDataStoreUrl(dmiServiceName, - cmHandle, resourceId, dataStoreEnum); + cmHandleId, resourceId, dataStoreEnum); return appendOptionsQuery(resourceInDataStoreUrl, optionsParamInQuery); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java index aec4517c03..bfe934dfd8 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java @@ -31,7 +31,7 @@ import java.util.List; import java.util.Map; import org.onap.cps.ncmp.api.impl.client.DmiRestClient; import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration; -import org.onap.cps.ncmp.api.models.PersistenceCmHandle; +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; import org.onap.cps.ncmp.api.models.YangResource; import org.onap.cps.spi.model.ModuleReference; import org.onap.cps.utils.JsonObjectMapper; @@ -50,7 +50,7 @@ public class DmiModelOperations extends DmiOperations { * * @param dmiRestClient {@code DmiRestClient} */ - public DmiModelOperations(final PersistenceCmHandleRetriever dmiPropertiesRetriever, + public DmiModelOperations(final YangModelCmHandleRetriever dmiPropertiesRetriever, final JsonObjectMapper jsonObjectMapper, final NcmpConfiguration.DmiProperties dmiProperties, final DmiRestClient dmiRestClient) { @@ -60,34 +60,34 @@ public class DmiModelOperations extends DmiOperations { /** * Retrieves module references. * - * @param persistenceCmHandle the persistence cm handle + * @param yangModelCmHandle the yang model cm handle * @return module references */ - public List<ModuleReference> getModuleReferences(final PersistenceCmHandle persistenceCmHandle) { + public List<ModuleReference> getModuleReferences(final YangModelCmHandle yangModelCmHandle) { final DmiRequestBody dmiRequestBody = DmiRequestBody.builder() .build(); - dmiRequestBody.asDmiProperties(persistenceCmHandle.getDmiProperties()); + dmiRequestBody.asDmiProperties(yangModelCmHandle.getDmiProperties()); final ResponseEntity<Object> dmiFetchModulesResponseEntity = getResourceFromDmiWithJsonData( - persistenceCmHandle.resolveDmiServiceName(MODEL), - jsonObjectMapper.asJsonString(dmiRequestBody), persistenceCmHandle.getId(), "modules"); + yangModelCmHandle.resolveDmiServiceName(MODEL), + jsonObjectMapper.asJsonString(dmiRequestBody), yangModelCmHandle.getId(), "modules"); return toModuleReferences((Map) dmiFetchModulesResponseEntity.getBody()); } /** * Retrieve yang resources from dmi for any modules that CPS-NCMP hasn't cached before. * - * @param persistenceCmHandle the persistenceCmHandle + * @param yangModelCmHandle the yangModelCmHandle * @param newModuleReferences the unknown module references * @return yang resources as map of module name to yang(re)source */ - public Map<String, String> getNewYangResourcesFromDmi(final PersistenceCmHandle persistenceCmHandle, + public Map<String, String> getNewYangResourcesFromDmi(final YangModelCmHandle yangModelCmHandle, final Collection<ModuleReference> newModuleReferences) { final String jsonWithDataAndDmiProperties = getRequestBodyToFetchYangResources( - newModuleReferences, persistenceCmHandle.getDmiProperties()); + newModuleReferences, yangModelCmHandle.getDmiProperties()); final ResponseEntity<Object> responseEntity = getResourceFromDmiWithJsonData( - persistenceCmHandle.resolveDmiServiceName(MODEL), + yangModelCmHandle.resolveDmiServiceName(MODEL), jsonWithDataAndDmiProperties, - persistenceCmHandle.getId(), + yangModelCmHandle.getId(), "moduleResources"); return asModuleNameToYangResourceMap(responseEntity); } @@ -110,7 +110,7 @@ public class DmiModelOperations extends DmiOperations { } private static String getRequestBodyToFetchYangResources(final Collection<ModuleReference> newModuleReferences, - final List<PersistenceCmHandle.Property> dmiProperties) { + final List<YangModelCmHandle.Property> dmiProperties) { final JsonArray moduleReferencesAsJson = getModuleReferencesAsJson(newModuleReferences); final JsonObject data = new JsonObject(); data.add("modules", moduleReferencesAsJson); @@ -132,10 +132,10 @@ public class DmiModelOperations extends DmiOperations { return moduleReferences; } - private static JsonObject toJsonObject(final List<PersistenceCmHandle.Property> + private static JsonObject toJsonObject(final List<YangModelCmHandle.Property> dmiProperties) { final JsonObject asJsonObject = new JsonObject(); - for (final PersistenceCmHandle.Property additionalProperty : dmiProperties) { + for (final YangModelCmHandle.Property additionalProperty : dmiProperties) { asJsonObject.addProperty(additionalProperty.getName(), additionalProperty.getValue()); } return asJsonObject; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java index 2f7376e87c..645d9799fb 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java @@ -46,7 +46,7 @@ public class DmiOperations { } } - protected final PersistenceCmHandleRetriever cmHandlePropertiesRetriever; + protected final YangModelCmHandleRetriever yangModelCmHandleRetriever; protected final JsonObjectMapper jsonObjectMapper; protected final NcmpConfiguration.DmiProperties dmiProperties; protected final DmiRestClient dmiRestClient; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiRequestBody.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiRequestBody.java index 1066eacf71..d97e90cbbe 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiRequestBody.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiRequestBody.java @@ -28,7 +28,7 @@ import java.util.List; import java.util.Map; import lombok.Builder; import lombok.Getter; -import org.onap.cps.ncmp.api.models.PersistenceCmHandle; +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; @JsonInclude(JsonInclude.Include.NON_NULL) @Getter @@ -60,14 +60,14 @@ public class DmiRequestBody { private Map<String, String> dmiProperties; /** - * Set DMI Properties by converting a list of PersistenceCmHandle.Property objects. + * Set DMI Properties by converting a list of YangModelCmHandle.Property objects. * - * @param dmiPropertiesAsList list of cm handle dmi properties + * @param yangModelCmHandleProperties list of cm handle dmi properties */ public void asDmiProperties( - final List<PersistenceCmHandle.Property> dmiPropertiesAsList) { + final List<YangModelCmHandle.Property> yangModelCmHandleProperties) { dmiProperties = new LinkedHashMap<>(); - for (final PersistenceCmHandle.Property dmiProperty : dmiPropertiesAsList) { + for (final YangModelCmHandle.Property dmiProperty : yangModelCmHandleProperties) { dmiProperties.put(dmiProperty.getName(), dmiProperty.getValue()); } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/PersistenceCmHandleRetriever.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetriever.java index c489eef8e9..6b6bdf5be4 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/PersistenceCmHandleRetriever.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetriever.java @@ -24,39 +24,39 @@ import java.util.LinkedHashMap; import java.util.Map; import lombok.AllArgsConstructor; import org.onap.cps.api.CpsDataService; -import org.onap.cps.ncmp.api.models.CmHandle; -import org.onap.cps.ncmp.api.models.PersistenceCmHandle; +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.onap.cps.spi.FetchDescendantsOption; import org.onap.cps.spi.model.DataNode; import org.springframework.stereotype.Component; /** - * Retrieves PersistenceCmHandles & properties. + * Retrieves YangModelCmHandles & properties. */ @Component @AllArgsConstructor -public class PersistenceCmHandleRetriever { +public class YangModelCmHandleRetriever { private static final String NCMP_DATASPACE_NAME = "NCMP-Admin"; private static final String NCMP_DMI_REGISTRY_ANCHOR = "ncmp-dmi-registry"; - private final CpsDataService cpsDataService; + private CpsDataService cpsDataService; /** * This method retrieves DMI service name and DMI properties for a given cm handle. * @param cmHandleId the id of the cm handle - * @return persistence cm handle + * @return yang model cm handle */ - public PersistenceCmHandle retrieveCmHandleDmiServiceNameAndDmiProperties(final String cmHandleId) { + public YangModelCmHandle getDmiServiceNamesAndProperties(final String cmHandleId) { final DataNode cmHandleDataNode = getCmHandleDataNode(cmHandleId); - final CmHandle cmHandle = new CmHandle(); - cmHandle.setCmHandleID(cmHandleId); - populateCmHandleDmiProperties(cmHandleDataNode, cmHandle); - return PersistenceCmHandle.toPersistenceCmHandle( + final NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle(); + ncmpServiceCmHandle.setCmHandleID(cmHandleId); + populateCmHandleProperties(cmHandleDataNode, ncmpServiceCmHandle); + return YangModelCmHandle.toYangModelCmHandle( String.valueOf(cmHandleDataNode.getLeaves().get("dmi-service-name")), String.valueOf(cmHandleDataNode.getLeaves().get("dmi-data-service-name")), String.valueOf(cmHandleDataNode.getLeaves().get("dmi-model-service-name")), - cmHandle + ncmpServiceCmHandle ); } @@ -68,14 +68,19 @@ public class PersistenceCmHandleRetriever { FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); } - private static void populateCmHandleDmiProperties(final DataNode cmHandleDataNode, final CmHandle cmHandle) { + private static void populateCmHandleProperties(final DataNode cmHandleDataNode, + final NcmpServiceCmHandle ncmpServiceCmHandle) { final Map<String, String> dmiProperties = new LinkedHashMap<>(); + final Map<String, String> publicProperties = new LinkedHashMap<>(); for (final DataNode childDataNode: cmHandleDataNode.getChildDataNodes()) { if (childDataNode.getXpath().contains("/additional-properties[@name=")) { addProperty(childDataNode, dmiProperties); + } else if (childDataNode.getXpath().contains("/public-properties[@name=")) { + addProperty(childDataNode, publicProperties); } } - cmHandle.setDmiProperties(dmiProperties); + ncmpServiceCmHandle.setDmiProperties(dmiProperties); + ncmpServiceCmHandle.setPublicProperties(publicProperties); } private static void addProperty(final DataNode propertyDataNode, final Map<String, String> propertiesAsMap) { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/PersistenceCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java index cc32bb75c0..47062b3545 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/PersistenceCmHandle.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java @@ -19,7 +19,7 @@ */ -package org.onap.cps.ncmp.api.models; +package org.onap.cps.ncmp.api.impl.yangmodels; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.base.Strings; @@ -32,14 +32,16 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService; +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; /** - * DmiRegistry. + * Cm Handle which follows the Yang resource dmi registry model when persisting data to DMI or the DB. + * Yang model CmHandle */ @Getter @Setter @NoArgsConstructor -public class PersistenceCmHandle { +public class YangModelCmHandle { private String id; @@ -59,25 +61,26 @@ public class PersistenceCmHandle { private List<Property> publicProperties; /** - * Create a persistenceCmHandle. + * Create a yangModelCmHandle. * @param dmiServiceName dmi service name * @param dmiDataServiceName dmi data service name * @param dmiModelServiceName dmi model service name - * @param cmHandle the cm handle - * @return instance of persistenceCmHandle + * @param ncmpServiceCmHandle the cm handle + * @return instance of yangModelCmHandle */ - public static PersistenceCmHandle toPersistenceCmHandle(final String dmiServiceName, - final String dmiDataServiceName, - final String dmiModelServiceName, - final CmHandle cmHandle) { - final PersistenceCmHandle persistenceCmHandle = new PersistenceCmHandle(); - persistenceCmHandle.setId(cmHandle.getCmHandleID()); - persistenceCmHandle.setDmiServiceName(dmiServiceName); - persistenceCmHandle.setDmiDataServiceName(dmiDataServiceName); - persistenceCmHandle.setDmiModelServiceName(dmiModelServiceName); - persistenceCmHandle.setDmiProperties(asPersistenceCmHandleProperties(cmHandle.getDmiProperties())); - persistenceCmHandle.setPublicProperties(asPersistenceCmHandleProperties(cmHandle.getPublicProperties())); - return persistenceCmHandle; + public static YangModelCmHandle toYangModelCmHandle(final String dmiServiceName, + final String dmiDataServiceName, + final String dmiModelServiceName, + final NcmpServiceCmHandle ncmpServiceCmHandle) { + final YangModelCmHandle yangModelCmHandle = new YangModelCmHandle(); + yangModelCmHandle.setId(ncmpServiceCmHandle.getCmHandleID()); + yangModelCmHandle.setDmiServiceName(dmiServiceName); + yangModelCmHandle.setDmiDataServiceName(dmiDataServiceName); + yangModelCmHandle.setDmiModelServiceName(dmiModelServiceName); + yangModelCmHandle.setDmiProperties(asYangModelCmHandleProperties(ncmpServiceCmHandle.getDmiProperties())); + yangModelCmHandle.setPublicProperties(asYangModelCmHandleProperties( + ncmpServiceCmHandle.getPublicProperties())); + return yangModelCmHandle; } /** @@ -95,12 +98,12 @@ public class PersistenceCmHandle { return dmiServiceName; } - private static List<Property> asPersistenceCmHandleProperties(final Map<String, String> propertiesAsMap) { - final List<Property> persistenceCmHandleProperties = new ArrayList<>(propertiesAsMap.size()); + private static List<Property> asYangModelCmHandleProperties(final Map<String, String> propertiesAsMap) { + final List<Property> yangModelCmHandleProperties = new ArrayList<>(propertiesAsMap.size()); for (final Map.Entry<String, String> entry : propertiesAsMap.entrySet()) { - persistenceCmHandleProperties.add(new PersistenceCmHandle.Property(entry.getKey(), entry.getValue())); + yangModelCmHandleProperties.add(new YangModelCmHandle.Property(entry.getKey(), entry.getValue())); } - return persistenceCmHandleProperties; + return yangModelCmHandleProperties; } private static boolean isNullEmptyOrBlank(final String serviceName) { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/PersistenceCmHandlesList.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandlesList.java index 9762ac4e12..261a0181cb 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/PersistenceCmHandlesList.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandlesList.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation + * Copyright (C) 2021-2022 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,51 +18,53 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.api.models; +package org.onap.cps.ncmp.api.impl.yangmodels; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; import java.util.Collection; import java.util.List; import lombok.Getter; +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; @Getter -public class PersistenceCmHandlesList { +public class YangModelCmHandlesList { @JsonProperty("cm-handles") - private final List<PersistenceCmHandle> persistenceCmHandles = new ArrayList<>(); + private final List<YangModelCmHandle> yangModelCmHandles = new ArrayList<>(); /** - * Create a PersistenceCmHandleList given all service names and a collection of cmHandles. + * Create a YangModelCmHandleList given all service names and a collection of cmHandles. * @param dmiServiceName the dmi service name * @param dmiDataServiceName the dmi data service name * @param dmiModelServiceName the dmi model service name - * @param cmHandles cm handles - * @return instance of PersistenceCmHandleList + * @param ncmpServiceCmHandles cm handles rest model + * @return instance of YangModelCmHandleList */ - public static PersistenceCmHandlesList toPersistenceCmHandlesList(final String dmiServiceName, - final String dmiDataServiceName, - final String dmiModelServiceName, - final Collection<CmHandle> cmHandles) { - final PersistenceCmHandlesList persistenceCmHandlesList = new PersistenceCmHandlesList(); - for (final CmHandle cmHandle : cmHandles) { - final PersistenceCmHandle persistenceCmHandle = - PersistenceCmHandle.toPersistenceCmHandle( + public static YangModelCmHandlesList toYangModelCmHandlesList(final String dmiServiceName, + final String dmiDataServiceName, + final String dmiModelServiceName, + final Collection<NcmpServiceCmHandle> + ncmpServiceCmHandles) { + final YangModelCmHandlesList yangModelCmHandlesList = new YangModelCmHandlesList(); + for (final NcmpServiceCmHandle ncmpServiceCmHandle : ncmpServiceCmHandles) { + final YangModelCmHandle yangModelCmHandle = + YangModelCmHandle.toYangModelCmHandle( dmiServiceName, dmiDataServiceName, dmiModelServiceName, - cmHandle); - persistenceCmHandlesList.add(persistenceCmHandle); + ncmpServiceCmHandle); + yangModelCmHandlesList.add(yangModelCmHandle); } - return persistenceCmHandlesList; + return yangModelCmHandlesList; } /** - * Add a persistenceCmHandle. + * Add a yangModelCmHandle. * - * @param persistenceCmHandle the persistenceCmHandle to add + * @param yangModelCmHandle the yangModelCmHandle to add */ - public void add(final PersistenceCmHandle persistenceCmHandle) { - persistenceCmHandles.add(persistenceCmHandle); + public void add(final YangModelCmHandle yangModelCmHandle) { + yangModelCmHandles.add(yangModelCmHandle); } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java index c302f7de5a..d1360c3256 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java @@ -44,15 +44,14 @@ public class DmiPluginRegistration { private String dmiModelPlugin; - private List<CmHandle> createdCmHandles = Collections.emptyList(); + private List<NcmpServiceCmHandle> createdCmHandles = Collections.emptyList(); - private List<CmHandle> updatedCmHandles = Collections.emptyList(); + private List<NcmpServiceCmHandle> updatedCmHandles = Collections.emptyList(); private List<String> removedCmHandles = Collections.emptyList(); /** * Validates plugin service names. - * * @throws NcmpException if validation fails. */ public void validateDmiPluginRegistration() throws NcmpException { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java index 88c6f33762..938127020c 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandle.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java @@ -30,13 +30,14 @@ import lombok.Setter; import org.springframework.validation.annotation.Validated; /** - * CmHandle. + * The NCMP Service model used for the java service API. + * NCMP Service CmHandle. */ @Validated @Getter @Setter @NoArgsConstructor -public class CmHandle { +public class NcmpServiceCmHandle { private String cmHandleID; diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplModelSyncSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplModelSyncSpec.groovy index 3f82f5e0b7..553ac72790 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplModelSyncSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplModelSyncSpec.groovy @@ -24,8 +24,9 @@ import org.onap.cps.api.CpsAdminService import org.onap.cps.api.CpsModuleService import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations -import org.onap.cps.ncmp.api.models.CmHandle -import org.onap.cps.ncmp.api.models.PersistenceCmHandle +import org.onap.cps.ncmp.api.impl.operations.YangModelCmHandleRetriever +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle import org.onap.cps.spi.model.ModuleReference import org.onap.cps.utils.JsonObjectMapper import spock.lang.Specification @@ -38,34 +39,35 @@ class NetworkCmProxyDataServiceImplModelSyncSpec extends Specification { def mockCpsAdminService = Mock(CpsAdminService) def mockDmiModelOperations = Mock(DmiModelOperations) def mockDmiDataOperations = Mock(DmiDataOperations) + def mockYangModelCmHandleRetriever = Mock(YangModelCmHandleRetriever) def nullNetworkCmProxyDataServicePropertyHandler = null def objectUnderTest = new NetworkCmProxyDataServiceImpl(nullCpsDataService, mockJsonObjectMapper, mockDmiDataOperations, mockDmiModelOperations, - mockCpsModuleService, mockCpsAdminService, nullNetworkCmProxyDataServicePropertyHandler) + mockCpsModuleService, mockCpsAdminService, nullNetworkCmProxyDataServicePropertyHandler,mockYangModelCmHandleRetriever) def expectedDataspaceName = 'NFP-Operational' def 'Sync model for a (new) cm handle with #scenario'() { - given: 'persistence cm handle is given' - def cmHandle = new CmHandle() + given: 'a cm handle' + def ncmpServiceCmHandle = new NcmpServiceCmHandle() def dmiServiceName = 'some service name' - cmHandle.cmHandleID = 'cm handle id 1' - def persistenceCmHandle = PersistenceCmHandle.toPersistenceCmHandle(dmiServiceName, '' , '', cmHandle) + ncmpServiceCmHandle.cmHandleID = 'cm handle id 1' + def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, '' , '', ncmpServiceCmHandle) and: 'DMI operations returns some module references' def moduleReferences = [ new ModuleReference(moduleName:'module1',revision:'1'), new ModuleReference(moduleName:'module2',revision:'2') ] - mockDmiModelOperations.getModuleReferences(persistenceCmHandle) >> moduleReferences + mockDmiModelOperations.getModuleReferences(yangModelCmHandle) >> moduleReferences and: 'CPS-Core returns list of existing module resources' mockCpsModuleService.getYangResourceModuleReferences(expectedDataspaceName) >> toModuleReference(existingModuleResourcesInCps) and: 'DMI-Plugin returns resource(s) for "new" module(s)' - mockDmiModelOperations.getNewYangResourcesFromDmi(persistenceCmHandle, [new ModuleReference('module1', '1')]) >> yangResourceToContentMap + mockDmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, [new ModuleReference('module1', '1')]) >> yangResourceToContentMap when: 'module sync is triggered' mockCpsModuleService.identifyNewModuleReferences(moduleReferences) >> toModuleReference(identifiedNewModuleReferences) - objectUnderTest.syncModulesAndCreateAnchor(persistenceCmHandle) + objectUnderTest.syncModulesAndCreateAnchor(yangModelCmHandle) then: 'the CPS module service is called once with the correct parameters' - 1 * mockCpsModuleService.createSchemaSetFromModules(expectedDataspaceName, persistenceCmHandle.getId(), yangResourceToContentMap, toModuleReference(expectedKnownModules)) + 1 * mockCpsModuleService.createSchemaSetFromModules(expectedDataspaceName, yangModelCmHandle.getId(), yangResourceToContentMap, toModuleReference(expectedKnownModules)) and: 'admin service create anchor method has been called with correct parameters' - 1 * mockCpsAdminService.createAnchor(expectedDataspaceName, persistenceCmHandle.getId(), persistenceCmHandle.getId()) + 1 * mockCpsAdminService.createAnchor(expectedDataspaceName, yangModelCmHandle.getId(), yangModelCmHandle.getId()) where: 'the following parameters are used' scenario | existingModuleResourcesInCps | identifiedNewModuleReferences | yangResourceToContentMap || expectedKnownModules 'one new module' | [['module2' : '2'], ['module3' : '3']] | [['module1' : '1']] | [module1: 'some yang source'] || [['module2' : '2']] diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy index a475f9c345..e410463afa 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy @@ -28,8 +28,9 @@ import org.onap.cps.api.CpsModuleService import org.onap.cps.ncmp.api.impl.exception.DmiRequestException import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations -import org.onap.cps.ncmp.api.models.CmHandle +import org.onap.cps.ncmp.api.impl.operations.YangModelCmHandleRetriever import org.onap.cps.ncmp.api.models.DmiPluginRegistration +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle import org.onap.cps.spi.exceptions.DataNodeNotFoundException import org.onap.cps.spi.exceptions.DataValidationException import org.onap.cps.utils.JsonObjectMapper @@ -41,7 +42,7 @@ import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { @Shared - def persistenceCmHandle = new CmHandle() + def ncmpServiceCmHandle = new NcmpServiceCmHandle() @Shared def cmHandlesArray = ['cmHandle001'] @@ -53,16 +54,17 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { def mockDmiModelOperations = Mock(DmiModelOperations) def mockDmiDataOperations = Mock(DmiDataOperations) def mockNetworkCmProxyDataServicePropertyHandler = Mock(NetworkCmProxyDataServicePropertyHandler) + def mockYangModelCmHandleRetriever = Mock(YangModelCmHandleRetriever) def noTimestamp = null def 'Register or re-register a DMI Plugin for the given cm-handle(s) with #scenario process.'() { given: 'a registration' def objectUnderTest = getObjectUnderTestWithModelSyncDisabled() - def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server') - persistenceCmHandle.cmHandleID = '123' - persistenceCmHandle.dmiProperties = [dmiProp1: 'dmiValue1', dmiProp2: 'dmiValue2'] - persistenceCmHandle.publicProperties = [publicProp1: 'publicValue1', publicProp2: 'publicValue2'] + def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin:'my-server') + ncmpServiceCmHandle.cmHandleID = '123' + ncmpServiceCmHandle.dmiProperties = [dmiProp1: 'dmiValue1', dmiProp2: 'dmiValue2'] + ncmpServiceCmHandle.publicProperties = [publicProp1: 'publicValue1', publicProp2: 'publicValue2' ] dmiPluginRegistration.createdCmHandles = createdCmHandles dmiPluginRegistration.updatedCmHandles = updatedCmHandles dmiPluginRegistration.removedCmHandles = removedCmHandles @@ -81,13 +83,13 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { expectedCallsToDeleteSchemaSetAndListElement * mockCpsModuleService.deleteSchemaSet('NFP-Operational', 'cmHandle001', CASCADE_DELETE_ALLOWED) and: 'delete list or list element is invoked with the correct parameters' expectedCallsToDeleteSchemaSetAndListElement * mockCpsDataService.deleteListOrListElement('NCMP-Admin', - 'ncmp-dmi-registry', "/dmi-registry/cm-handles[@id='cmHandle001']", noTimestamp) + 'ncmp-dmi-registry', "/dmi-registry/cm-handles[@id='cmHandle001']", noTimestamp) where: scenario | createdCmHandles | updatedCmHandles | removedCmHandles || expectedCallsToSaveNode | expectedCallsToDeleteSchemaSetAndListElement | expectedCallsToUpdateCmHandleProperty - 'create' | [persistenceCmHandle] | [] | [] || 1 | 0 | 0 - 'update' | [] | [persistenceCmHandle] | [] || 0 | 0 | 1 + 'create' | [ncmpServiceCmHandle] | [] | [] || 1 | 0 | 0 + 'update' | [] | [ncmpServiceCmHandle] | [] || 0 | 0 | 1 'delete' | [] | [] | cmHandlesArray || 0 | 1 | 0 - 'create, update and delete' | [persistenceCmHandle] | [persistenceCmHandle] | cmHandlesArray || 1 | 1 | 1 + 'create, update and delete' | [ncmpServiceCmHandle] | [ncmpServiceCmHandle] | cmHandlesArray || 1 | 1 | 1 'no valid data' | [] | [] | [] || 0 | 0 | 0 } @@ -95,10 +97,10 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { given: 'a registration without cm-handle properties' NetworkCmProxyDataServiceImpl objectUnderTest = getObjectUnderTestWithModelSyncDisabled() def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin:'my-server') - persistenceCmHandle.cmHandleID = '123' - persistenceCmHandle.dmiProperties = Collections.emptyMap() - persistenceCmHandle.publicProperties = Collections.emptyMap() - dmiPluginRegistration.createdCmHandles = [persistenceCmHandle] + ncmpServiceCmHandle.cmHandleID = '123' + ncmpServiceCmHandle.dmiProperties = Collections.emptyMap() + ncmpServiceCmHandle.publicProperties = Collections.emptyMap() + dmiPluginRegistration.createdCmHandles = [ncmpServiceCmHandle] def expectedJsonData = '{"cm-handles":[{"id":"123","dmi-service-name":"my-server","dmi-data-service-name":null,"dmi-model-service-name":null,"additional-properties":[],"public-properties":[]}]}' when: 'registration is updated' objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration) @@ -111,7 +113,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { given: 'a registration without cm-handle properties ' NetworkCmProxyDataServiceImpl objectUnderTest = getObjectUnderTestWithModelSyncDisabled() def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin:'some-plugin') - dmiPluginRegistration.createdCmHandles = [persistenceCmHandle] + dmiPluginRegistration.createdCmHandles = [ncmpServiceCmHandle] and: 'an json processing exception occurs' spiedJsonObjectMapper.asJsonString(_) >> { throw (new JsonProcessingException('')) } when: 'registration is updated and modules are synced' @@ -151,7 +153,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { def objectUnderTest = getObjectUnderTestWithModelSyncDisabled() def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin:dmiPlugin, dmiModelPlugin:dmiModelPlugin, dmiDataPlugin:dmiDataPlugin) - dmiPluginRegistration.createdCmHandles = [persistenceCmHandle] + dmiPluginRegistration.createdCmHandles = [ncmpServiceCmHandle] when: 'update registration and sync module is called with correct DMI plugin information' objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration) then: 'create cm handles registration and sync modules is called with the correct plugin information' @@ -168,7 +170,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { def objectUnderTest = getObjectUnderTestWithModelSyncDisabled() def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin:dmiPlugin, dmiModelPlugin:dmiModelPlugin, dmiDataPlugin:dmiDataPlugin) - dmiPluginRegistration.createdCmHandles = [persistenceCmHandle] + dmiPluginRegistration.createdCmHandles = [ncmpServiceCmHandle] when: 'registration is called with incorrect DMI plugin information' objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration) then: 'a DMI Request Exception is thrown with correct message details' @@ -194,7 +196,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { and: 'dmi plugin registration input update request' def dmiPluginReg = new DmiPluginRegistration(); dmiPluginReg.dmiPlugin = 'onap.dmap.plugin'; - dmiPluginReg.updatedCmHandles = [new CmHandle(cmHandleID: 'unknownHandle')] + dmiPluginReg.updatedCmHandles = [new NcmpServiceCmHandle(cmHandleID: 'unknownHandle')] and: 'update data node leaves is unable to find data node' mockNetworkCmProxyDataServicePropertyHandler.updateCmHandleProperties(*_) >> { throw new DataNodeNotFoundException('NCMP-Admin', 'ncmp-dmi-registry') } when: 'update dmi registration is called' @@ -206,7 +208,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { def getObjectUnderTestWithModelSyncDisabled() { def objectUnderTest = Spy(new NetworkCmProxyDataServiceImpl(mockCpsDataService, spiedJsonObjectMapper, mockDmiDataOperations, mockDmiModelOperations, - mockCpsModuleService, mockCpsAdminService, mockNetworkCmProxyDataServicePropertyHandler)) + mockCpsModuleService, mockCpsAdminService, mockNetworkCmProxyDataServicePropertyHandler,mockYangModelCmHandleRetriever)) objectUnderTest.syncModulesAndCreateAnchor(*_) >> null return objectUnderTest } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy index 6d7bdefb8b..b2a3d77cac 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy @@ -22,6 +22,9 @@ package org.onap.cps.ncmp.api.impl +import org.onap.cps.ncmp.api.impl.operations.YangModelCmHandleRetriever +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle + import static org.onap.cps.ncmp.api.impl.operations.DmiOperations.DataStoreEnum.PASSTHROUGH_OPERATIONAL import static org.onap.cps.ncmp.api.impl.operations.DmiOperations.DataStoreEnum.PASSTHROUGH_RUNNING import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.CREATE @@ -52,9 +55,10 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { def mockDmiModelOperations = Mock(DmiModelOperations) def mockDmiDataOperations = Mock(DmiDataOperations) def nullNetworkCmProxyDataServicePropertyHandler = null + def mockYangModelCmHandleRetriever = Mock(YangModelCmHandleRetriever) def objectUnderTest = new NetworkCmProxyDataServiceImpl(mockCpsDataService, spiedJsonObjectMapper, mockDmiDataOperations, mockDmiModelOperations, - mockCpsModuleService, mockCpsAdminService, nullNetworkCmProxyDataServicePropertyHandler) + mockCpsModuleService, mockCpsAdminService, nullNetworkCmProxyDataServicePropertyHandler, mockYangModelCmHandleRetriever) def cmHandleXPath = "/dmi-registry/cm-handles[@id='testCmHandle']" @@ -210,6 +214,22 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { 1 * mockCpsAdminService.queryAnchorNames('NFP-Operational', ['some-module-name']) } + def 'Get a cm handle.'() { + given: 'the system returns a yang modelled cm handle' + def dmiServiceName = 'some service name' + def dmiProperties = [new YangModelCmHandle.Property('Book', 'Romance Novel')] + def publicProperties = [new YangModelCmHandle.Property('Public Book', 'Public Romance Novel')] + def yangModelCmHandle = new YangModelCmHandle(id:'Some-Cm-Handle', dmiServiceName: dmiServiceName, dmiProperties: dmiProperties, publicProperties: publicProperties) + 1 * mockYangModelCmHandleRetriever.getDmiServiceNamesAndProperties('Some-Cm-Handle') >> yangModelCmHandle + when: 'getting cm handle details for a given cm handle id from ncmp service' + def result = objectUnderTest.getNcmpServiceCmHandle('Some-Cm-Handle') + then: 'the result returns the correct data' + result.cmHandleID == 'Some-Cm-Handle' + result.dmiProperties ==[ Book:'Romance Novel' ] + result.publicProperties == [ "Public Book":'Public Romance Novel' ] + + } + def 'Update resource data for pass-through running from dmi using POST #scenario DMI properties.'() { given: 'cpsDataService returns valid datanode' mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry', diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy index 5bdb744b21..9b8d4ada56 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy @@ -21,7 +21,7 @@ package org.onap.cps.ncmp.api.impl import org.onap.cps.api.CpsDataService -import org.onap.cps.ncmp.api.models.CmHandle +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle import org.onap.cps.spi.FetchDescendantsOption import org.onap.cps.spi.exceptions.DataNodeNotFoundException import org.onap.cps.spi.exceptions.DataValidationException @@ -50,7 +50,7 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification { given: 'the CPS service return a CM handle' mockCpsDataService.getDataNode(dataspaceName, anchorName, cmHandleXpath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> cmHandleDataNode and: 'an update cm handle request with public properties updates' - def cmHandleUpdateRequest = [new CmHandle(cmHandleID: cmHandleId, publicProperties: updatedPublicProperties)] + def cmHandleUpdateRequest = [new NcmpServiceCmHandle(cmHandleID: cmHandleId, publicProperties: updatedPublicProperties)] when: 'update data node leaves is called with the update request' objectUnderTest.updateCmHandleProperties(cmHandleUpdateRequest) then: 'the replace list method is called with correct params' @@ -72,7 +72,7 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification { given: 'the CPS service return a CM handle' mockCpsDataService.getDataNode(dataspaceName, anchorName, cmHandleXpath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> cmHandleDataNode and: 'an update cm handle request with DMI properties updates' - def cmHandleUpdateRequest = [new CmHandle(cmHandleID: cmHandleId, dmiProperties: updatedDmiProperties)] + def cmHandleUpdateRequest = [new NcmpServiceCmHandle(cmHandleID: cmHandleId, dmiProperties: updatedDmiProperties)] when: 'update data node leaves is called with the update request' objectUnderTest.updateCmHandleProperties(cmHandleUpdateRequest) then: 'replace list method should is called with correct params' @@ -96,7 +96,7 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification { def cmHandleDataNode = new DataNode(xpath: cmHandleXpath, childDataNodes: originalPropertyDataNodes) mockCpsDataService.getDataNode(dataspaceName, anchorName, cmHandleXpath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> cmHandleDataNode and: 'an update cm handle request that removes all public properties(existing and non-existing)' - def cmHandleUpdateRequest = [new CmHandle(cmHandleID: cmHandleId, publicProperties: ['publicProp3': null, 'publicProp4': null])] + def cmHandleUpdateRequest = [new NcmpServiceCmHandle(cmHandleID: cmHandleId, publicProperties: ['publicProp3': null, 'publicProp4': null])] when: 'update data node leaves is called with the update request' objectUnderTest.updateCmHandleProperties(cmHandleUpdateRequest) then: 'the replace list method is not called' @@ -115,7 +115,7 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification { def 'Exception thrown when we try to update cmHandle'() { given: 'cm handles request' - def cmHandleUpdateRequest = [new CmHandle(cmHandleID: cmHandleId, publicProperties: [:], dmiProperties: [:])] + def cmHandleUpdateRequest = [new NcmpServiceCmHandle(cmHandleID: cmHandleId, publicProperties: [:], dmiProperties: [:])] and: 'data node cannot be found' mockCpsDataService.getDataNode(*_) >> { throw new DataNodeNotFoundException(dataspaceName, anchorName, cmHandleXpath) } when: 'update data node leaves is called using correct parameters' diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy index 7873f39bbd..e585825ca3 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy @@ -46,8 +46,8 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec { DmiDataOperations objectUnderTest def 'call get resource data for #expectedDatastoreInUrl from DMI #scenario.'() { - given: 'a persistence cm handle for #cmHandleId' - mockPersistenceCmHandleRetrieval(dmiProperties) + given: 'a cm handle for #cmHandleId' + mockYangModelCmHandleRetrieval(dmiProperties) and: 'a positive response from DMI service when it is called with the expected parameters' def responseFromDmi = new ResponseEntity<Object>(HttpStatus.OK) mockDmiRestClient.postOperationWithJsonData( @@ -60,15 +60,15 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec { where: 'the following parameters are used' scenario | dmiProperties | dataStore | options || expectedJson | expectedDatastoreInUrl | expectedOptionsInUrl 'without properties' | [] | PASSTHROUGH_OPERATIONAL | '(a=1,b=2)' || '{"operation":"read","cmHandleProperties":{}}' | 'passthrough-operational' | '&options=(a=1,b=2)' - 'with properties' | [dmiSampleProperty] | PASSTHROUGH_OPERATIONAL | '(a=1,b=2)' || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | '&options=(a=1,b=2)' - 'null options' | [dmiSampleProperty] | PASSTHROUGH_OPERATIONAL | null || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | '' - 'empty options' | [dmiSampleProperty] | PASSTHROUGH_OPERATIONAL | '' || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | '' + 'with properties' | [yangModelCmHandleProperty] | PASSTHROUGH_OPERATIONAL | '(a=1,b=2)' || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | '&options=(a=1,b=2)' + 'null options' | [yangModelCmHandleProperty] | PASSTHROUGH_OPERATIONAL | null || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | '' + 'empty options' | [yangModelCmHandleProperty] | PASSTHROUGH_OPERATIONAL | '' || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | '' 'datastore running' | [] | PASSTHROUGH_RUNNING | '(a=1,b=2)' || '{"operation":"read","cmHandleProperties":{}}' | 'passthrough-running' | '&options=(a=1,b=2)' } def 'Write data for pass-through:running datastore in DMI.'() { - given: 'a persistence cm handle for #cmHandleId' - mockPersistenceCmHandleRetrieval([dmiSampleProperty]) + given: 'a cm handle for #cmHandleId' + mockYangModelCmHandleRetrieval([yangModelCmHandleProperty]) and: 'a positive response from DMI service when it is called with the expected parameters' def expectedUrl = "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/data/ds" + "/ncmp-datastore:passthrough-running?resourceIdentifier=${resourceIdentifier}" diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy index bd5fe6f87c..cd2cb7112c 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy @@ -47,28 +47,28 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { JsonObjectMapper spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper())) def 'Retrieving module references.'() { - given: 'a persistence cm handle' - mockPersistenceCmHandleRetrieval([]) + given: 'a cm handle' + mockYangModelCmHandleRetrieval([]) and: 'a positive response from DMI service when it is called with the expected parameters' def moduleReferencesAsLisOfMaps = [[moduleName:'mod1',revision:'A'],[moduleName:'mod2',revision:'X']] def responseFromDmi = new ResponseEntity([schemas:moduleReferencesAsLisOfMaps], HttpStatus.OK) mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/modules", '{"cmHandleProperties":{}}', [:]) >> responseFromDmi when: 'get module references is called' - def result = objectUnderTest.getModuleReferences(persistenceCmHandle) + def result = objectUnderTest.getModuleReferences(yangModelCmHandle) then: 'the result consists of expected module references' assert result == [new ModuleReference(moduleName:'mod1',revision:'A'), new ModuleReference(moduleName:'mod2',revision:'X')] } def 'Retrieving module references edge case: #scenario.'() { - given: 'a persistence cm handle' - mockPersistenceCmHandleRetrieval([]) + given: 'a cm handle' + mockYangModelCmHandleRetrieval([]) and: 'any response from DMI service when it is called with the expected parameters' // TODO (toine): production code ignores any error code from DMI, this should be improved in future def responseFromDmi = new ResponseEntity(bodyAsMap, HttpStatus.NO_CONTENT) mockDmiRestClient.postOperationWithJsonData(*_) >> responseFromDmi when: 'get module references is called' - def result = objectUnderTest.getModuleReferences(persistenceCmHandle) + def result = objectUnderTest.getModuleReferences(yangModelCmHandle) then: 'the result is empty' assert result == [] where: 'the DMI response body has the following content' @@ -80,25 +80,25 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { } def 'Retrieving module references, DMI property handling: #scenario.'() { - given: 'a persistence cm handle' - mockPersistenceCmHandleRetrieval(dmiProperties) + given: 'a cm handle' + mockYangModelCmHandleRetrieval(dmiProperties) and: 'a positive response from DMI service when it is called with tha expected parameters' def responseFromDmi = new ResponseEntity<String>(HttpStatus.OK) mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/modules", '{"cmHandleProperties":' + expectedAdditionalPropertiesInRequest + '}', [:]) >> responseFromDmi when: 'a get module references is called' - def result = objectUnderTest.getModuleReferences(persistenceCmHandle) + def result = objectUnderTest.getModuleReferences(yangModelCmHandle) then: 'the result is the response from DMI service' assert result == [] where: 'the following DMI properties are used' scenario | dmiProperties || expectedAdditionalPropertiesInRequest - 'with properties' | [dmiSampleProperty] || '{"prop1":"val1"}' + 'with properties' | [yangModelCmHandleProperty] || '{"prop1":"val1"}' 'without properties' | [] || '{}' } def 'Retrieving yang resources.'() { - given: 'a persistence cm handle' - mockPersistenceCmHandleRetrieval([]) + given: 'a cm handle' + mockYangModelCmHandleRetrieval([]) and: 'a positive response from DMI service when it is called with the expected parameters' def responseFromDmi = new ResponseEntity([[moduleName: 'mod1', revision: 'A', yangSource: 'some yang source'], [moduleName: 'mod2', revision: 'C', yangSource: 'other yang source']], HttpStatus.OK) @@ -106,7 +106,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources", '{"data":{"modules":[' + expectedModuleReferencesInRequest + ']},"cmHandleProperties":{}}', [:]) >> responseFromDmi when: 'get new yang resources from DMI service' - def result = objectUnderTest.getNewYangResourcesFromDmi(persistenceCmHandle, newModuleReferences) + def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, newModuleReferences) then: 'the result has the 2 expected yang (re)sources (order is not guaranteed)' assert result.size() == 2 assert result.get('mod1') == 'some yang source' @@ -114,14 +114,14 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { } def 'Retrieving yang resources, edge case: scenario.'() { - given: 'a persistence cm handle' - mockPersistenceCmHandleRetrieval([]) + given: 'a cm handle' + mockYangModelCmHandleRetrieval([]) and: 'a positive response from DMI service when it is called with tha expected parameters' // TODO (toine): production code ignores any error code from DMI, this should be improved in future def responseFromDmi = new ResponseEntity(responseFromDmiBody, HttpStatus.NO_CONTENT) mockDmiRestClient.postOperationWithJsonData(*_) >> responseFromDmi when: 'get new yang resources from DMI service' - def result = objectUnderTest.getNewYangResourcesFromDmi(persistenceCmHandle, newModuleReferences) + def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, newModuleReferences) then: 'the result is empty' assert result == [:] where: 'the DMI response body has the following content' @@ -131,40 +131,40 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { } def 'Retrieving yang resources, DMI property handling #scenario.'() { - given: 'a persistence cm handle' - mockPersistenceCmHandleRetrieval(dmiProperties) + given: 'a cm handle' + mockYangModelCmHandleRetrieval(dmiProperties) and: 'a positive response from DMI service when it is called with the expected parameters' def responseFromDmi = new ResponseEntity<>([[moduleName: 'mod1', revision: 'A', yangSource: 'some yang source']], HttpStatus.OK) mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources", '{"data":{"modules":[' + expectedModuleReferencesInRequest + ']},"cmHandleProperties":'+expectedAdditionalPropertiesInRequest+'}', [:]) >> responseFromDmi when: 'get new yang resources from DMI service' - def result = objectUnderTest.getNewYangResourcesFromDmi(persistenceCmHandle, unknownModuleReferences) + def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, unknownModuleReferences) then: 'the result is the response from DMI service' assert result == [mod1:'some yang source'] where: 'the following DMI properties are used' scenario | dmiProperties | unknownModuleReferences || expectedAdditionalPropertiesInRequest | expectedModuleReferencesInRequest - 'with module references and properties' | [dmiSampleProperty] | newModuleReferences || '{"prop1":"val1"}' | '{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}' - 'without module references' | [dmiSampleProperty] | [] || '{"prop1":"val1"}' | '' + 'with module references and properties' | [yangModelCmHandleProperty] | newModuleReferences || '{"prop1":"val1"}' | '{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}' + 'without module references' | [yangModelCmHandleProperty] | [] || '{"prop1":"val1"}' | '' 'without properties' | [] | newModuleReferences || '{}' | '{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}' } def 'Retrieving yang resources from DMI with null DMI properties.'() { - given: 'a persistence cm handle' - mockPersistenceCmHandleRetrieval(null) + given: 'a cm handle' + mockYangModelCmHandleRetrieval(null) when: 'a get new yang resources from DMI is called' - objectUnderTest.getNewYangResourcesFromDmi(persistenceCmHandle, []) + objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, []) then: 'a null pointer is thrown (we might need to address this later)' thrown(NullPointerException) } def 'Retrieving module references with Json processing exception.'() { - given: 'a persistence cm handle' - mockPersistenceCmHandleRetrieval([]) + given: 'a cm handle' + mockYangModelCmHandleRetrieval([]) and: 'a Json processing exception occurs' spiedJsonObjectMapper.asJsonString(_) >> {throw (new JsonProcessingException('parsing error'))} when: 'a DMI operation is executed' - objectUnderTest.getModuleReferences(persistenceCmHandle) + objectUnderTest.getModuleReferences(yangModelCmHandle) then: 'an ncmp exception is thrown' def exceptionThrown = thrown(JsonProcessingException) and: 'the message indicates a parsing error' diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy index 7b295f68b1..dd0d64dd61 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy @@ -22,7 +22,7 @@ package org.onap.cps.ncmp.api.impl.operations import com.fasterxml.jackson.databind.ObjectMapper import org.onap.cps.ncmp.api.impl.client.DmiRestClient -import org.onap.cps.ncmp.api.models.PersistenceCmHandle +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle import org.spockframework.spring.SpringBean import spock.lang.Shared import spock.lang.Specification @@ -30,27 +30,27 @@ import spock.lang.Specification abstract class DmiOperationsBaseSpec extends Specification { @Shared - def dmiSampleProperty = new PersistenceCmHandle.Property('prop1', 'val1') + def yangModelCmHandleProperty = new YangModelCmHandle.Property('prop1', 'val1') @SpringBean DmiRestClient mockDmiRestClient = Mock() @SpringBean - PersistenceCmHandleRetriever mockCmHandlePropertiesRetriever = Mock() + YangModelCmHandleRetriever mockCmHandlePropertiesRetriever = Mock() @SpringBean ObjectMapper spyObjectMapper = Spy() - def persistenceCmHandle = new PersistenceCmHandle() + def yangModelCmHandle = new YangModelCmHandle() def static dmiServiceName = 'some service name' def static cmHandleId = 'some cm handle' def static resourceIdentifier = 'parent/child' - def mockPersistenceCmHandleRetrieval(dmiProperties) { - persistenceCmHandle.dmiDataServiceName = dmiServiceName - persistenceCmHandle.dmiServiceName = dmiServiceName - persistenceCmHandle.dmiProperties = dmiProperties - persistenceCmHandle.id = cmHandleId - mockCmHandlePropertiesRetriever.retrieveCmHandleDmiServiceNameAndDmiProperties(cmHandleId) >> persistenceCmHandle + def mockYangModelCmHandleRetrieval(dmiProperties) { + yangModelCmHandle.dmiDataServiceName = dmiServiceName + yangModelCmHandle.dmiServiceName = dmiServiceName + yangModelCmHandle.dmiProperties = dmiProperties + yangModelCmHandle.id = cmHandleId + mockCmHandlePropertiesRetriever.getDmiServiceNamesAndProperties(cmHandleId) >> yangModelCmHandle } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/PersistenceCmHandleRetrieverSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/PersistenceCmHandleRetrieverSpec.groovy deleted file mode 100644 index c92234f9a6..0000000000 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/PersistenceCmHandleRetrieverSpec.groovy +++ /dev/null @@ -1,63 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021-2022 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.api.impl.operations - -import org.onap.cps.api.CpsDataService -import org.onap.cps.ncmp.api.models.PersistenceCmHandle -import spock.lang.Shared - -import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS -import org.onap.cps.spi.model.DataNode -import spock.lang.Specification - -class PersistenceCmHandleRetrieverSpec extends Specification { - - def mockCpsDataService = Mock(CpsDataService) - - def objectUnderTest = new PersistenceCmHandleRetriever(mockCpsDataService) - - def cmHandleId = 'some cm handle' - def leaves = ["dmi-service-name":"common service name","dmi-data-service-name":"data service name","dmi-model-service-name":"model service name"] - def xpath = "/dmi-registry/cm-handles[@id='some cm handle']" - - @Shared - def childDataNodesForCmHandleProperties = [new DataNode(xpath: "/dmi-registry/cm-handles[@id='some cm handle']/additional-properties[@name='name1']", leaves: ["name":"name1","value":"value1"]), - new DataNode(xpath: "/dmi-registry/cm-handles[@id='some cm handle']/public-properties[@name='name2']", leaves: ["name":"name2","value":"value2"])] - - def "Retrieve CmHandle using datanode #scenario."() { - given: 'the cps data service returns a data node from the DMI registry' - def dataNode = new DataNode(childDataNodes:childDataNodes, leaves: leaves) - mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry', xpath, INCLUDE_ALL_DESCENDANTS) >> dataNode - when: 'retrieving the persisted cm handle' - def result = objectUnderTest.retrieveCmHandleDmiServiceNameAndDmiProperties(cmHandleId) - then: 'the result has the correct id and service names' - result.id == cmHandleId - result.dmiServiceName == 'common service name' - result.dmiDataServiceName == 'data service name' - result.dmiModelServiceName == 'model service name' - and: 'the expected DMI properties' - result.dmiProperties == expectedCmHandleProperties - where: 'the following parameters are used' - scenario | childDataNodes || expectedCmHandleProperties - 'without DMI properties' | [] || [] - 'with DMI properties' | childDataNodesForCmHandleProperties || [new PersistenceCmHandle.Property("name1", "value1")] - } -} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetrieverSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetrieverSpec.groovy new file mode 100644 index 0000000000..593a6ec936 --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetrieverSpec.groovy @@ -0,0 +1,72 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021-2022 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.api.impl.operations + +import org.onap.cps.api.CpsDataService +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle +import spock.lang.Shared + +import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS +import org.onap.cps.spi.model.DataNode +import spock.lang.Specification + +class YangModelCmHandleRetrieverSpec extends Specification { + + def mockCpsDataService = Mock(CpsDataService) + + def objectUnderTest = new YangModelCmHandleRetriever(mockCpsDataService) + + def cmHandleId = 'some cm handle' + def leaves = ["dmi-service-name":"common service name","dmi-data-service-name":"data service name","dmi-model-service-name":"model service name"] + def xpath = "/dmi-registry/cm-handles[@id='some cm handle']" + + @Shared + def childDataNodesForCmHandleWithAllProperties = [new DataNode(xpath: "/dmi-registry/cm-handles[@id='some cm handle']/additional-properties[@name='name1']", leaves: ["name":"name1", "value":"value1"]), + new DataNode(xpath: "/dmi-registry/cm-handles[@id='some cm handle']/public-properties[@name='name2']", leaves: ["name":"name2","value":"value2"])] + + @Shared + def childDataNodesForCmHandleWithDMIProperties = [new DataNode(xpath: "/dmi-registry/cm-handles[@id='some cm handle']/additional-properties[@name='name1']", leaves: ["name":"name1", "value":"value1"])] + + @Shared + def childDataNodesForCmHandleWithPublicProperties = [new DataNode(xpath: "/dmi-registry/cm-handles[@id='some cm handle']/public-properties[@name='name2']", leaves: ["name":"name2","value":"value2"])] + + def "Retrieve CmHandle using datanode with #scenario."() { + given: 'the cps data service returns a data node from the DMI registry' + def dataNode = new DataNode(childDataNodes:childDataNodes, leaves: leaves) + mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry', xpath, INCLUDE_ALL_DESCENDANTS) >> dataNode + when: 'retrieving the yang modelled cm handle' + def result = objectUnderTest.getDmiServiceNamesAndProperties(cmHandleId) + then: 'the result has the correct id and service names' + result.id == cmHandleId + result.dmiServiceName == 'common service name' + result.dmiDataServiceName == 'data service name' + result.dmiModelServiceName == 'model service name' + and: 'the expected DMI properties' + result.dmiProperties == expectedDmiProperties + result.publicProperties == expectedPublicProperties + where: 'the following parameters are used' + scenario | childDataNodes || expectedDmiProperties || expectedPublicProperties + 'no properties' | [] || [] || [] + 'DMI and public properties' | childDataNodesForCmHandleWithAllProperties || [new YangModelCmHandle.Property("name1", "value1")] || [new YangModelCmHandle.Property("name2", "value2")] + 'just DMI properties' | childDataNodesForCmHandleWithDMIProperties || [new YangModelCmHandle.Property("name1", "value1")] || [] + 'just public properties' | childDataNodesForCmHandleWithPublicProperties || [] || [new YangModelCmHandle.Property("name2", "value2")] + } +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/PersistenceCmHandleSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/YangModelCmHandleSpec.groovy index 49de4422e5..470015ec17 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/PersistenceCmHandleSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/YangModelCmHandleSpec.groovy @@ -20,20 +20,21 @@ package org.onap.cps.ncmp.api.models +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle import spock.lang.Specification import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.DATA import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.MODEL -class PersistenceCmHandleSpec extends Specification { +class YangModelCmHandleSpec extends Specification { - def 'Creating persistence cm handle from a cm handle.'() { + def 'Creating yang model cm handle from a service api cm handle.'() { given: 'a cm handle with properties' - def cmHandle = new CmHandle() - cmHandle.dmiProperties = [myDmiProperty:'value1'] - cmHandle.publicProperties = [myPublicProperty:'value2'] - when: 'it is converted to a persistence cm handle' - def objectUnderTest = PersistenceCmHandle.toPersistenceCmHandle('','','', cmHandle) + def ncmpServiceCmHandle = new NcmpServiceCmHandle() + ncmpServiceCmHandle.dmiProperties = [myDmiProperty:'value1'] + ncmpServiceCmHandle.publicProperties = [myPublicProperty:'value2'] + when: 'it is converted to a yang model cm handle' + def objectUnderTest = YangModelCmHandle.toYangModelCmHandle('','','', ncmpServiceCmHandle) then: 'the result has the right size' assert objectUnderTest.dmiProperties.size() == 1 and: 'the DMI property in the result has the correct name and value' @@ -45,8 +46,8 @@ class PersistenceCmHandleSpec extends Specification { } def 'Resolve DMI service name: #scenario and #requiredService service require.'() { - given: 'a Persistence CM Handle' - def objectUnderTest = PersistenceCmHandle.toPersistenceCmHandle(dmiServiceName, dmiDataServiceName, dmiModelServiceName, new CmHandle()) + given: 'a yang model cm handle' + def objectUnderTest = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, dmiDataServiceName, dmiModelServiceName, new NcmpServiceCmHandle()) expect: assert objectUnderTest.resolveDmiServiceName(requiredService) == expectedService where: diff --git a/cps-rest/src/main/java/org/onap/cps/rest/exceptions/CpsRestExceptionHandler.java b/cps-rest/src/main/java/org/onap/cps/rest/exceptions/CpsRestExceptionHandler.java index ceb5dc1eca..9495b3d9e6 100755 --- a/cps-rest/src/main/java/org/onap/cps/rest/exceptions/CpsRestExceptionHandler.java +++ b/cps-rest/src/main/java/org/onap/cps/rest/exceptions/CpsRestExceptionHandler.java @@ -63,30 +63,25 @@ public class CpsRestExceptionHandler { } @ExceptionHandler({ModelValidationException.class, DataValidationException.class, CpsAdminException.class, - CpsPathException.class}) - public static ResponseEntity<Object> handleBadRequestExceptions(final CpsException exception) { + CpsPathException.class, ValidationException.class}) + public static ResponseEntity<Object> handleBadRequestExceptions(final Exception exception) { return buildErrorResponse(HttpStatus.BAD_REQUEST, exception); } - @ExceptionHandler({ValidationException.class}) - public static ResponseEntity<Object> handleBadRequestExceptions(final ValidationException validationException) { - return buildErrorResponse(HttpStatus.BAD_REQUEST, validationException); - } - @ExceptionHandler({NotFoundInDataspaceException.class, DataNodeNotFoundException.class}) - public static ResponseEntity<Object> handleNotFoundExceptions(final CpsException exception, + public static ResponseEntity<Object> handleNotFoundExceptions(final Exception exception, final HttpServletRequest request) { return buildErrorResponse(HttpMethod.GET.matches(request.getMethod()) ? HttpStatus.NOT_FOUND : HttpStatus.BAD_REQUEST, exception); } @ExceptionHandler({DataInUseException.class, AlreadyDefinedException.class}) - public static ResponseEntity<Object> handleDataInUseException(final CpsException exception) { + public static ResponseEntity<Object> handleDataInUseException(final Exception exception) { return buildErrorResponse(HttpStatus.CONFLICT, exception); } @ExceptionHandler({CpsException.class}) - public static ResponseEntity<Object> handleAnyOtherCpsExceptions(final CpsException exception) { + public static ResponseEntity<Object> handleAnyOtherCpsExceptions(final Exception exception) { return buildErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, exception); } diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java index 5b89d9f4c4..50b27207ee 100755 --- a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. + * Copyright (C) 2020-2022 Nordix Foundation. * Modifications Copyright (C) 2020-2022 Bell Canada. * Modifications Copyright (C) 2021 Pantheon.tech * ================================================================================ @@ -147,20 +147,24 @@ public class CpsAdminPersistenceServiceImpl implements CpsAdminPersistenceServic private void validateDataspaceAndModuleNames(final String dataspaceName, final Collection<String> inputModuleNames) { - final Collection<String> retrievedModuleNames = - yangResourceRepository.findAllModuleReferences(dataspaceName, inputModuleNames) + final Collection<String> retrievedModuleReferences = + yangResourceRepository.findAllModuleReferencesByDataspaceAndModuleNames(dataspaceName, inputModuleNames) .stream().map(YangResourceModuleReference::getModuleName) .collect(Collectors.toList()); - if (retrievedModuleNames.isEmpty()) { - dataspaceRepository.getByName(dataspaceName); + if (retrievedModuleReferences.isEmpty()) { + verifyDataspaceName(dataspaceName); } - if (inputModuleNames.size() > retrievedModuleNames.size()) { + if (inputModuleNames.size() > retrievedModuleReferences.size()) { final List<String> moduleNamesNotFound = inputModuleNames.stream() - .filter(moduleName -> !retrievedModuleNames.contains(moduleName)) + .filter(moduleName -> !retrievedModuleReferences.contains(moduleName)) .collect(Collectors.toList()); if (!moduleNamesNotFound.isEmpty()) { throw new ModuleNamesNotFoundException(dataspaceName, moduleNamesNotFound); } } } + + private void verifyDataspaceName(final String dataspaceName) { + dataspaceRepository.getByName(dataspaceName); + } } diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java index ec720b8a96..3719256fcd 100755 --- a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java @@ -106,7 +106,7 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ @Override public Collection<ModuleReference> getYangResourceModuleReferences(final String dataspaceName) { final Set<YangResourceModuleReference> yangResourceModuleReferenceList = - yangResourceRepository.findAllModuleReferences(dataspaceName); + yangResourceRepository.findAllModuleReferencesByDataspace(dataspaceName); return yangResourceModuleReferenceList.stream().map(CpsModulePersistenceServiceImpl::toModuleReference) .collect(Collectors.toList()); } @@ -116,7 +116,7 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ final String anchorName) { final Set<YangResourceModuleReference> yangResourceModuleReferenceList = yangResourceRepository - .findAllModuleReferences(dataspaceName, anchorName); + .findAllModuleReferencesByDataspaceAndAnchor(dataspaceName, anchorName); return yangResourceModuleReferenceList.stream().map(CpsModulePersistenceServiceImpl::toModuleReference) .collect(Collectors.toList()); } diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java index 895937b60a..5e9c47429b 100644 --- a/cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java +++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java @@ -49,7 +49,7 @@ public interface YangResourceRepository extends JpaRepository<YangResourceEntity + "JOIN yang_resource ON yang_resource.id = schema_set_yang_resources.yang_resource_id\n" + "WHERE\n" + "dataspace.name = :dataspaceName", nativeQuery = true) - Set<YangResourceModuleReference> findAllModuleReferences(@Param("dataspaceName") String dataspaceName); + Set<YangResourceModuleReference> findAllModuleReferencesByDataspace(@Param("dataspaceName") String dataspaceName); @Query(value = "SELECT DISTINCT\n" + "yang_resource.module_Name AS module_name,\n" @@ -64,7 +64,7 @@ public interface YangResourceRepository extends JpaRepository<YangResourceEntity + "WHERE\n" + "dataspace.name = :dataspaceName AND\n" + "anchor.name =:anchorName", nativeQuery = true) - Set<YangResourceModuleReference> findAllModuleReferences( + Set<YangResourceModuleReference> findAllModuleReferencesByDataspaceAndAnchor( @Param("dataspaceName") String dataspaceName, @Param("anchorName") String anchorName); @Query(value = "SELECT DISTINCT\n" @@ -77,8 +77,8 @@ public interface YangResourceRepository extends JpaRepository<YangResourceEntity + "JOIN yang_resource ON yang_resource.id = schema_set_yang_resources.yang_resource_id\n" + "WHERE\n" + "dataspace.name = :dataspaceName and yang_resource.module_Name IN (:moduleNames)", nativeQuery = true) - Set<YangResourceModuleReference> findAllModuleReferences(@Param("dataspaceName") String dataspaceName, - @Param("moduleNames") Collection<String> moduleNames); + Set<YangResourceModuleReference> findAllModuleReferencesByDataspaceAndModuleNames( + @Param("dataspaceName") String dataspaceName, @Param("moduleNames") Collection<String> moduleNames); @Query(value = "SELECT id FROM yang_resource WHERE module_name=:name and revision=:revision", nativeQuery = true) diff --git a/cps-ri/src/main/resources/changelog/db/changes/10-loadData-dmi-registry-fragment.yaml b/cps-ri/src/main/resources/changelog/db/changes/10-loadData-dmi-registry-fragment.yaml index 8325690516..068a61580d 100644 --- a/cps-ri/src/main/resources/changelog/db/changes/10-loadData-dmi-registry-fragment.yaml +++ b/cps-ri/src/main/resources/changelog/db/changes/10-loadData-dmi-registry-fragment.yaml @@ -1,3 +1,21 @@ +# ============LICENSE_START======================================================= +# Copyright (C) 2021-2022 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========================================================= + databaseChangeLog: - changeSet: author: cps @@ -40,6 +58,9 @@ databaseChangeLog: header: schema_node_id name: schema_node_id type: NUMERIC + rollback: + sql: DELETE FROM fragment WHERE xpath = '/dmi-registry' AND anchor_id = (select id from anchor where name='ncmp-dmi-registry') AND dataspace_id = (select id from dataspace where name='NCMP-Admin') + comment: Removes the fragment added by fragment.csv file - changeSet: author: cps @@ -50,4 +71,6 @@ databaseChangeLog: comment: Fixes the id sequence after data insert with predefined ids dbms: postgresql sql: ALTER SEQUENCE IF EXISTS fragment_id_seq RESTART WITH 200 + rollback: + comment: Rollback for 10.1 is not supported. Please rollback change set 10 to undo change set 10.1. Cannot revert sequence altering. diff --git a/cps-ri/src/main/resources/changelog/db/changes/11-add-column-to-yang-resources-table.yaml b/cps-ri/src/main/resources/changelog/db/changes/11-add-column-to-yang-resources-table.yaml index a2bfb67f94..139e83be2d 100644 --- a/cps-ri/src/main/resources/changelog/db/changes/11-add-column-to-yang-resources-table.yaml +++ b/cps-ri/src/main/resources/changelog/db/changes/11-add-column-to-yang-resources-table.yaml @@ -1,5 +1,5 @@ # ============LICENSE_START======================================================= -# Copyright (C) 2021 Nordix Foundation. +# Copyright (C) 2021-2022 Nordix Foundation. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ databaseChangeLog: - column: name: revision type: TEXT + - changeSet: id: 11.1 label: update-previous-data-module-name-and-revision @@ -38,3 +39,5 @@ databaseChangeLog: changes: - sql: sql: update yang_resource set module_name = 'dummy_module_name', revision = '2021-08-04' where module_name is null and revision is null + rollback: + comment: Rollback for change set 11.1 is not supported. Please rollback change set 11 to rollback changeset 11.1. Change set 11.1 removes null values from the yang_resource table created by change set 11.
\ No newline at end of file diff --git a/csit/tests/cps-model-sync/cps-model-sync.robot b/csit/tests/cps-model-sync/cps-model-sync.robot index 5021f77e90..dfad948614 100644 --- a/csit/tests/cps-model-sync/cps-model-sync.robot +++ b/csit/tests/cps-model-sync/cps-model-sync.robot @@ -34,15 +34,48 @@ ${auth} Basic Y3BzdXNlcjpjcHNyMGNrcyE= ${ncmpInventoryBasePath} /ncmpInventory ${ncmpBasePath} /ncmp ${dmiUrl} http://${DMI_HOST}:${DMI_PORT} -${jsonData} {"dmiPlugin":"${dmiUrl}","dmiDataPlugin":"","dmiModelPlugin":"","createdCmHandles":[{"cmHandle":"PNFDemo","cmHandleProperties":{"Book1":"Sci-Fi Book"},"publicCmHandleProperties":{"Contact":"storeemail@bookstore.com"}}],"updatedCmHandles":[{"cmHandle":"PNFDemo","cmHandleProperties":{"Book1":"Romance Book"},"publicCmHandleProperties":{"Contact":"newemailforstore@bookstore.com"}}]} +${jsonDataCreate} {"dmiPlugin":"${dmiUrl}","dmiDataPlugin":"","dmiModelPlugin":"","createdCmHandles":[{"cmHandle":"PNFDemo","cmHandleProperties":{"Book1":"Sci-Fi Book"},"publicCmHandleProperties":{"Contact":"storeemail@bookstore.com"}}]} +${jsonDataUpdate} {"dmiPlugin":"${dmiUrl}","dmiDataPlugin":"","dmiModelPlugin":"","updatedCmHandles":[{"cmHandle":"PNFDemo","cmHandleProperties":{"Book1":"Romance Book"},"publicCmHandleProperties":{"Contact":"newemailforstore@bookstore.com"}}]} *** Test Cases *** -Register node, update data node and sync modules. +Register data node and sync modules. ${uri}= Set Variable ${ncmpInventoryBasePath}/v1/ch ${headers}= Create Dictionary Content-Type=application/json Authorization=${auth} - ${response}= POST On Session CPS_URL ${uri} headers=${headers} data=${jsonData} + ${response}= POST On Session CPS_URL ${uri} headers=${headers} data=${jsonDataCreate} Should Be Equal As Strings ${response.status_code} 204 +Get CM Handle details and confirm it has been registered. + ${uri}= Set Variable ${ncmpBasePath}/v1/ch/PNFDemo + ${headers}= Create Dictionary Authorization=${auth} + ${response}= GET On Session CPS_URL ${uri} headers=${headers} + ${responseJson}= Set Variable ${response.json()} + ${schemaCount}= Get length ${responseJson} + Should Be Equal As Strings ${response.status_code} 200 + IF "${responseJson['cmHandle']}" == "PNFDemo" + FOR ${item} IN @{responseJson['publicCmHandleProperties']} + Should Be Equal As Strings "${item['Contact']}" "storeemail@bookstore.com" + END + END + +Update data node and sync modules. + ${uri}= Set Variable ${ncmpInventoryBasePath}/v1/ch + ${headers}= Create Dictionary Content-Type=application/json Authorization=${auth} + ${response}= POST On Session CPS_URL ${uri} headers=${headers} data=${jsonDataUpdate} + Should Be Equal As Strings ${response.status_code} 204 + +Get CM Handle details and confirm it has been updated. + ${uri}= Set Variable ${ncmpBasePath}/v1/ch/PNFDemo + ${headers}= Create Dictionary Authorization=${auth} + ${response}= GET On Session CPS_URL ${uri} headers=${headers} + ${responseJson}= Set Variable ${response.json()} + ${schemaCount}= Get length ${responseJson} + Should Be Equal As Strings ${response.status_code} 200 + IF "${responseJson['cmHandle']}" == "PNFDemo" + FOR ${item} IN @{responseJson['publicCmHandleProperties']} + Should Be Equal As Strings "${item['Contact']}" "newemailforstore@bookstore.com" + END + END + Get modules for registered data node ${uri}= Set Variable ${ncmpBasePath}/v1/ch/PNFDemo/modules ${headers}= Create Dictionary Authorization=${auth} diff --git a/docs/api/swagger/ncmp/openapi-inventory.yaml b/docs/api/swagger/ncmp/openapi-inventory.yaml index 34a087b85c..154a4411da 100644 --- a/docs/api/swagger/ncmp/openapi-inventory.yaml +++ b/docs/api/swagger/ncmp/openapi-inventory.yaml @@ -53,6 +53,16 @@ paths: status: 403 message: Forbidden error message details: Forbidden error details + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 500 + message: Internal Server Error + details: Internal Server Error occurred components: schemas: RestDmiPluginRegistration: @@ -61,26 +71,39 @@ components: dmiPlugin: type: string example: my-dmi-plugin + default: "" dmiDataPlugin: type: string example: my-dmi-data-plugin + default: "" dmiModelPlugin: type: string example: my-dmi-model-plugin + default: "" createdCmHandles: type: array items: - $ref: '#/components/schemas/RestCmHandle' + $ref: '#/components/schemas/RestInputCmHandle' updatedCmHandles: type: array + example: + cmHandle: my-cm-handle + cmHandleProperties: + add-my-property: add-property + update-my-property: updated-property + delete-my-property: ~ + publicCmHandleProperties: + add-my-property: add-property + update-my-property: updated-property + delete-my-property: ~ items: - $ref: '#/components/schemas/RestCmHandle' + $ref: '#/components/schemas/RestInputCmHandle' removedCmHandles: type: array items: type: string example: "[\"my-cm-handle1\",\"my-cm-handle2\",\"my-cm-handle3\"]" - RestCmHandle: + RestInputCmHandle: required: - cmHandle type: object diff --git a/docs/api/swagger/ncmp/openapi.yaml b/docs/api/swagger/ncmp/openapi.yaml index a3b9dc7501..b7a65632e7 100644 --- a/docs/api/swagger/ncmp/openapi.yaml +++ b/docs/api/swagger/ncmp/openapi.yaml @@ -4,73 +4,72 @@ info: description: NCMP to CPS Proxy API version: "1.0" servers: - - url: /ncmp +- url: /ncmp paths: /v1/ch/{cm-handle}/data/ds/ncmp-datastore:passthrough-operational: get: tags: - - network-cm-proxy + - network-cm-proxy summary: Get resource data from pass-through operational for cm handle description: Get resource data from pass-through operational for given cm handle operationId: getResourceDataOperationalForCmHandle parameters: - - name: cm-handle - in: path - description: "The identifier for a network function, network element, subnetwork\ + - name: cm-handle + in: path + description: "The identifier for a network function, network element, subnetwork\ \ or any other cm object by managed Network CM Proxy" - required: true - schema: - type: string - - name: resourceIdentifier - in: query - description: The format of resource identifier depend on the associated DMI - Plugin implementation. For ONAP DMI Plugin it will be RESTConf paths but - it can really be anything. - required: true - allowReserved: true - schema: - type: string - examples: - sample1: - value: - resourceIdentifier: \parent\child - sample2: - value: - resourceIdentifier: "\\parent\\listElement[key=value]" - sample3: - value: - resourceIdentifier: "\\parent\\listElement[key=value]\\grandChild" - sample4: - value: - resourceIdentifier: "parent=1,child=abc" - - name: Accept - in: header - description: "Accept parameter for response, if accept parameter is null,\ + required: true + schema: + type: string + example: my-cm-handle + - name: resourceIdentifier + in: query + description: The format of resource identifier depend on the associated DMI + Plugin implementation. For ONAP DMI Plugin it will be RESTConf paths but + it can really be anything. + required: true + allowReserved: true + schema: + type: string + examples: + sample 1: + value: + resourceIdentifier: \shops\bookstore + sample 2: + value: + resourceIdentifier: "\\shops\\bookstore\\categories[@code=1]" + sample 3: + value: + resourceIdentifier: "parent=shops,child=bookstore" + - name: Accept + in: header + description: "Accept parameter for response, if accept parameter is null,\ \ that means client can accept any format." - required: false - schema: - type: string - enum: - - application/json - - application/yang-data+json - - name: options - in: query - description: "options parameter in query, it is mandatory to wrap key(s)=value(s)\ - \ in parenthesis'()'." - required: false - allowReserved: true - schema: - type: string - examples: - sample1: - value: - options: "(key1=value1,key2=value2)" - sample2: - value: - options: "(key1=value1,key2=value1/value2)" - sample3: - value: - options: "(key1=10,key2=value2,key3=[val31;val32])" + required: false + schema: + type: string + enum: + - application/json + - application/yang-data+json + - name: options + in: query + description: "options parameter in query, it is mandatory to wrap key(s)=value(s)\ + \ in parenthesis'()'. The format of options parameter depend on the associated\ + \ DMI Plugin implementation." + required: false + allowReserved: true + schema: + type: string + examples: + sample 1: + value: + options: (depth=3) + sample 2: + value: + options: (fields=book) + sample 3: + value: + options: "(depth=2,fields=book/authors)" responses: "200": description: OK @@ -78,95 +77,113 @@ paths: application/json: schema: type: object + examples: + dataSampleResponse: + $ref: '#/components/examples/dataSampleResponse' "400": description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' + example: + status: 400 BAD_REQUEST + message: Bad request error message + details: Bad request error details "401": description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' + example: + status: 401 + message: Unauthorized error message + details: Unauthorized error details "403": description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' - "404": - description: The specified resource was not found + example: + status: 403 + message: Forbidden error message + details: Forbidden error details + "500": + description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' + example: + status: 500 + message: Internal Server Error + details: Internal Server Error occurred /v1/ch/{cm-handle}/data/ds/ncmp-datastore:passthrough-running: get: tags: - - network-cm-proxy + - network-cm-proxy summary: Get resource data from pass-through running for cm handle description: Get resource data from pass-through running for given cm handle operationId: getResourceDataRunningForCmHandle parameters: - - name: cm-handle - in: path - description: "The identifier for a network function, network element, subnetwork\ + - name: cm-handle + in: path + description: "The identifier for a network function, network element, subnetwork\ \ or any other cm object by managed Network CM Proxy" - required: true - schema: - type: string - - name: resourceIdentifier - in: query - description: The format of resource identifier depend on the associated DMI - Plugin implementation. For ONAP DMI Plugin it will be RESTConf paths but - it can really be anything. - required: true - allowReserved: true - schema: - type: string - examples: - sample1: - value: - resourceIdentifier: \parent\child - sample2: - value: - resourceIdentifier: "\\parent\\listElement[key=value]" - sample3: - value: - resourceIdentifier: "\\parent\\listElement[key=value]\\grandChild" - sample4: - value: - resourceIdentifier: "parent=1,child=abc" - - name: Accept - in: header - description: "Accept parameter for response, if accept parameter is null,\ + required: true + schema: + type: string + example: my-cm-handle + - name: resourceIdentifier + in: query + description: The format of resource identifier depend on the associated DMI + Plugin implementation. For ONAP DMI Plugin it will be RESTConf paths but + it can really be anything. + required: true + allowReserved: true + schema: + type: string + examples: + sample 1: + value: + resourceIdentifier: \shops\bookstore + sample 2: + value: + resourceIdentifier: "\\shops\\bookstore\\categories[@code=1]" + sample 3: + value: + resourceIdentifier: "parent=shops,child=bookstore" + - name: Accept + in: header + description: "Accept parameter for response, if accept parameter is null,\ \ that means client can accept any format." - required: false - schema: - type: string - enum: - - application/json - - application/yang-data+json - - name: options - in: query - description: "options parameter in query, it is mandatory to wrap key(s)=value(s)\ - \ in parenthesis'()'." - required: false - allowReserved: true - schema: - type: string - examples: - sample1: - value: - options: "(key1=value1,key2=value2)" - sample2: - value: - options: "(key1=value1,key2=value1/value2)" - sample3: - value: - options: "(key1=10,key2=value2,key3=[val31;val32])" + required: false + schema: + type: string + enum: + - application/json + - application/yang-data+json + - name: options + in: query + description: "options parameter in query, it is mandatory to wrap key(s)=value(s)\ + \ in parenthesis'()'. The format of options parameter depend on the associated\ + \ DMI Plugin implementation." + required: false + allowReserved: true + schema: + type: string + examples: + sample 1: + value: + options: (depth=3) + sample 2: + value: + options: (fields=book) + sample 3: + value: + options: "(depth=2,fields=book/authors)" responses: "200": description: OK @@ -174,82 +191,212 @@ paths: application/json: schema: type: object + examples: + dataSampleResponse: + $ref: '#/components/examples/dataSampleResponse' "400": description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' + example: + status: 400 BAD_REQUEST + message: Bad request error message + details: Bad request error details "401": description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' + example: + status: 401 + message: Unauthorized error message + details: Unauthorized error details "403": description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' - "404": - description: The specified resource was not found + example: + status: 403 + message: Forbidden error message + details: Forbidden error details + "500": + description: Internal Server Error content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' + example: + status: 500 + message: Internal Server Error + details: Internal Server Error occurred + put: + tags: + - network-cm-proxy + summary: Update resource data from pass-through running for a cm handle + description: Update resource data from pass-through running for the given cm + handle + operationId: updateResourceDataRunningForCmHandle + parameters: + - name: cm-handle + in: path + description: "The identifier for a network function, network element, subnetwork\ + \ or any other cm object by managed Network CM Proxy" + required: true + schema: + type: string + example: my-cm-handle + - name: resourceIdentifier + in: query + description: The format of resource identifier depend on the associated DMI + Plugin implementation. For ONAP DMI Plugin it will be RESTConf paths but + it can really be anything. + required: true + allowReserved: true + schema: + type: string + examples: + sample 1: + value: + resourceIdentifier: \shops\bookstore + sample 2: + value: + resourceIdentifier: "\\shops\\bookstore\\categories[@code=1]" + sample 3: + value: + resourceIdentifier: "parent=shops,child=bookstore" + - name: Content-Type + in: header + description: "Content parameter for request, if content parameter is null,\ + \ default value is application/json." + required: false + schema: + type: string + example: application/yang-data+json + default: application/json + requestBody: + content: + application/json: + schema: + type: object + examples: + dataSampleRequest: + $ref: '#/components/examples/dataSampleRequest' + application/yang-data+json: + schema: + type: object + examples: + dataSampleRequest: + $ref: '#/components/examples/dataSampleRequest' + required: true + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + "400": + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 400 BAD_REQUEST + message: Bad request error message + details: Bad request error details + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 401 + message: Unauthorized error message + details: Unauthorized error details + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 403 + message: Forbidden error message + details: Forbidden error details + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 500 + message: Internal Server Error + details: Internal Server Error occurred post: tags: - - network-cm-proxy + - network-cm-proxy summary: create resource data from pass-through running for cm handle description: create resource data from pass-through running for given cm handle operationId: createResourceDataRunningForCmHandle parameters: - - name: cm-handle - in: path - description: "The identifier for a network function, network element, subnetwork\ + - name: cm-handle + in: path + description: "The identifier for a network function, network element, subnetwork\ \ or any other cm object by managed Network CM Proxy" - required: true - schema: - type: string - - name: resourceIdentifier - in: query - description: The format of resource identifier depend on the associated DMI - Plugin implementation. For ONAP DMI Plugin it will be RESTConf paths but - it can really be anything. - required: true - allowReserved: true - schema: - type: string - examples: - sample1: - value: - resourceIdentifier: \parent\child - sample2: - value: - resourceIdentifier: "\\parent\\listElement[key=value]" - sample3: - value: - resourceIdentifier: "\\parent\\listElement[key=value]\\grandChild" - sample4: - value: - resourceIdentifier: "parent=1,child=abc" - - name: Content-Type - in: header - description: "Content parameter for request, if content parameter is null,\ + required: true + schema: + type: string + example: my-cm-handle + - name: resourceIdentifier + in: query + description: The format of resource identifier depend on the associated DMI + Plugin implementation. For ONAP DMI Plugin it will be RESTConf paths but + it can really be anything. + required: true + allowReserved: true + schema: + type: string + examples: + sample 1: + value: + resourceIdentifier: \shops\bookstore + sample 2: + value: + resourceIdentifier: "\\shops\\bookstore\\categories[@code=1]" + sample 3: + value: + resourceIdentifier: "parent=shops,child=bookstore" + - name: Content-Type + in: header + description: "Content parameter for request, if content parameter is null,\ \ default value is application/json." - required: false - schema: - type: string - default: application/json + required: false + schema: + type: string + example: application/yang-data+json + default: application/json requestBody: content: application/json: schema: - type: string + type: object + examples: + dataSampleRequest: + $ref: '#/components/examples/dataSampleRequest' application/yang-data+json: schema: - type: string + type: object + examples: + dataSampleRequest: + $ref: '#/components/examples/dataSampleRequest' required: true responses: "201": @@ -261,71 +408,437 @@ paths: application/json: schema: $ref: '#/components/schemas/ErrorMessage' + example: + status: 400 BAD_REQUEST + message: Bad request error message + details: Bad request error details + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 401 + message: Unauthorized error message + details: Unauthorized error details + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 403 + message: Forbidden error message + details: Forbidden error details + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 500 + message: Internal Server Error + details: Internal Server Error occurred + delete: + tags: + - network-cm-proxy + summary: Delete resource data + description: Delete resource data from pass-through running for a given cm handle + operationId: deleteResourceDataRunningForCmHandle + parameters: + - name: cm-handle + in: path + description: "The identifier for a network function, network element, subnetwork\ + \ or any other cm object by managed Network CM Proxy" + required: true + schema: + type: string + example: my-cm-handle + - name: resourceIdentifier + in: query + description: The format of resource identifier depend on the associated DMI + Plugin implementation. For ONAP DMI Plugin it will be RESTConf paths but + it can really be anything. + required: true + allowReserved: true + schema: + type: string + examples: + sample 1: + value: + resourceIdentifier: \shops\bookstore + sample 2: + value: + resourceIdentifier: "\\shops\\bookstore\\categories[@code=1]" + sample 3: + value: + resourceIdentifier: "parent=shops,child=bookstore" + - name: Content-Type + in: header + description: "Content parameter for request, if content parameter is null,\ + \ default value is application/json." + required: false + schema: + type: string + example: application/yang-data+json + default: application/json + responses: + "204": + description: No Content + content: {} + "400": + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 400 BAD_REQUEST + message: Bad request error message + details: Bad request error details "401": description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' + example: + status: 401 + message: Unauthorized error message + details: Unauthorized error details "403": description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' + example: + status: 403 + message: Forbidden error message + details: Forbidden error details "404": description: The specified resource was not found content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' + example: + status: 400 + message: Not found error message + details: Not found error details + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 500 + message: Internal Server Error + details: Internal Server Error occurred + patch: + tags: + - network-cm-proxy + summary: Patch resource data from pass-through running + description: Patch resource data from pass-through running for the given cm + handle + operationId: patchResourceDataRunningForCmHandle + parameters: + - name: cm-handle + in: path + description: "The identifier for a network function, network element, subnetwork\ + \ or any other cm object by managed Network CM Proxy" + required: true + schema: + type: string + example: my-cm-handle + - name: resourceIdentifier + in: query + description: The format of resource identifier depend on the associated DMI + Plugin implementation. For ONAP DMI Plugin it will be RESTConf paths but + it can really be anything. + required: true + allowReserved: true + schema: + type: string + examples: + sample 1: + value: + resourceIdentifier: \shops\bookstore + sample 2: + value: + resourceIdentifier: "\\shops\\bookstore\\categories[@code=1]" + sample 3: + value: + resourceIdentifier: "parent=shops,child=bookstore" + - name: Content-Type + in: header + description: "Content parameter for request, if content parameter is null,\ + \ default value is application/json." + required: false + schema: + type: string + example: application/yang-data+json + default: application/json + requestBody: + content: + '*/*': + schema: + type: object + examples: + dataSampleRequest: + $ref: '#/components/examples/dataSamplePatchRequest' + required: true + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + "400": + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 400 BAD_REQUEST + message: Bad request error message + details: Bad request error details + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 401 + message: Unauthorized error message + details: Unauthorized error details + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 403 + message: Forbidden error message + details: Forbidden error details + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 500 + message: Internal Server Error + details: Internal Server Error occurred /v1/ch/{cm-handle}/modules: get: tags: - - network-cm-proxy + - network-cm-proxy summary: Fetch all module references (name and revision) for a given cm handle description: fetch all module references (name and revision) for a given cm handle operationId: getModuleReferencesByCmHandle parameters: - - name: cm-handle - in: path - description: "The identifier for a network function, network element, subnetwork\ + - name: cm-handle + in: path + description: "The identifier for a network function, network element, subnetwork\ \ or any other cm object by managed Network CM Proxy" - required: true - schema: - type: string + required: true + schema: + type: string + example: my-cm-handle responses: "200": description: OK content: application/json: schema: - type: object + type: array + items: + $ref: '#/components/schemas/ModuleReference' + "400": + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 400 BAD_REQUEST + message: Bad request error message + details: Bad request error details + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 401 + message: Unauthorized error message + details: Unauthorized error details + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 403 + message: Forbidden error message + details: Forbidden error details + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 500 + message: Internal Server Error + details: Internal Server Error occurred + /v1/ch/searches: + post: + tags: + - network-cm-proxy + summary: Execute cm handle search using the available conditions + description: Execute cm handle searches using 'hasAllModules' condition to get + all cm handles for the given module names + operationId: executeCmHandleSearch + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Conditions' + required: true + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/CmHandles' + "400": + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 400 BAD_REQUEST + message: Bad request error message + details: Bad request error details + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 401 + message: Unauthorized error message + details: Unauthorized error details + "403": + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 403 + message: Forbidden error message + details: Forbidden error details + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 500 + message: Internal Server Error + details: Internal Server Error occurred + /v1/ch/{cm-handle}: + get: + tags: + - network-cm-proxy + summary: Retrieve CM handle details + description: Retrieve CM handle details and properties by cm handle id + operationId: retrieveCmHandleDetailsById + parameters: + - name: cm-handle + in: path + description: "The identifier for a network function, network element, subnetwork\ + \ or any other cm object by managed Network CM Proxy" + required: true + schema: + type: string + example: my-cm-handle + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/RestOutputCmHandle' "400": description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' + example: + status: 400 BAD_REQUEST + message: Bad request error message + details: Bad request error details "401": description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' + example: + status: 401 + message: Unauthorized error message + details: Unauthorized error details "403": description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' + example: + status: 403 + message: Forbidden error message + details: Forbidden error details "404": description: The specified resource was not found content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' + example: + status: 400 + message: Not found error message + details: Not found error details + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorMessage' + example: + status: 500 + message: Internal Server Error + details: Internal Server Error occurred components: schemas: ErrorMessage: @@ -338,3 +851,147 @@ components: type: string details: type: string + ModuleReference: + title: Module reference details + type: object + properties: + moduleName: + type: string + example: my-module-name + revision: + type: string + example: my-module-revision + Conditions: + type: object + properties: + conditions: + $ref: '#/components/schemas/ConditionsData' + ConditionsData: + type: array + items: + $ref: '#/components/schemas/ConditionProperties' + ConditionProperties: + properties: + name: + type: string + example: hasAllModules + conditionParameters: + $ref: '#/components/schemas/ModuleNamesAsJsonArray' + ModuleNamesAsJsonArray: + type: array + items: + $ref: '#/components/schemas/ModuleNameAsJsonObject' + ModuleNameAsJsonObject: + properties: + moduleName: + type: string + example: my-module + CmHandles: + type: object + properties: + cmHandles: + $ref: '#/components/schemas/CmHandleProperties' + CmHandleProperties: + type: array + items: + $ref: '#/components/schemas/CmHandleProperty' + CmHandleProperty: + properties: + cmHandleId: + type: string + example: my-cm-handle-id + RestOutputCmHandle: + title: CM handle Details + type: object + properties: + cmHandle: + type: string + example: my-cm-handle1 + publicCmHandleProperties: + $ref: '#/components/schemas/CmHandlePublicProperties' + CmHandlePublicProperties: + type: array + items: + type: object + additionalProperties: + type: string + example: Book Type + examples: + dataSampleResponse: + summary: Sample response + description: Sample response for selecting 'sample 1'. + value: + bookstore: + categories: + - code: "01" + books: + - authors: + - Iain M. Banks + - Ursula K. Le Guin + name: SciFi + - code: "02" + books: + - authors: + - Philip Pullman + name: kids + dataSampleRequest: + summary: Sample request + description: Sample request body + value: + test:bookstore: + bookstore-name: Chapters + categories: + - code: "01" + name: SciFi + books: + - authors: + - Iain M. Banks + - Ursula K. Le Guin + - code: "02" + name: kids + books: + - authors: + - Philip Pullman + dataSamplePatchRequest: + summary: Sample patch request + description: Sample patch request body + value: + ietf-restconf:yang-patch: + patch-id: patch-1 + edit: + - edit-id: edit1 + operation: merge + target: / + value: + test:bookstore: + bookstore-name: Chapters + categories: + - code: "01" + name: Science + books: + - authors: + - Author1 + - Author2 + - code: "02" + name: Arts + books: + - authors: + - Author3 + - edit-id: edit2 + operation: merge + target: / + value: + test:bookstore: + bookstore-name: Novels + categories: + - code: "03" + name: History + books: + - authors: + - Iain M. Banks + - Ursula K. Le Guin + - code: "04" + name: Fiction + books: + - authors: + - Philip Pullman diff --git a/docs/release-notes.rst b/docs/release-notes.rst index ff8a988679..0ca0547fad 100755 --- a/docs/release-notes.rst +++ b/docs/release-notes.rst @@ -29,9 +29,11 @@ Features - `CPS-559 <https://jira.onap.org/browse/CPS-559>`_ Define response objects (schemas) in cps-ncmp - `CPS-636 <https://jira.onap.org/browse/CPS-636>`_ Update operation for datastore pass through running - `CPS-638 <https://jira.onap.org/browse/CPS-638>`_ Delete operation for datastore pass through running + - `CPS-677 <https://jira.onap.org/browse/CPS-677>`_ Support 'public' Cm Handle Properties - `CPS-741 <https://jira.onap.org/browse/CPS-741>`_ Re sync after removing cm handles - `CPS-777 <https://jira.onap.org/browse/CPS-777>`_ Ensure all DMI operations use POST method - `CPS-780 <https://jira.onap.org/browse/CPS-780>`_ Add examples for parameters, request and response in openapi yaml for cps-core + - `CPS-817 <https://jira.onap.org/browse/CPS-817>`_ Create Endpoint For Get Cm Handles (incl. public properties) By Name - `CPS-837 <https://jira.onap.org/browse/CPS-837>`_ Add Remove and Update properties (DMI and Public) as part of CM Handle Registration update Bug Fixes @@ -43,15 +45,19 @@ Bug Fixes - `CPS-841 <https://jira.onap.org/browse/CPS-841>`_ Upgrade log4j to 2.17.1 as recommended by ONAP SECCOM - `CPS-856 <https://jira.onap.org/browse/CPS-856>`_ Retry mechanism not working for concurrent CmHandle registration - `CPS-867 <https://jira.onap.org/browse/CPS-867>`_ Database port made configurable through env variable DB_PORT + - `CPS-886 <https://jira.onap.org/browse/CPS-886>`_ Fragment handling decreasing performance for large number of cmHandles - `CPS-887 <https://jira.onap.org/browse/CPS-887>`_ Increase performance of cmHandle registration for large number of schema sets in DB - `CPS-892 <https://jira.onap.org/browse/CPS-892>`_ Fixed the response code during CM-Handle Registration from 201 CREATED to 204 NO_CONTENT + - `CPS-893 <https://jira.onap.org/browse/CPS-893>`_ NCMP Java API depends on NCM-Rest-API (cyclic) through json properties on Java API Known Limitations, Issues and Workarounds ----------------------------------------- *System Limitations* -None +Null can no longer be passed within the dmi plugin service names when registering a cm handle, as part of +`CPS-837 <https://jira.onap.org/browse/CPS-837>`_ null is now used to indicate if a property should be removed as part +of cm handle registration. *Known Vulnerabilities* @@ -59,7 +65,8 @@ None *Workarounds* -None +Instead of passing null as a value within the dmi plugin service names, remove them from the request completely, or +pass an empty string as the value if you do not want to include names for these values. Security Notes -------------- |