summaryrefslogtreecommitdiffstats
path: root/cps-ncmp-rest
diff options
context:
space:
mode:
authorToine Siebelink <toine.siebelink@est.tech>2023-05-29 08:52:22 +0000
committerGerrit Code Review <gerrit@onap.org>2023-05-29 08:52:22 +0000
commit325ac091ddea291c5659fa6e803f132a578deb14 (patch)
tree3b06c9f393e97e54ae26ef7038123cc750df937c /cps-ncmp-rest
parentacae85ffc8eac8dd919b59b1fc804a1d3743eb0f (diff)
parentf232f30bede7d35c71db2d0201695a1416e37323 (diff)
Merge "NCMP: Update existing Batch endpoint (Moving url param into rest body)"
Diffstat (limited to 'cps-ncmp-rest')
-rw-r--r--cps-ncmp-rest/docs/openapi/components.yaml37
-rwxr-xr-xcps-ncmp-rest/docs/openapi/ncmp.yml6
-rwxr-xr-xcps-ncmp-rest/docs/openapi/openapi.yml2
-rwxr-xr-xcps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java43
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandler.java81
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpPassthroughResourceRequestHandler.java20
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/TaskManagementDefaultHandler.java14
-rwxr-xr-xcps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandler.java2
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/OperationNotSupportedException.java32
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/mapper/ResourceDataBatchRequestMapper.java41
-rw-r--r--cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy94
-rw-r--r--cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy4
12 files changed, 272 insertions, 104 deletions
diff --git a/cps-ncmp-rest/docs/openapi/components.yaml b/cps-ncmp-rest/docs/openapi/components.yaml
index 7fc1063a12..2781f572f2 100644
--- a/cps-ncmp-rest/docs/openapi/components.yaml
+++ b/cps-ncmp-rest/docs/openapi/components.yaml
@@ -285,6 +285,43 @@ components:
properties:
state:
$ref: '#/components/schemas/CmHandleCompositeState'
+ # Batch Request Schemas
+ ResourceDataBatchRequest:
+ type: object
+ title: get resource data for given array of operations
+ properties:
+ operations:
+ type: array
+ items:
+ type: object
+ $ref: '#/components/schemas/BatchOperationDefinition'
+ description: contains batch request details
+ BatchOperationDefinition:
+ required:
+ - operation
+ - datastore
+ - operationId
+ properties:
+ operation:
+ type: string
+ example: 'read'
+ operationId:
+ type: string
+ example: '12'
+ datastore:
+ type: string
+ example: 'ncmp-datastore:passthrough-operational'
+ options:
+ type: string
+ example: '(fields=schemas/schema)'
+ resourceIdentifier:
+ type: string
+ example: 'parent/child'
+ targetIds:
+ type: array
+ items:
+ type: string
+ example: [ "da310eecdb8d44c2acc0ddaae01174b1","c748c58f8e0b438f9fd1f28370b17d47" ]
examples:
dataSampleRequest:
diff --git a/cps-ncmp-rest/docs/openapi/ncmp.yml b/cps-ncmp-rest/docs/openapi/ncmp.yml
index 2b70d94892..957a3b8735 100755
--- a/cps-ncmp-rest/docs/openapi/ncmp.yml
+++ b/cps-ncmp-rest/docs/openapi/ncmp.yml
@@ -202,17 +202,13 @@ getResourceDataForCmHandleBatch:
description: This request will be handled asynchronously using messaging to the supplied topic. The rest response will be an acknowledge with a requestId to identify the relevant messages.
operationId: getResourceDataForCmHandleBatch
parameters:
- - $ref: 'components.yaml#/components/parameters/datastoreName'
- - $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
- - $ref: 'components.yaml#/components/parameters/optionsParamInQuery'
- $ref: 'components.yaml#/components/parameters/requiredTopicParamInQuery'
- - $ref: 'components.yaml#/components/parameters/includeDescendantsOptionInQuery'
requestBody:
required: true
content:
application/json:
schema:
- type: object
+ $ref: 'components.yaml#/components/schemas/ResourceDataBatchRequest'
responses:
200:
description: OK
diff --git a/cps-ncmp-rest/docs/openapi/openapi.yml b/cps-ncmp-rest/docs/openapi/openapi.yml
index 5b4c0d3496..b63b568234 100755
--- a/cps-ncmp-rest/docs/openapi/openapi.yml
+++ b/cps-ncmp-rest/docs/openapi/openapi.yml
@@ -34,7 +34,7 @@ paths:
/v1/ch/{cm-handle}/data/ds/{datastore-name}:
$ref: 'ncmp.yml#/resourceDataForCmHandle'
- /v1/batch/data/ds/{datastore-name}:
+ /v1/data:
$ref: 'ncmp.yml#/getResourceDataForCmHandleBatch'
/v1/ch/{cm-handle}/data/ds/{datastore-name}/query:
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 fca1d6310f..1b78fa0343 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
@@ -23,10 +23,12 @@
package org.onap.cps.ncmp.rest.controller;
-import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.CREATE;
-import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.DELETE;
-import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.PATCH;
-import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.UPDATE;
+import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.OPERATIONAL;
+import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING;
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.CREATE;
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.DELETE;
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.PATCH;
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.UPDATE;
import java.util.Collection;
import java.util.List;
@@ -44,8 +46,10 @@ import org.onap.cps.ncmp.rest.controller.handlers.NcmpCachedResourceRequestHandl
import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastoreRequestHandler;
import org.onap.cps.ncmp.rest.controller.handlers.NcmpPassthroughResourceRequestHandler;
import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper;
+import org.onap.cps.ncmp.rest.mapper.ResourceDataBatchRequestMapper;
import org.onap.cps.ncmp.rest.model.CmHandlePublicProperties;
import org.onap.cps.ncmp.rest.model.CmHandleQueryParameters;
+import org.onap.cps.ncmp.rest.model.ResourceDataBatchRequest;
import org.onap.cps.ncmp.rest.model.RestModuleDefinition;
import org.onap.cps.ncmp.rest.model.RestModuleReference;
import org.onap.cps.ncmp.rest.model.RestOutputCmHandle;
@@ -72,6 +76,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
private final CmHandleStateMapper cmHandleStateMapper;
private final NcmpCachedResourceRequestHandler ncmpCachedResourceRequestHandler;
private final NcmpPassthroughResourceRequestHandler ncmpPassthroughResourceRequestHandler;
+ private final ResourceDataBatchRequestMapper resourceDataBatchRequestMapper;
/**
* Get resource data from datastore.
@@ -100,19 +105,11 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
}
@Override
- public ResponseEntity<Object> getResourceDataForCmHandleBatch(final String resourceIdentifier,
- final String topicParamInQuery,
- final String datastoreName,
- final Object requestBody,
- final String optionsParamInQuery,
- final Boolean includeDescendants) {
-
- final NcmpDatastoreRequestHandler ncmpDatastoreRequestHandler = getNcmpDatastoreRequestHandler(datastoreName);
-
- final List<String> cmHandleIds = jsonObjectMapper.convertJsonString(jsonObjectMapper.asJsonString(requestBody),
- List.class);
- return ncmpDatastoreRequestHandler.executeRequest(datastoreName, cmHandleIds, resourceIdentifier,
- optionsParamInQuery, topicParamInQuery, includeDescendants);
+ public ResponseEntity<Object> getResourceDataForCmHandleBatch(final String topicParamInQuery,
+ final ResourceDataBatchRequest
+ resourceDataBatchRequest) {
+ return ncmpPassthroughResourceRequestHandler.executeRequest(topicParamInQuery,
+ resourceDataBatchRequestMapper.toResourceDataBatchRequest(resourceDataBatchRequest));
}
/**
@@ -134,7 +131,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
final String optionsParamInQuery,
final String topicParamInQuery,
final Boolean includeDescendants) {
- validateDataStore(DatastoreType.OPERATIONAL, datastoreName);
+ validateDataStore(OPERATIONAL, datastoreName);
return ncmpCachedResourceRequestHandler.executeRequest(cmHandle, cpsPath, includeDescendants);
}
@@ -156,7 +153,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
final Object requestBody,
final String contentType) {
- validateDataStore(DatastoreType.PASSTHROUGH_RUNNING, datastoreName);
+ validateDataStore(PASSTHROUGH_RUNNING, datastoreName);
final Object responseObject = networkCmProxyDataService
.writeResourceDataPassThroughRunningForCmHandle(
@@ -182,7 +179,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
final Object requestBody,
final String contentType) {
- validateDataStore(DatastoreType.PASSTHROUGH_RUNNING, datastoreName);
+ validateDataStore(PASSTHROUGH_RUNNING, datastoreName);
networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
resourceIdentifier, CREATE, jsonObjectMapper.asJsonString(requestBody), contentType);
@@ -206,7 +203,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
final String cmHandle,
final Object requestBody,
final String contentType) {
- validateDataStore(DatastoreType.PASSTHROUGH_RUNNING, datastoreName);
+ validateDataStore(PASSTHROUGH_RUNNING, datastoreName);
networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
resourceIdentifier, UPDATE, jsonObjectMapper.asJsonString(requestBody), contentType);
@@ -228,7 +225,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
final String resourceIdentifier,
final String contentType) {
- validateDataStore(DatastoreType.PASSTHROUGH_RUNNING, datastoreName);
+ validateDataStore(PASSTHROUGH_RUNNING, datastoreName);
networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
resourceIdentifier, DELETE, NO_BODY, contentType);
@@ -381,7 +378,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
}
private NcmpDatastoreRequestHandler getNcmpDatastoreRequestHandler(final String datastoreName) {
- if (DatastoreType.OPERATIONAL.equals(DatastoreType.fromDatastoreName(datastoreName))) {
+ if (OPERATIONAL.equals(DatastoreType.fromDatastoreName(datastoreName))) {
return ncmpCachedResourceRequestHandler;
}
return ncmpPassthroughResourceRequestHandler;
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandler.java
index a32c462e76..a8ca13a752 100644
--- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandler.java
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandler.java
@@ -20,12 +20,19 @@
package org.onap.cps.ncmp.rest.controller.handlers;
-import java.util.List;
+import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.OPERATIONAL;
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ;
+
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.impl.exception.InvalidDatastoreException;
+import org.onap.cps.ncmp.api.impl.operations.DatastoreType;
+import org.onap.cps.ncmp.api.impl.operations.OperationType;
+import org.onap.cps.ncmp.api.models.ResourceDataBatchRequest;
+import org.onap.cps.ncmp.rest.exceptions.OperationNotSupportedException;
import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor;
import org.onap.cps.ncmp.rest.util.TopicValidator;
import org.springframework.beans.factory.annotation.Value;
@@ -67,7 +74,7 @@ public class NcmpDatastoreRequestHandler implements TaskManagementDefaultHandler
final boolean asyncResponseRequested = topicParamInQuery != null;
if (asyncResponseRequested && notificationFeatureEnabled) {
return executeAsyncTaskAndGetResponseEntity(datastoreName, cmHandleId, resourceIdentifier,
- optionsParamInQuery, topicParamInQuery, includeDescendants, false);
+ optionsParamInQuery, topicParamInQuery, includeDescendants);
}
if (asyncResponseRequested) {
@@ -98,26 +105,21 @@ public class NcmpDatastoreRequestHandler implements TaskManagementDefaultHandler
}
/**
- * Executes synchronous/asynchronous request for batch of cm handles.
+ * Executes asynchronous request for batch of cm handles to resource data.
*
- * @param datastoreName the name of the datastore
- * @param cmHandleIds list of cm handles
- * @param resourceIdentifier the resource identifier
- * @param optionsParamInQuery the options param in query
- * @param topicParamInQuery the topic param in query
- * @param includeDescendants whether to include descendants or not
+ * @param topicParamInQuery the topic param in query
+ * @param resourceDataBatchRequest batch request details for resource data
* @return the response entity
*/
- public ResponseEntity<Object> executeRequest(final String datastoreName,
- final List<String> cmHandleIds,
- final String resourceIdentifier,
- final String optionsParamInQuery,
- final String topicParamInQuery,
- final boolean includeDescendants) {
-
- return executeAsyncTaskAndGetResponseEntity(datastoreName, cmHandleIds, resourceIdentifier, optionsParamInQuery,
- topicParamInQuery, includeDescendants, true);
-
+ public ResponseEntity<Object> executeRequest(final String topicParamInQuery,
+ final ResourceDataBatchRequest
+ resourceDataBatchRequest) {
+ validateBatchRequest(topicParamInQuery, resourceDataBatchRequest);
+ if (!notificationFeatureEnabled) {
+ return ResponseEntity.ok(Map.of("status",
+ "Asynchronous request is unavailable as notification feature is currently disabled."));
+ }
+ return getRequestIdAndSendBatchRequestToDmiService(topicParamInQuery, resourceDataBatchRequest);
}
protected ResponseEntity<Object> executeTaskAsync(final String topicParamInQuery,
@@ -127,7 +129,6 @@ public class NcmpDatastoreRequestHandler implements TaskManagementDefaultHandler
TopicValidator.validateTopicName(topicParamInQuery);
log.debug("Received Async request with id {}", requestId);
cpsNcmpTaskExecutor.executeTask(taskSupplier, timeOutInMilliSeconds);
-
return ResponseEntity.ok(Map.of("requestId", requestId));
}
@@ -136,25 +137,43 @@ public class NcmpDatastoreRequestHandler implements TaskManagementDefaultHandler
}
private ResponseEntity<Object> executeAsyncTaskAndGetResponseEntity(final String datastoreName,
- final Object targetObject,
+ final String cmHandleId,
final String resourceIdentifier,
final String optionsParamInQuery,
final String topicParamInQuery,
- final boolean includeDescendants,
- final boolean isBulkRequest) {
+ final boolean includeDescendants) {
final String requestId = UUID.randomUUID().toString();
- final Supplier<Object> taskSupplier;
- if (isBulkRequest) {
- taskSupplier = getTaskSupplierForBulkRequest(datastoreName, (List<String>) targetObject,
- resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId, includeDescendants);
- } else {
- taskSupplier = getTaskSupplierForGetRequest(datastoreName, targetObject.toString(), resourceIdentifier,
- optionsParamInQuery, topicParamInQuery, requestId, includeDescendants);
- }
+ final Supplier<Object> taskSupplier = getTaskSupplierForGetRequest(datastoreName, cmHandleId,
+ resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId, includeDescendants);
if (taskSupplier == NO_OBJECT_SUPPLIER) {
return new ResponseEntity<>(Map.of("status", "Unable to execute request as "
+ "datastore is not implemented."), HttpStatus.NOT_IMPLEMENTED);
}
return executeTaskAsync(topicParamInQuery, requestId, taskSupplier);
}
+
+ private ResponseEntity<Object> getRequestIdAndSendBatchRequestToDmiService(final String topicParamInQuery,
+ final ResourceDataBatchRequest
+ resourceDataBatchRequest) {
+ final String requestId = UUID.randomUUID().toString();
+ sendResourceDataBatchRequestAsynchronously(topicParamInQuery, resourceDataBatchRequest, requestId);
+ return ResponseEntity.ok(Map.of("requestId", requestId));
+ }
+
+ private void validateBatchRequest(final String topicParamInQuery,
+ final ResourceDataBatchRequest
+ resourceDataBatchRequest) {
+ TopicValidator.validateTopicName(topicParamInQuery);
+ resourceDataBatchRequest.getBatchOperationDefinitions().forEach(batchOperationDetail -> {
+ if (OperationType.fromOperationName(batchOperationDetail.getOperation()) != READ) {
+ throw new OperationNotSupportedException(
+ batchOperationDetail.getOperation() + " operation not yet supported for target ids :"
+ + batchOperationDetail.getCmHandleIds());
+ } else if (DatastoreType.fromDatastoreName(batchOperationDetail.getDatastore()) == OPERATIONAL) {
+ throw new InvalidDatastoreException(batchOperationDetail.getDatastore()
+ + " datastore is not supported for target ids : "
+ + batchOperationDetail.getCmHandleIds());
+ }
+ });
+ }
}
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpPassthroughResourceRequestHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpPassthroughResourceRequestHandler.java
index 18e5a9f5ac..5c35818a3a 100644
--- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpPassthroughResourceRequestHandler.java
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpPassthroughResourceRequestHandler.java
@@ -20,10 +20,11 @@
package org.onap.cps.ncmp.rest.controller.handlers;
-import java.util.List;
import java.util.function.Supplier;
import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
+import org.onap.cps.ncmp.api.models.ResourceDataBatchRequest;
import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor;
+import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
@@ -56,17 +57,14 @@ public class NcmpPassthroughResourceRequestHandler extends NcmpDatastoreRequestH
datastoreName, cmHandleId, resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId);
}
+ @Async
@Override
- public Supplier<Object> getTaskSupplierForBulkRequest(final String datastoreName,
- final List<String> cmHandleIds,
- final String resourceIdentifier,
- final String optionsParamInQuery,
- final String topicParamInQuery,
- final String requestId,
- final boolean includeDescendants) {
+ public void sendResourceDataBatchRequestAsynchronously(final String topicParamInQuery,
+ final ResourceDataBatchRequest
+ resourceDataBatchRequest,
+ final String requestId) {
+ networkCmProxyDataService.requestResourceDataForCmHandleBatch(topicParamInQuery, resourceDataBatchRequest,
+ requestId);
- return () -> networkCmProxyDataService.getResourceDataForCmHandleBatch(
- datastoreName, cmHandleIds, resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId);
}
-
}
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/TaskManagementDefaultHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/TaskManagementDefaultHandler.java
index 6d68f76802..937935bec4 100644
--- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/TaskManagementDefaultHandler.java
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/TaskManagementDefaultHandler.java
@@ -20,8 +20,8 @@
package org.onap.cps.ncmp.rest.controller.handlers;
-import java.util.List;
import java.util.function.Supplier;
+import org.onap.cps.ncmp.api.models.ResourceDataBatchRequest;
import org.onap.cps.spi.FetchDescendantsOption;
public interface TaskManagementDefaultHandler {
@@ -46,14 +46,10 @@ public interface TaskManagementDefaultHandler {
return NO_OBJECT_SUPPLIER;
}
- default Supplier<Object> getTaskSupplierForBulkRequest(final String datastoreName,
- final List<String> cmHandleIds,
- final String resourceIdentifier,
- final String optionsParamInQuery,
- final String topicParamInQuery,
- final String requestId,
- final boolean includeDescendant) {
- return NO_OBJECT_SUPPLIER;
+ default void sendResourceDataBatchRequestAsynchronously(final String topicParamInQuery,
+ final ResourceDataBatchRequest
+ resourceDataBatchRequest,
+ final String requestId) {
}
static FetchDescendantsOption getFetchDescendantsOption(final boolean includeDescendants) {
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 5faeee69fc..f459acec25 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
@@ -77,7 +77,7 @@ public class NetworkCmProxyRestExceptionHandler {
return wrapDmiErrorResponse(HttpStatus.BAD_GATEWAY, httpClientRequestException);
}
- @ExceptionHandler({DmiRequestException.class, DataValidationException.class,
+ @ExceptionHandler({DmiRequestException.class, DataValidationException.class, OperationNotSupportedException.class,
HttpMessageNotReadableException.class, InvalidTopicException.class, InvalidDatastoreException.class})
public static ResponseEntity<Object> handleDmiRequestExceptions(final Exception exception) {
return buildErrorResponse(HttpStatus.BAD_REQUEST, exception);
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/OperationNotSupportedException.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/OperationNotSupportedException.java
new file mode 100644
index 0000000000..e1daf3df6f
--- /dev/null
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/OperationNotSupportedException.java
@@ -0,0 +1,32 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 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 OperationNotSupportedException extends RuntimeException {
+ /**
+ * Instantiates a new not implemented operation exception.
+ *
+ * @param message the message
+ */
+ public OperationNotSupportedException(final String message) {
+ super(message);
+ }
+}
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/mapper/ResourceDataBatchRequestMapper.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/mapper/ResourceDataBatchRequestMapper.java
new file mode 100644
index 0000000000..d045e31610
--- /dev/null
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/mapper/ResourceDataBatchRequestMapper.java
@@ -0,0 +1,41 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 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.mapper;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.NullValueCheckStrategy;
+import org.mapstruct.NullValuePropertyMappingStrategy;
+import org.onap.cps.ncmp.api.models.BatchOperationDefinition;
+import org.onap.cps.ncmp.api.models.ResourceDataBatchRequest;
+
+@Mapper(componentModel = "spring", nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS,
+ nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT)
+public interface ResourceDataBatchRequestMapper {
+
+ @Mapping(source = "operations", target = "batchOperationDefinitions")
+ ResourceDataBatchRequest toResourceDataBatchRequest(
+ org.onap.cps.ncmp.rest.model.ResourceDataBatchRequest resourceDataBatchRequest);
+
+ @Mapping(source = "targetIds", target = "cmHandleIds")
+ BatchOperationDefinition toBatchOperationDefinition(
+ org.onap.cps.ncmp.rest.model.BatchOperationDefinition batchOperationDefinition);
+}
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 fb411c054a..31e83aa7a1 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
@@ -32,11 +32,14 @@ import org.onap.cps.ncmp.api.inventory.CmHandleState
import org.onap.cps.ncmp.api.inventory.CompositeState
import org.onap.cps.ncmp.api.inventory.DataStoreSyncState
import org.onap.cps.ncmp.api.inventory.LockReasonCategory
+import org.onap.cps.ncmp.rest.model.BatchOperationDefinition
import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
import org.onap.cps.ncmp.rest.controller.handlers.NcmpCachedResourceRequestHandler
import org.onap.cps.ncmp.rest.controller.handlers.NcmpPassthroughResourceRequestHandler
import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor
import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper
+import org.onap.cps.ncmp.rest.mapper.ResourceDataBatchRequestMapper
+import org.onap.cps.ncmp.rest.model.ResourceDataBatchRequest
import org.onap.cps.ncmp.rest.util.DeprecationHelper
import org.onap.cps.spi.FetchDescendantsOption
import org.onap.cps.spi.model.ModuleDefinition
@@ -62,10 +65,10 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
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
-import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.CREATE
-import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.UPDATE
-import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.PATCH
-import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.DELETE
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.CREATE
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.UPDATE
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.PATCH
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.DELETE
import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL
import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING
import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.OPERATIONAL
@@ -98,6 +101,9 @@ class NetworkCmProxyControllerSpec extends Specification {
CmHandleStateMapper cmHandleStateMapper = Mappers.getMapper(CmHandleStateMapper)
@SpringBean
+ ResourceDataBatchRequestMapper resourceDataBatchRequestMapper = Mappers.getMapper(ResourceDataBatchRequestMapper)
+
+ @SpringBean
CpsNcmpTaskExecutor spiedCpsTaskExecutor = Spy()
@SpringBean
@@ -113,7 +119,6 @@ class NetworkCmProxyControllerSpec extends Specification {
def ncmpBasePathV1
def requestBody = '{"some-key":"some-value"}'
- def bulkRequestBody = '["testCmHandle"]'
def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(OffsetDateTime.of(2022, 12, 31, 20, 30, 40, 1, ZoneOffset.UTC))
@@ -200,44 +205,69 @@ class NetworkCmProxyControllerSpec extends Specification {
'invalid non-empty topic value in url' | 'passthrough-operational' | '&topic=1_5_*_#'
}
- def 'Get (async) bulk resource data from dmi service.'() {
- given: 'bulk resource data url'
- def getUrl = "$ncmpBasePathV1/batch/data/ds/${datastore.datastoreName}" +
- "?resourceIdentifier=parent/child&options=(a=1,b=2)&topic=myTopic"
+ def 'Get (async) batch resource data from dmi service.'() {
+ given: 'batch resource data url'
+ def getUrl = "$ncmpBasePathV1/data?topic=my-topic-name"
+ def resourceDataBatchRequestJsonData = jsonObjectMapper.asJsonString(
+ getResourceDataBatchRequest("read", datastore.datastoreName))
+ def expectedDmiResourceDataBatchRequest
+ = jsonObjectMapper.convertJsonString(resourceDataBatchRequestJsonData, org.onap.cps.ncmp.api.models.ResourceDataBatchRequest.class)
when: 'post data resource request is performed'
def response = mvc.perform(
post(getUrl)
.contentType(MediaType.APPLICATION_JSON)
- .content(bulkRequestBody)
+ .content(resourceDataBatchRequestJsonData)
).andReturn().response
then: 'response status is Ok'
response.status == HttpStatus.OK.value()
and: 'async request id is generated'
assert response.contentAsString.contains("requestId")
then: 'wait a little to allow execution of service method by task executor (on separate thread)'
- Thread.sleep(100);
+ Thread.sleep(100)
then: 'the service has been invoked with the correct parameters '
- 1 * mockNetworkCmProxyDataService.getResourceDataForCmHandleBatch(datastore.datastoreName, ['testCmHandle'],
- 'parent/child',
- '(a=1,b=2)',
- 'myTopic',
- _)
+ 1 * mockNetworkCmProxyDataService.requestResourceDataForCmHandleBatch('my-topic-name', expectedDmiResourceDataBatchRequest, _)
where: 'the following data stores are used'
datastore << [PASSTHROUGH_RUNNING, PASSTHROUGH_OPERATIONAL]
}
- def 'Get bulk resource data for non-supported #datastoreName from dmi service.'() {
- given: 'bulk resource data url'
- def getUrl = "$ncmpBasePathV1/batch/data/ds/ncmp-datastore:operational" +
- "?resourceIdentifier=parent/child&options=(a=1,b=2)&topic=myTopic"
+ def 'Get batch resource data for #scenario from dmi service.'() {
+ given: 'batch resource data url'
+ def getUrl = "$ncmpBasePathV1/data?topic=my-topic-name"
+ def resourceDataBatchRequestJsonData = jsonObjectMapper.asJsonString(
+ getResourceDataBatchRequest(operation, datastore))
+ when: 'post data resource request is performed'
+ def response = mvc.perform(
+ post(getUrl)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(resourceDataBatchRequestJsonData)
+ ).andReturn().response
+ then: 'response status is BAD_REQUEST'
+ response.status == HttpStatus.BAD_REQUEST.value()
+ where: 'the following parameters are used'
+ scenario | datastore | operation
+ 'non-supported datastoreName' | OPERATIONAL.datastoreName | 'read'
+ 'non-supported operation (passthrough-running)' | PASSTHROUGH_RUNNING.datastoreName | 'create'
+ 'non-supported operation (passthrough-operational)' | PASSTHROUGH_OPERATIONAL.datastoreName | 'create'
+ }
+
+ def 'Get batch resource data when notification feature is disabled for datastore: #datastore.'() {
+ given: 'batch resource data url'
+ def getUrl = "$ncmpBasePathV1/data?topic=my-topic-name"
+ def resourceDataBatchRequestJsonData = jsonObjectMapper.asJsonString(
+ getResourceDataBatchRequest("read", datastore.datastoreName))
+ ncmpPassthroughResourceRequestHandler.notificationFeatureEnabled = false
when: 'post data resource request is performed'
def response = mvc.perform(
post(getUrl)
.contentType(MediaType.APPLICATION_JSON)
- .content(bulkRequestBody)
+ .content(resourceDataBatchRequestJsonData)
).andReturn().response
- then: 'response status code is 501 not implemented'
- response.status == HttpStatus.NOT_IMPLEMENTED.value()
+ then: 'response status is Ok'
+ response.status == HttpStatus.OK.value()
+ and: 'async request id is unavailable'
+ assert response.contentAsString == '{"status":"Asynchronous request is unavailable as notification feature is currently disabled."}'
+ where: 'the following data stores are used'
+ datastore << [PASSTHROUGH_RUNNING, PASSTHROUGH_OPERATIONAL]
}
def 'Query Resource Data from operational.'() {
@@ -656,5 +686,23 @@ class NetworkCmProxyControllerSpec extends Specification {
return assertContainsAll(response, expectedContent)
}
+ def getResourceDataBatchRequest(operation, datastore) {
+ def resourceDataBatchRequest = new ResourceDataBatchRequest()
+ def batchOperationDefinitions = new ArrayList()
+ batchOperationDefinitions.add(getBatchOperationDefinition(operation, datastore))
+ resourceDataBatchRequest.addOperationsItem(batchOperationDefinitions)
+ }
+
+ def getBatchOperationDefinition(operation, datastore) {
+ def batchOperationDefinition = new BatchOperationDefinition()
+ batchOperationDefinition.setOperation(operation)
+ batchOperationDefinition.setOperationId("operational-12")
+ batchOperationDefinition.setDatastore(datastore)
+ batchOperationDefinition.setOptions("some option")
+ batchOperationDefinition.setResourceIdentifier("some resource identifier")
+ batchOperationDefinition.addTargetIdsItem("some-cm-handle")
+ return batchOperationDefinition
+ }
+
}
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 f44d6c9907..a3afc5546f 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
@@ -33,6 +33,7 @@ import org.onap.cps.ncmp.rest.controller.handlers.NcmpCachedResourceRequestHandl
import org.onap.cps.ncmp.rest.controller.handlers.NcmpPassthroughResourceRequestHandler
import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor
import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper
+import org.onap.cps.ncmp.rest.mapper.ResourceDataBatchRequestMapper
import org.onap.cps.ncmp.rest.util.DeprecationHelper
import org.onap.cps.spi.exceptions.AlreadyDefinedException
import org.onap.cps.spi.exceptions.AlreadyDefinedExceptionBatch
@@ -75,6 +76,9 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification {
CmHandleStateMapper cmHandleStateMapper = Mappers.getMapper(CmHandleStateMapper)
@SpringBean
+ ResourceDataBatchRequestMapper resourceDataBatchRequestMapper = Mappers.getMapper(ResourceDataBatchRequestMapper)
+
+ @SpringBean
CpsNcmpTaskExecutor stubbedCpsTaskExecutor = Stub()
@SpringBean