diff options
20 files changed, 518 insertions, 158 deletions
diff --git a/cps-ncmp-rest-stub/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java b/cps-ncmp-rest-stub/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java index bb919b5c6e..3990dd15d4 100644 --- a/cps-ncmp-rest-stub/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java +++ b/cps-ncmp-rest-stub/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java @@ -163,6 +163,16 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi { } @Override + public ResponseEntity<Object> queryResourceDataForCmHandle(final String datastoreName, + final String cmHandle, + final String cpsPath, + final String options, + final String topic, + final Boolean includeDescendants) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + } + + @Override public ResponseEntity<RestOutputCmHandle> retrieveCmHandleDetailsById(final String cmHandleId) { return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); } diff --git a/cps-ncmp-rest/docs/openapi/components.yaml b/cps-ncmp-rest/docs/openapi/components.yaml index 7ca09ceedb..b4b8c84673 100644 --- a/cps-ncmp-rest/docs/openapi/components.yaml +++ b/cps-ncmp-rest/docs/openapi/components.yaml @@ -456,11 +456,16 @@ components: cpsPathInQuery: name: cps-path in: query - description: cps-path + description: For more details on cps path, please refer https://docs.onap.org/projects/onap-cps/en/latest/cps-path.html required: false schema: type: string default: / + examples: + container cps path: + value: //bookstore + list attributes cps path: + value: //categories[@code=1] dmiPluginIdentifierInQuery: name: dmi-plugin-identifier in: query @@ -527,7 +532,7 @@ components: default: application/json example: application/yang-data+json datastoreName: - name: ncmp-datastore-name + name: datastore-name in: path description: The type of the requested data required: true diff --git a/cps-ncmp-rest/docs/openapi/ncmp.yml b/cps-ncmp-rest/docs/openapi/ncmp.yml index 38db26f470..1f7cce96ff 100755 --- a/cps-ncmp-rest/docs/openapi/ncmp.yml +++ b/cps-ncmp-rest/docs/openapi/ncmp.yml @@ -194,6 +194,41 @@ resourceDataForCmHandle: 502: $ref: 'components.yaml#/components/responses/BadGateway' +queryResourceDataForCmHandle: + get: + tags: + - network-cm-proxy + summary: Query resource data for a given cm handle + description: Query resource data for a given cm handle + operationId: queryResourceDataForCmHandle + parameters: + - $ref: 'components.yaml#/components/parameters/datastoreName' + - $ref: 'components.yaml#/components/parameters/cmHandleInPath' + - $ref: 'components.yaml#/components/parameters/cpsPathInQuery' + - $ref: 'components.yaml#/components/parameters/optionsParamInQuery' + - $ref: 'components.yaml#/components/parameters/topicParamInQuery' + - $ref: 'components.yaml#/components/parameters/includeDescendantsOptionInQuery' + 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' + fetchModuleReferencesByCmHandle: get: description: fetch all module references (name and revision) for a given cm handle diff --git a/cps-ncmp-rest/docs/openapi/openapi.yml b/cps-ncmp-rest/docs/openapi/openapi.yml index fe0c4acfc7..ee29366906 100755 --- a/cps-ncmp-rest/docs/openapi/openapi.yml +++ b/cps-ncmp-rest/docs/openapi/openapi.yml @@ -31,9 +31,12 @@ components: type: http scheme: basic paths: - /v1/ch/{cm-handle}/data/ds/{ncmp-datastore-name}: + /v1/ch/{cm-handle}/data/ds/{datastore-name}: $ref: 'ncmp.yml#/resourceDataForCmHandle' + /v1/ch/{cm-handle}/data/ds/{datastore-name}/query: + $ref: 'ncmp.yml#/queryResourceDataForCmHandle' + /v1/ch/{cm-handle}/modules: $ref: 'ncmp.yml#/fetchModuleReferencesByCmHandle' 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 2f6668a351..9f171f6094 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 @@ -39,7 +39,7 @@ 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.controller.handlers.DatastoreType; -import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastoreResourceRequestHandler; +import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastoreRequestHandler; 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; @@ -91,15 +91,42 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { final String topicParamInQuery, final Boolean includeDescendants) { - final NcmpDatastoreResourceRequestHandler ncmpDatastoreResourceRequestHandler = + final NcmpDatastoreRequestHandler ncmpDatastoreRequestHandler = ncmpDatastoreResourceRequestHandlerFactory.getNcmpDatastoreResourceRequestHandler( DatastoreType.fromDatastoreName(datastoreName)); - return ncmpDatastoreResourceRequestHandler.getResourceData(cmHandle, resourceIdentifier, + return ncmpDatastoreRequestHandler.executeRequest(cmHandle, resourceIdentifier, optionsParamInQuery, topicParamInQuery, includeDescendants); } /** + * Query resource data from datastore. + * + * @param datastoreName name of the datastore + * @param cmHandle cm handle identifier + * @param cpsPath CPS Path + * @param optionsParamInQuery options query parameter + * @param topicParamInQuery topic query parameter + * @param includeDescendants whether include descendants + * @return {@code ResponseEntity} response from dmi plugin + */ + + @Override + public ResponseEntity<Object> queryResourceDataForCmHandle(final String datastoreName, + final String cmHandle, + final String cpsPath, + final String optionsParamInQuery, + final String topicParamInQuery, + final Boolean includeDescendants) { + validateDataStore(DatastoreType.OPERATIONAL, datastoreName); + final NcmpDatastoreRequestHandler ncmpDatastoreRequestHandler = + ncmpDatastoreResourceRequestHandlerFactory.getNcmpDatastoreResourceQueryHandler(); + + return ncmpDatastoreRequestHandler.executeRequest(cmHandle, cpsPath, optionsParamInQuery, + topicParamInQuery, includeDescendants); + } + + /** * Patch resource data from passthrough-running. * * @param resourceIdentifier resource identifier @@ -117,7 +144,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { final Object requestBody, final String contentType) { - acceptPassthroughRunningOnly(datastoreName); + validateDataStore(DatastoreType.PASSTHROUGH_RUNNING, datastoreName); final Object responseObject = networkCmProxyDataService .writeResourceDataPassThroughRunningForCmHandle( @@ -143,7 +170,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { final Object requestBody, final String contentType) { - acceptPassthroughRunningOnly(datastoreName); + validateDataStore(DatastoreType.PASSTHROUGH_RUNNING, datastoreName); networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle, resourceIdentifier, CREATE, jsonObjectMapper.asJsonString(requestBody), contentType); @@ -167,7 +194,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { final String cmHandle, final Object requestBody, final String contentType) { - acceptPassthroughRunningOnly(datastoreName); + validateDataStore(DatastoreType.PASSTHROUGH_RUNNING, datastoreName); networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle, resourceIdentifier, UPDATE, jsonObjectMapper.asJsonString(requestBody), contentType); @@ -189,7 +216,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { final String resourceIdentifier, final String contentType) { - acceptPassthroughRunningOnly(datastoreName); + validateDataStore(DatastoreType.PASSTHROUGH_RUNNING, datastoreName); networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle, resourceIdentifier, DELETE, NO_BODY, contentType); @@ -332,11 +359,11 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { return restOutputCmHandle; } - private void acceptPassthroughRunningOnly(final String datastoreName) { - final DatastoreType datastoreType = DatastoreType.fromDatastoreName(datastoreName); + private void validateDataStore(final DatastoreType acceptableDataStoreType, final String requestedDatastoreName) { + final DatastoreType datastoreType = DatastoreType.fromDatastoreName(requestedDatastoreName); - if (DatastoreType.PASSTHROUGH_RUNNING != datastoreType) { - throw new InvalidDatastoreException(datastoreName + " is not supported"); + if (acceptableDataStoreType != datastoreType) { + throw new InvalidDatastoreException(requestedDatastoreName + " is not supported"); } } } diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreOperationalQueryHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreOperationalQueryHandler.java new file mode 100644 index 0000000000..0586d42625 --- /dev/null +++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreOperationalQueryHandler.java @@ -0,0 +1,56 @@ +/* + * ============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.NetworkCmProxyQueryService; +import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor; +import org.onap.cps.spi.FetchDescendantsOption; + +@Slf4j +public class NcmpDatastoreOperationalQueryHandler extends NcmpDatastoreRequestHandler { + + private final NetworkCmProxyQueryService networkCmProxyQueryService; + + public NcmpDatastoreOperationalQueryHandler(final NetworkCmProxyQueryService networkCmProxyQueryService, + final CpsNcmpTaskExecutor cpsNcmpTaskExecutor, + final int timeOutInMilliSeconds, + final boolean notificationFeatureEnabled) { + super(null, cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled); + this.networkCmProxyQueryService = networkCmProxyQueryService; + } + + @Override + public Supplier<Object> getTaskSupplier(final String cmHandle, + final String resourceIdentifier, + final String optionsParamInQuery, + final String topicParamInQuery, + final String requestId, + final Boolean includeDescendant) { + + final FetchDescendantsOption fetchDescendantsOption = getFetchDescendantsOption(includeDescendant); + + return () -> networkCmProxyQueryService.queryResourceDataOperational(cmHandle, resourceIdentifier, + fetchDescendantsOption); + } + +} 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 index 6ed9b8c4d1..a4720b22ff 100644 --- 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 @@ -27,7 +27,7 @@ import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor; import org.onap.cps.spi.FetchDescendantsOption; @Slf4j -public class NcmpDatastoreOperationalResourceRequestHandler extends NcmpDatastoreResourceRequestHandler { +public class NcmpDatastoreOperationalResourceRequestHandler extends NcmpDatastoreRequestHandler { public NcmpDatastoreOperationalResourceRequestHandler(final NetworkCmProxyDataService networkCmProxyDataService, final CpsNcmpTaskExecutor cpsNcmpTaskExecutor, @@ -37,16 +37,14 @@ public class NcmpDatastoreOperationalResourceRequestHandler extends NcmpDatastor } @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; + public Supplier<Object> getTaskSupplier(final String cmHandle, + final String resourceIdentifier, + final String optionsParamInQuery, + final String topicParamInQuery, + final String requestId, + final Boolean includeDescendant) { + + final FetchDescendantsOption fetchDescendantsOption = getFetchDescendantsOption(includeDescendant); 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 index 196e5bd33d..1445e3e271 100644 --- 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 @@ -26,7 +26,7 @@ import org.onap.cps.ncmp.api.NetworkCmProxyDataService; import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor; @Slf4j -public class NcmpDatastorePassthroughOperationalResourceRequestHandler extends NcmpDatastoreResourceRequestHandler { +public class NcmpDatastorePassthroughOperationalResourceRequestHandler extends NcmpDatastoreRequestHandler { public NcmpDatastorePassthroughOperationalResourceRequestHandler( final NetworkCmProxyDataService networkCmProxyDataService, @@ -37,12 +37,12 @@ public class NcmpDatastorePassthroughOperationalResourceRequestHandler extends N } @Override - public Supplier<Object> getTask(final String cmHandle, - final String resourceIdentifier, - final String optionsParamInQuery, - final String topicParamInQuery, - final String requestId, - final Boolean includeDescendant) { + public Supplier<Object> getTaskSupplier(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 index 5bf16b7499..8194ec9fd5 100644 --- 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 @@ -26,7 +26,7 @@ import org.onap.cps.ncmp.api.NetworkCmProxyDataService; import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor; @Slf4j -public class NcmpDatastorePassthroughRunningResourceRequestHandler extends NcmpDatastoreResourceRequestHandler { +public class NcmpDatastorePassthroughRunningResourceRequestHandler extends NcmpDatastoreRequestHandler { public NcmpDatastorePassthroughRunningResourceRequestHandler( final NetworkCmProxyDataService networkCmProxyDataService, @@ -37,12 +37,12 @@ public class NcmpDatastorePassthroughRunningResourceRequestHandler extends NcmpD } @Override - public Supplier<Object> getTask(final String cmHandle, - final String resourceIdentifier, - final String optionsParamInQuery, - final String topicParamInQuery, - final String requestId, - final Boolean includeDescendant) { + public Supplier<Object> getTaskSupplier(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/NcmpDatastoreRequestHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandler.java new file mode 100644 index 0000000000..850200396b --- /dev/null +++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandler.java @@ -0,0 +1,106 @@ +/* + * ============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.onap.cps.spi.FetchDescendantsOption; +import org.springframework.http.ResponseEntity; + +@RequiredArgsConstructor +@Slf4j +public abstract class NcmpDatastoreRequestHandler { + + 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> getTaskSupplier(final String cmHandle, + final String resourceIdentifier, + final String optionsParamInQuery, + final String topicParamInQuery, + final String requestId, + final Boolean includeDescendant); + + /** + * Execute a request on a 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> executeRequest(final String cmHandleId, + final String resourceIdentifier, + final String optionsParamInQuery, + final String topicParamInQuery, + final Boolean includeDescendants) { + + final boolean asyncResponseRequested = topicParamInQuery != null; + if (asyncResponseRequested && notificationFeatureEnabled) { + final String requestId = UUID.randomUUID().toString(); + final Supplier<Object> taskSupplier = getTaskSupplier(cmHandleId, resourceIdentifier, optionsParamInQuery, + topicParamInQuery, requestId, includeDescendants); + return executeTaskAsync(topicParamInQuery, requestId, taskSupplier); + } + + if (asyncResponseRequested) { + log.warn("Asynchronous request is unavailable as notification feature is currently disabled, " + + "will use synchronous operation."); + } + final Supplier<Object> taskSupplier = getTaskSupplier(cmHandleId, resourceIdentifier, optionsParamInQuery, + NO_TOPIC, NO_REQUEST_ID, includeDescendants); + return executeTaskSync(taskSupplier); + } + + protected ResponseEntity<Object> executeTaskAsync(final String topicParamInQuery, + final String requestId, + final Supplier<Object> taskSupplier) { + + TopicValidator.validateTopicName(topicParamInQuery); + log.debug("Received Async request with id {}", requestId); + cpsNcmpTaskExecutor.executeTask(taskSupplier, timeOutInMilliSeconds); + + return ResponseEntity.ok(Map.of("requestId", requestId)); + } + + protected ResponseEntity<Object> executeTaskSync(final Supplier<Object> taskSupplier) { + return ResponseEntity.ok(taskSupplier.get()); + } + + protected static FetchDescendantsOption getFetchDescendantsOption(final Boolean includeDescendant) { + return Boolean.TRUE.equals(includeDescendant) ? FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS + : FetchDescendantsOption.OMIT_DESCENDANTS; + } + +} 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 deleted file mode 100644 index a6d313b05f..0000000000 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandler.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * ============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 index 7db754279c..ff7bda6a47 100644 --- 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 @@ -22,6 +22,7 @@ package org.onap.cps.ncmp.rest.controller.handlers; import lombok.RequiredArgsConstructor; import org.onap.cps.ncmp.api.NetworkCmProxyDataService; +import org.onap.cps.ncmp.api.NetworkCmProxyQueryService; import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -31,6 +32,7 @@ import org.springframework.stereotype.Component; public class NcmpDatastoreResourceRequestHandlerFactory { private final NetworkCmProxyDataService networkCmProxyDataService; + private final NetworkCmProxyQueryService networkCmProxyQueryService; private final CpsNcmpTaskExecutor cpsNcmpTaskExecutor; @Value("${notification.async.executor.time-out-value-in-ms:2000}") @@ -44,7 +46,7 @@ public class NcmpDatastoreResourceRequestHandlerFactory { * @param datastoreType the datastore type * @return the ncmp datastore handler */ - public NcmpDatastoreResourceRequestHandler getNcmpDatastoreResourceRequestHandler( + public NcmpDatastoreRequestHandler getNcmpDatastoreResourceRequestHandler( final DatastoreType datastoreType) { switch (datastoreType) { @@ -60,4 +62,15 @@ public class NcmpDatastoreResourceRequestHandlerFactory { cpsNcmpTaskExecutor, timeOutInMilliSeconds, notificationFeatureEnabled); } } + + /** + * Gets ncmp datastore query handler. + * Note. Currently only ncmp-datastore:operational supports query operations + * @return a ncmp datastore query handler. + */ + public NcmpDatastoreRequestHandler getNcmpDatastoreResourceQueryHandler() { + return new NcmpDatastoreOperationalQueryHandler(networkCmProxyQueryService, cpsNcmpTaskExecutor, + timeOutInMilliSeconds, notificationFeatureEnabled); + } + } 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 b6194bc796..d67804e128 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 @@ -27,20 +27,24 @@ 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.NetworkCmProxyQueryService 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.api.models.NcmpServiceCmHandle import org.onap.cps.ncmp.rest.controller.handlers.DatastoreType +import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastoreOperationalQueryHandler 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.exceptions.InvalidDatastoreException 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.exceptions.DataValidationException import org.onap.cps.spi.model.ModuleDefinition import org.onap.cps.spi.model.ModuleReference import org.onap.cps.utils.JsonObjectMapper @@ -84,6 +88,9 @@ class NetworkCmProxyControllerSpec extends Specification { NetworkCmProxyDataService mockNetworkCmProxyDataService = Mock() @SpringBean + NetworkCmProxyQueryService mockNetworkCmProxyQueryService = Mock() + + @SpringBean ObjectMapper objectMapper = new ObjectMapper() @SpringBean @@ -131,6 +138,10 @@ class NetworkCmProxyControllerSpec extends Specification { DatastoreType.PASSTHROUGH_RUNNING) >> new NcmpDatastorePassthroughRunningResourceRequestHandler( mockNetworkCmProxyDataService, spiedCpsTaskExecutor, TIMEOUT_IN_MS, NOTIFICATION_ENABLED) + + stubbedNcmpDatastoreResourceRequestHandlerFactory.getNcmpDatastoreResourceQueryHandler() >> + new NcmpDatastoreOperationalQueryHandler(mockNetworkCmProxyQueryService, spiedCpsTaskExecutor, + TIMEOUT_IN_MS, NOTIFICATION_ENABLED); } def 'Get Resource Data from pass-through operational.'() { @@ -194,6 +205,40 @@ class NetworkCmProxyControllerSpec extends Specification { 'invalid non-empty topic value in url' | 'passthrough-running' | '&topic=1_5_*_#' } + def 'Query Resource Data from operational.'() { + given: 'the query resource data url' + def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:operational/query" + + "?cps-path=/cps/path" + when: 'the query data resource request is performed' + def response = mvc.perform( + get(getUrl) + .contentType(MediaType.APPLICATION_JSON) + ).andReturn().response + then: 'the NCMP query service is called with queryResourceDataOperationalForCmHandle' + 1 * mockNetworkCmProxyQueryService.queryResourceDataOperational('testCmHandle', + '/cps/path', + FetchDescendantsOption.OMIT_DESCENDANTS) + and: 'response status is Ok' + response.status == HttpStatus.OK.value() + } + + def 'Query Resource Data using datastore of #datastore'() { + given: 'the query resource data url' + def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:${datastore}/query" + + "?cps-path=/cps/path" + when: 'the query data resource request is performed' + def response = mvc.perform( + get(getUrl) + .contentType(MediaType.APPLICATION_JSON) + ).andReturn().response + then: 'a 400 BAD_REQUEST is returned for the unsupported datastore' + response.status == 400 + and: 'the error message is that datastore #datastore is not supported' + response.contentAsString.contains("ncmp-datastore:${datastore} is not supported") + where: 'the following datastore is used' + datastore << ["passthrough-running", "passthrough-operational"] + } + 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" + diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandlerFactorySpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandlerFactorySpec.groovy new file mode 100644 index 0000000000..7c504981e2 --- /dev/null +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandlerFactorySpec.groovy @@ -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.controller.handlers + +import spock.lang.Specification + +class NcmpDatastoreRequestHandlerFactorySpec extends Specification { + + def objectUnderTest = new NcmpDatastoreResourceRequestHandlerFactory(null, 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 + } +} 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 deleted file mode 100644 index 3f7a8a5ce2..0000000000 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreResourceRequestHandlerFactorySpec.groovy +++ /dev/null @@ -1,20 +0,0 @@ -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-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyQueryService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyQueryService.java new file mode 100644 index 0000000000..340806b892 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyQueryService.java @@ -0,0 +1,41 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.api; + +import org.onap.cps.spi.FetchDescendantsOption; + +/* + * Datastore interface for handling cached CPS data query requests. + */ +public interface NetworkCmProxyQueryService { + + /** + * Get resource data for operational. + * + * @param cmHandleId cm handle identifier + * @param cpsPath cps path + * @Link FetchDescendantsOption fetch descendants option + * @return {@code Object} resource data + */ + Object queryResourceDataOperational(String cmHandleId, + String cpsPath, + FetchDescendantsOption fetchDescendantsOption); +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java new file mode 100644 index 0000000000..5540ecd213 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java @@ -0,0 +1,46 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.api.impl; + +import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.api.CpsQueryService; +import org.onap.cps.ncmp.api.NetworkCmProxyQueryService; +import org.onap.cps.spi.FetchDescendantsOption; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class NetworkCmProxyQueryServiceImpl implements NetworkCmProxyQueryService { + + private final CpsQueryService cpsQueryService; + + @Override + public Object queryResourceDataOperational(final String cmHandleId, + final String cpsPath, + final FetchDescendantsOption fetchDescendantsOption) { + return cpsQueryService.queryDataNodes(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, cpsPath, + fetchDescendantsOption); + } +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImplSpec.groovy new file mode 100644 index 0000000000..1e86a0b80a --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImplSpec.groovy @@ -0,0 +1,46 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.api.impl + +import org.onap.cps.api.CpsQueryService +import org.onap.cps.spi.FetchDescendantsOption +import org.onap.cps.spi.model.DataNode +import spock.lang.Specification + +class NetworkCmProxyQueryServiceImplSpec extends Specification { + + def mockCpsQueryService = Mock(CpsQueryService) + + def objectUnderTest = new NetworkCmProxyQueryServiceImpl(mockCpsQueryService) + + def 'Query resource data for operational from DMI.'() { + given: 'a list of datanodes' + def dataNodes = [new DataNode(xpath: '/cps/path'), new DataNode(xpath: '/cps/path/child')] + and: 'the list of datanodes is returned for query data node' + 1 * mockCpsQueryService.queryDataNodes('NFP-Operational', 'ncmp-dmi-registry', + '//cps/path', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNodes + when: 'query resource data operational for cm-handle is called' + def response = objectUnderTest.queryResourceDataOperational('ncmp-dmi-registry', + '//cps/path', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) + then: 'the expected datanodes are returned from the DMI' + response == dataNodes + } +} diff --git a/docs/api/swagger/ncmp/openapi.yaml b/docs/api/swagger/ncmp/openapi.yaml index b9eee5603d..44c4788cfd 100644 --- a/docs/api/swagger/ncmp/openapi.yaml +++ b/docs/api/swagger/ncmp/openapi.yaml @@ -6,7 +6,7 @@ info: servers: - url: /ncmp paths: - /v1/ch/{cm-handle}/data/ds/{ncmp-datastore-name}: + /v1/ch/{cm-handle}/data/ds/{datastore-name}: get: tags: - network-cm-proxy @@ -14,7 +14,7 @@ paths: description: Get resource data for given cm handle operationId: getResourceDataForCmHandle parameters: - - name: ncmp-datastore-name + - name: datastore-name in: path description: The type of the requested data required: true @@ -154,7 +154,7 @@ paths: handle operationId: updateResourceDataRunningForCmHandle parameters: - - name: ncmp-datastore-name + - name: datastore-name in: path description: The type of the requested data required: true @@ -277,7 +277,7 @@ paths: description: create resource data from pass-through running for given cm handle operationId: createResourceDataRunningForCmHandle parameters: - - name: ncmp-datastore-name + - name: datastore-name in: path description: The type of the requested data required: true @@ -397,7 +397,7 @@ paths: description: Delete resource data from pass-through running for a given cm handle operationId: deleteResourceDataRunningForCmHandle parameters: - - name: ncmp-datastore-name + - name: datastore-name in: path description: The type of the requested data required: true @@ -513,7 +513,7 @@ paths: handle operationId: patchResourceDataRunningForCmHandle parameters: - - name: ncmp-datastore-name + - name: datastore-name in: path description: The type of the requested data required: true diff --git a/docs/release-notes.rst b/docs/release-notes.rst index 195f062237..b757f19d85 100755 --- a/docs/release-notes.rst +++ b/docs/release-notes.rst @@ -37,6 +37,7 @@ Release Data +--------------------------------------+--------------------------------------------------------+ Features -------- + - `CPS-1002 <https://jira.onap.org/browse/CPS-1002>`_ Query data NCMP-Operational with CPSpath - `CPS-1185 <https://jira.onap.org/browse/CPS-1185>`_ Get all dataspaces - `CPS-1186 <https://jira.onap.org/browse/CPS-1186>`_ Get all schema sets for a dataspace - `CPS-1187 <https://jira.onap.org/browse/CPS-1187>`_ Get single dataspace |