diff options
Diffstat (limited to 'cps-ncmp-rest')
13 files changed, 57 insertions, 709 deletions
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 5b54ac243e..58d6ce7108 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,6 +39,9 @@ import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.NetworkCmProxyDataService; +import org.onap.cps.ncmp.api.impl.NcmpCachedResourceRequestHandler; +import org.onap.cps.ncmp.api.impl.NcmpDatastoreRequestHandler; +import org.onap.cps.ncmp.api.impl.NcmpPassthroughResourceRequestHandler; import org.onap.cps.ncmp.api.impl.config.embeddedcache.TrustLevelCacheConfig; import org.onap.cps.ncmp.api.impl.exception.InvalidDatastoreException; import org.onap.cps.ncmp.api.impl.inventory.CompositeState; @@ -48,9 +51,6 @@ import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters; import org.onap.cps.ncmp.api.models.CmResourceAddress; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.onap.cps.ncmp.rest.api.NetworkCmProxyApi; -import org.onap.cps.ncmp.rest.controller.handlers.NcmpCachedResourceRequestHandler; -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.DataOperationRequestMapper; import org.onap.cps.ncmp.rest.model.CmHandlePublicProperties; @@ -62,6 +62,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.spi.model.DataNode; import org.onap.cps.spi.model.ModuleDefinition; import org.onap.cps.utils.JsonObjectMapper; import org.springframework.beans.factory.annotation.Qualifier; @@ -112,16 +113,18 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { final String authorization) { final NcmpDatastoreRequestHandler ncmpDatastoreRequestHandler = getNcmpDatastoreRequestHandler(datastoreName); final CmResourceAddress cmResourceAddress = new CmResourceAddress(datastoreName, cmHandle, resourceIdentifier); - return ncmpDatastoreRequestHandler.executeRequest(cmResourceAddress, optionsParamInQuery, topicParamInQuery, - includeDescendants, authorization); + final Object result = ncmpDatastoreRequestHandler.executeRequest(cmResourceAddress, optionsParamInQuery, + topicParamInQuery, includeDescendants, authorization); + return ResponseEntity.ok(result); } @Override public ResponseEntity<Object> executeDataOperationForCmHandles(final String topicParamInQuery, final DataOperationRequest dataOperationRequest, final String authorization) { - return ncmpPassthroughResourceRequestHandler.executeRequest(topicParamInQuery, + final Object result = ncmpPassthroughResourceRequestHandler.executeRequest(topicParamInQuery, dataOperationRequestMapper.toDataOperationRequest(dataOperationRequest), authorization); + return ResponseEntity.ok(result); } /** @@ -133,7 +136,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { * @param optionsParamInQuery options query parameter * @param topicParamInQuery topic query parameter * @param includeDescendants whether to include descendants or not - * @return {@code ResponseEntity} response from dmi plugin + * @return {@code ResponseEntity} response. Body contains a collection of DataNodes */ @Override @@ -144,7 +147,9 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { final String topicParamInQuery, final Boolean includeDescendants) { validateDataStore(OPERATIONAL, datastoreName); - return ncmpCachedResourceRequestHandler.executeRequest(cmHandle, cpsPath, includeDescendants); + final Collection<DataNode> dataNodes = ncmpCachedResourceRequestHandler.executeRequest(cmHandle, cpsPath, + includeDescendants); + return ResponseEntity.ok(dataNodes); } /** diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpCachedResourceRequestHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpCachedResourceRequestHandler.java deleted file mode 100644 index 80e1c442e9..0000000000 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpCachedResourceRequestHandler.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 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.Collection; -import org.onap.cps.ncmp.api.NetworkCmProxyDataService; -import org.onap.cps.ncmp.api.NetworkCmProxyQueryService; -import org.onap.cps.ncmp.api.models.CmResourceAddress; -import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.model.DataNode; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Component; -import reactor.core.publisher.Mono; - -@Component -public class NcmpCachedResourceRequestHandler extends NcmpDatastoreRequestHandler { - - private final NetworkCmProxyDataService networkCmProxyDataService; - private final NetworkCmProxyQueryService networkCmProxyQueryService; - - /** - * Constructor. - * - * @param networkCmProxyDataService @see org.onap.cps.ncmp.api.NetworkCmProxyDataService - * @param networkCmProxyQueryService @see org.onap.cps.ncmp.api.NetworkCmProxyQueryService - */ - public NcmpCachedResourceRequestHandler(final NetworkCmProxyDataService networkCmProxyDataService, - final NetworkCmProxyQueryService networkCmProxyQueryService) { - this.networkCmProxyDataService = networkCmProxyDataService; - this.networkCmProxyQueryService = networkCmProxyQueryService; - } - - /** - * Executes a synchronous query request for given cm handle. - * Note. Currently only ncmp-datastore:operational supports query operations. - * - * @param cmHandleId the cm handle - * @param resourceIdentifier the resource identifier - * @param includeDescendants whether include descendants - * @return the response entity - */ - public ResponseEntity<Object> executeRequest(final String cmHandleId, final String resourceIdentifier, - final boolean includeDescendants) { - final Collection<DataNode> dataNodes = getTaskSupplierForQueryRequest(cmHandleId, resourceIdentifier, - includeDescendants); - return ResponseEntity.ok(dataNodes); - } - - @Override - protected Mono<Object> getResourceDataForCmHandle(final CmResourceAddress cmResourceAddress, - final String optionsParamInQuery, - final String topicParamInQuery, - final String requestId, - final boolean includeDescendants, - final String authorization) { - final FetchDescendantsOption fetchDescendantsOption = getFetchDescendantsOption(includeDescendants); - return Mono.fromSupplier( - () -> networkCmProxyDataService.getResourceDataForCmHandle(cmResourceAddress, fetchDescendantsOption)); - } - - private Collection<DataNode> getTaskSupplierForQueryRequest(final String cmHandleId, - final String resourceIdentifier, - final boolean includeDescendants) { - final FetchDescendantsOption fetchDescendantsOption = getFetchDescendantsOption(includeDescendants); - return networkCmProxyQueryService.queryResourceDataOperational(cmHandleId, resourceIdentifier, - fetchDescendantsOption); - } - - private static FetchDescendantsOption getFetchDescendantsOption(final boolean includeDescendants) { - return includeDescendants ? FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS - : FetchDescendantsOption.OMIT_DESCENDANTS; - } -} 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 deleted file mode 100644 index 20059e20f4..0000000000 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandler.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 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 lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.models.CmResourceAddress; -import org.onap.cps.ncmp.rest.util.TopicValidator; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Service; -import reactor.core.publisher.Mono; - -@Slf4j -@Service -@RequiredArgsConstructor -public abstract class NcmpDatastoreRequestHandler { - - private static final String NO_REQUEST_ID = null; - private static final String NO_TOPIC = null; - - @Value("${notification.async.executor.time-out-value-in-ms:60000}") - protected int timeOutInMilliSeconds; - @Value("${notification.enabled:true}") - protected boolean notificationFeatureEnabled; - - /** - * Executes synchronous/asynchronous get request for given cm handle. - * - * @param cmResourceAddress the name of the datastore, cm handle and resource identifier - * @param optionsParamInQuery the options param in query - * @param topicParamInQuery the topic param in query - * @param includeDescendants whether include descendants - * @param authorization contents of Authorization header, or null if not present - * @return the response entity - */ - public ResponseEntity<Object> executeRequest(final CmResourceAddress cmResourceAddress, - final String optionsParamInQuery, - final String topicParamInQuery, - final boolean includeDescendants, - final String authorization) { - - final boolean asyncResponseRequested = topicParamInQuery != null; - if (asyncResponseRequested && notificationFeatureEnabled) { - return fetchResourceDataAsynchronously(cmResourceAddress, optionsParamInQuery, topicParamInQuery, - includeDescendants, authorization); - } - - if (asyncResponseRequested) { - log.warn("Asynchronous request is unavailable as notification feature is currently disabled, " - + "will use synchronous operation."); - } - final Mono<Object> resourceDataMono = getResourceDataForCmHandle(cmResourceAddress, optionsParamInQuery, - NO_TOPIC, NO_REQUEST_ID, includeDescendants, authorization); - return fetchResourceDataSynchronously(resourceDataMono); - } - - private ResponseEntity<Object> fetchResourceDataSynchronously(final Mono<Object> resourceDataMono) { - return ResponseEntity.ok(resourceDataMono.block()); - } - - private ResponseEntity<Object> fetchResourceDataAsynchronously(final CmResourceAddress cmResourceAddress, - final String optionsParamInQuery, - final String topicParamInQuery, - final boolean includeDescendants, - final String authorization) { - TopicValidator.validateTopicName(topicParamInQuery); - final String requestId = UUID.randomUUID().toString(); - getResourceDataForCmHandle(cmResourceAddress, optionsParamInQuery, topicParamInQuery, requestId, - includeDescendants, authorization) - .doOnSuccess(result -> log.debug("Async operation succeeded for request id {}: {}", requestId, result)) - .doOnError(error -> - log.error("Async operation failed for request id {}: {}", requestId, error.getMessage())) - .subscribe(); - log.debug("Received Async request with id {}", requestId); - return ResponseEntity.ok(Map.of("requestId", requestId)); - } - - protected abstract Mono<Object> getResourceDataForCmHandle(final CmResourceAddress cmResourceAddress, - final String optionsParamInQuery, - final String topicParamInQuery, - final String requestId, - final boolean includeDescendant, - final String authorization); -} 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 deleted file mode 100644 index 53e374d30a..0000000000 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpPassthroughResourceRequestHandler.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 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 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 org.onap.cps.ncmp.api.NetworkCmProxyDataService; -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.CmResourceAddress; -import org.onap.cps.ncmp.api.models.DataOperationRequest; -import org.onap.cps.ncmp.rest.exceptions.OperationNotSupportedException; -import org.onap.cps.ncmp.rest.exceptions.PayloadTooLargeException; -import org.onap.cps.ncmp.rest.util.TopicValidator; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Service; -import reactor.core.publisher.Mono; - -@Service -public class NcmpPassthroughResourceRequestHandler extends NcmpDatastoreRequestHandler { - - private final NetworkCmProxyDataService networkCmProxyDataService; - private static final int MAXIMUM_CM_HANDLES_PER_OPERATION = 200; - private static final String PAYLOAD_TOO_LARGE_TEMPLATE = "Operation '%s' affects too many (%d) cm handles"; - - /** - * Constructor. - * - * @param networkCmProxyDataService @see org.onap.cps.ncmp.api.NetworkCmProxyDataService - */ - public NcmpPassthroughResourceRequestHandler(final NetworkCmProxyDataService networkCmProxyDataService) { - this.networkCmProxyDataService = networkCmProxyDataService; - } - - /** - * Executes asynchronous request for group of cm handles to resource data. - * - * @param topicParamInQuery the topic param in query - * @param dataOperationRequest data operation request details for resource data - * @param authorization contents of Authorization header, or null if not present - * @return the response entity - */ - public ResponseEntity<Object> executeRequest(final String topicParamInQuery, - final DataOperationRequest dataOperationRequest, - final String authorization) { - validateDataOperationRequest(topicParamInQuery, dataOperationRequest); - if (!notificationFeatureEnabled) { - return ResponseEntity.ok(Map.of("status", - "Asynchronous request is unavailable as notification feature is currently disabled.")); - } - return getRequestIdAndSendDataOperationRequestToDmiService(topicParamInQuery, dataOperationRequest, - authorization); - } - - @Override - protected Mono<Object> getResourceDataForCmHandle(final CmResourceAddress cmResourceAddress, - final String optionsParamInQuery, - final String topicParamInQuery, - final String requestId, - final boolean includeDescendants, - final String authorization) { - return networkCmProxyDataService.getResourceDataForCmHandle(cmResourceAddress, optionsParamInQuery, - topicParamInQuery, requestId, authorization); - } - - private ResponseEntity<Object> getRequestIdAndSendDataOperationRequestToDmiService( - final String topicParamInQuery, - final DataOperationRequest dataOperationRequest, - final String authorization) { - final String requestId = UUID.randomUUID().toString(); - networkCmProxyDataService.executeDataOperationForCmHandles(topicParamInQuery, dataOperationRequest, requestId, - authorization); - return ResponseEntity.ok(Map.of("requestId", requestId)); - } - - private void validateDataOperationRequest(final String topicParamInQuery, - final DataOperationRequest dataOperationRequest) { - TopicValidator.validateTopicName(topicParamInQuery); - dataOperationRequest.getDataOperationDefinitions().forEach(dataOperationDetail -> { - if (OperationType.fromOperationName(dataOperationDetail.getOperation()) != READ) { - throw new OperationNotSupportedException( - dataOperationDetail.getOperation() + " operation not yet supported"); - } - if (DatastoreType.fromDatastoreName(dataOperationDetail.getDatastore()) == OPERATIONAL) { - throw new InvalidDatastoreException(dataOperationDetail.getDatastore() - + " datastore is not supported"); - } - if (dataOperationDetail.getCmHandleIds().size() > MAXIMUM_CM_HANDLES_PER_OPERATION) { - final String errorMessage = String.format(PAYLOAD_TOO_LARGE_TEMPLATE, - dataOperationDetail.getOperationId(), - dataOperationDetail.getCmHandleIds().size()); - throw new PayloadTooLargeException(errorMessage); - } - }); - } -} 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 deleted file mode 100644 index 6a52d5861e..0000000000 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/InvalidTopicException.java +++ /dev/null @@ -1,40 +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.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 7263000896..ba39178c7b 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 @@ -29,6 +29,9 @@ import org.onap.cps.ncmp.api.impl.exception.InvalidDatastoreException; import org.onap.cps.ncmp.api.impl.exception.InvalidDmiResourceUrlException; import org.onap.cps.ncmp.api.impl.exception.NcmpException; import org.onap.cps.ncmp.api.impl.exception.ServerNcmpException; +import org.onap.cps.ncmp.exceptions.InvalidTopicException; +import org.onap.cps.ncmp.exceptions.OperationNotSupportedException; +import org.onap.cps.ncmp.exceptions.PayloadTooLargeException; import org.onap.cps.ncmp.rest.controller.NetworkCmProxyController; import org.onap.cps.ncmp.rest.controller.NetworkCmProxyInventoryController; import org.onap.cps.ncmp.rest.model.DmiErrorMessage; 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 deleted file mode 100644 index e1daf3df6f..0000000000 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/OperationNotSupportedException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * ============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/exceptions/PayloadTooLargeException.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/PayloadTooLargeException.java deleted file mode 100644 index cddbd08379..0000000000 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/PayloadTooLargeException.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2024 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 PayloadTooLargeException extends RuntimeException { - - /** - * Instantiates a new payload too large exception. - */ - public PayloadTooLargeException(final String message) { - super(message); - } -} 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 deleted file mode 100644 index 6a46fbd638..0000000000 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/util/TopicValidator.java +++ /dev/null @@ -1,47 +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.util; - -import java.util.regex.Pattern; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.onap.cps.ncmp.rest.exceptions.InvalidTopicException; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -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 3a5748f002..34b9dbe950 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,42 +23,26 @@ package org.onap.cps.ncmp.rest.controller -import static org.onap.cps.ncmp.api.impl.inventory.CompositeState.DataStores -import static org.onap.cps.ncmp.api.impl.inventory.CompositeState.Operational -import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.OPERATIONAL -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.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 static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS -import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS -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 ch.qos.logback.classic.Level import ch.qos.logback.classic.Logger import ch.qos.logback.classic.spi.ILoggingEvent import ch.qos.logback.core.read.ListAppender import com.fasterxml.jackson.databind.ObjectMapper +import groovy.json.JsonSlurper import org.mapstruct.factory.Mappers import org.onap.cps.TestUtils import org.onap.cps.events.EventsPublisher import org.onap.cps.ncmp.api.NetworkCmProxyDataService import org.onap.cps.ncmp.api.NetworkCmProxyQueryService +import org.onap.cps.ncmp.api.impl.NcmpCachedResourceRequestHandler +import org.onap.cps.ncmp.api.impl.NcmpPassthroughResourceRequestHandler import org.onap.cps.ncmp.api.impl.inventory.CmHandleState import org.onap.cps.ncmp.api.impl.inventory.CompositeState import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel -import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle import org.onap.cps.ncmp.api.models.CmResourceAddress -import org.onap.cps.ncmp.rest.controller.handlers.NcmpCachedResourceRequestHandler -import org.onap.cps.ncmp.rest.controller.handlers.NcmpPassthroughResourceRequestHandler +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper import org.onap.cps.ncmp.rest.mapper.DataOperationRequestMapper import org.onap.cps.ncmp.rest.model.DataOperationDefinition @@ -75,15 +59,32 @@ 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.http.ResponseEntity import org.springframework.test.web.servlet.MockMvc +import reactor.core.publisher.Mono import spock.lang.Shared import spock.lang.Specification + import java.time.OffsetDateTime import java.time.ZoneOffset import java.time.format.DateTimeFormatter -import groovy.json.JsonSlurper -import org.springframework.http.ResponseEntity -import reactor.core.publisher.Mono + +import static org.onap.cps.ncmp.api.impl.inventory.CompositeState.DataStores +import static org.onap.cps.ncmp.api.impl.inventory.CompositeState.Operational +import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.OPERATIONAL +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.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 static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS +import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS +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 @WebMvcTest(NetworkCmProxyController) class NetworkCmProxyControllerSpec extends Specification { diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandlerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandlerSpec.groovy deleted file mode 100644 index 00b0cb04c5..0000000000 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandlerSpec.groovy +++ /dev/null @@ -1,152 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 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 org.onap.cps.ncmp.api.NetworkCmProxyDataService -import org.onap.cps.ncmp.api.impl.exception.InvalidDatastoreException -import org.onap.cps.ncmp.api.impl.exception.InvalidOperationException -import org.onap.cps.ncmp.api.models.DataOperationDefinition -import org.onap.cps.ncmp.api.models.DataOperationRequest -import org.onap.cps.ncmp.api.models.CmResourceAddress -import org.onap.cps.ncmp.rest.exceptions.OperationNotSupportedException -import org.onap.cps.ncmp.rest.exceptions.PayloadTooLargeException -import org.springframework.http.HttpStatus -import reactor.core.publisher.Mono -import spock.lang.Specification -import spock.util.concurrent.PollingConditions - -class NcmpDatastoreRequestHandlerSpec extends Specification { - - def mockNetworkCmProxyDataService = Mock(NetworkCmProxyDataService) - - def objectUnderTest = new NcmpPassthroughResourceRequestHandler(mockNetworkCmProxyDataService) - - def NO_AUTH_HEADER = null - - def setup() { - objectUnderTest.timeOutInMilliSeconds = 100 - } - - def 'Attempt to execute async get request with #scenario.'() { - given: 'notification feature is turned on/off' - objectUnderTest.notificationFeatureEnabled = notificationFeatureEnabled - and: 'a CM resource address' - def cmResourceAddress = new CmResourceAddress('ds', 'ch1', 'resource1') - and: 'the (mocked) service is called with the correct parameters returns OK' - 1 * mockNetworkCmProxyDataService.getResourceDataForCmHandle(cmResourceAddress, 'options', _, _, NO_AUTH_HEADER) >> Mono.just(HttpStatus.OK) - when: 'get request is executed with topic = #topic' - def response= objectUnderTest.executeRequest(cmResourceAddress, 'options', topic, false, NO_AUTH_HEADER) - then: 'a successful response with/without request id is returned' - assert response.statusCode.value == 200 - assert response.body instanceof Map == expectedResponseBodyIsMap - where: 'the following parameters are used' - scenario | notificationFeatureEnabled | topic || expectedCalls | expectedResponseBodyIsMap - 'feature on, valid topic' | true | 'valid' || 1 | true - 'feature on, no topic' | true | null || 0 | false - 'feature off, valid topic' | false | 'valid' || 0 | false - 'feature off, no topic' | false | null || 0 | false - } - - def 'Attempt to execute async data operation request with feature #scenario.'() { - given: 'a extended request handler that supports bulk requests' - def objectUnderTest = new NcmpPassthroughResourceRequestHandler(mockNetworkCmProxyDataService) - and: 'notification feature is turned on/off' - objectUnderTest.notificationFeatureEnabled = notificationFeatureEnabled - when: 'data operation request is executed' - objectUnderTest.executeRequest('someTopic', new DataOperationRequest(), NO_AUTH_HEADER) - then: 'the task is executed in an async fashion or not' - expectedCalls * mockNetworkCmProxyDataService.executeDataOperationForCmHandles('someTopic', _, _, null) - where: 'the following parameters are used' - scenario | notificationFeatureEnabled || expectedCalls - 'on' | true || 1 - 'off' | false || 0 - } - - def 'Execute async data operation request with datastore #datastore.'() { - given: 'notification feature is turned on' - objectUnderTest.notificationFeatureEnabled = true - and: 'a data operation request with datastore: #datastore' - def dataOperationDefinition = new DataOperationDefinition(operation: 'read', datastore: datastore) - def dataOperationRequest = new DataOperationRequest(dataOperationDefinitions: [dataOperationDefinition]) - and: ' a flag to track the network service call' - def networkServiceMethodCalled = false - and: 'the (mocked) service will use the flag to indicate it is called' - mockNetworkCmProxyDataService.executeDataOperationForCmHandles('myTopic', dataOperationRequest, _, NO_AUTH_HEADER) >> { - networkServiceMethodCalled = true - } - when: 'data operation request is executed' - def response = objectUnderTest.executeRequest('myTopic', dataOperationRequest, NO_AUTH_HEADER) - and: 'a successful response with request id is returned' - assert response.statusCode.value == 200 - assert response.body.requestId != null - then: 'the network service is invoked' - new PollingConditions().within(1) { - assert networkServiceMethodCalled == true - } - where: 'the following datastores are used' - datastore << ['ncmp-datastore:passthrough-running', 'ncmp-datastore:passthrough-operational'] - } - - def 'Attempt to execute async data operation request with error #scenario'() { - given: 'a data operation definition with datastore: #datastore' - def dataOperationDefinition = new DataOperationDefinition(operation: 'read', datastore: datastore) - when: 'data operation request is executed' - def dataOperationRequest = new DataOperationRequest(dataOperationDefinitions: [dataOperationDefinition]) - objectUnderTest.executeRequest('myTopic', dataOperationRequest, NO_AUTH_HEADER) - then: 'the correct error is thrown' - def thrown = thrown(InvalidDatastoreException) - assert thrown.message.contains(expectedErrorMessage) - where: 'the following datastore names are used' - scenario | datastore || expectedErrorMessage - 'unsupported datastore' | 'ncmp-datastore:operational' || 'not supported' - 'invalid datastore' | 'invalid' || 'invalid datastore name' - } - - def 'Attempt to execute async data operation request with #scenario operation: #operation.'() { - given: 'a data operation definition with operation: #operation' - def dataOperationDefinition = new DataOperationDefinition(operation: operation, datastore: 'ncmp-datastore:passthrough-running') - when: 'data operation request is executed' - objectUnderTest.executeRequest('someTopic', new DataOperationRequest(dataOperationDefinitions:[dataOperationDefinition]), NO_AUTH_HEADER) - then: 'the expected type of exception is thrown' - thrown(expectedException) - where: 'the following operations are used' - scenario | operation || expectedException - 'invalid' | 'invalid' || InvalidOperationException - 'unsupported' | 'create' || OperationNotSupportedException - 'unsupported' | 'update' || OperationNotSupportedException - 'unsupported' | 'patch' || OperationNotSupportedException - 'unsupported' | 'delete' || OperationNotSupportedException - } - - def 'Attempt to execute async data operation request with too many cm handles.'() { - given: 'a data operation definition with too many cm handles' - def tooMany = objectUnderTest.MAXIMUM_CM_HANDLES_PER_OPERATION+1 - def cmHandleIds = new String[tooMany] - def dataOperationDefinition = new DataOperationDefinition(operationId: 'abc', operation: 'read', datastore: 'ncmp-datastore:passthrough-running', cmHandleIds: cmHandleIds) - when: 'data operation request is executed' - objectUnderTest.executeRequest('someTopic', new DataOperationRequest(dataOperationDefinitions:[dataOperationDefinition]), NO_AUTH_HEADER) - then: 'a payload too large exception is thrown' - def exceptionThrown = thrown(PayloadTooLargeException) - and: 'the error message contains the offending number of cm handles' - assert exceptionThrown.message == "Operation 'abc' affects too many (${tooMany}) cm handles" - } - -} 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 33eb48ffa2..af8a8ea12a 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 @@ -21,28 +21,17 @@ package org.onap.cps.ncmp.rest.exceptions -import static org.springframework.http.HttpStatus.BAD_GATEWAY -import static org.springframework.http.HttpStatus.BAD_REQUEST -import static org.springframework.http.HttpStatus.CONFLICT -import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR -import static org.springframework.http.HttpStatus.NOT_FOUND -import static org.springframework.http.HttpStatus.PAYLOAD_TOO_LARGE -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.test.web.servlet.request.MockMvcRequestBuilders.get -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post -import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNABLE_TO_READ_RESOURCE_DATA - import groovy.json.JsonSlurper import org.mapstruct.factory.Mappers import org.onap.cps.TestUtils import org.onap.cps.ncmp.api.NetworkCmProxyDataService -import org.onap.cps.ncmp.api.impl.exception.DmiRequestException +import org.onap.cps.ncmp.api.impl.NcmpCachedResourceRequestHandler +import org.onap.cps.ncmp.api.impl.NcmpPassthroughResourceRequestHandler import org.onap.cps.ncmp.api.impl.exception.DmiClientRequestException +import org.onap.cps.ncmp.api.impl.exception.DmiRequestException import org.onap.cps.ncmp.api.impl.exception.ServerNcmpException +import org.onap.cps.ncmp.exceptions.PayloadTooLargeException import org.onap.cps.ncmp.rest.controller.NcmpRestInputMapper -import org.onap.cps.ncmp.rest.controller.handlers.NcmpCachedResourceRequestHandler -import org.onap.cps.ncmp.rest.controller.handlers.NcmpPassthroughResourceRequestHandler import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper import org.onap.cps.ncmp.rest.mapper.DataOperationRequestMapper import org.onap.cps.ncmp.rest.util.DeprecationHelper @@ -60,6 +49,18 @@ import org.springframework.test.web.servlet.MockMvc import spock.lang.Shared import spock.lang.Specification +import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNABLE_TO_READ_RESOURCE_DATA +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_GATEWAY +import static org.springframework.http.HttpStatus.BAD_REQUEST +import static org.springframework.http.HttpStatus.CONFLICT +import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR +import static org.springframework.http.HttpStatus.NOT_FOUND +import static org.springframework.http.HttpStatus.PAYLOAD_TOO_LARGE +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post + @WebMvcTest class NetworkCmProxyRestExceptionHandlerSpec extends Specification { @@ -125,7 +126,7 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification { 'Data Node Not Found' | new DataNodeNotFoundException('myDataspaceName', 'myAnchorName') || NOT_FOUND | 'DataNode not found' | 'DataNode not found' 'Existing entry' | new AlreadyDefinedException('name',null) || CONFLICT | 'Already defined exception' | 'name already exists' 'Existing entries' | AlreadyDefinedException.forDataNodes(['A', 'B'], 'myAnchorName') || CONFLICT | 'Already defined exception' | '2 data node(s) already exist' - 'Operation too large' | new PayloadTooLargeException(sampleErrorMessage) || PAYLOAD_TOO_LARGE | sampleErrorMessage | 'Check logs' + 'Operation too large' | new PayloadTooLargeException(sampleErrorMessage) || PAYLOAD_TOO_LARGE | sampleErrorMessage | 'Check logs' } def 'Post request with exception returns correct HTTP Status.'() { 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 deleted file mode 100644 index 15e2c1c6a0..0000000000 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/util/TopicValidatorSpec.groovy +++ /dev/null @@ -1,46 +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.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_*_#' - } -} |