aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cps-application/src/main/resources/application.yml2
-rw-r--r--cps-ncmp-rest/docs/openapi/components.yaml12
-rwxr-xr-xcps-ncmp-rest/docs/openapi/ncmp.yml2
-rwxr-xr-xcps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java14
-rwxr-xr-xcps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandler.java6
-rw-r--r--cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy41
-rw-r--r--cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy32
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java8
-rwxr-xr-xcps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java63
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java59
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java5
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java32
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiRequestBody.java1
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilder.java124
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy159
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy45
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy13
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy5
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/utils/DmiServiceUrlBuilderSpec.groovy79
-rw-r--r--cps-ncmp-service/src/test/resources/application.yml4
20 files changed, 537 insertions, 169 deletions
diff --git a/cps-application/src/main/resources/application.yml b/cps-application/src/main/resources/application.yml
index 723e2ca196..4dfeee8098 100644
--- a/cps-application/src/main/resources/application.yml
+++ b/cps-application/src/main/resources/application.yml
@@ -135,4 +135,4 @@ dmi:
username: ${DMI_USERNAME}
password: ${DMI_PASSWORD}
api:
- base-path: /dmi
+ base-path: dmi
diff --git a/cps-ncmp-rest/docs/openapi/components.yaml b/cps-ncmp-rest/docs/openapi/components.yaml
index d82813b874..4dd7e47115 100644
--- a/cps-ncmp-rest/docs/openapi/components.yaml
+++ b/cps-ncmp-rest/docs/openapi/components.yaml
@@ -329,6 +329,18 @@ components:
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
diff --git a/cps-ncmp-rest/docs/openapi/ncmp.yml b/cps-ncmp-rest/docs/openapi/ncmp.yml
index a267fb4919..1afd7c9111 100755
--- a/cps-ncmp-rest/docs/openapi/ncmp.yml
+++ b/cps-ncmp-rest/docs/openapi/ncmp.yml
@@ -29,6 +29,7 @@ getResourceDataForPassthroughOperational:
- $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
@@ -60,6 +61,7 @@ resourceDataForPassthroughRunning:
- $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
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 86f4460eaa..385180d8b7 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
@@ -76,17 +76,20 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
* @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);
}
@@ -97,17 +100,20 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
* @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);
}
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 5aaf1c31f0..2495f36426 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
@@ -30,6 +30,7 @@ import org.onap.cps.ncmp.rest.controller.NetworkCmProxyController;
import org.onap.cps.ncmp.rest.controller.NetworkCmProxyInventoryController;
import org.onap.cps.ncmp.rest.model.ErrorMessage;
import org.onap.cps.spi.exceptions.CpsException;
+import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
import org.onap.cps.spi.exceptions.DataValidationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@@ -69,6 +70,11 @@ public class NetworkCmProxyRestExceptionHandler {
return buildErrorResponse(HttpStatus.BAD_REQUEST, exception);
}
+ @ExceptionHandler({DataNodeNotFoundException.class})
+ public static ResponseEntity<Object> handleNotFoundExceptions(final CpsException exception) {
+ return buildErrorResponse(HttpStatus.NOT_FOUND, exception);
+ }
+
private static ResponseEntity<Object> buildErrorResponse(final HttpStatus status, final Exception exception) {
if (exception.getCause() != null || !(exception instanceof CpsException)) {
log.error("Exception occurred", 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 c99771443a..9cbf626ba9 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
@@ -24,6 +24,7 @@ package org.onap.cps.ncmp.rest.controller
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
@@ -70,7 +71,10 @@ class NetworkCmProxyControllerSpec extends Specification {
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)"
@@ -84,12 +88,40 @@ class NetworkCmProxyControllerSpec extends Specification {
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)"
@@ -97,7 +129,8 @@ class NetworkCmProxyControllerSpec extends Specification {
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)
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 8004328bc2..260ffd2132 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
@@ -45,6 +45,7 @@ import static org.onap.cps.ncmp.rest.exceptions.NetworkCmProxyRestExceptionHandl
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
@@ -76,40 +77,39 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification {
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) {
@@ -130,9 +130,9 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification {
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 {
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 471e97e081..d942d26c88 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
@@ -49,12 +49,14 @@ public interface NetworkCmProxyDataService {
* @param resourceIdentifier resource identifier
* @param acceptParamInHeader accept param
* @param optionsParamInQuery options query
+ * @param topicParamInQuery topic name for (triggering) async responses
* @return {@code Object} resource data
*/
Object getResourceDataOperationalForCmHandle(String cmHandleId,
String resourceIdentifier,
String acceptParamInHeader,
- String optionsParamInQuery);
+ String optionsParamInQuery,
+ String topicParamInQuery);
/**
* Get resource data for data store pass-through running
@@ -64,12 +66,14 @@ public interface NetworkCmProxyDataService {
* @param resourceIdentifier resource identifier
* @param acceptParamInHeader accept param
* @param optionsParamInQuery options query
+ * @param topicParamInQuery topic query
* @return {@code Object} resource data
*/
Object getResourceDataPassThroughRunningForCmHandle(String cmHandleId,
String resourceIdentifier,
String acceptParamInHeader,
- String optionsParamInQuery);
+ String optionsParamInQuery,
+ String topicParamInQuery);
/**
* Write resource data for data store pass-through running
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 1762e46287..e923ce4145 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
@@ -37,9 +37,12 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.UUID;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.apache.logging.log4j.util.Strings;
import org.onap.cps.api.CpsAdminService;
import org.onap.cps.api.CpsDataService;
import org.onap.cps.api.CpsModuleService;
@@ -57,6 +60,7 @@ import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
import org.onap.cps.spi.exceptions.DataValidationException;
import org.onap.cps.spi.model.ModuleReference;
import org.onap.cps.utils.JsonObjectMapper;
+import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
@@ -81,6 +85,12 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
private final YangModelCmHandleRetriever yangModelCmHandleRetriever;
+ // valid kafka topic name regex
+ private static final Pattern TOPIC_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9]([._-](?![._-])|"
+ + "[a-zA-Z0-9]){0,120}[a-zA-Z0-9]$");
+ private static final String NO_REQUEST_ID = null;
+ private static final String NO_TOPIC = null;
+
@Override
public void updateDmiRegistrationAndSyncModule(final DmiPluginRegistration dmiPluginRegistration) {
dmiPluginRegistration.validateDmiPluginRegistration();
@@ -104,26 +114,21 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
public Object getResourceDataOperationalForCmHandle(final String cmHandleId,
final String resourceIdentifier,
final String acceptParamInHeader,
- final String optionsParamInQuery) {
- return handleResponse(dmiDataOperations.getResourceDataFromDmi(
- cmHandleId,
- resourceIdentifier,
- optionsParamInQuery,
- acceptParamInHeader,
- DmiOperations.DataStoreEnum.PASSTHROUGH_OPERATIONAL), "Not able to get resource data.");
+ final String optionsParamInQuery,
+ final String topicParamInQuery) {
+
+ return validateTopicNameAndGetResourceData(cmHandleId, resourceIdentifier, acceptParamInHeader,
+ DmiOperations.DataStoreEnum.PASSTHROUGH_OPERATIONAL, optionsParamInQuery, topicParamInQuery);
}
@Override
public Object getResourceDataPassThroughRunningForCmHandle(final String cmHandleId,
final String resourceIdentifier,
final String acceptParamInHeader,
- final String optionsParamInQuery) {
- return handleResponse(dmiDataOperations.getResourceDataFromDmi(
- cmHandleId,
- resourceIdentifier,
- optionsParamInQuery,
- acceptParamInHeader,
- DmiOperations.DataStoreEnum.PASSTHROUGH_RUNNING), "Not able to get resource data.");
+ final String optionsParamInQuery,
+ final String topicParamInQuery) {
+ return validateTopicNameAndGetResourceData(cmHandleId, resourceIdentifier, acceptParamInHeader,
+ DmiOperations.DataStoreEnum.PASSTHROUGH_RUNNING, optionsParamInQuery, topicParamInQuery);
}
@Override
@@ -297,4 +302,32 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
cpsAdminService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, yangModelCmHandle.getId(),
yangModelCmHandle.getId());
}
-}
+
+ private static boolean isValidTopicName(final String topicName) {
+ return Strings.isNotEmpty(topicName) && TOPIC_NAME_PATTERN.matcher(topicName).matches();
+ }
+
+ private Map<String, Object> buildDmiResponse(final String requestId) {
+ final Map<String, Object> dmiResponseMap = new HashMap<>();
+ dmiResponseMap.put("requestId", requestId);
+ return dmiResponseMap;
+ }
+
+ private Object validateTopicNameAndGetResourceData(final String cmHandleId,
+ final String resourceIdentifier,
+ final String acceptParamInHeader,
+ final DmiOperations.DataStoreEnum dataStore,
+ final String optionsParamInQuery,
+ final String topicParamInQuery) {
+ final boolean processAsynchronously = isValidTopicName(topicParamInQuery);
+ if (processAsynchronously) {
+ final String resourceDataRequestId = UUID.randomUUID().toString();
+ return ResponseEntity.status(HttpStatus.OK)
+ .body(buildDmiResponse(resourceDataRequestId));
+ }
+ final ResponseEntity<?> responseEntity = dmiDataOperations.getResourceDataFromDmi(
+ cmHandleId, resourceIdentifier, optionsParamInQuery, acceptParamInHeader,
+ dataStore, NO_REQUEST_ID, NO_TOPIC);
+ return handleResponse(responseEntity, "Not able to get resource data.");
+ }
+} \ No newline at end of file
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 229d4fc917..68de9d5c6b 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
@@ -23,10 +23,10 @@ package org.onap.cps.ncmp.api.impl.operations;
import static org.onap.cps.ncmp.api.impl.operations.DmiOperations.DataStoreEnum.PASSTHROUGH_RUNNING;
import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum;
import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.READ;
-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.impl.utils.DmiServiceUrlBuilder;
import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.http.HttpHeaders;
@@ -47,8 +47,8 @@ public class DmiDataOperations extends DmiOperations {
public DmiDataOperations(final YangModelCmHandleRetriever cmHandlePropertiesRetriever,
final JsonObjectMapper jsonObjectMapper,
final NcmpConfiguration.DmiProperties dmiProperties,
- final DmiRestClient dmiRestClient) {
- super(cmHandlePropertiesRetriever, jsonObjectMapper, dmiProperties, dmiRestClient);
+ final DmiRestClient dmiRestClient, final DmiServiceUrlBuilder dmiServiceUrlBuilder) {
+ super(cmHandlePropertiesRetriever, jsonObjectMapper, dmiProperties, dmiRestClient, dmiServiceUrlBuilder);
}
/**
@@ -59,25 +59,31 @@ public class DmiDataOperations extends DmiOperations {
* @param resourceId resource identifier
* @param optionsParamInQuery options query
* @param acceptParamInHeader accept parameter
- * @param dataStore data store enum
+ * @param dataStore data store enum
+ * @param requestId requestId for async responses
+ * @param topicParamInQuery topic name for (triggering) async responses
* @return {@code ResponseEntity} response entity
*/
public ResponseEntity<Object> getResourceDataFromDmi(final String cmHandleId,
- final String resourceId,
- final String optionsParamInQuery,
- final String acceptParamInHeader,
- final DataStoreEnum dataStore) {
+ final String resourceId,
+ final String optionsParamInQuery,
+ final String acceptParamInHeader,
+ final DataStoreEnum dataStore,
+ final String requestId,
+ final String topicParamInQuery) {
final YangModelCmHandle yangModelCmHandle =
- yangModelCmHandleRetriever.getDmiServiceNamesAndProperties(cmHandleId);
+ yangModelCmHandleRetriever.getDmiServiceNamesAndProperties(cmHandleId);
final DmiRequestBody dmiRequestBody = DmiRequestBody.builder()
.operation(READ)
+ .requestId(requestId)
.build();
dmiRequestBody.asDmiProperties(yangModelCmHandle.getDmiProperties());
final String jsonBody = jsonObjectMapper.asJsonString(dmiRequestBody);
- final var dmiResourceDataUrl = getDmiDatastoreUrlWithOptions(
- yangModelCmHandle.resolveDmiServiceName(DATA), cmHandleId, resourceId,
- optionsParamInQuery, dataStore);
+ final var dmiResourceDataUrl = dmiServiceUrlBuilder.getDmiDatastoreUrl(
+ dmiServiceUrlBuilder.populateQueryParams(resourceId, optionsParamInQuery,
+ topicParamInQuery), dmiServiceUrlBuilder.populateUriVariables(
+ yangModelCmHandle, cmHandleId, dataStore));
final var httpHeaders = prepareHeader(acceptParamInHeader);
return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonBody, httpHeaders);
}
@@ -108,33 +114,10 @@ public class DmiDataOperations extends DmiOperations {
dmiRequestBody.asDmiProperties(yangModelCmHandle.getDmiProperties());
final String jsonBody = jsonObjectMapper.asJsonString(dmiRequestBody);
final String dmiUrl =
- getResourceInDataStoreUrl(yangModelCmHandle.resolveDmiServiceName(DATA),
- cmHandleId, resourceId, PASSTHROUGH_RUNNING);
+ dmiServiceUrlBuilder.getDmiDatastoreUrl(dmiServiceUrlBuilder.populateQueryParams(resourceId,
+ null, null),
+ dmiServiceUrlBuilder.populateUriVariables(yangModelCmHandle, cmHandleId, PASSTHROUGH_RUNNING));
return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonBody, new HttpHeaders());
}
- private String getResourceInDataStoreUrl(final String dmiServiceName,
- final String cmHandleId,
- final String resourceId,
- final DataStoreEnum dataStoreEnum) {
- return getCmHandleUrl(dmiServiceName, cmHandleId)
- + "data"
- + URL_SEPARATOR
- + "ds"
- + URL_SEPARATOR
- + dataStoreEnum.getValue()
- + "?resourceIdentifier="
- + resourceId;
- }
-
- private String getDmiDatastoreUrlWithOptions(final String dmiServiceName,
- final String cmHandleId,
- final String resourceId,
- final String optionsParamInQuery,
- final DataStoreEnum dataStoreEnum) {
- final String resourceInDataStoreUrl = getResourceInDataStoreUrl(dmiServiceName,
- 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 bfe934dfd8..d79988e2e0 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,6 +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.impl.utils.DmiServiceUrlBuilder;
import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
import org.onap.cps.ncmp.api.models.YangResource;
import org.onap.cps.spi.model.ModuleReference;
@@ -53,8 +54,8 @@ public class DmiModelOperations extends DmiOperations {
public DmiModelOperations(final YangModelCmHandleRetriever dmiPropertiesRetriever,
final JsonObjectMapper jsonObjectMapper,
final NcmpConfiguration.DmiProperties dmiProperties,
- final DmiRestClient dmiRestClient) {
- super(dmiPropertiesRetriever, jsonObjectMapper, dmiProperties, dmiRestClient);
+ final DmiRestClient dmiRestClient, final DmiServiceUrlBuilder dmiServiceUrlBuilder) {
+ super(dmiPropertiesRetriever, jsonObjectMapper, dmiProperties, dmiRestClient, dmiServiceUrlBuilder);
}
/**
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 645d9799fb..75ba91b4f7 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
@@ -20,17 +20,15 @@
package org.onap.cps.ncmp.api.impl.operations;
-import com.google.common.base.Strings;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration;
+import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
-@Slf4j
@RequiredArgsConstructor
@Service
public class DmiOperations {
@@ -39,7 +37,7 @@ public class DmiOperations {
public enum DataStoreEnum {
PASSTHROUGH_OPERATIONAL("ncmp-datastore:passthrough-operational"),
PASSTHROUGH_RUNNING("ncmp-datastore:passthrough-running");
- private String value;
+ private final String value;
DataStoreEnum(final String value) {
this.value = value;
@@ -50,30 +48,12 @@ public class DmiOperations {
protected final JsonObjectMapper jsonObjectMapper;
protected final NcmpConfiguration.DmiProperties dmiProperties;
protected final DmiRestClient dmiRestClient;
-
- static final String URL_SEPARATOR = "/";
-
- String getCmHandleUrl(final String dmiServiceName, final String cmHandle) {
- return dmiServiceName
- + dmiProperties.getDmiBasePath()
- + URL_SEPARATOR
- + "v1"
- + URL_SEPARATOR
- + "ch"
- + URL_SEPARATOR
- + cmHandle
- + URL_SEPARATOR;
- }
+ protected final DmiServiceUrlBuilder dmiServiceUrlBuilder;
String getDmiResourceUrl(final String dmiServiceName, final String cmHandle, final String resourceName) {
- return getCmHandleUrl(dmiServiceName, cmHandle) + resourceName;
- }
-
- static String appendOptionsQuery(final String url, final String optionsParamInQuery) {
- if (Strings.isNullOrEmpty(optionsParamInQuery)) {
- return url;
- }
- return url + "&options=" + optionsParamInQuery;
+ return dmiServiceUrlBuilder.getCmHandleUrl()
+ .pathSegment("{resourceName}")
+ .buildAndExpand(dmiServiceName, dmiProperties.getDmiBasePath(), cmHandle, resourceName).toUriString();
}
static HttpHeaders prepareHeader(final String acceptParam) {
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 d97e90cbbe..c84e4cb870 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
@@ -58,6 +58,7 @@ public class DmiRequestBody {
private String data;
@JsonProperty("cmHandleProperties")
private Map<String, String> dmiProperties;
+ private String requestId;
/**
* Set DMI Properties by converting a list of YangModelCmHandle.Property objects.
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilder.java
new file mode 100644
index 0000000000..b60aac9518
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilder.java
@@ -0,0 +1,124 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 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.utils;
+
+import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.DATA;
+
+import java.util.HashMap;
+import java.util.Map;
+import lombok.RequiredArgsConstructor;
+import org.apache.logging.log4j.util.Strings;
+import org.apache.logging.log4j.util.TriConsumer;
+import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration;
+import org.onap.cps.ncmp.api.impl.operations.DmiOperations;
+import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
+import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.util.UriComponentsBuilder;
+
+@Component
+@RequiredArgsConstructor
+public class DmiServiceUrlBuilder {
+
+ private final NcmpConfiguration.DmiProperties dmiProperties;
+
+ /**
+ * This method creates the dmi service url.
+ *
+ * @param queryParams query param map as key,value pair
+ * @param uriVariables uri param map as key (placeholder),value pair
+ * @return {@code String} dmi service url as string
+ */
+ public String getDmiDatastoreUrl(final MultiValueMap<String, String> queryParams,
+ final Map<String, Object> uriVariables) {
+ final UriComponentsBuilder uriComponentsBuilder = getCmHandleUrl()
+ .pathSegment("data")
+ .pathSegment("ds")
+ .pathSegment("{dataStore}")
+ .queryParams(queryParams)
+ .uriVariables(uriVariables);
+ return uriComponentsBuilder.buildAndExpand().toUriString();
+ }
+
+ /**
+ * This method creates the dmi service url builder object with path variables.
+ *
+ * @return {@code UriComponentsBuilder} dmi service url builder object
+ */
+ public UriComponentsBuilder getCmHandleUrl() {
+ return UriComponentsBuilder.newInstance()
+ .path("{dmiServiceName}")
+ .pathSegment("{dmiBasePath}")
+ .pathSegment("v1")
+ .pathSegment("ch")
+ .pathSegment("{cmHandle}");
+ }
+
+ /**
+ * This method populates uri variables.
+ *
+ * @param yangModelCmHandle get dmi service name
+ * @param cmHandle cm handle name for dmi registration
+ * @return {@code String} dmi service url as string
+ */
+ public Map<String, Object> populateUriVariables(final YangModelCmHandle yangModelCmHandle,
+ final String cmHandle,
+ final DmiOperations.DataStoreEnum dataStore) {
+ final Map<String, Object> uriVariables = new HashMap<>();
+ final String dmiBasePath = dmiProperties.getDmiBasePath();
+ uriVariables.put("dmiServiceName",
+ yangModelCmHandle.resolveDmiServiceName(DATA));
+ uriVariables.put("dmiBasePath", dmiBasePath);
+ uriVariables.put("cmHandle", cmHandle);
+ uriVariables.put("dataStore", dataStore.getValue());
+ return uriVariables;
+ }
+
+ /**
+ * This method is used to populate map from query params.
+ *
+ * @param resourceId unique id of response for valid topic
+ * @param optionsParamInQuery options into url param
+ * @param topicParamInQuery topic into url param
+ * @return all valid query params as map
+ */
+ public MultiValueMap<String, String> populateQueryParams(final String resourceId,
+ final String optionsParamInQuery,
+ final String topicParamInQuery) {
+ final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
+ getQueryParamConsumer().accept("resourceIdentifier",
+ resourceId, queryParams);
+ getQueryParamConsumer().accept("options", optionsParamInQuery, queryParams);
+ if (Strings.isNotEmpty(topicParamInQuery)) {
+ getQueryParamConsumer().accept("topic", topicParamInQuery, queryParams);
+ }
+ return queryParams;
+ }
+
+ private TriConsumer<String, String, MultiValueMap<String, String>> getQueryParamConsumer() {
+ return (paramName, paramValue, paramMap) -> {
+ if (Strings.isNotEmpty(paramValue)) {
+ paramMap.add(paramName, paramValue);
+ }
+ };
+ }
+}
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 b2a3d77cac..e6d18d9156 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
@@ -24,6 +24,7 @@ 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 spock.lang.Shared
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
@@ -56,6 +57,10 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
def mockDmiDataOperations = Mock(DmiDataOperations)
def nullNetworkCmProxyDataServicePropertyHandler = null
def mockYangModelCmHandleRetriever = Mock(YangModelCmHandleRetriever)
+ def NO_TOPIC = null
+ def NO_REQUEST_ID = null
+ @Shared
+ def OPTIONS_PARAM = '(a=1,b=2)'
def objectUnderTest = new NetworkCmProxyDataServiceImpl(mockCpsDataService, spiedJsonObjectMapper, mockDmiDataOperations, mockDmiModelOperations,
mockCpsModuleService, mockCpsAdminService, nullNetworkCmProxyDataServicePropertyHandler, mockYangModelCmHandleRetriever)
@@ -64,7 +69,6 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
def dataNode = new DataNode(leaves: ['dmi-service-name': 'testDmiService'])
-
def 'Write resource data for pass-through running from DMI using POST #scenario cm handle properties.'() {
given: 'cpsDataService returns valid datanode'
mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
@@ -104,18 +108,21 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
and: 'get resource data from DMI is called'
mockDmiDataOperations.getResourceDataFromDmi(
- 'testCmHandle',
- 'testResourceId',
- '(a=1,b=2)',
- 'testAcceptParam' ,
- PASSTHROUGH_OPERATIONAL) >> new ResponseEntity<>('result-json', HttpStatus.OK)
+ 'testCmHandle',
+ 'testResourceId',
+ OPTIONS_PARAM,
+ 'testAcceptParam',
+ PASSTHROUGH_OPERATIONAL,
+ NO_REQUEST_ID,
+ NO_TOPIC) >> new ResponseEntity<>('dmi-response', HttpStatus.OK)
when: 'get resource data operational for cm-handle is called'
def response = objectUnderTest.getResourceDataOperationalForCmHandle('testCmHandle',
- 'testResourceId',
- 'testAcceptParam',
- '(a=1,b=2)')
+ 'testResourceId',
+ 'testAcceptParam',
+ OPTIONS_PARAM,
+ NO_TOPIC)
then: 'DMI returns a json response'
- response == 'result-json'
+ response == 'dmi-response'
}
def 'Get resource data for pass-through operational from DMI with Json Processing Exception.'() {
@@ -129,9 +136,10 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
>> new ResponseEntity<>('NOK-json', HttpStatus.NOT_FOUND)
when: 'get resource data is called'
objectUnderTest.getResourceDataOperationalForCmHandle('testCmHandle',
- 'testResourceId',
- 'testAcceptParam',
- '(a=1,b=2)')
+ 'testResourceId',
+ 'testAcceptParam',
+ OPTIONS_PARAM,
+ NO_TOPIC)
then: 'exception is thrown with the expected details'
def exceptionThrown = thrown(ServerNcmpException.class)
exceptionThrown.details == 'DMI status code: 404, DMI response body: NOK-json'
@@ -143,16 +151,19 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
and: 'DMI returns NOK response'
mockDmiDataOperations.getResourceDataFromDmi('testCmHandle',
- 'testResourceId',
- '(a=1,b=2)',
- 'testAcceptParam',
- PASSTHROUGH_OPERATIONAL)
- >> new ResponseEntity<>('NOK-json', HttpStatus.NOT_FOUND)
+ 'testResourceId',
+ OPTIONS_PARAM,
+ 'testAcceptParam',
+ PASSTHROUGH_OPERATIONAL,
+ NO_REQUEST_ID,
+ NO_TOPIC)
+ >> new ResponseEntity<>('NOK-json', HttpStatus.NOT_FOUND)
when: 'get resource data is called'
objectUnderTest.getResourceDataOperationalForCmHandle('testCmHandle',
- 'testResourceId',
- 'testAcceptParam',
- '(a=1,b=2)')
+ 'testResourceId',
+ 'testAcceptParam',
+ OPTIONS_PARAM,
+ NO_TOPIC)
then: 'exception is thrown'
def exceptionThrown = thrown(ServerNcmpException.class)
and: 'details contains the original response'
@@ -165,17 +176,20 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
and: 'DMI returns valid response and data'
mockDmiDataOperations.getResourceDataFromDmi('testCmHandle',
- 'testResourceId',
- '(a=1,b=2)',
- 'testAcceptParam',
- PASSTHROUGH_RUNNING) >> new ResponseEntity<>('{result-json}', HttpStatus.OK)
+ 'testResourceId',
+ OPTIONS_PARAM,
+ 'testAcceptParam',
+ PASSTHROUGH_RUNNING,
+ NO_REQUEST_ID,
+ NO_TOPIC) >> new ResponseEntity<>('{dmi-response}', HttpStatus.OK)
when: 'get resource data is called'
def response = objectUnderTest.getResourceDataPassThroughRunningForCmHandle('testCmHandle',
- 'testResourceId',
- 'testAcceptParam',
- '(a=1,b=2)')
+ 'testResourceId',
+ 'testAcceptParam',
+ OPTIONS_PARAM,
+ NO_TOPIC)
then: 'get resource data returns expected response'
- response == '{result-json}'
+ response == '{dmi-response}'
}
def 'Get resource data for pass-through running from DMI return NOK response.'() {
@@ -184,22 +198,91 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
and: 'DMI returns NOK response'
mockDmiDataOperations.getResourceDataFromDmi('testCmHandle',
- 'testResourceId',
- '(a=1,b=2)',
- 'testAcceptParam',
- PASSTHROUGH_RUNNING)
- >> new ResponseEntity<>('NOK-json', HttpStatus.NOT_FOUND)
+ 'testResourceId',
+ OPTIONS_PARAM,
+ 'testAcceptParam',
+ PASSTHROUGH_RUNNING,
+ NO_REQUEST_ID,
+ NO_TOPIC)
+ >> new ResponseEntity<>('NOK-json', HttpStatus.NOT_FOUND)
when: 'get resource data is called'
objectUnderTest.getResourceDataPassThroughRunningForCmHandle('testCmHandle',
- 'testResourceId',
- 'testAcceptParam',
- '(a=1,b=2)')
+ 'testResourceId',
+ 'testAcceptParam',
+ OPTIONS_PARAM,
+ NO_TOPIC)
then: 'exception is thrown'
def exceptionThrown = thrown(ServerNcmpException.class)
and: 'details contains the original response'
exceptionThrown.details.contains('NOK-json')
}
+ def 'Get resource data for operational from DMI with empty topic sync request.'() {
+ given: 'cps data service returns valid data node'
+ mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
+ cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
+ and: 'dmi data operation returns valid response and data'
+ mockDmiDataOperations.getResourceDataFromDmi(_, _, _, _, _, NO_REQUEST_ID, NO_TOPIC)
+ >> new ResponseEntity<>('{dmi-response}', HttpStatus.OK)
+ when: 'get resource data is called data operational with blank topic'
+ def responseData = objectUnderTest.getResourceDataOperationalForCmHandle('', '',
+ '', '', emptyTopic)
+ then: '(synchronous) the dmi response is expected'
+ assert responseData == '{dmi-response}'
+ where: 'the following parameters are used'
+ scenario | emptyTopic
+ 'No topic in url' | ''
+ 'Null topic in url' | null
+ 'Empty topic in url' | '\"\"'
+ 'Blank topic in url' | ' '
+ }
+
+ def 'Get resource data for data operational from DMI with valid topic i.e. async request.'() {
+ given: 'cps data service returns valid data node'
+ mockCpsDataService.getDataNode(*_) >> dataNode
+ and: 'dmi data operation returns valid response and data'
+ mockDmiDataOperations.getResourceDataFromDmi(_, _, _, _, _, _, 'my-topic-name')
+ >> new ResponseEntity<>('{dmi-response}', HttpStatus.OK)
+ when: 'get resource data is called for data operational with valid topic'
+ def responseData = objectUnderTest.getResourceDataOperationalForCmHandle('', '', '', '', 'my-topic-name')
+ then: 'non empty request id is generated'
+ assert responseData.body.requestId.length() > 0
+ }
+
+ def 'Get resource data for pass through running from DMI with valid topic async request.'() {
+ given: 'cps data service returns valid data node'
+ mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
+ cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
+ and: 'dmi data operation returns valid response and data'
+ mockDmiDataOperations.getResourceDataFromDmi(_, _, _, _, _, _, 'my-topic-name')
+ >> new ResponseEntity<>('{dmi-response}', HttpStatus.OK)
+ when: 'get resource data is called for data operational with valid topic'
+ def responseData = objectUnderTest.getResourceDataPassThroughRunningForCmHandle('',
+ '', '', OPTIONS_PARAM, 'my-topic-name')
+ then: 'non empty request id is generated'
+ assert responseData.body.requestId.length() > 0
+ }
+
+ def 'Get resource data for pass through running from DMI sync request where #scenario.'() {
+ given: 'cps data service returns valid data node'
+ mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
+ cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
+ and: 'dmi data operation returns valid response and data'
+ mockDmiDataOperations.getResourceDataFromDmi(_, _, _, _, _, NO_REQUEST_ID, NO_TOPIC)
+ >> new ResponseEntity<>('{dmi-response}', HttpStatus.OK)
+ when: 'get resource data is called for data operational with valid topic'
+ def responseData = objectUnderTest.getResourceDataPassThroughRunningForCmHandle('',
+ '', '', '', emptyTopic)
+ then: '(synchronous) the dmi response is expected'
+ assert responseData == '{dmi-response}'
+ where: 'the following parameters are used'
+ scenario | emptyTopic
+ 'No topic in url' | ''
+ 'Null topic in url' | null
+ 'Empty topic in url' | '\"\"'
+ 'Blank topic in url' | ' '
+ }
+
def 'Getting Yang Resources.'() {
when: 'yang resources is called'
objectUnderTest.getYangResourcesModuleReferences('some cm handle')
@@ -255,7 +338,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
givenOperation,
'{some-json}',
'application/json')
- then: 'an exception is thrown with the expected error message detailsd with correct operation'
+ then: 'an exception is thrown with the expected error message details with correct operation'
def exceptionThrown = thrown(ServerNcmpException.class)
exceptionThrown.getMessage().contains(expectedResponseMessage)
where:
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 e585825ca3..3df862ac5c 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
@@ -22,12 +22,15 @@ package org.onap.cps.ncmp.api.impl.operations
import com.fasterxml.jackson.databind.ObjectMapper
import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration
+import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder
import org.onap.cps.utils.JsonObjectMapper
import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.ResponseEntity
import org.springframework.test.context.ContextConfiguration
+import org.springframework.util.MultiValueMap
+import spock.lang.Shared
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
@@ -40,43 +43,54 @@ import org.springframework.http.HttpStatus
class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
@SpringBean
- JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
+ DmiServiceUrlBuilder dmiServiceUrlBuilder = Mock()
+ def dmiServiceBaseUrl = "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/data/ds/ncmp-datastore:"
+ def NO_TOPIC = null
+ def NO_REQUEST_ID = null
+ @Shared
+ def OPTIONS_PARAM = '(a=1,b=2)'
+
+ @SpringBean
+ JsonObjectMapper spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
@Autowired
DmiDataOperations objectUnderTest
- def 'call get resource data for #expectedDatastoreInUrl from DMI #scenario.'() {
+ def 'call get resource data for #expectedDatastoreInUrl from DMI without topic #scenario.'() {
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(
- "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/data/ds/ncmp-datastore:${expectedDatastoreInUrl}?resourceIdentifier=${resourceIdentifier}${expectedOptionsInUrl}",
- expectedJson, [Accept:['sample accept header']]) >> responseFromDmi
+ def expectedUrl = dmiServiceBaseUrl + "${expectedDatastoreInUrl}?resourceIdentifier=${resourceIdentifier}${expectedOptionsInUrl}"
+ mockDmiRestClient.postOperationWithJsonData(expectedUrl,
+ expectedJson, [Accept: ['sample accept header']]) >> responseFromDmi
+ dmiServiceUrlBuilder.getDmiDatastoreUrl(_, _) >> expectedUrl
when: 'get resource data is invoked'
- def result = objectUnderTest.getResourceDataFromDmi(cmHandleId,resourceIdentifier, options,'sample accept header', dataStore)
+ def result = objectUnderTest.getResourceDataFromDmi(cmHandleId, resourceIdentifier,
+ options, 'sample accept header', dataStore, NO_REQUEST_ID, NO_TOPIC)
then: 'the result is the response from the DMI service'
assert result == responseFromDmi
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' | [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)'
+ scenario | dmiProperties | dataStore | options || expectedJson | expectedDatastoreInUrl | expectedOptionsInUrl
+ 'without properties' | [] | PASSTHROUGH_OPERATIONAL | OPTIONS_PARAM || '{"operation":"read","cmHandleProperties":{}}' | 'passthrough-operational' | '&options=(a=1,b=2)'
+ 'with properties' | [yangModelCmHandleProperty] | PASSTHROUGH_OPERATIONAL | OPTIONS_PARAM || '{"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 without properties' | [] | PASSTHROUGH_RUNNING | OPTIONS_PARAM || '{"operation":"read","cmHandleProperties":{}}' | 'passthrough-running' | '&options=(a=1,b=2)'
+ 'datastore running with properties' | [yangModelCmHandleProperty] | PASSTHROUGH_RUNNING | OPTIONS_PARAM || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-running' | '&options=(a=1,b=2)'
}
def 'Write data for pass-through:running datastore in DMI.'() {
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}"
+ def expectedUrl = dmiServiceBaseUrl + "passthrough-running?resourceIdentifier=${resourceIdentifier}"
def expectedJson = '{"operation":"' + expectedOperationInUrl + '","dataType":"some data type","data":"requestData","cmHandleProperties":{"prop1":"val1"}}'
def responseFromDmi = new ResponseEntity<Object>(HttpStatus.OK)
+ dmiServiceUrlBuilder.getDmiDatastoreUrl(_, _) >> expectedUrl
mockDmiRestClient.postOperationWithJsonData(expectedUrl, expectedJson, [:]) >> responseFromDmi
when: 'write resource method is invoked'
- def result = objectUnderTest.writeResourceDataPassThroughRunningFromDmi(cmHandleId,'parent/child', operation, 'requestData', 'some data type')
+ def result = objectUnderTest.writeResourceDataPassThroughRunningFromDmi(cmHandleId, 'parent/child', operation, 'requestData', 'some data type')
then: 'the result is the response from the DMI service'
assert result == responseFromDmi
where: 'the following operation is performed'
@@ -84,5 +98,4 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
CREATE || 'create'
UPDATE || 'update'
}
-
} \ No newline at end of file
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 cd2cb7112c..d3fc17cc07 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
@@ -23,6 +23,7 @@ package org.onap.cps.ncmp.api.impl.operations
import com.fasterxml.jackson.core.JsonProcessingException
import com.fasterxml.jackson.databind.ObjectMapper
import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration
+import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder
import org.onap.cps.spi.model.ModuleReference
import org.onap.cps.utils.JsonObjectMapper
import org.spockframework.spring.SpringBean
@@ -31,6 +32,7 @@ import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.test.context.ContextConfiguration
+import org.springframework.web.util.UriComponentsBuilder
import spock.lang.Shared
@SpringBootTest
@@ -50,14 +52,15 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
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
+ def moduleReferencesAsLisOfMaps = [[moduleName: 'mod1', revision: 'A'], [moduleName: 'mod2', revision: 'X']]
+ def expectedUrl = "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/modules"
+ def responseFromDmi = new ResponseEntity([schemas: moduleReferencesAsLisOfMaps], HttpStatus.OK)
+ mockDmiRestClient.postOperationWithJsonData(expectedUrl, '{"cmHandleProperties":{}}', [:])
+ >> responseFromDmi
when: 'get module references is called'
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')]
+ assert result == [new ModuleReference(moduleName: 'mod1', revision: 'A'), new ModuleReference(moduleName: 'mod2', revision: 'X')]
}
def 'Retrieving module references edge case: #scenario.'() {
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 dd0d64dd61..e6f63ce1a2 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,9 @@ 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.impl.config.NcmpConfiguration
import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
+import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder
import org.spockframework.spring.SpringBean
import spock.lang.Shared
import spock.lang.Specification
@@ -41,6 +43,9 @@ abstract class DmiOperationsBaseSpec extends Specification {
@SpringBean
ObjectMapper spyObjectMapper = Spy()
+ @SpringBean
+ DmiServiceUrlBuilder dmiServiceUrlBuilder = new DmiServiceUrlBuilder(new NcmpConfiguration.DmiProperties())
+
def yangModelCmHandle = new YangModelCmHandle()
def static dmiServiceName = 'some service name'
def static cmHandleId = 'some cm handle'
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/utils/DmiServiceUrlBuilderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/utils/DmiServiceUrlBuilderSpec.groovy
new file mode 100644
index 0000000000..1615d055db
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/utils/DmiServiceUrlBuilderSpec.groovy
@@ -0,0 +1,79 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 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.utils
+
+import static org.onap.cps.ncmp.api.impl.operations.DmiOperations.DataStoreEnum.PASSTHROUGH_RUNNING
+
+import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
+import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration
+import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder
+import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
+import spock.lang.Shared
+import spock.lang.Specification
+
+class DmiServiceUrlBuilderSpec extends Specification {
+
+ @Shared
+ YangModelCmHandle yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle("dmiServiceName",
+ "dmiDataServiceName", "dmiModuleServiceName", new NcmpServiceCmHandle())
+
+ NcmpConfiguration.DmiProperties dmiProperties = new NcmpConfiguration.DmiProperties();
+
+ def objectUnderTest = new DmiServiceUrlBuilder(dmiProperties)
+
+ def 'Create the dmi service url with #scenario.'() {
+ given: 'uri variables'
+ dmiProperties.dmiBasePath = 'dmi';
+ def uriVars = objectUnderTest.populateUriVariables(yangModelCmHandle,
+ "cmHandle", PASSTHROUGH_RUNNING);
+ and: 'query params'
+ def uriQueries = objectUnderTest.populateQueryParams(resourceId,
+ 'optionsParamInQuery', topicParamInQuery);
+ when: 'a dmi datastore service url is generated'
+ def dmiServiceUrl = objectUnderTest.getDmiDatastoreUrl(uriQueries, uriVars)
+ then: 'service url is generated as expected'
+ assert dmiServiceUrl == expectedDmiServiceUrl
+ where: 'the following parameters are used'
+ scenario | topicParamInQuery | resourceId || expectedDmiServiceUrl
+ 'With valid resourceId' | 'topicParamInQuery' | 'resourceId' || 'dmiServiceName/dmi/v1/ch/cmHandle/data/ds/ncmp-datastore:passthrough-running?resourceIdentifier=resourceId&options=optionsParamInQuery&topic=topicParamInQuery'
+ 'With Empty resourceId' | 'topicParamInQuery' | '' || 'dmiServiceName/dmi/v1/ch/cmHandle/data/ds/ncmp-datastore:passthrough-running?options=optionsParamInQuery&topic=topicParamInQuery'
+ 'With Empty dmi base path' | 'topicParamInQuery' | 'resourceId' || 'dmiServiceName/dmi/v1/ch/cmHandle/data/ds/ncmp-datastore:passthrough-running?resourceIdentifier=resourceId&options=optionsParamInQuery&topic=topicParamInQuery'
+ 'With Empty topicParamInQuery' | '' | 'resourceId' || 'dmiServiceName/dmi/v1/ch/cmHandle/data/ds/ncmp-datastore:passthrough-running?resourceIdentifier=resourceId&options=optionsParamInQuery'
+ }
+
+ def 'Populate dmi data store url #scenario.'() {
+ given: 'uri variables are created'
+ dmiProperties.dmiBasePath = dmiBasePath;
+ def uriVars = objectUnderTest.populateUriVariables(yangModelCmHandle,
+ "cmHandle", PASSTHROUGH_RUNNING);
+ and: 'null query params'
+ def uriQueries = objectUnderTest.populateQueryParams(null,
+ null, null);
+ when: 'a dmi datastore service url is generated'
+ def dmiServiceUrl = objectUnderTest.getDmiDatastoreUrl(uriQueries, uriVars)
+ then: 'the created dmi service url matches the expected'
+ assert dmiServiceUrl == expectedDmiServiceUrl
+ where: 'the following parameters are used'
+ scenario | decription | dmiBasePath || expectedDmiServiceUrl
+ 'with base path / ' | 'Invalid base path as it starts with /' | '/dmi' || 'dmiServiceName//dmi/v1/ch/cmHandle/data/ds/ncmp-datastore:passthrough-running'
+ 'without base path / ' | 'Valid path as it does not starts with /' | 'dmi' || 'dmiServiceName/dmi/v1/ch/cmHandle/data/ds/ncmp-datastore:passthrough-running'
+ }
+}
diff --git a/cps-ncmp-service/src/test/resources/application.yml b/cps-ncmp-service/src/test/resources/application.yml
index d8fbb64c5f..c23926e4eb 100644
--- a/cps-ncmp-service/src/test/resources/application.yml
+++ b/cps-ncmp-service/src/test/resources/application.yml
@@ -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.
@@ -21,5 +21,5 @@ dmi:
username: some-user
password: some-password
api:
- base-path: /dmi
+ base-path: dmi