summaryrefslogtreecommitdiffstats
path: root/cps-ncmp-rest
diff options
context:
space:
mode:
Diffstat (limited to 'cps-ncmp-rest')
-rw-r--r--cps-ncmp-rest/docs/openapi/components.yaml108
-rwxr-xr-xcps-ncmp-rest/docs/openapi/ncmp.yml47
-rwxr-xr-xcps-ncmp-rest/docs/openapi/openapi.yml7
-rw-r--r--cps-ncmp-rest/pom.xml3
-rwxr-xr-xcps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java192
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/DatastoreType.java67
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreOperationalResourceRequestHandler.java55
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastorePassthroughOperationalResourceRequestHandler.java51
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastorePassthroughRunningResourceRequestHandler.java50
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandler.java92
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandlerFactory.java64
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/InvalidDatastoreException.java32
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/InvalidTopicException.java40
-rwxr-xr-xcps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandler.java17
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/util/TopicValidator.java44
-rw-r--r--cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy304
-rw-r--r--cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandlerFactorySpec.groovy20
-rw-r--r--cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy34
-rw-r--r--cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/util/TopicValidatorSpec.groovy47
19 files changed, 956 insertions, 318 deletions
diff --git a/cps-ncmp-rest/docs/openapi/components.yaml b/cps-ncmp-rest/docs/openapi/components.yaml
index 427f083698..7ca09ceedb 100644
--- a/cps-ncmp-rest/docs/openapi/components.yaml
+++ b/cps-ncmp-rest/docs/openapi/components.yaml
@@ -86,7 +86,7 @@ components:
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 ]
DmiPluginRegistrationErrorResponse:
type: object
properties:
@@ -124,14 +124,14 @@ components:
type: string
example: my-cm-handle
cmHandleProperties:
- $ref: '#/components/schemas/RestCmHandleProperties'
+ $ref: '#/components/schemas/RestCmHandleProperties'
publicCmHandleProperties:
- $ref: '#/components/schemas/RestCmHandleProperties'
+ $ref: '#/components/schemas/RestCmHandleProperties'
RestCmHandleProperties:
- type: object
- additionalProperties:
- type: string
- example: my-property
+ type: object
+ additionalProperties:
+ type: string
+ example: my-property
#Response Schemas
RestModuleReference:
@@ -288,21 +288,21 @@ components:
examples:
dataSampleRequest:
- summary: Sample request
- description: Sample request body
- value:
- test:bookstore:
- bookstore-name: Chapters
- categories:
- - code: '01'
- name: SciFi
- books:
+ 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:
+ - code: '02'
+ name: kids
+ books:
- authors:
- Philip Pullman
@@ -351,22 +351,22 @@ components:
- Philip Pullman
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
+ 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
allCmHandleQueryParameters:
value:
@@ -448,7 +448,7 @@ components:
includeDescendantsOptionInQuery:
name: include-descendants
in: query
- description: include-descendants
+ description: Determines if descendants are included in response
required: false
schema:
type: boolean
@@ -526,6 +526,14 @@ components:
type: string
default: application/json
example: application/yang-data+json
+ datastoreName:
+ name: ncmp-datastore-name
+ in: path
+ description: The type of the requested data
+ required: true
+ schema:
+ type: string
+ example: ncmp-datastore:operational
responses:
NotFound:
@@ -555,9 +563,9 @@ components:
schema:
$ref: '#/components/schemas/ErrorMessage'
example:
- status: 403
- message: Forbidden error message
- details: Forbidden error details
+ status: 403
+ message: Forbidden error message
+ details: Forbidden error details
BadRequest:
description: Bad Request
content:
@@ -565,9 +573,9 @@ components:
schema:
$ref: '#/components/schemas/ErrorMessage'
example:
- status: 400 BAD_REQUEST
- message: Bad request error message
- details: Bad request error details
+ status: 400 BAD_REQUEST
+ message: Bad request error message
+ details: Bad request error details
Conflict:
description: Conflict
content:
@@ -575,9 +583,9 @@ components:
schema:
$ref: '#/components/schemas/ErrorMessage'
example:
- status: 409 CONFLICT
- message: Conflict error message
- details: Conflict error details
+ status: 409 CONFLICT
+ message: Conflict error message
+ details: Conflict error details
NotImplemented:
description: The given path has not been implemented
content:
@@ -585,9 +593,9 @@ components:
schema:
$ref: '#/components/schemas/ErrorMessage'
example:
- status: 501
- message: Not implemented error message
- details: Not implemented error details
+ status: 501
+ message: Not implemented error message
+ details: Not implemented error details
Ok:
description: OK
content:
@@ -596,10 +604,10 @@ components:
type: object
Created:
description: Created
- content: {}
+ content: { }
NoContent:
description: No Content
- content: {}
+ content: { }
InternalServerError:
description: Internal Server Error
content:
diff --git a/cps-ncmp-rest/docs/openapi/ncmp.yml b/cps-ncmp-rest/docs/openapi/ncmp.yml
index 4266fc4152..38db26f470 100755
--- a/cps-ncmp-rest/docs/openapi/ncmp.yml
+++ b/cps-ncmp-rest/docs/openapi/ncmp.yml
@@ -17,51 +17,21 @@
#
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=========================================================
-getResourceDataForPassthroughOperational:
- get:
- tags:
- - 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:
- - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
- - $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
- - $ref: 'components.yaml#/components/parameters/optionsParamInQuery'
- - $ref: 'components.yaml#/components/parameters/topicParamInQuery'
- responses:
- 200:
- description: OK
- content:
- application/json:
- schema:
- type: object
- examples:
- dataSampleResponse:
- $ref: 'components.yaml#/components/examples/dataSampleResponse'
- 400:
- $ref: 'components.yaml#/components/responses/BadRequest'
- 401:
- $ref: 'components.yaml#/components/responses/Unauthorized'
- 403:
- $ref: 'components.yaml#/components/responses/Forbidden'
- 500:
- $ref: 'components.yaml#/components/responses/InternalServerError'
- 502:
- $ref: 'components.yaml#/components/responses/BadGateway'
-resourceDataForPassthroughRunning:
+resourceDataForCmHandle:
get:
tags:
- 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
+ summary: Get resource data for cm handle
+ description: Get resource data for given cm handle
+ operationId: getResourceDataForCmHandle
parameters:
+ - $ref: 'components.yaml#/components/parameters/datastoreName'
- $ref: 'components.yaml#/components/parameters/cmHandleInPath'
- $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
- $ref: 'components.yaml#/components/parameters/optionsParamInQuery'
- $ref: 'components.yaml#/components/parameters/topicParamInQuery'
+ - $ref: 'components.yaml#/components/parameters/includeDescendantsOptionInQuery'
responses:
200:
description: OK
@@ -82,6 +52,7 @@ resourceDataForPassthroughRunning:
$ref: 'components.yaml#/components/responses/InternalServerError'
502:
$ref: 'components.yaml#/components/responses/BadGateway'
+
post:
tags:
- network-cm-proxy
@@ -89,6 +60,7 @@ resourceDataForPassthroughRunning:
description: create resource data from pass-through running for given cm handle
operationId: createResourceDataRunningForCmHandle
parameters:
+ - $ref: 'components.yaml#/components/parameters/datastoreName'
- $ref: 'components.yaml#/components/parameters/cmHandleInPath'
- $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
- $ref: 'components.yaml#/components/parameters/contentParamInHeader'
@@ -128,6 +100,7 @@ resourceDataForPassthroughRunning:
description: Update resource data from pass-through running for the given cm handle
operationId: updateResourceDataRunningForCmHandle
parameters:
+ - $ref: 'components.yaml#/components/parameters/datastoreName'
- $ref: 'components.yaml#/components/parameters/cmHandleInPath'
- $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
- $ref: 'components.yaml#/components/parameters/contentParamInHeader'
@@ -167,6 +140,7 @@ resourceDataForPassthroughRunning:
description: Patch resource data from pass-through running for the given cm handle
operationId: patchResourceDataRunningForCmHandle
parameters:
+ - $ref: 'components.yaml#/components/parameters/datastoreName'
- $ref: 'components.yaml#/components/parameters/cmHandleInPath'
- $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
- $ref: 'components.yaml#/components/parameters/contentParamInHeader'
@@ -200,6 +174,7 @@ resourceDataForPassthroughRunning:
description: Delete resource data from pass-through running for a given cm handle
operationId: deleteResourceDataRunningForCmHandle
parameters:
+ - $ref: 'components.yaml#/components/parameters/datastoreName'
- $ref: 'components.yaml#/components/parameters/cmHandleInPath'
- $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
- $ref: 'components.yaml#/components/parameters/contentParamInHeader'
diff --git a/cps-ncmp-rest/docs/openapi/openapi.yml b/cps-ncmp-rest/docs/openapi/openapi.yml
index 8e020668a0..4c546beb26 100755
--- a/cps-ncmp-rest/docs/openapi/openapi.yml
+++ b/cps-ncmp-rest/docs/openapi/openapi.yml
@@ -26,11 +26,8 @@ info:
servers:
- url: /ncmp
paths:
- /v1/ch/{cm-handle}/data/ds/ncmp-datastore:passthrough-operational:
- $ref: 'ncmp.yml#/getResourceDataForPassthroughOperational'
-
- /v1/ch/{cm-handle}/data/ds/ncmp-datastore:passthrough-running:
- $ref: 'ncmp.yml#/resourceDataForPassthroughRunning'
+ /v1/ch/{cm-handle}/data/ds/{ncmp-datastore-name}:
+ $ref: 'ncmp.yml#/resourceDataForCmHandle'
/v1/ch/{cm-handle}/modules:
$ref: 'ncmp.yml#/fetchModuleReferencesByCmHandle'
diff --git a/cps-ncmp-rest/pom.xml b/cps-ncmp-rest/pom.xml
index 6a700c3e12..b3021d2410 100644
--- a/cps-ncmp-rest/pom.xml
+++ b/cps-ncmp-rest/pom.xml
@@ -185,7 +185,8 @@
<goal>copy-resources</goal>
</goals>
<configuration>
- <outputDirectory>${project.basedir}/target/classes/static/api-docs/cps-ncmp</outputDirectory>
+ <outputDirectory>${project.basedir}/target/classes/static/api-docs/cps-ncmp
+ </outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/target/generated-sources/swagger/</directory>
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 d2ed393794..2f6668a351 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
@@ -29,21 +29,19 @@ import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum
import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.UPDATE;
import java.util.List;
-import java.util.Map;
import java.util.Set;
-import java.util.UUID;
import java.util.stream.Collectors;
-import javax.validation.Valid;
-import javax.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
-import org.onap.cps.ncmp.api.impl.exception.InvalidTopicException;
import org.onap.cps.ncmp.api.inventory.CompositeState;
import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters;
import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
import org.onap.cps.ncmp.rest.api.NetworkCmProxyApi;
-import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor;
+import org.onap.cps.ncmp.rest.controller.handlers.DatastoreType;
+import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastoreResourceRequestHandler;
+import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastoreResourceRequestHandlerFactory;
+import org.onap.cps.ncmp.rest.exceptions.InvalidDatastoreException;
import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper;
import org.onap.cps.ncmp.rest.model.CmHandlePublicProperties;
import org.onap.cps.ncmp.rest.model.CmHandleQueryParameters;
@@ -53,9 +51,7 @@ import org.onap.cps.ncmp.rest.model.RestOutputCmHandle;
import org.onap.cps.ncmp.rest.model.RestOutputCmHandleCompositeState;
import org.onap.cps.ncmp.rest.model.RestOutputCmHandlePublicProperties;
import org.onap.cps.ncmp.rest.util.DeprecationHelper;
-import org.onap.cps.utils.CpsValidator;
import org.onap.cps.utils.JsonObjectMapper;
-import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -68,94 +64,65 @@ import org.springframework.web.bind.annotation.RestController;
public class NetworkCmProxyController implements NetworkCmProxyApi {
private static final String NO_BODY = null;
- private static final String NO_REQUEST_ID = null;
- private static final String NO_TOPIC = null;
private final NetworkCmProxyDataService networkCmProxyDataService;
private final JsonObjectMapper jsonObjectMapper;
-
private final DeprecationHelper deprecationHelper;
private final NcmpRestInputMapper ncmpRestInputMapper;
private final CmHandleStateMapper cmHandleStateMapper;
- private final CpsNcmpTaskExecutor cpsNcmpTaskExecutor;
- @Value("${notification.async.executor.time-out-value-in-ms:2000}")
- private int timeOutInMilliSeconds;
- @Value("${notification.enabled:true}")
- private boolean asyncEnabled;
+ private final NcmpDatastoreResourceRequestHandlerFactory ncmpDatastoreResourceRequestHandlerFactory;
/**
- * Get resource data from operational datastore.
+ * Get resource data from datastore.
*
- * @param cmHandle cm handle identifier
- * @param resourceIdentifier resource identifier
+ * @param datastoreName name of the datastore
+ * @param cmHandle cm handle identifier
+ * @param resourceIdentifier resource identifier
* @param optionsParamInQuery options query parameter
- * @param topicParamInQuery topic query parameter
+ * @param topicParamInQuery topic query parameter
+ * @param includeDescendants whether include descendants
* @return {@code ResponseEntity} response from dmi plugin
*/
+
@Override
- public ResponseEntity<Object> getResourceDataOperationalForCmHandle(final String cmHandle,
- final @NotNull @Valid String resourceIdentifier,
- final @Valid String optionsParamInQuery,
- final @Valid String topicParamInQuery) {
- if (asyncEnabled && isValidTopic(topicParamInQuery)) {
- final String requestId = UUID.randomUUID().toString();
- log.info("Received Async passthrough-operational request with id {}", requestId);
- cpsNcmpTaskExecutor.executeTask(() ->
- networkCmProxyDataService.getResourceDataOperationalForCmHandle(
- cmHandle, resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId
- ), timeOutInMilliSeconds
- );
- return ResponseEntity.ok(Map.of("requestId", requestId));
- } else {
- log.warn("Asynchronous messaging is currently disabled for passthrough-operational."
- + " Will use synchronous operation.");
- }
+ public ResponseEntity<Object> getResourceDataForCmHandle(final String datastoreName,
+ final String cmHandle,
+ final String resourceIdentifier,
+ final String optionsParamInQuery,
+ final String topicParamInQuery,
+ final Boolean includeDescendants) {
- final Object responseObject = networkCmProxyDataService.getResourceDataOperationalForCmHandle(
- cmHandle, resourceIdentifier, optionsParamInQuery, NO_TOPIC, NO_REQUEST_ID);
+ final NcmpDatastoreResourceRequestHandler ncmpDatastoreResourceRequestHandler =
+ ncmpDatastoreResourceRequestHandlerFactory.getNcmpDatastoreResourceRequestHandler(
+ DatastoreType.fromDatastoreName(datastoreName));
- return ResponseEntity.ok(responseObject);
+ return ncmpDatastoreResourceRequestHandler.getResourceData(cmHandle, resourceIdentifier,
+ optionsParamInQuery, topicParamInQuery, includeDescendants);
}
/**
- * Get resource data from pass-through running datastore.
+ * Patch resource data from passthrough-running.
*
- * @param cmHandle cm handle identifier
* @param resourceIdentifier resource identifier
- * @param optionsParamInQuery options query parameter
- * @param topicParamInQuery topic query parameter
+ * @param datastoreName name of the datastore
+ * @param cmHandle cm handle identifier
+ * @param requestBody the request body
+ * @param contentType content type of body
* @return {@code ResponseEntity} response from dmi plugin
*/
- @Override
- public ResponseEntity<Object> getResourceDataRunningForCmHandle(final String cmHandle,
- final @NotNull @Valid String resourceIdentifier,
- final @Valid String optionsParamInQuery,
- final @Valid String topicParamInQuery) {
- if (asyncEnabled && isValidTopic(topicParamInQuery)) {
- final String requestId = UUID.randomUUID().toString();
- log.info("Received Async passthrough-running request with id {}", requestId);
- cpsNcmpTaskExecutor.executeTask(() ->
- networkCmProxyDataService.getResourceDataPassThroughRunningForCmHandle(
- cmHandle, resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId
- ), timeOutInMilliSeconds
- );
- return ResponseEntity.ok(Map.of("requestId", requestId));
- } else {
- log.warn("Asynchronous messaging is currently disabled for passthrough-running."
- + " Will use synchronous operation.");
- }
-
- final Object responseObject = networkCmProxyDataService.getResourceDataPassThroughRunningForCmHandle(
- cmHandle, resourceIdentifier, optionsParamInQuery, NO_TOPIC, NO_REQUEST_ID);
-
- return ResponseEntity.ok(responseObject);
- }
@Override
public ResponseEntity<Object> patchResourceDataRunningForCmHandle(final String resourceIdentifier,
- final String cmHandle,
- final Object requestBody, final String contentType) {
- final Object responseObject = networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
- resourceIdentifier, PATCH, jsonObjectMapper.asJsonString(requestBody), contentType);
+ final String datastoreName,
+ final String cmHandle,
+ final Object requestBody,
+ final String contentType) {
+
+ acceptPassthroughRunningOnly(datastoreName);
+
+ final Object responseObject = networkCmProxyDataService
+ .writeResourceDataPassThroughRunningForCmHandle(
+ cmHandle, resourceIdentifier, PATCH,
+ jsonObjectMapper.asJsonString(requestBody), contentType);
return ResponseEntity.ok(responseObject);
}
@@ -163,14 +130,21 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
* Create resource data in datastore pass-through running for given cm-handle.
*
* @param resourceIdentifier resource identifier
- * @param cmHandle cm handle identifier
- * @param requestBody the request body
- * @param contentType content type of body
+ * @param datastoreName name of the datastore
+ * @param cmHandle cm handle identifier
+ * @param requestBody the request body
+ * @param contentType content type of body
* @return {@code ResponseEntity} response from dmi plugin
*/
@Override
public ResponseEntity<Void> createResourceDataRunningForCmHandle(final String resourceIdentifier,
- final String cmHandle, final Object requestBody, final String contentType) {
+ final String datastoreName,
+ final String cmHandle,
+ final Object requestBody,
+ final String contentType) {
+
+ acceptPassthroughRunningOnly(datastoreName);
+
networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
resourceIdentifier, CREATE, jsonObjectMapper.asJsonString(requestBody), contentType);
return new ResponseEntity<>(HttpStatus.CREATED);
@@ -180,36 +154,45 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
* Update resource data in datastore pass-through running for given cm-handle.
*
* @param resourceIdentifier resource identifier
- * @param cmHandle cm handle identifier
- * @param requestBody the request body
- * @param contentType content type of the body
+ * @param datastoreName name of the datastore
+ * @param cmHandle cm handle identifier
+ * @param requestBody the request body
+ * @param contentType content type of the body
* @return response entity
*/
+
@Override
public ResponseEntity<Object> updateResourceDataRunningForCmHandle(final String resourceIdentifier,
+ final String datastoreName,
final String cmHandle,
final Object requestBody,
final String contentType) {
+ acceptPassthroughRunningOnly(datastoreName);
+
networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
resourceIdentifier, UPDATE, jsonObjectMapper.asJsonString(requestBody), contentType);
return new ResponseEntity<>(HttpStatus.OK);
}
-
/**
- * Delete resource data in datastore pass-through running for a given cm-handle.
+ * Delete resource data in datastore pass-through running for a given cm-handle.
*
+ * @param datastoreName name of the datastore
+ * @param cmHandle cm handle identifier
* @param resourceIdentifier resource identifier
- * @param cmHandle cm handle identifier
- * @param contentType content type of the body
+ * @param contentType content type of the body
* @return response entity no content if request is successful
*/
@Override
- public ResponseEntity<Void> deleteResourceDataRunningForCmHandle(final String cmHandle,
+ public ResponseEntity<Void> deleteResourceDataRunningForCmHandle(final String datastoreName,
+ final String cmHandle,
final String resourceIdentifier,
final String contentType) {
+
+ acceptPassthroughRunningOnly(datastoreName);
+
networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
- resourceIdentifier, DELETE, NO_BODY, contentType);
+ resourceIdentifier, DELETE, NO_BODY, contentType);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@@ -240,7 +223,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
*/
@Override
public ResponseEntity<List<String>> searchCmHandleIds(
- final CmHandleQueryParameters cmHandleQueryParameters) {
+ final CmHandleQueryParameters cmHandleQueryParameters) {
final CmHandleQueryApiParameters cmHandleQueryApiParameters =
jsonObjectMapper.convertToValueType(cmHandleQueryParameters, CmHandleQueryApiParameters.class);
final Set<String> cmHandleIds = networkCmProxyDataService.executeCmHandleIdSearch(cmHandleQueryApiParameters);
@@ -249,6 +232,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
/**
* Search for Cm Handle and Properties by Name.
+ *
* @param cmHandleId cm-handle identifier
* @return cm handle and its properties
*/
@@ -261,33 +245,35 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
/**
* Get Cm Handle Properties by Cm Handle Id.
+ *
* @param cmHandleId cm-handle identifier
* @return cm handle properties
*/
@Override
public ResponseEntity<RestOutputCmHandlePublicProperties> getCmHandlePublicPropertiesByCmHandleId(
- final String cmHandleId) {
+ final String cmHandleId) {
final CmHandlePublicProperties cmHandlePublicProperties = new CmHandlePublicProperties();
cmHandlePublicProperties.add(networkCmProxyDataService.getCmHandlePublicProperties(cmHandleId));
final RestOutputCmHandlePublicProperties restOutputCmHandlePublicProperties =
- new RestOutputCmHandlePublicProperties();
+ new RestOutputCmHandlePublicProperties();
restOutputCmHandlePublicProperties.setPublicCmHandleProperties(cmHandlePublicProperties);
return ResponseEntity.ok(restOutputCmHandlePublicProperties);
}
/**
* Get Cm Handle State by Cm Handle Id.
+ *
* @param cmHandleId cm-handle identifier
* @return cm handle state
*/
@Override
public ResponseEntity<RestOutputCmHandleCompositeState> getCmHandleStateByCmHandleId(
- final String cmHandleId) {
+ final String cmHandleId) {
final CompositeState cmHandleState = networkCmProxyDataService.getCmHandleCompositeState(cmHandleId);
final RestOutputCmHandleCompositeState restOutputCmHandleCompositeState =
- new RestOutputCmHandleCompositeState();
+ new RestOutputCmHandleCompositeState();
restOutputCmHandleCompositeState.setState(
- cmHandleStateMapper.toCmHandleCompositeStateExternalLockReason(cmHandleState));
+ cmHandleStateMapper.toCmHandleCompositeStateExternalLockReason(cmHandleState));
return ResponseEntity.ok(restOutputCmHandleCompositeState);
}
@@ -314,26 +300,27 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
*/
public ResponseEntity<List<RestModuleReference>> getModuleReferencesByCmHandle(final String cmHandle) {
final List<RestModuleReference> restModuleReferences =
- networkCmProxyDataService.getYangResourcesModuleReferences(cmHandle).stream()
- .map(ncmpRestInputMapper::toRestModuleReference)
- .collect(Collectors.toList());
+ networkCmProxyDataService.getYangResourcesModuleReferences(cmHandle).stream()
+ .map(ncmpRestInputMapper::toRestModuleReference)
+ .collect(Collectors.toList());
return new ResponseEntity<>(restModuleReferences, HttpStatus.OK);
}
/**
* Set the data sync enabled flag, along with the data sync state for the specified cm handle.
*
- * @param cmHandleId cm handle id
+ * @param cmHandleId cm handle id
* @param dataSyncEnabledFlag data sync enabled flag
* @return response entity ok if request is successful
*/
@Override
public ResponseEntity<Object> setDataSyncEnabledFlagForCmHandle(final String cmHandleId,
- final Boolean dataSyncEnabledFlag) {
+ final Boolean dataSyncEnabledFlag) {
networkCmProxyDataService.setDataSyncEnabled(cmHandleId, dataSyncEnabledFlag);
return new ResponseEntity<>(HttpStatus.OK);
}
+
private RestOutputCmHandle toRestOutputCmHandle(final NcmpServiceCmHandle ncmpServiceCmHandle) {
final RestOutputCmHandle restOutputCmHandle = new RestOutputCmHandle();
final CmHandlePublicProperties cmHandlePublicProperties = new CmHandlePublicProperties();
@@ -345,15 +332,12 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
return restOutputCmHandle;
}
- private static boolean isValidTopic(final String topicName) {
- if (topicName == null) {
- return false;
- }
- if (CpsValidator.validateTopicName(topicName)) {
- return true;
+ private void acceptPassthroughRunningOnly(final String datastoreName) {
+ final DatastoreType datastoreType = DatastoreType.fromDatastoreName(datastoreName);
+
+ if (DatastoreType.PASSTHROUGH_RUNNING != datastoreType) {
+ throw new InvalidDatastoreException(datastoreName + " is not supported");
}
- throw new InvalidTopicException("Topic name " + topicName + " is invalid", "invalid topic");
}
-
}
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/DatastoreType.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/DatastoreType.java
new file mode 100644
index 0000000000..e8ab997d6f
--- /dev/null
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/DatastoreType.java
@@ -0,0 +1,67 @@
+/*
+ * ============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.rest.controller.handlers;
+
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import lombok.Getter;
+import org.onap.cps.ncmp.rest.exceptions.InvalidDatastoreException;
+
+@Getter
+public enum DatastoreType {
+
+ OPERATIONAL("ncmp-datastore:operational"),
+ PASSTHROUGH_RUNNING("ncmp-datastore:passthrough-running"),
+ PASSTHROUGH_OPERATIONAL("ncmp-datastore:passthrough-operational");
+
+ DatastoreType(final String datastoreName) {
+ this.datastoreName = datastoreName;
+ }
+
+ private final String datastoreName;
+ private static final Map<String, DatastoreType> datastoreNameToDatastoreType = new HashMap<>();
+
+ static {
+ Arrays.stream(DatastoreType.values()).forEach(
+ type -> datastoreNameToDatastoreType.put(type.getDatastoreName(), type));
+ }
+
+ /**
+ * From datastore name get datastore type.
+ *
+ * @param datastoreName the datastore name
+ * @return the datastore type
+ */
+ public static DatastoreType fromDatastoreName(final String datastoreName) {
+
+ final DatastoreType datastoreType = datastoreNameToDatastoreType.get(datastoreName);
+
+ if (null == datastoreType) {
+ throw new InvalidDatastoreException(datastoreName + " is an invalid datastore name");
+ }
+
+ return datastoreType;
+ }
+
+}
+
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreOperationalResourceRequestHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreOperationalResourceRequestHandler.java
new file mode 100644
index 0000000000..6ed9b8c4d1
--- /dev/null
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreOperationalResourceRequestHandler.java
@@ -0,0 +1,55 @@
+/*
+ * ============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.rest.controller.handlers;
+
+import java.util.function.Supplier;
+import lombok.extern.slf4j.Slf4j;
+import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
+import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor;
+import org.onap.cps.spi.FetchDescendantsOption;
+
+@Slf4j
+public class NcmpDatastoreOperationalResourceRequestHandler extends NcmpDatastoreResourceRequestHandler {
+
+ public NcmpDatastoreOperationalResourceRequestHandler(final NetworkCmProxyDataService networkCmProxyDataService,
+ final CpsNcmpTaskExecutor cpsNcmpTaskExecutor,
+ final int timeOutInMilliSeconds,
+ final boolean notificationFeatureEnabled) {
+ super(networkCmProxyDataService, cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled);
+ }
+
+ @Override
+ public Supplier<Object> getTask(final String cmHandle,
+ final String resourceIdentifier,
+ final String optionsParamInQuery,
+ final String topicParamInQuery,
+ final String requestId,
+ final Boolean includeDescendant) {
+
+ final FetchDescendantsOption fetchDescendantsOption =
+ Boolean.TRUE.equals(includeDescendant) ? FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
+ : FetchDescendantsOption.OMIT_DESCENDANTS;
+
+ return () -> networkCmProxyDataService.getResourceDataOperational(cmHandle, resourceIdentifier,
+ fetchDescendantsOption);
+ }
+
+}
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastorePassthroughOperationalResourceRequestHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastorePassthroughOperationalResourceRequestHandler.java
new file mode 100644
index 0000000000..196e5bd33d
--- /dev/null
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastorePassthroughOperationalResourceRequestHandler.java
@@ -0,0 +1,51 @@
+/*
+ * ============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.rest.controller.handlers;
+
+import java.util.function.Supplier;
+import lombok.extern.slf4j.Slf4j;
+import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
+import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor;
+
+@Slf4j
+public class NcmpDatastorePassthroughOperationalResourceRequestHandler extends NcmpDatastoreResourceRequestHandler {
+
+ public NcmpDatastorePassthroughOperationalResourceRequestHandler(
+ final NetworkCmProxyDataService networkCmProxyDataService,
+ final CpsNcmpTaskExecutor cpsNcmpTaskExecutor,
+ final int timeOutInMilliSeconds,
+ final boolean notificationFeatureEnabled) {
+ super(networkCmProxyDataService, cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled);
+ }
+
+ @Override
+ public Supplier<Object> getTask(final String cmHandle,
+ final String resourceIdentifier,
+ final String optionsParamInQuery,
+ final String topicParamInQuery,
+ final String requestId,
+ final Boolean includeDescendant) {
+
+ return () -> networkCmProxyDataService.getResourceDataOperationalForCmHandle(
+ cmHandle, resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId);
+ }
+
+}
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastorePassthroughRunningResourceRequestHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastorePassthroughRunningResourceRequestHandler.java
new file mode 100644
index 0000000000..5bf16b7499
--- /dev/null
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastorePassthroughRunningResourceRequestHandler.java
@@ -0,0 +1,50 @@
+/*
+ * ============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.rest.controller.handlers;
+
+import java.util.function.Supplier;
+import lombok.extern.slf4j.Slf4j;
+import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
+import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor;
+
+@Slf4j
+public class NcmpDatastorePassthroughRunningResourceRequestHandler extends NcmpDatastoreResourceRequestHandler {
+
+ public NcmpDatastorePassthroughRunningResourceRequestHandler(
+ final NetworkCmProxyDataService networkCmProxyDataService,
+ final CpsNcmpTaskExecutor cpsNcmpTaskExecutor,
+ final int timeOutInMilliSeconds,
+ final boolean notificationFeatureEnabled) {
+ super(networkCmProxyDataService, cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled);
+ }
+
+ @Override
+ public Supplier<Object> getTask(final String cmHandle,
+ final String resourceIdentifier,
+ final String optionsParamInQuery,
+ final String topicParamInQuery,
+ final String requestId,
+ final Boolean includeDescendant) {
+
+ return () -> networkCmProxyDataService.getResourceDataPassThroughRunningForCmHandle(
+ cmHandle, resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId);
+ }
+}
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandler.java
new file mode 100644
index 0000000000..a6d313b05f
--- /dev/null
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandler.java
@@ -0,0 +1,92 @@
+/*
+ * ============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.rest.controller.handlers;
+
+import java.util.Map;
+import java.util.UUID;
+import java.util.function.Supplier;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
+import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor;
+import org.onap.cps.ncmp.rest.util.TopicValidator;
+import org.springframework.http.ResponseEntity;
+
+@RequiredArgsConstructor
+@Slf4j
+public abstract class NcmpDatastoreResourceRequestHandler {
+
+ private static final String NO_REQUEST_ID = null;
+ private static final String NO_TOPIC = null;
+
+ protected final NetworkCmProxyDataService networkCmProxyDataService;
+ protected final CpsNcmpTaskExecutor cpsNcmpTaskExecutor;
+ protected final int timeOutInMilliSeconds;
+ protected final boolean notificationFeatureEnabled;
+
+ protected abstract Supplier<Object> getTask(final String cmHandle,
+ final String resourceIdentifier,
+ final String optionsParamInQuery,
+ final String topicParamInQuery,
+ final String requestId,
+ final Boolean includeDescendant);
+
+
+ /**
+ * Get resource data from datastore.
+ *
+ * @param cmHandleId the cm handle
+ * @param resourceIdentifier the resource identifier
+ * @param optionsParamInQuery the options param in query
+ * @param topicParamInQuery the topic param in query
+ * @param includeDescendants whether include descendants
+ * @return the response entity
+ */
+ public ResponseEntity<Object> getResourceData(final String cmHandleId,
+ final String resourceIdentifier,
+ final String optionsParamInQuery,
+ final String topicParamInQuery,
+ final Boolean includeDescendants) {
+
+ final String requestId = UUID.randomUUID().toString();
+ final boolean asyncResponseRequested = topicParamInQuery != null;
+
+ if (asyncResponseRequested && notificationFeatureEnabled) {
+ TopicValidator.validateTopicName(topicParamInQuery);
+ log.debug("Received Async request with id {}", requestId);
+ cpsNcmpTaskExecutor.executeTask(
+ getTask(cmHandleId, resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId,
+ includeDescendants), timeOutInMilliSeconds);
+
+ return ResponseEntity.ok(Map.of("requestId", requestId));
+ }
+
+ if (asyncResponseRequested) {
+ log.warn("Asynchronous messaging is currently disabled, will use synchronous operation.");
+ }
+
+ final Object responseObject =
+ getTask(cmHandleId, resourceIdentifier, optionsParamInQuery, NO_TOPIC, NO_REQUEST_ID,
+ includeDescendants).get();
+
+ return ResponseEntity.ok(responseObject);
+ }
+}
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandlerFactory.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandlerFactory.java
new file mode 100644
index 0000000000..35bd578ce2
--- /dev/null
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandlerFactory.java
@@ -0,0 +1,64 @@
+/*
+ * ============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.rest.controller.handlers;
+
+import lombok.RequiredArgsConstructor;
+import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
+import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class NcmpDatastoreResourceRequestHandlerFactory {
+
+ private final NetworkCmProxyDataService networkCmProxyDataService;
+ private final CpsNcmpTaskExecutor cpsNcmpTaskExecutor;
+
+ @Value("${notification.async.executor.time-out-value-in-ms:2000}")
+ private int timeOutInMilliSeconds;
+ @Value("${notification.enabled:true}")
+ private boolean notificationFeatureEnabled;
+
+ /**
+ * Gets ncmp datastore handler.
+ *
+ * @param datastoreType the datastore type
+ * @return the ncmp datastore handler
+ */
+ public NcmpDatastoreResourceRequestHandler getNcmpDatastoreResourceRequestHandler(
+ final DatastoreType datastoreType) {
+
+ switch (datastoreType) {
+ case OPERATIONAL:
+ return new NcmpDatastoreOperationalResourceRequestHandler(networkCmProxyDataService,
+ cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled);
+ case PASSTHROUGH_RUNNING:
+ return new NcmpDatastorePassthroughRunningResourceRequestHandler(networkCmProxyDataService,
+ cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled);
+ case PASSTHROUGH_OPERATIONAL:
+ return new NcmpDatastorePassthroughOperationalResourceRequestHandler(networkCmProxyDataService,
+ cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled);
+ default:
+ return null;
+ }
+ }
+}
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/InvalidDatastoreException.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/InvalidDatastoreException.java
new file mode 100644
index 0000000000..ff13a93e58
--- /dev/null
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/InvalidDatastoreException.java
@@ -0,0 +1,32 @@
+/*
+ * ============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.rest.exceptions;
+
+public class InvalidDatastoreException extends RuntimeException {
+ /**
+ * Instantiates a new Invalid datastore exception.
+ *
+ * @param message the message
+ */
+ public InvalidDatastoreException(final String message) {
+ super(message);
+ }
+}
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/InvalidTopicException.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/InvalidTopicException.java
new file mode 100644
index 0000000000..6a52d5861e
--- /dev/null
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/InvalidTopicException.java
@@ -0,0 +1,40 @@
+/*
+ * ============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.rest.exceptions;
+
+import lombok.Getter;
+
+public class InvalidTopicException extends RuntimeException {
+
+ @Getter
+ final String details;
+
+ /**
+ * Constructor.
+ *
+ * @param message the error message
+ * @param details the error details
+ */
+ public InvalidTopicException(final String message, final String details) {
+ super(message);
+ this.details = details;
+ }
+}
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 c72373344d..58a60d2e1c 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
@@ -25,7 +25,6 @@ import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.impl.exception.DmiRequestException;
import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException;
-import org.onap.cps.ncmp.api.impl.exception.InvalidTopicException;
import org.onap.cps.ncmp.api.impl.exception.NcmpException;
import org.onap.cps.ncmp.api.impl.exception.ServerNcmpException;
import org.onap.cps.ncmp.rest.controller.NetworkCmProxyController;
@@ -33,6 +32,8 @@ import org.onap.cps.ncmp.rest.controller.NetworkCmProxyInventoryController;
import org.onap.cps.ncmp.rest.model.DmiErrorMessage;
import org.onap.cps.ncmp.rest.model.DmiErrorMessageDmiresponse;
import org.onap.cps.ncmp.rest.model.ErrorMessage;
+import org.onap.cps.spi.exceptions.AlreadyDefinedException;
+import org.onap.cps.spi.exceptions.AlreadyDefinedExceptionBatch;
import org.onap.cps.spi.exceptions.CpsException;
import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
import org.onap.cps.spi.exceptions.DataValidationException;
@@ -60,7 +61,7 @@ public class NetworkCmProxyRestExceptionHandler {
*/
@ExceptionHandler
public static ResponseEntity<Object> handleInternalServerErrorExceptions(
- final Exception exception) {
+ final Exception exception) {
return buildErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, exception);
}
@@ -75,12 +76,17 @@ public class NetworkCmProxyRestExceptionHandler {
return wrapDmiErrorResponse(HttpStatus.BAD_GATEWAY, httpClientRequestException);
}
- @ExceptionHandler({DmiRequestException.class, DataValidationException.class, HttpMessageNotReadableException.class,
- InvalidTopicException.class})
+ @ExceptionHandler({DmiRequestException.class, DataValidationException.class,
+ HttpMessageNotReadableException.class, InvalidTopicException.class, InvalidDatastoreException.class})
public static ResponseEntity<Object> handleDmiRequestExceptions(final Exception exception) {
return buildErrorResponse(HttpStatus.BAD_REQUEST, exception);
}
+ @ExceptionHandler({AlreadyDefinedException.class, AlreadyDefinedExceptionBatch.class })
+ public static ResponseEntity<Object> handleAlreadyDefinedExceptions(final Exception exception) {
+ return buildErrorResponse(HttpStatus.CONFLICT, exception);
+ }
+
@ExceptionHandler({DataNodeNotFoundException.class})
public static ResponseEntity<Object> handleNotFoundExceptions(final CpsException exception) {
return buildErrorResponse(HttpStatus.NOT_FOUND, exception);
@@ -105,7 +111,8 @@ public class NetworkCmProxyRestExceptionHandler {
return new ResponseEntity<>(errorMessage, status);
}
- private static ResponseEntity<Object> wrapDmiErrorResponse(final HttpStatus httpStatus,
+ private static ResponseEntity<Object> wrapDmiErrorResponse(
+ final HttpStatus httpStatus,
final HttpClientRequestException httpClientRequestException) {
final var dmiErrorMessage = new DmiErrorMessage();
final var dmiErrorResponse = new DmiErrorMessageDmiresponse();
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/util/TopicValidator.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/util/TopicValidator.java
new file mode 100644
index 0000000000..313e7bc012
--- /dev/null
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/util/TopicValidator.java
@@ -0,0 +1,44 @@
+/*
+ * ============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.rest.util;
+
+import java.util.regex.Pattern;
+import org.onap.cps.ncmp.rest.exceptions.InvalidTopicException;
+
+public class TopicValidator {
+
+ private static final Pattern TOPIC_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9]([._-](?![._-])|"
+ + "[a-zA-Z0-9]){0,120}[a-zA-Z0-9]$");
+
+ /**
+ * Validate kafka topic name pattern.
+ *
+ * @param topicName name of the topic to be validated
+ *
+ * @throws InvalidTopicException if the topic is not valid
+ */
+ public static void validateTopicName(final String topicName) {
+ if (!TOPIC_NAME_PATTERN.matcher(topicName).matches()) {
+ throw new InvalidTopicException("Topic name " + topicName + " is invalid", "invalid topic");
+ }
+ }
+
+}
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 d568a5a925..b6194bc796 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
@@ -23,51 +23,60 @@
package org.onap.cps.ncmp.rest.controller
+import com.fasterxml.jackson.databind.ObjectMapper
import org.mapstruct.factory.Mappers
+import org.onap.cps.TestUtils
+import org.onap.cps.ncmp.api.NetworkCmProxyDataService
import org.onap.cps.ncmp.api.inventory.CmHandleState
import org.onap.cps.ncmp.api.inventory.CompositeState
-import org.onap.cps.ncmp.api.inventory.LockReasonCategory
import org.onap.cps.ncmp.api.inventory.DataStoreSyncState
+import org.onap.cps.ncmp.api.inventory.LockReasonCategory
import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
-import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper
+import org.onap.cps.ncmp.rest.controller.handlers.DatastoreType
+import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastoreOperationalResourceRequestHandler
+import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastorePassthroughOperationalResourceRequestHandler
+import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastorePassthroughRunningResourceRequestHandler
+import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastoreResourceRequestHandlerFactory
import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor
+import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper
import org.onap.cps.ncmp.rest.util.DeprecationHelper
+import org.onap.cps.spi.FetchDescendantsOption
import org.onap.cps.spi.model.ModuleDefinition
+import org.onap.cps.spi.model.ModuleReference
+import org.onap.cps.utils.JsonObjectMapper
+import org.spockframework.spring.SpringBean
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.beans.factory.annotation.Value
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
+import org.springframework.http.HttpStatus
+import org.springframework.http.MediaType
+import org.springframework.test.web.servlet.MockMvc
+import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder
import spock.lang.Shared
+import spock.lang.Specification
import java.time.OffsetDateTime
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.PATCH
import static org.onap.cps.ncmp.api.inventory.CompositeState.DataStores
import static org.onap.cps.ncmp.api.inventory.CompositeState.Operational
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put
import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.CREATE
import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.UPDATE
+import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.PATCH
import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.DELETE
-
-import com.fasterxml.jackson.databind.ObjectMapper
-import org.onap.cps.TestUtils
-import org.onap.cps.spi.model.ModuleReference
-import org.onap.cps.utils.JsonObjectMapper
-import org.onap.cps.ncmp.api.NetworkCmProxyDataService
-import org.spockframework.spring.SpringBean
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.beans.factory.annotation.Value
-import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
-import org.springframework.http.HttpStatus
-import org.springframework.http.MediaType
-import org.springframework.test.web.servlet.MockMvc
-import spock.lang.Specification
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete
@WebMvcTest(NetworkCmProxyController)
class NetworkCmProxyControllerSpec extends Specification {
+ public static final int TIMEOUT_IN_MS = 2000
+ public static final boolean NOTIFICATION_ENABLED = true
+
@Autowired
MockMvc mvc
@@ -92,6 +101,9 @@ class NetworkCmProxyControllerSpec extends Specification {
@SpringBean
DeprecationHelper stubbedDeprecationHelper = Stub()
+ @SpringBean
+ NcmpDatastoreResourceRequestHandlerFactory stubbedNcmpDatastoreResourceRequestHandlerFactory = Stub()
+
@Value('${rest.api.ncmp-base-path}/v1')
def ncmpBasePathV1
@@ -104,21 +116,38 @@ class NetworkCmProxyControllerSpec extends Specification {
def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
.format(OffsetDateTime.of(2022, 12, 31, 20, 30, 40, 1, ZoneOffset.UTC))
+ void setup() {
+ stubbedNcmpDatastoreResourceRequestHandlerFactory.getNcmpDatastoreResourceRequestHandler(
+ DatastoreType.OPERATIONAL) >>
+ new NcmpDatastoreOperationalResourceRequestHandler(
+ mockNetworkCmProxyDataService, spiedCpsTaskExecutor, TIMEOUT_IN_MS, NOTIFICATION_ENABLED)
+
+ stubbedNcmpDatastoreResourceRequestHandlerFactory.getNcmpDatastoreResourceRequestHandler(
+ DatastoreType.PASSTHROUGH_OPERATIONAL) >>
+ new NcmpDatastorePassthroughOperationalResourceRequestHandler(
+ mockNetworkCmProxyDataService, spiedCpsTaskExecutor, TIMEOUT_IN_MS, NOTIFICATION_ENABLED)
+
+ stubbedNcmpDatastoreResourceRequestHandlerFactory.getNcmpDatastoreResourceRequestHandler(
+ DatastoreType.PASSTHROUGH_RUNNING) >>
+ new NcmpDatastorePassthroughRunningResourceRequestHandler(
+ mockNetworkCmProxyDataService, spiedCpsTaskExecutor, TIMEOUT_IN_MS, NOTIFICATION_ENABLED)
+ }
+
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)"
+ "?resourceIdentifier=parent/child&options=(a=1,b=2)"
when: 'get data resource request is performed'
def response = mvc.perform(
- get(getUrl)
- .contentType(MediaType.APPLICATION_JSON)
+ get(getUrl)
+ .contentType(MediaType.APPLICATION_JSON)
).andReturn().response
then: 'the NCMP data service is called with getResourceDataOperationalForCmHandle'
1 * mockNetworkCmProxyDataService.getResourceDataOperationalForCmHandle('testCmHandle',
- 'parent/child',
- '(a=1,b=2)',
- NO_TOPIC,
- NO_REQUEST_ID)
+ 'parent/child',
+ '(a=1,b=2)',
+ NO_TOPIC,
+ NO_REQUEST_ID)
and: 'response status is Ok'
response.status == HttpStatus.OK.value()
}
@@ -126,22 +155,22 @@ class NetworkCmProxyControllerSpec extends Specification {
def 'Get Resource Data from #datastoreInUrl with #scenario.'() {
given: 'resource data url'
def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:${datastoreInUrl}" +
- "?resourceIdentifier=parent/child&options=(a=1,b=2)${topicQueryParam}"
+ "?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)).andReturn().response
+ get(getUrl).contentType(MediaType.APPLICATION_JSON)).andReturn().response
then: 'task executor is called appropriate number of times'
- expectedNumberOfExecutorExecutions * spiedCpsTaskExecutor.executeTask(_, 2000)
+ expectedNumberOfExecutorExecutions * spiedCpsTaskExecutor.executeTask(_, TIMEOUT_IN_MS)
and: 'response status is expected'
response.status == HttpStatus.OK.value()
where: 'the following parameters are used'
- scenario | datastoreInUrl | topicQueryParam || expectedTopicName | expectedNumberOfExecutorExecutions
- 'url with valid topic' | 'passthrough-operational' | '&topic=my-topic-name' || 'my-topic-name' | 1
- 'no topic in url' | 'passthrough-operational' | '' || NO_TOPIC | 0
- 'null topic in url' | 'passthrough-operational' | '&topic=null' || 'null' | 1
- 'url with valid topic' | 'passthrough-running' | '&topic=my-topic-name' || 'my-topic-name' | 1
- 'no topic in url' | 'passthrough-running' | '' || NO_TOPIC | 0
- 'null topic in url' | 'passthrough-running' | '&topic=null' || 'null' | 1
+ scenario | datastoreInUrl | topicQueryParam || expectedTopicName | expectedNumberOfExecutorExecutions
+ 'url with valid topic' | 'passthrough-operational' | '&topic=my-topic-name' || 'my-topic-name' | 1
+ 'no topic in url' | 'passthrough-operational' | '' || NO_TOPIC | 0
+ 'null topic in url' | 'passthrough-operational' | '&topic=null' || 'null' | 1
+ 'url with valid topic' | 'passthrough-running' | '&topic=my-topic-name' || 'my-topic-name' | 1
+ 'no topic in url' | 'passthrough-running' | '' || NO_TOPIC | 0
+ 'null topic in url' | 'passthrough-running' | '&topic=null' || 'null' | 1
}
def 'Fail to get Resource Data from #datastoreInUrl when #scenario.'() {
@@ -168,17 +197,17 @@ class NetworkCmProxyControllerSpec extends Specification {
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)"
+ "?resourceIdentifier=" + resourceIdentifier + "&options=(a=1,b=2)"
and: 'ncmp service returns json object'
mockNetworkCmProxyDataService.getResourceDataPassThroughRunningForCmHandle('testCmHandle',
- resourceIdentifier,
- '(a=1,b=2)',
- NO_TOPIC,
- NO_REQUEST_ID) >> '{valid-json}'
+ resourceIdentifier,
+ '(a=1,b=2)',
+ NO_TOPIC,
+ NO_REQUEST_ID) >> '{valid-json}'
when: 'get data resource request is performed'
def response = mvc.perform(
- get(getUrl)
- .contentType(MediaType.APPLICATION_JSON)
+ get(getUrl)
+ .contentType(MediaType.APPLICATION_JSON)
).andReturn().response
then: 'response status is Ok'
response.status == HttpStatus.OK.value()
@@ -194,7 +223,7 @@ class NetworkCmProxyControllerSpec extends Specification {
'? needs to be encoded as %3F' | 'idWith%3F'
}
- def 'Update resource data from pass-through running.' () {
+ def 'Update resource data from pass-through running.'() {
given: 'update resource data url'
def updateUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
"?resourceIdentifier=parent/child"
@@ -210,15 +239,14 @@ class NetworkCmProxyControllerSpec extends Specification {
response.status == HttpStatus.OK.value()
}
- def 'Create Resource Data from pass-through running with #scenario.' () {
+ def 'Create Resource Data from pass-through running with #scenario.'() {
given: 'resource data url'
def url = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
- "?resourceIdentifier=parent/child"
- def requestBody = '{"some-key":"some-value"}'
+ "?resourceIdentifier=parent/child"
when: 'create resource request is performed'
def response = mvc.perform(
- post(url)
- .contentType(MediaType.APPLICATION_JSON_VALUE).content(requestBody)
+ post(url)
+ .contentType(MediaType.APPLICATION_JSON_VALUE).content(requestBody)
).andReturn().response
then: 'ncmp service method to create resource called'
1 * mockNetworkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
@@ -227,14 +255,14 @@ class NetworkCmProxyControllerSpec extends Specification {
response.status == HttpStatus.CREATED.value()
}
- def 'Get module references for the given dataspace and cm handle.' () {
+ def 'Get module references for the given dataspace and cm handle.'() {
given: 'get module references url'
def getUrl = "$ncmpBasePathV1/ch/some-cmhandle/modules"
when: 'get module resource request is performed'
- def response =mvc.perform(get(getUrl)).andReturn().response
+ def response = mvc.perform(get(getUrl)).andReturn().response
then: 'ncmp service method to get yang resource module references is called'
mockNetworkCmProxyDataService.getYangResourcesModuleReferences('some-cmhandle')
- >> [new ModuleReference(moduleName: 'some-name1',revision: '2021-10-03')]
+ >> [new ModuleReference(moduleName: 'some-name1', revision: '2021-10-03')]
and: 'response contains an array with the module name and revision'
response.getContentAsString() == '[{"moduleName":"some-name1","revision":"2021-10-03"}]'
and: 'response returns an OK http code'
@@ -248,15 +276,15 @@ class NetworkCmProxyControllerSpec extends Specification {
and: 'the service method is invoked with module names and returns two cm handles'
def cmHandle1 = new NcmpServiceCmHandle()
cmHandle1.cmHandleId = 'some-cmhandle-id1'
- cmHandle1.publicProperties = [color:'yellow']
+ cmHandle1.publicProperties = [color: 'yellow']
def cmHandle2 = new NcmpServiceCmHandle()
cmHandle2.cmHandleId = 'some-cmhandle-id2'
- cmHandle2.publicProperties = [color:'green']
+ cmHandle2.publicProperties = [color: 'green']
mockNetworkCmProxyDataService.executeCmHandleSearch(_) >> [cmHandle1, cmHandle2]
when: 'the searches api is invoked'
def response = mvc.perform(post(searchesEndpoint)
- .contentType(MediaType.APPLICATION_JSON)
- .content(jsonString)).andReturn().response
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(jsonString)).andReturn().response
then: 'response status returns OK'
response.status == HttpStatus.OK.value()
and: 'the expected response content is returned'
@@ -268,14 +296,15 @@ class NetworkCmProxyControllerSpec extends Specification {
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 dmiProperties = [prop: 'some DMI property']
+ def publicProperties = ["public prop": 'some public property']
def compositeState = compositeStateTestObject()
def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: cmHandleId, dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState)
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
+ def response = mvc.perform(
+ get(cmHandleDetailsEndpoint)).andReturn().response
then: 'the correct response is returned'
response.status == HttpStatus.OK.value()
and: 'the response contains the public properties'
@@ -286,30 +315,34 @@ class NetworkCmProxyControllerSpec extends Specification {
!response.contentAsString.contains("some DMI property")
}
- def 'Get Cm Handle public properties by Cm Handle id.' () {
+ def 'Get Cm Handle public properties by Cm Handle id.'() {
given: 'a cm handle properties endpoint'
def cmHandlePropertiesEndpoint = "$ncmpBasePathV1/ch/some-cm-handle/properties"
and: 'some cm handle public properties'
- def publicProperties = [ 'public prop':'some public property' ]
+ def publicProperties = ['public prop': 'some public property']
and: 'the service method is invoked with the cm handle id returning the cm handle public properties'
- 1 * mockNetworkCmProxyDataService.getCmHandlePublicProperties('some-cm-handle') >> publicProperties
+ 1 * mockNetworkCmProxyDataService
+ .getCmHandlePublicProperties('some-cm-handle') >> publicProperties
when: 'the cm handle properties api is invoked'
- def response = mvc.perform(get(cmHandlePropertiesEndpoint)).andReturn().response
+ def response = mvc.perform(
+ get(cmHandlePropertiesEndpoint)).andReturn().response
then: 'the correct response is returned'
response.status == HttpStatus.OK.value()
and: 'the response contains the public properties'
assertContainsPublicProperties(response)
}
- def 'Get Cm Handle composite state by Cm Handle id.' () {
+ def 'Get Cm Handle composite state by Cm Handle id.'() {
given: 'a cm handle state endpoint'
def cmHandlePropertiesEndpoint = "$ncmpBasePathV1/ch/some-cm-handle/state"
and: 'some cm handle composite state'
def compositeState = compositeStateTestObject()
and: 'the service method is invoked with the cm handle id returning the cm handle composite state'
- 1 * mockNetworkCmProxyDataService.getCmHandleCompositeState('some-cm-handle') >> compositeState
+ 1 * mockNetworkCmProxyDataService
+ .getCmHandleCompositeState('some-cm-handle') >> compositeState
when: 'the cm handle state api is invoked'
- def response = mvc.perform(get(cmHandlePropertiesEndpoint)).andReturn().response
+ def response = mvc.perform(
+ get(cmHandlePropertiesEndpoint)).andReturn().response
then: 'the correct response is returned'
response.status == HttpStatus.OK.value()
and: 'the response contains the cm handle state'
@@ -323,13 +356,14 @@ class NetworkCmProxyControllerSpec extends Specification {
and: 'the service method is invoked with module names and returns two cm handles'
def cmHandel1 = new NcmpServiceCmHandle()
cmHandel1.cmHandleId = 'some-cmhandle-id1'
- cmHandel1.publicProperties = [color:'yellow']
+ cmHandel1.publicProperties = [color: 'yellow']
def cmHandel2 = new NcmpServiceCmHandle()
cmHandel2.cmHandleId = 'some-cmhandle-id2'
- cmHandel2.publicProperties = [color:'green']
+ cmHandel2.publicProperties = [color: 'green']
mockNetworkCmProxyDataService.executeCmHandleSearch(_) >> [cmHandel1, cmHandel2]
when: 'the searches api is invoked'
- def response = mvc.perform(post(searchesEndpoint)
+ def response = mvc.perform(
+ post(searchesEndpoint)
.contentType(MediaType.APPLICATION_JSON)
.content(jsonString)).andReturn().response
then: 'an empty cm handle identifier is returned'
@@ -342,9 +376,10 @@ class NetworkCmProxyControllerSpec extends Specification {
and: 'the service method is invoked with module names and returns cm handle ids'
1 * mockNetworkCmProxyDataService.executeCmHandleIdSearch(_) >> ['some-cmhandle-id1', 'some-cmhandle-id2']
when: 'the searches api is invoked'
- def response = mvc.perform(post(searchesEndpoint)
- .contentType(MediaType.APPLICATION_JSON)
- .content('{}')).andReturn().response
+ def response = mvc.perform(
+ post(searchesEndpoint)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content('{}')).andReturn().response
then: 'cm handle ids are returned'
response.contentAsString == '["some-cmhandle-id1","some-cmhandle-id2"]'
}
@@ -353,37 +388,39 @@ class NetworkCmProxyControllerSpec extends Specification {
when: 'the searches api is invoked'
def searchesEndpoint = "$ncmpBasePathV1/ch/id-searches"
def invalidInputData = '{invalidJson}'
- def response = mvc.perform(post(searchesEndpoint)
+ def response = mvc.perform(
+ post(searchesEndpoint)
.contentType(MediaType.APPLICATION_JSON)
.content(invalidInputData)).andReturn().response
then: 'BAD_REQUEST is returned'
response.getStatus() == 400
}
- def 'Patch resource data in pass-through running datastore.' () {
+ def 'Patch resource data in pass-through running datastore.'() {
given: 'patch resource data url'
def url = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
- "?resourceIdentifier=parent/child"
+ "?resourceIdentifier=parent/child"
when: 'patch data resource request is performed'
def response = mvc.perform(
- patch(url)
- .contentType(MediaType.APPLICATION_JSON)
- .accept(MediaType.APPLICATION_JSON).content(requestBody)
+ patch(url)
+ .contentType(MediaType.APPLICATION_JSON)
+ .accept(MediaType.APPLICATION_JSON).content(requestBody)
).andReturn().response
then: 'ncmp service method to update resource is called'
1 * mockNetworkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
- 'parent/child', PATCH, requestBody, 'application/json;charset=UTF-8')
+ 'parent/child', PATCH, requestBody, 'application/json;charset=UTF-8')
and: 'the response status is OK'
response.status == HttpStatus.OK.value()
}
- def 'Delete resource data in pass-through running datastore.' () {
+ def 'Delete resource data in pass-through running datastore.'() {
given: 'delete resource data url'
def url = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
- "?resourceIdentifier=parent/child"
+ "?resourceIdentifier=parent/child"
when: 'delete data resource request is performed'
def response = mvc.perform(
- delete(url).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)).andReturn().response
+ delete(url)
+ .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)).andReturn().response
then: 'the ncmp service method to delete resource is called (with null as body)'
1 * mockNetworkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
'parent/child', DELETE, null, 'application/json;charset=UTF-8')
@@ -394,12 +431,12 @@ class NetworkCmProxyControllerSpec extends Specification {
def 'Get resource data from DMI with valid topic i.e. async request for #scenario'() {
given: 'resource data url'
def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:${datastoreInUrl}" +
- "?resourceIdentifier=parent/child&options=(a=1,b=2)&topic=my-topic-name"
+ "?resourceIdentifier=parent/child&options=(a=1,b=2)&topic=my-topic-name"
when: 'get data resource request is performed'
def response = mvc.perform(
- get(getUrl)
- .contentType(MediaType.APPLICATION_JSON)
- .accept(MediaType.APPLICATION_JSON_VALUE)
+ get(getUrl)
+ .contentType(MediaType.APPLICATION_JSON)
+ .accept(MediaType.APPLICATION_JSON_VALUE)
).andReturn().response
then: 'async request id is generated'
assert response.contentAsString.contains("requestId")
@@ -409,32 +446,93 @@ class NetworkCmProxyControllerSpec extends Specification {
':passthrough-running' | 'passthrough-running'
}
- def 'Get module definitions based on cmHandleId.' () {
+ def 'Get module definitions based on cmHandleId.'() {
when: 'get module definition request is performed'
- def response = mvc.perform(get("$ncmpBasePathV1/ch/some-cmhandle/modules/definitions"))
- .andReturn().response
+ def response = mvc.perform(
+ get("$ncmpBasePathV1/ch/some-cmhandle/modules/definitions"))
+ .andReturn().response
then: 'ncmp service method to get module definitions is called'
mockNetworkCmProxyDataService.getModuleDefinitionsByCmHandleId('some-cmhandle')
- >> [new ModuleDefinition('sampleModuleName', '2021-10-03',
- 'module sampleModuleName{ sample module content }')]
+ >> [new ModuleDefinition('sampleModuleName', '2021-10-03',
+ 'module sampleModuleName{ sample module content }')]
and: 'response contains an array with the module name, revision and content'
response.getContentAsString() == '[{"moduleName":"sampleModuleName","revision":"2021-10-03","content":"module sampleModuleName{ sample module content }"}]'
and: 'response returns an OK http code'
response.status == HttpStatus.OK.value()
}
- def 'Set the data sync enabled based on the cm handle id and the data sync flag is #scenario' () {
+ def 'Set the data sync enabled based on the cm handle id and the data sync flag is #scenario'() {
when: 'the set data sync enabled request is invoked'
- def response = mvc.perform(put("$ncmpBasePathV1/ch/some-cm-handle-id/data-sync?dataSyncEnabled=" + dataSyncEnabledFlag))
- .andReturn().response
+ def response = mvc.perform(
+ put("$ncmpBasePathV1/ch/some-cm-handle-id/data-sync?dataSyncEnabled=" + dataSyncEnabledFlag))
+ .andReturn().response
then: 'method to set data sync enabled is called'
1 * mockNetworkCmProxyDataService.setDataSyncEnabled('some-cm-handle-id', dataSyncEnabledFlag)
and: 'the response returns an OK http code'
response.status == HttpStatus.OK.value()
where: 'the following parameters are used'
- scenario | dataSyncEnabledFlag
- 'enabled' | true
- 'disabled' | false
+ scenario | dataSyncEnabledFlag
+ 'enabled' | true
+ 'disabled' | false
+ }
+
+ def 'Get Resource Data from operational with or without descendants'() {
+ given: 'resource data url with descendants #enabled'
+ def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:operational" +
+ "?resourceIdentifier=parent/child&include-descendants=${enabled}"
+ when: 'get data resource request is performed'
+ def response = mvc.perform(
+ get(getUrl)
+ .contentType(MediaType.APPLICATION_JSON)
+ ).andReturn().response
+ then: 'the NCMP data service is called with getResourceDataOperational with #descendantsOption'
+ 1 * mockNetworkCmProxyDataService.getResourceDataOperational('testCmHandle',
+ 'parent/child',
+ descendantsOption)
+ and: 'response status is Ok'
+ response.status == HttpStatus.OK.value()
+ where: 'the following parameters are used'
+ enabled | descendantsOption
+ false | FetchDescendantsOption.OMIT_DESCENDANTS
+ true | FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
+ }
+
+ def 'Attempt execute #operation rest operation on resource data with #scenario'() {
+ given: 'resource data url'
+ def url = "$ncmpBasePathV1/ch/testCmHandle/data/ds/${datastoreInUrl}?resourceIdentifier=parent/child"
+ when: 'selected request for data resource is performed on url'
+ def response = mvc.perform(
+ executeRestOperation(operation, url))
+ .andReturn().response
+ then: 'the response status is as expected'
+ assert response.status == HttpStatus.BAD_REQUEST.value()
+ and: 'the response is as expected'
+ assert response.getContentAsString().contains(datastoreInUrl)
+ where: 'the following parameters are used'
+ scenario | operation | datastoreInUrl
+ 'unsupported datastore' | 'POST' | 'ncmp-datastore:operational'
+ 'invalid datastore' | 'POST' | 'invalid'
+ 'unsupported datastore' | 'PUT' | 'ncmp-datastore:operational'
+ 'invalid datastore' | 'PUT' | 'invalid'
+ 'unsupported datastore' | 'PATCH' | 'ncmp-datastore:operational'
+ 'invalid datastore' | 'PATCH' | 'invalid'
+ 'unsupported datastore' | 'DELETE' | 'ncmp-datastore:operational'
+ 'invalid datastore' | 'DELETE' | 'invalid'
+ }
+
+ def executeRestOperation(operation, url) {
+ if (operation == 'POST') {
+ return post(url).contentType(MediaType.APPLICATION_JSON_VALUE).content(requestBody)
+ }
+ if (operation == 'PUT') {
+ return put(url).contentType(MediaType.APPLICATION_JSON_VALUE).content(requestBody)
+ }
+ if (operation == 'PATCH') {
+ return patch(url).contentType(MediaType.APPLICATION_JSON_VALUE).content(requestBody)
+ }
+ if (operation == 'DELETE') {
+ return delete(url).contentType(MediaType.APPLICATION_JSON_VALUE)
+ }
}
def dataStores() {
@@ -453,7 +551,7 @@ class NetworkCmProxyControllerSpec extends Specification {
}
def assertContainsAll(response, assertContent) {
- assertContent.forEach( string -> { assert(response.contentAsString.contains(string)) })
+ assertContent.forEach(string -> { assert (response.contentAsString.contains(string)) })
return void
}
@@ -476,8 +574,8 @@ class NetworkCmProxyControllerSpec extends Specification {
def assertContainsPublicProperties(response) {
def expectedContent = [
- '"publicCmHandleProperties":' ,
- '"public prop"' ,
+ '"publicCmHandleProperties":',
+ '"public prop"',
'"some public property"'
]
return assertContainsAll(response, expectedContent)
diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandlerFactorySpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandlerFactorySpec.groovy
new file mode 100644
index 0000000000..3f7a8a5ce2
--- /dev/null
+++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandlerFactorySpec.groovy
@@ -0,0 +1,20 @@
+package org.onap.cps.ncmp.rest.controller.handlers
+
+import spock.lang.Specification
+
+class NcmpDatastoreResourceRequestHandlerFactorySpec extends Specification {
+
+ def objectUnderTest = new NcmpDatastoreResourceRequestHandlerFactory(null, null)
+
+ def 'Creating ncmp datastore request handlers.'() {
+ when: 'a ncmp datastore request handler is created for #datastoreType'
+ def result = objectUnderTest.getNcmpDatastoreResourceRequestHandler(datastoreType)
+ then: 'the result is of the expected class'
+ result.class == expectedClass
+ where: 'the following type of datastore is used'
+ datastoreType || expectedClass
+ DatastoreType.OPERATIONAL || NcmpDatastoreOperationalResourceRequestHandler
+ DatastoreType.PASSTHROUGH_OPERATIONAL || NcmpDatastorePassthroughOperationalResourceRequestHandler
+ DatastoreType.PASSTHROUGH_RUNNING || NcmpDatastorePassthroughRunningResourceRequestHandler
+ }
+} \ No newline at end of file
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 ce908e7547..9d1077fd2f 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,9 +29,12 @@ import org.onap.cps.ncmp.api.impl.exception.DmiRequestException
import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException
import org.onap.cps.ncmp.api.impl.exception.ServerNcmpException
import org.onap.cps.ncmp.rest.controller.NcmpRestInputMapper
-import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper
+import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastoreResourceRequestHandlerFactory
import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor
+import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper
import org.onap.cps.ncmp.rest.util.DeprecationHelper
+import org.onap.cps.spi.exceptions.AlreadyDefinedException
+import org.onap.cps.spi.exceptions.AlreadyDefinedExceptionBatch
import org.onap.cps.spi.exceptions.CpsException
import org.onap.cps.spi.exceptions.DataNodeNotFoundException
import org.onap.cps.spi.exceptions.DataValidationException
@@ -48,9 +51,7 @@ import spock.lang.Specification
import static org.onap.cps.ncmp.rest.exceptions.NetworkCmProxyRestExceptionHandlerSpec.ApiType.NCMP
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.http.HttpStatus.*
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
@@ -78,6 +79,9 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification {
@SpringBean
DeprecationHelper stubbedDeprecationHelper = Stub()
+ @SpringBean
+ NcmpDatastoreResourceRequestHandlerFactory mockedNcmpDatastoreResourceRequestHandlerFactory = Mock()
+
@Value('${rest.api.ncmp-base-path}')
def basePathNcmp
@@ -104,13 +108,15 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification {
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(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
+ 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
+ 'Existing entry' | new AlreadyDefinedException('name',null) || 'name already exists' | 'Already defined exception' | CONFLICT
+ 'Existing entries' | new AlreadyDefinedExceptionBatch(["x[@id='abc']"]) || 'Check logs for details' | null | CONFLICT
}
def 'Post request with exception returns correct HTTP Status.'() {
@@ -125,7 +131,7 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification {
def 'Failing DMI Request - passthrough scenario'() {
given: 'failing DMI request'
- setupTestException(new HttpClientRequestException('Error Message Details NCMP', 'Bad Request from DMI', 400) , NCMP)
+ setupTestException(new HttpClientRequestException('Error Message Details NCMP', 'Bad Request from DMI', 400), NCMP)
when: 'the DMI request is executed'
def response = performTestRequest(NCMP)
then: 'NCMP service responds with 502 Bad Gateway status'
@@ -150,11 +156,11 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification {
return mvc.perform(post("$dataNodeBaseEndpointNcmpInventory/ch").contentType(MediaType.APPLICATION_JSON).content(jsonData)).andReturn().response
}
- static void assertTestResponse(response, expectedStatus , expectedErrorMessage , expectedErrorDetails) {
+ static void assertTestResponse(response, expectedStatus, expectedErrorMessage, expectedErrorDetails) {
assert response.status == expectedStatus.value()
def content = new JsonSlurper().parseText(response.contentAsString)
assert content['status'].toString().contains(expectedStatus.toString())
- assert content['message'].toString().contains(expectedErrorMessage)
+ assert expectedErrorMessage == null || content['message'].toString().contains(expectedErrorMessage)
assert expectedErrorDetails == null || content['details'].toString().contains(expectedErrorDetails)
}
diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/util/TopicValidatorSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/util/TopicValidatorSpec.groovy
new file mode 100644
index 0000000000..e626e1505d
--- /dev/null
+++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/util/TopicValidatorSpec.groovy
@@ -0,0 +1,47 @@
+/*
+ * ============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.rest.util
+
+import org.onap.cps.ncmp.rest.exceptions.InvalidTopicException
+import spock.lang.Specification
+
+class TopicValidatorSpec extends Specification {
+
+ def 'Valid topic name validation.'() {
+ when: 'a valid topic name is validated'
+ TopicValidator.validateTopicName('my-valid-topic')
+ then: 'no exception is thrown'
+ noExceptionThrown()
+ }
+
+ def 'Validating invalid topic names.'() {
+ when: 'the invalid topic name is validated'
+ TopicValidator.validateTopicName(topicName)
+ then: 'boolean response will be returned for #scenario'
+ thrown(InvalidTopicException)
+ where: 'the following names are used'
+ scenario | topicName
+ 'empty topic' | ''
+ 'blank topic' | ' '
+ 'invalid non empty topic' | '1_5_*_#'
+ }
+
+}