$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/RestInputCmHandle'
+ 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: '~'
removedCmHandles:
type: array
items:
type: string
- example: [my-cm-handle1, my-cm-handle2, my-cm-handle3]
+ example: [my-cm-handle1, my-cm-handle2, my-cm-handle3]
RestInputCmHandle:
required:
type: string
example: my-cm-handle-id
- ModuleReference:
+ RestModuleReference:
type: object
title: Module reference details
properties:
sample 3:
value:
options: (depth=2,fields=book/authors)
+ topicParamInQuery:
+ name: topic
+ in: query
+ description: topic parameter in query.
+ required: false
+ schema:
+ type: string
+ allowReserved: true
+ examples:
+ sample 1:
+ value:
+ topic: my-topic-name
contentParamInHeader:
name: Content-Type
in: header
- $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
- $ref: 'components.yaml#/components/parameters/acceptParamInHeader'
- $ref: 'components.yaml#/components/parameters/optionsParamInQuery'
+ - $ref: 'components.yaml#/components/parameters/topicParamInQuery'
responses:
200:
description: OK
- $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
- $ref: 'components.yaml#/components/parameters/acceptParamInHeader'
- $ref: 'components.yaml#/components/parameters/optionsParamInQuery'
+ - $ref: 'components.yaml#/components/parameters/topicParamInQuery'
responses:
200:
description: OK
schema:
type: array
items:
- $ref: 'components.yaml#/components/schemas/ModuleReference'
+ $ref: 'components.yaml#/components/schemas/RestModuleReference'
400:
$ref: 'components.yaml#/components/responses/BadRequest'
401:
import javax.validation.constraints.NotNull;
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.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.RestModuleReference;
import org.onap.cps.ncmp.rest.model.RestOutputCmHandle;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.http.HttpStatus;
private static final String NO_BODY = null;
- private final ModelMapper modelMapper;
private final NetworkCmProxyDataService networkCmProxyDataService;
private final JsonObjectMapper jsonObjectMapper;
+ private final NcmpRestInputMapper ncmpRestInputMapper;
/**
* Get resource data from operational datastore.
* @param resourceIdentifier resource identifier
* @param acceptParamInHeader accept header parameter
* @param optionsParamInQuery options query parameter
+ * @param topicParamInQuery topic query parameter
* @return {@code ResponseEntity} response from dmi plugin
*/
@Override
public ResponseEntity<Object> getResourceDataOperationalForCmHandle(final String cmHandle,
final @NotNull @Valid String resourceIdentifier,
final String acceptParamInHeader,
- final @Valid String optionsParamInQuery) {
+ final @Valid String optionsParamInQuery,
+ final @Valid String topicParamInQuery) {
final Object responseObject = networkCmProxyDataService.getResourceDataOperationalForCmHandle(cmHandle,
resourceIdentifier,
acceptParamInHeader,
- optionsParamInQuery);
+ optionsParamInQuery,
+ topicParamInQuery);
return ResponseEntity.ok(responseObject);
}
* @param resourceIdentifier resource identifier
* @param acceptParamInHeader accept header parameter
* @param optionsParamInQuery options query parameter
+ * @param topicParamInQuery topic query parameter
* @return {@code ResponseEntity} response from dmi plugin
*/
@Override
public ResponseEntity<Object> getResourceDataRunningForCmHandle(final String cmHandle,
final @NotNull @Valid String resourceIdentifier,
final String acceptParamInHeader,
- final @Valid String optionsParamInQuery) {
+ final @Valid String optionsParamInQuery,
+ final @Valid String topicParamInQuery) {
final Object responseObject = networkCmProxyDataService.getResourceDataPassThroughRunningForCmHandle(cmHandle,
resourceIdentifier,
acceptParamInHeader,
- optionsParamInQuery);
+ optionsParamInQuery,
+ topicParamInQuery);
return ResponseEntity.ok(responseObject);
}
* @param cmHandle the cm handle
* @return module references for cm handle. Namespace will be always blank because restConf does not include this.
*/
- public ResponseEntity<List<ModuleReference>> getModuleReferencesByCmHandle(final String cmHandle) {
- final List<ModuleReference> moduleReferences =
+ public ResponseEntity<List<RestModuleReference>> getModuleReferencesByCmHandle(final String cmHandle) {
+ final List<RestModuleReference> restModuleReferences =
networkCmProxyDataService.getYangResourcesModuleReferences(cmHandle).stream()
- .map(moduleReference -> modelMapper.map(moduleReference, ModuleReference.class))
+ .map(ncmpRestInputMapper::toRestModuleReference)
.collect(Collectors.toList());
- return new ResponseEntity<>(moduleReferences, HttpStatus.OK);
+ return new ResponseEntity<>(restModuleReferences, HttpStatus.OK);
}
private Collection<String> processConditions(final List<ConditionProperties> conditionProperties) {
package org.onap.cps.ncmp.rest.controller
-
+ import org.mapstruct.factory.Mappers
import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
+import spock.lang.Shared
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.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.DELETE
import com.fasterxml.jackson.databind.ObjectMapper
- import org.modelmapper.ModelMapper
import org.onap.cps.TestUtils
import org.onap.cps.spi.model.ModuleReference
import org.onap.cps.utils.JsonObjectMapper
NetworkCmProxyDataService mockNetworkCmProxyDataService = Mock()
@SpringBean
- ModelMapper modelMapper = new ModelMapper()
+ JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
@SpringBean
- JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
+ NcmpRestInputMapper ncmpRestInputMapper = Mappers.getMapper(NcmpRestInputMapper)
@Value('${rest.api.ncmp-base-path}/v1')
def ncmpBasePathV1
def requestBody = '{"some-key":"some-value"}'
- def 'Get Resource Data from pass-through operational.' () {
+ @Shared
+ def NO_TOPIC = null
+
+ def 'Get Resource Data from pass-through operational.'() {
given: 'resource data url'
def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-operational" +
"?resourceIdentifier=parent/child&options=(a=1,b=2)"
1 * mockNetworkCmProxyDataService.getResourceDataOperationalForCmHandle('testCmHandle',
'parent/child',
'application/json',
- '(a=1,b=2)')
+ '(a=1,b=2)',
+ NO_TOPIC)
+ and: 'response status is Ok'
+ response.status == HttpStatus.OK.value()
+ }
+
+ def 'Get Resource Data from pass-through operational with #scenario.'() {
+ given: 'resource data url'
+ def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-operational" +
+ "?resourceIdentifier=parent/child&options=(a=1,b=2)${topicQueryParam}"
+ when: 'get data resource request is performed'
+ def response = mvc.perform(
+ get(getUrl)
+ .contentType(MediaType.APPLICATION_JSON)
+ .accept(MediaType.APPLICATION_JSON_VALUE)
+ ).andReturn().response
+ then: 'the NCMP data service is called with operational data for cm handle'
+ 1 * mockNetworkCmProxyDataService.getResourceDataOperationalForCmHandle('testCmHandle',
+ 'parent/child',
+ 'application/json',
+ '(a=1,b=2)',
+ expectedTopicName)
and: 'response status is Ok'
response.status == HttpStatus.OK.value()
+ where: 'the following parameters are used'
+ scenario | topicQueryParam || expectedTopicName
+ 'Url with valid topic' | "&topic=my-topic-name" || "my-topic-name"
+ 'No topic in url' | '' || NO_TOPIC
+ 'Null topic in url' | "&topic=null" || "null"
+ 'Empty topic in url' | "&topic=\"\"" || "\"\""
+ 'Missing topic in url' | "&topic=" || ""
}
- def 'Get Resource Data from pass-through running with #scenario value in resource identifier param.' () {
+ def 'Get Resource Data from pass-through running with #scenario value in resource identifier param.'() {
given: 'resource data url'
def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
"?resourceIdentifier=" + resourceIdentifier + "&options=(a=1,b=2)"
mockNetworkCmProxyDataService.getResourceDataPassThroughRunningForCmHandle('testCmHandle',
resourceIdentifier,
'application/json',
- '(a=1,b=2)') >> '{valid-json}'
+ '(a=1,b=2)',
+ NO_TOPIC) >> '{valid-json}'
when: 'get data resource request is performed'
def response = mvc.perform(
get(getUrl)
package org.onap.cps.ncmp.rest.exceptions
+ import com.fasterxml.jackson.databind.ObjectMapper
import groovy.json.JsonSlurper
- import org.modelmapper.ModelMapper
+ import org.mapstruct.factory.Mappers
import org.onap.cps.TestUtils
import org.onap.cps.ncmp.api.NetworkCmProxyDataService
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.ncmp.api.models.NcmpServiceCmHandle
+ import org.onap.cps.ncmp.rest.controller.NcmpRestInputMapper
import org.onap.cps.spi.exceptions.CpsException
import org.onap.cps.spi.exceptions.DataNodeNotFoundException
import org.onap.cps.spi.exceptions.DataValidationException
import static org.onap.cps.ncmp.rest.exceptions.NetworkCmProxyRestExceptionHandlerSpec.ApiType.NCMPINVENTORY
import static org.springframework.http.HttpStatus.BAD_REQUEST
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR
+import static org.springframework.http.HttpStatus.NOT_FOUND
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
@SpringBean
NetworkCmProxyDataService mockNetworkCmProxyDataService = Mock()
- @SpringBean
- ModelMapper modelMapper = Stub()
-
@SpringBean
JsonObjectMapper jsonObjectMapper = Stub()
@SpringBean
- RestInputMapper restInputMapper = Mock()
+ NcmpRestInputMapper ncmpRestInputMapper = Mappers.getMapper(NcmpRestInputMapper)
@Value('${rest.api.ncmp-base-path}')
def basePathNcmp
def dataNodeBaseEndpointNcmpInventory
@Shared
- def errorMessage = 'some error message'
+ def sampleErrorMessage = 'some error message'
@Shared
- def errorDetails = 'some error details'
- @Shared
- def dataNodeNotFoundErrorMessage = 'DataNode not found'
+ def sampleErrorDetails = 'some error details'
def setup() {
dataNodeBaseEndpointNcmp = "$basePathNcmp/v1"
dataNodeBaseEndpointNcmpInventory = "$basePathNcmpInventory/v1"
}
- def 'Get request with generic #scenario exception returns correct HTTP Status.'() {
+ def 'Get request with generic #scenario exception returns correct HTTP Status with #scenario'() {
when: 'an exception is thrown by the service'
setupTestException(exception, NCMP)
def response = performTestRequest(NCMP)
then: 'an HTTP response is returned with correct message and details'
assertTestResponse(response, expectedErrorCode, expectedErrorMessage, expectedErrorDetails)
where:
- 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
+ scenario | exception || expectedErrorDetails | expectedErrorMessage | expectedErrorCode
+ 'CPS' | new CpsException(sampleErrorMessage, sampleErrorDetails) || sampleErrorDetails | sampleErrorMessage | INTERNAL_SERVER_ERROR
+ 'NCMP-server' | new ServerNcmpException(sampleErrorMessage, sampleErrorDetails) || null | sampleErrorMessage | INTERNAL_SERVER_ERROR
+ 'NCMP-client' | new DmiRequestException(sampleErrorMessage, sampleErrorDetails) || null | sampleErrorMessage | BAD_REQUEST
+ 'DataNode Validation' | new DataNodeNotFoundException('myDataspaceName', 'myAnchorName') || null | 'DataNode not found' | NOT_FOUND
+ 'other' | new IllegalStateException(sampleErrorMessage) || null | sampleErrorMessage | INTERNAL_SERVER_ERROR
+ 'Data Node Not Found' | new DataNodeNotFoundException('myDataspaceName', 'myAnchorName') || 'DataNode not found' | 'DataNode not found' | NOT_FOUND
}
def 'Post request with exception returns correct HTTP Status.'() {
given: 'the service throws data validation exception'
- def exception = new DataValidationException(errorMessage, errorDetails)
+ def exception = new DataValidationException(sampleErrorMessage, sampleErrorDetails)
setupTestException(exception, NCMPINVENTORY)
when: 'the HTTP request is made'
def response = performTestRequest(NCMPINVENTORY)
then: 'an HTTP response is returned with correct message and details'
- assertTestResponse(response, BAD_REQUEST, errorMessage, errorDetails)
+ assertTestResponse(response, BAD_REQUEST, sampleErrorMessage, sampleErrorDetails)
}
def setupTestException(exception, apiType) {
static void assertTestResponse(response, expectedStatus , expectedErrorMessage , expectedErrorDetails) {
assert response.status == expectedStatus.value()
def content = new JsonSlurper().parseText(response.contentAsString)
- assert content['status'] == expectedStatus.toString()
- assert content['message'] == expectedErrorMessage
- assert expectedErrorDetails == null || content['details'] == expectedErrorDetails
+ assert content['status'].toString().contains(expectedStatus.toString())
+ assert content['message'].toString().contains(expectedErrorMessage)
+ assert expectedErrorDetails == null || content['details'].toString().contains(expectedErrorDetails)
}
enum ApiType {