From 735cc72cdf706de32e4b55848da1d5242ba1be26 Mon Sep 17 00:00:00 2001 From: ToineSiebelink Date: Tue, 9 Jul 2024 12:41:59 +0100 Subject: Refactor remaining classes package structure -Introduced org.onap.cps.ncmp.config for all config type classes like http, kafka etc. -Introduced org.onap.cps.ncmp.impl.dmi for dmi specif classes like DmiRestClient etc. -Moved most exception classes to org.onap.cps.ncmp.api.exceptions (only two were 'internal' i.e. NOT used in REST so left in org.onap.cps.ncmp.exceptions) -Deleted unused DateNodeHelper class (and related testware) -Moved some classes to org.onap.cps.ncmp.impl.utils -Moved messaging test base classes to org.onap.cps.ncmp.impl.utils.events -All imports were reorganised automatically by IntelliJ -did NOT update any copyright dates (seems incorrect to me anyway) Issue-ID: CPS-2257 Change-Id: Ie28b1777ea278064b46c6a1c3a28f4d0696565e2 Signed-off-by: ToineSiebelink --- .../api/exceptions/DmiClientRequestException.java | 54 ++++++ .../ncmp/api/exceptions/DmiRequestException.java | 37 ++++ .../ncmp/api/exceptions/InvalidTopicException.java | 40 +++++ .../cps/ncmp/api/exceptions/NcmpException.java | 47 +++++ .../api/exceptions/PayloadTooLargeException.java | 31 ++++ .../ncmp/api/exceptions/ServerNcmpException.java | 37 ++++ .../cps/ncmp/api/impl/client/DmiRestClient.java | 188 ------------------- .../cps/ncmp/api/impl/config/DmiProperties.java | 55 ------ .../api/impl/config/DmiWebClientConfiguration.java | 121 ------------- .../api/impl/config/HttpClientConfiguration.java | 72 -------- .../ncmp/api/impl/config/OpenTelemetryConfig.java | 111 ------------ .../ncmp/api/impl/config/kafka/KafkaConfig.java | 198 --------------------- .../impl/exception/DmiClientRequestException.java | 54 ------ .../api/impl/exception/DmiRequestException.java | 37 ---- .../cps/ncmp/api/impl/exception/NcmpException.java | 47 ----- .../api/impl/exception/NcmpStartUpException.java | 37 ---- .../api/impl/exception/ServerNcmpException.java | 37 ---- .../cps/ncmp/api/impl/utils/DataNodeHelper.java | 100 ----------- .../api/impl/utils/DmiServiceNameOrganizer.java | 64 ------- .../api/impl/utils/EventDateTimeFormatter.java | 47 ----- .../impl/utils/context/CpsApplicationContext.java | 51 ------ .../url/builder/DmiServiceUrlTemplateBuilder.java | 137 -------------- .../utils/url/builder/UrlTemplateParameters.java | 30 ---- .../inventory/models/DmiPluginRegistration.java | 4 +- .../cps/ncmp/config/CpsApplicationContext.java | 51 ++++++ .../cps/ncmp/config/HttpClientConfiguration.java | 72 ++++++++ .../java/org/onap/cps/ncmp/config/KafkaConfig.java | 198 +++++++++++++++++++++ .../onap/cps/ncmp/config/OpenTelemetryConfig.java | 111 ++++++++++++ .../cps/ncmp/exceptions/InvalidTopicException.java | 40 ----- .../cps/ncmp/exceptions/NcmpStartUpException.java | 39 ++++ .../NoAlternateIdMatchFoundException.java | 2 +- .../ncmp/exceptions/PayloadTooLargeException.java | 31 ---- .../onap/cps/ncmp/impl/data/DmiDataOperations.java | 10 +- .../NcmpPassthroughResourceRequestHandler.java | 2 +- .../impl/data/utils/DmiDataOperationsHelper.java | 4 +- .../impl/datajobs/DmiSubJobRequestHandler.java | 8 +- .../org/onap/cps/ncmp/impl/dmi/DmiProperties.java | 55 ++++++ .../org/onap/cps/ncmp/impl/dmi/DmiRestClient.java | 186 +++++++++++++++++++ .../cps/ncmp/impl/dmi/DmiServiceNameOrganizer.java | 64 +++++++ .../impl/dmi/DmiServiceUrlTemplateBuilder.java | 137 ++++++++++++++ .../ncmp/impl/dmi/DmiWebClientConfiguration.java | 122 +++++++++++++ .../cps/ncmp/impl/dmi/UrlTemplateParameters.java | 30 ++++ .../impl/inventory/sync/DmiModelOperations.java | 8 +- .../impl/inventory/sync/lcm/LcmEventsCreator.java | 2 +- .../trustlevel/DmiPluginTrustLevelWatchDog.java | 6 +- .../ncmp/impl/utils/EventDateTimeFormatter.java | 47 +++++ .../onap/cps/ncmp/init/AbstractModelLoader.java | 2 +- .../ncmp/init/CmDataSubscriptionModelLoader.java | 2 +- .../org/onap/cps/ncmp/utils/events/NcmpEvent.java | 4 +- .../onap/cps/ncmp/utils/events/TopicValidator.java | 2 +- 50 files changed, 1386 insertions(+), 1485 deletions(-) create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/DmiClientRequestException.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/DmiRequestException.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/InvalidTopicException.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/NcmpException.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/PayloadTooLargeException.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/ServerNcmpException.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiProperties.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfiguration.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/HttpClientConfiguration.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/OpenTelemetryConfig.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/kafka/KafkaConfig.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/DmiClientRequestException.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/DmiRequestException.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NcmpException.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NcmpStartUpException.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/ServerNcmpException.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DataNodeHelper.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceNameOrganizer.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/EventDateTimeFormatter.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/context/CpsApplicationContext.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/url/builder/DmiServiceUrlTemplateBuilder.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/url/builder/UrlTemplateParameters.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/CpsApplicationContext.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/HttpClientConfiguration.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/KafkaConfig.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/OpenTelemetryConfig.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/InvalidTopicException.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/NcmpStartUpException.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/PayloadTooLargeException.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiProperties.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceNameOrganizer.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilder.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiWebClientConfiguration.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/UrlTemplateParameters.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/EventDateTimeFormatter.java (limited to 'cps-ncmp-service/src/main/java/org/onap') diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/DmiClientRequestException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/DmiClientRequestException.java new file mode 100644 index 0000000000..65ccba8018 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/DmiClientRequestException.java @@ -0,0 +1,54 @@ +/* + * ============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.api.exceptions; + +import lombok.Getter; +import org.onap.cps.ncmp.api.NcmpResponseStatus; + +/** + * Http Client Request exception from dmi service. + */ +@Getter +public class DmiClientRequestException extends NcmpException { + + private static final long serialVersionUID = 6659897770659834797L; + final NcmpResponseStatus ncmpResponseStatus; + final String message; + final String responseBodyAsString; + final int httpStatusCode; + + /** + * Constructor to form exception for dmi service response. + * + * @param httpStatusCode http response code from the client + * @param message response message from the client + * @param responseBodyAsString response body from the client + * @param ncmpResponseStatus ncmp status message and code + */ + public DmiClientRequestException(final int httpStatusCode, final String message, final String responseBodyAsString, + final NcmpResponseStatus ncmpResponseStatus) { + super(message, responseBodyAsString); + this.httpStatusCode = httpStatusCode; + this.message = message; + this.responseBodyAsString = responseBodyAsString; + this.ncmpResponseStatus = ncmpResponseStatus; + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/DmiRequestException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/DmiRequestException.java new file mode 100644 index 0000000000..b2cfbc01be --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/DmiRequestException.java @@ -0,0 +1,37 @@ +/* + * ============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.exceptions; + +/** + * Client Based Network CM Proxy exception. + */ +public class DmiRequestException extends NcmpException { + + /** + * Constructor. + * + * @param message the error message + * @param details the error details + */ + public DmiRequestException(final String message, final String details) { + super(message, details); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/InvalidTopicException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/InvalidTopicException.java new file mode 100644 index 0000000000..07b186dae4 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/InvalidTopicException.java @@ -0,0 +1,40 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.api.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-service/src/main/java/org/onap/cps/ncmp/api/exceptions/NcmpException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/NcmpException.java new file mode 100644 index 0000000000..6754965866 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/NcmpException.java @@ -0,0 +1,47 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.exceptions; + +import lombok.Getter; + +/** + * Network CM Proxy exception. + */ +public class NcmpException extends RuntimeException { + + private static final long serialVersionUID = 1482619410918497467L; + + @Getter + final String details; + + /** + * Constructor. + * + * @param message the error message + * @param details the error details + */ + public NcmpException(final String message, final String details) { + super(message); + this.details = details; + } + +} + diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/PayloadTooLargeException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/PayloadTooLargeException.java new file mode 100644 index 0000000000..edb295dbbf --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/PayloadTooLargeException.java @@ -0,0 +1,31 @@ +/* + * ============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.api.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-service/src/main/java/org/onap/cps/ncmp/api/exceptions/ServerNcmpException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/ServerNcmpException.java new file mode 100644 index 0000000000..03dc3bc8dd --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/ServerNcmpException.java @@ -0,0 +1,37 @@ +/* + * ============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.exceptions; + +/** + * Server Based Network CM Proxy exception. + */ +public class ServerNcmpException extends NcmpException { + + /** + * Constructor. + * + * @param message the error message + * @param details the error details + */ + public ServerNcmpException(final String message, final String details) { + super(message, details); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java deleted file mode 100644 index ac7728da92..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021-2024 Nordix Foundation - * Modifications Copyright (C) 2022 Bell Canada - * ================================================================================ - * 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.client; - -import static org.onap.cps.ncmp.api.NcmpResponseStatus.DMI_SERVICE_NOT_RESPONDING; -import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNABLE_TO_READ_RESOURCE_DATA; -import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR; -import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; -import static org.springframework.http.HttpStatus.REQUEST_TIMEOUT; - -import com.fasterxml.jackson.databind.JsonNode; -import java.util.Locale; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.data.models.OperationType; -import org.onap.cps.ncmp.api.impl.config.DmiProperties; -import org.onap.cps.ncmp.api.impl.exception.DmiClientRequestException; -import org.onap.cps.ncmp.api.impl.utils.url.builder.UrlTemplateParameters; -import org.onap.cps.ncmp.impl.models.RequiredDmiService; -import org.onap.cps.utils.JsonObjectMapper; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Component; -import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.reactive.function.BodyInserters; -import org.springframework.web.reactive.function.client.WebClient; -import org.springframework.web.reactive.function.client.WebClientRequestException; -import org.springframework.web.reactive.function.client.WebClientResponseException; -import reactor.core.publisher.Mono; - -@Component -@RequiredArgsConstructor -@Slf4j -public class DmiRestClient { - - private static final String NOT_SPECIFIED = ""; - private static final String NO_AUTHORIZATION = null; - - private final DmiProperties dmiProperties; - private final JsonObjectMapper jsonObjectMapper; - @Qualifier("dataServicesWebClient") - private final WebClient dataServicesWebClient; - @Qualifier("modelServicesWebClient") - private final WebClient modelServicesWebClient; - @Qualifier("healthChecksWebClient") - private final WebClient healthChecksWebClient; - - /** - * Sends a synchronous (blocking) POST operation to the DMI with a JSON body containing module references. - * - * @param requiredDmiService Determines if the required service is for a data or model operation. - * @param urlTemplateParameters The DMI resource URL template with variables. - * @param requestBodyAsJsonString JSON data body. - * @param operationType The type of operation being executed (for error reporting only). - * @param authorization Contents of the Authorization header, or null if not present. - * @return ResponseEntity containing the response from the DMI. - * @throws DmiClientRequestException If there is an error during the DMI request. - */ - public ResponseEntity synchronousPostOperationWithJsonData(final RequiredDmiService requiredDmiService, - final UrlTemplateParameters - urlTemplateParameters, - final String requestBodyAsJsonString, - final OperationType operationType, - final String authorization) { - final Mono> responseEntityMono = - asynchronousPostOperationWithJsonData(requiredDmiService, - urlTemplateParameters, - requestBodyAsJsonString, - operationType, - authorization); - return responseEntityMono.block(); - } - - /** - * Asynchronously performs an HTTP POST operation with the given JSON data. - * - * @param requiredDmiService The service object required for retrieving or configuring the WebClient. - * @param urlTemplateParameters The URL template with variables for the POST request. - * @param requestBodyAsJsonString The JSON string that will be sent as the request body. - * @param operationType An enumeration or object that holds information about the type of operation - * being performed. - * @param authorization The authorization token to be added to the request headers. - * @return A Mono emitting the response entity containing the server's response. - */ - public Mono> asynchronousPostOperationWithJsonData(final RequiredDmiService - requiredDmiService, - final UrlTemplateParameters - urlTemplateParameters, - final String requestBodyAsJsonString, - final OperationType operationType, - final String authorization) { - final WebClient webClient = getWebClient(requiredDmiService); - return webClient.post() - .uri(urlTemplateParameters.urlTemplate(), urlTemplateParameters.urlVariables()) - .headers(httpHeaders -> configureHttpHeaders(httpHeaders, authorization)) - .body(BodyInserters.fromValue(requestBodyAsJsonString)) - .retrieve() - .toEntity(Object.class) - .onErrorMap(throwable -> handleDmiClientException(throwable, operationType.getOperationName())); - } - - /** - * Retrieves the health status of the DMI plugin. - * This method performs an HTTP GET request to the DMI health check endpoint specified by the URL template - * parameters. If the response status code indicates a client error (4xx) or a server error (5xx), it logs a warning - * and returns an empty Mono. In case of an error during the request, it logs the exception and returns a default - * value of "NOT_SPECIFIED". If the response body contains a JSON node with a "status" field, the value of this - * field is returned. - * - * @param urlTemplateParameters the URL template parameters for the DMI health check endpoint - * @return a Mono emitting the health status as a String, or "NOT_SPECIFIED" if an error occurs - */ - public Mono getDmiHealthStatus(final UrlTemplateParameters urlTemplateParameters) { - return healthChecksWebClient.get() - .uri(urlTemplateParameters.urlTemplate(), urlTemplateParameters.urlVariables()) - .headers(httpHeaders -> configureHttpHeaders(httpHeaders, NO_AUTHORIZATION)) - .retrieve() - .bodyToMono(JsonNode.class) - .map(responseHealthStatus -> responseHealthStatus.path("status").asText()) - .onErrorResume(Exception.class, ex -> { - log.warn("Failed to retrieve health status from {}. Status: {}", - urlTemplateParameters.urlTemplate(), ex.getMessage()); - return Mono.empty(); - }) - .defaultIfEmpty(NOT_SPECIFIED); - } - - private WebClient getWebClient(final RequiredDmiService requiredDmiService) { - return requiredDmiService.equals(RequiredDmiService.DATA) ? dataServicesWebClient : modelServicesWebClient; - } - - private void configureHttpHeaders(final HttpHeaders httpHeaders, final String authorization) { - if (dmiProperties.isDmiBasicAuthEnabled()) { - httpHeaders.setBasicAuth(dmiProperties.getAuthUsername(), dmiProperties.getAuthPassword()); - } else if (authorization != null && authorization.toLowerCase(Locale.getDefault()).startsWith("bearer ")) { - httpHeaders.add(HttpHeaders.AUTHORIZATION, authorization); - } - } - - private DmiClientRequestException handleDmiClientException(final Throwable throwable, final String operationType) { - if (throwable instanceof WebClientResponseException webClientResponseException) { - if (webClientResponseException.getStatusCode().isSameCodeAs(REQUEST_TIMEOUT)) { - throw new DmiClientRequestException(webClientResponseException.getStatusCode().value(), - webClientResponseException.getMessage(), - jsonObjectMapper.asJsonString(webClientResponseException.getResponseBodyAsString()), - DMI_SERVICE_NOT_RESPONDING); - } - throw new DmiClientRequestException(webClientResponseException.getStatusCode().value(), - webClientResponseException.getMessage(), - jsonObjectMapper.asJsonString(webClientResponseException.getResponseBodyAsString()), - UNABLE_TO_READ_RESOURCE_DATA); - - } - final String exceptionMessage = "Unable to " + operationType + " resource data."; - if (throwable instanceof WebClientRequestException webClientRequestException) { - throw new DmiClientRequestException(HttpStatus.SERVICE_UNAVAILABLE.value(), - webClientRequestException.getMessage(), - exceptionMessage, DMI_SERVICE_NOT_RESPONDING); - } - if (throwable instanceof HttpServerErrorException httpServerErrorException) { - throw new DmiClientRequestException(httpServerErrorException.getStatusCode().value(), exceptionMessage, - httpServerErrorException.getResponseBodyAsString(), DMI_SERVICE_NOT_RESPONDING); - } - throw new DmiClientRequestException(INTERNAL_SERVER_ERROR.value(), exceptionMessage, throwable.getMessage(), - UNKNOWN_ERROR); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiProperties.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiProperties.java deleted file mode 100644 index 5453efecd0..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiProperties.java +++ /dev/null @@ -1,55 +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.api.impl.config; - -import lombok.AccessLevel; -import lombok.Getter; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -@Getter -@Component -public class DmiProperties { - @Value("${ncmp.dmi.auth.username}") - private String authUsername; - @Value("${ncmp.dmi.auth.password}") - private String authPassword; - @Getter(AccessLevel.NONE) - @Value("${ncmp.dmi.api.base-path}") - private String dmiBasePath; - @Value("${ncmp.dmi.auth.enabled}") - private boolean dmiBasicAuthEnabled; - - /** - * Removes both leading and trailing slashes if they are present. - * - * @return dmi base path without any slashes ("/") - */ - public String getDmiBasePath() { - if (dmiBasePath.startsWith("/")) { - dmiBasePath = dmiBasePath.substring(1); - } - if (dmiBasePath.endsWith("/")) { - dmiBasePath = dmiBasePath.substring(0, dmiBasePath.length() - 1); - } - return dmiBasePath; - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfiguration.java deleted file mode 100644 index be46105d13..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfiguration.java +++ /dev/null @@ -1,121 +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.api.impl.config; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import io.netty.channel.ChannelOption; -import io.netty.handler.timeout.ReadTimeoutHandler; -import io.netty.handler.timeout.WriteTimeoutHandler; -import io.netty.resolver.DefaultAddressResolverGroup; -import java.time.Duration; -import java.util.concurrent.TimeUnit; -import lombok.RequiredArgsConstructor; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.client.reactive.ReactorClientHttpConnector; -import org.springframework.web.reactive.function.client.WebClient; -import reactor.netty.http.client.HttpClient; -import reactor.netty.resources.ConnectionProvider; - -/** - * Configures and creates WebClient beans for various DMI services including data, model, and health check services. - * The configuration utilizes Netty-based HttpClient with custom connection settings, read and write timeouts, - * and initializes WebClient with these settings to ensure optimal performance and resource management. - */ -@Configuration -@RequiredArgsConstructor -public class DmiWebClientConfiguration { - - private final HttpClientConfiguration httpClientConfiguration; - private static final Duration DEFAULT_RESPONSE_TIMEOUT = Duration.ofSeconds(30); - - /** - * Configures and creates a web client bean for DMI data services. - * - * @param webClientBuilder The builder instance to create the WebClient. - * @return a WebClient instance configured for data services. - */ - @Bean - public WebClient dataServicesWebClient(final WebClient.Builder webClientBuilder) { - return configureWebClient(webClientBuilder, httpClientConfiguration.getDataServices()); - } - - /** - * Configures and creates a web client bean for DMI model services. - * - * @param webClientBuilder The builder instance to create the WebClient. - * @return a WebClient instance configured for model services. - */ - @Bean - public WebClient modelServicesWebClient(final WebClient.Builder webClientBuilder) { - return configureWebClient(webClientBuilder, httpClientConfiguration.getModelServices()); - } - - /** - * Configures and creates a web client bean for DMI health check services. - * - * @param webClientBuilder The builder instance to create the WebClient. - * @return a WebClient instance configured for health check services. - */ - @Bean - public WebClient healthChecksWebClient(final WebClient.Builder webClientBuilder) { - return configureWebClient(webClientBuilder, httpClientConfiguration.getHealthCheckServices()); - } - - private WebClient configureWebClient(final WebClient.Builder webClientBuilder, - final HttpClientConfiguration.ServiceConfig serviceConfig) { - final ConnectionProvider connectionProvider = getConnectionProvider(serviceConfig); - final HttpClient httpClient = createHttpClient(serviceConfig, connectionProvider); - return buildAndGetWebClient(webClientBuilder, httpClient, serviceConfig.getMaximumInMemorySizeInMegabytes()); - } - - private static HttpClient createHttpClient(final HttpClientConfiguration.ServiceConfig serviceConfig, - final ConnectionProvider connectionProvider) { - return HttpClient.create(connectionProvider) - .responseTimeout(DEFAULT_RESPONSE_TIMEOUT) - .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, serviceConfig.getConnectionTimeoutInSeconds() * 1000) - .doOnConnected(connection -> connection.addHandlerLast(new ReadTimeoutHandler( - serviceConfig.getReadTimeoutInSeconds(), TimeUnit.SECONDS)).addHandlerLast( - new WriteTimeoutHandler(serviceConfig.getWriteTimeoutInSeconds(), TimeUnit.SECONDS))) - .resolver(DefaultAddressResolverGroup.INSTANCE) - .compress(true); - } - - @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE") - private static ConnectionProvider getConnectionProvider(final HttpClientConfiguration.ServiceConfig serviceConfig) { - return ConnectionProvider.builder(serviceConfig.getConnectionProviderName()) - .maxConnections(serviceConfig.getMaximumConnectionsTotal()) - .pendingAcquireMaxCount(serviceConfig.getPendingAcquireMaxCount()) - .build(); - } - - private WebClient buildAndGetWebClient(final WebClient.Builder webClientBuilder, final HttpClient httpClient, - final int maximumInMemorySizeInMegabytes) { - return webClientBuilder - .defaultHeaders(header -> header.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)) - .defaultHeaders(header -> header.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)) - .clientConnector(new ReactorClientHttpConnector(httpClient)) - .codecs(configurer -> configurer.defaultCodecs() - .maxInMemorySize(maximumInMemorySizeInMegabytes * 1024 * 1024)).build(); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/HttpClientConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/HttpClientConfiguration.java deleted file mode 100644 index 0acbabbbaf..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/HttpClientConfiguration.java +++ /dev/null @@ -1,72 +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.api.impl.config; - -import lombok.Getter; -import lombok.Setter; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -@Getter -@Setter -@Configuration -@ConfigurationProperties(prefix = "ncmp.dmi.httpclient") -public class HttpClientConfiguration { - - private final DataServices dataServices = new DataServices(); - private final ModelServices modelServices = new ModelServices(); - private final HealthCheckServices healthCheckServices = new HealthCheckServices(); - - @Getter - @Setter - public static class DataServices extends ServiceConfig { - private String connectionProviderName = "dataConnectionPool"; - } - - @Getter - @Setter - public static class ModelServices extends ServiceConfig { - private String connectionProviderName = "modelConnectionPool"; - } - - @Getter - @Setter - public static class HealthCheckServices extends ServiceConfig { - private String connectionProviderName = "healthConnectionPool"; - private int maximumConnectionsTotal = 10; - private int pendingAcquireMaxCount = 5; - } - - /** - * Base configuration properties for all services. - */ - @Getter - @Setter - public static class ServiceConfig { - private String connectionProviderName = "cpsConnectionPool"; - private int maximumConnectionsTotal = 100; - private int pendingAcquireMaxCount = 50; - private Integer connectionTimeoutInSeconds = 30; - private long readTimeoutInSeconds = 30; - private long writeTimeoutInSeconds = 30; - private int maximumInMemorySizeInMegabytes = 1; - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/OpenTelemetryConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/OpenTelemetryConfig.java deleted file mode 100644 index bcbacbd421..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/OpenTelemetryConfig.java +++ /dev/null @@ -1,111 +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.api.impl.config; - -import io.micrometer.observation.ObservationPredicate; -import io.micrometer.observation.ObservationRegistry; -import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter; -import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; -import io.opentelemetry.sdk.extension.trace.jaeger.sampler.JaegerRemoteSampler; -import io.opentelemetry.sdk.trace.samplers.Sampler; -import java.time.Duration; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.actuate.autoconfigure.observation.ObservationRegistryCustomizer; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.server.observation.ServerRequestObservationContext; -import org.springframework.util.AntPathMatcher; -import org.springframework.util.PathMatcher; - -@Configuration -public class OpenTelemetryConfig { - - public static final int JAEGER_REMOTE_SAMPLER_POLLING_INTERVAL_IN_SECOND = 30; - - @Value("${spring.application.name:cps-application}") - private String serviceId; - - @Value("${cps.tracing.exporter.endpoint:http://onap-otel-collector:4317}") - private String tracingExporterEndpointUrl; - - @Value("${cps.tracing.sampler.jaeger_remote.endpoint:http://onap-otel-collector:14250}") - private String jaegerRemoteSamplerUrl; - - /** - * OTLP Exporter with Grpc exporter protocol. - */ - @Bean - @ConditionalOnExpression( - "${cps.tracing.enabled} && 'grpc'.equals('${cps.tracing.exporter.protocol}')") - public OtlpGrpcSpanExporter createOtlpExporterGrpc() { - return OtlpGrpcSpanExporter.builder().setEndpoint(tracingExporterEndpointUrl).build(); - } - - /** - * OTLP Exporter with HTTP exporter protocol. - */ - @Bean - @ConditionalOnExpression( - "${cps.tracing.enabled} && 'http'.equals('${cps.tracing.exporter.protocol}')") - public OtlpHttpSpanExporter createOtlpExporterHttp() { - return OtlpHttpSpanExporter.builder().setEndpoint(tracingExporterEndpointUrl).build(); - } - - /** - * Jaeger Remote Sampler. - */ - @Bean - @ConditionalOnProperty("cps.tracing.enabled") - public JaegerRemoteSampler createJaegerRemoteSampler() { - return JaegerRemoteSampler.builder() - .setEndpoint(jaegerRemoteSamplerUrl) - .setPollingInterval(Duration.ofSeconds(JAEGER_REMOTE_SAMPLER_POLLING_INTERVAL_IN_SECOND)) - .setInitialSampler(Sampler.alwaysOff()) - .setServiceName(serviceId) - .build(); - } - - /** - * Excluding /actuator/** endpoints. - */ - @Bean - @ConditionalOnProperty("cps.tracing.enabled") - ObservationRegistryCustomizer skipActuatorEndpointsFromObservation() { - final PathMatcher pathMatcher = new AntPathMatcher("/"); - return registry -> - registry.observationConfig().observationPredicate(observationPredicate(pathMatcher)); - } - - /** - * Excluding /actuator/** endpoints. - */ - static ObservationPredicate observationPredicate(final PathMatcher pathMatcher) { - return (name, context) -> { - if (context instanceof ServerRequestObservationContext observationContext) { - return !pathMatcher.match("/actuator/**", observationContext.getCarrier().getRequestURI()); - } else { - return true; - } - }; - } -} \ No newline at end of file diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/kafka/KafkaConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/kafka/KafkaConfig.java deleted file mode 100644 index cf6f1c5b17..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/kafka/KafkaConfig.java +++ /dev/null @@ -1,198 +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.api.impl.config.kafka; - -import io.cloudevents.CloudEvent; -import io.opentelemetry.instrumentation.kafkaclients.v2_6.TracingConsumerInterceptor; -import io.opentelemetry.instrumentation.kafkaclients.v2_6.TracingProducerInterceptor; -import java.time.Duration; -import java.util.Map; -import lombok.RequiredArgsConstructor; -import org.apache.kafka.clients.consumer.ConsumerConfig; -import org.apache.kafka.clients.producer.ProducerConfig; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.kafka.KafkaProperties; -import org.springframework.boot.ssl.SslBundles; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import org.springframework.kafka.annotation.EnableKafka; -import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; -import org.springframework.kafka.core.ConsumerFactory; -import org.springframework.kafka.core.DefaultKafkaConsumerFactory; -import org.springframework.kafka.core.DefaultKafkaProducerFactory; -import org.springframework.kafka.core.KafkaTemplate; -import org.springframework.kafka.core.ProducerFactory; -import org.springframework.kafka.support.serializer.JsonDeserializer; -import org.springframework.kafka.support.serializer.JsonSerializer; - -/** - * kafka Configuration for legacy and cloud events. - * - * @param valid legacy event to be published over the wire. - */ -@Configuration -@EnableKafka -@RequiredArgsConstructor -public class KafkaConfig { - - private final KafkaProperties kafkaProperties; - - @Value("${cps.tracing.enabled:false}") - private boolean tracingEnabled; - - private static final SslBundles NO_SSL = null; - - /** - * This sets the strategy for creating legacy Kafka producer instance from kafka properties defined into - * application.yml and replaces value-serializer by JsonSerializer. - * - * @return legacy event producer instance. - */ - @Bean - public ProducerFactory legacyEventProducerFactory() { - final Map producerConfigProperties = kafkaProperties.buildProducerProperties(NO_SSL); - producerConfigProperties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class); - if (tracingEnabled) { - producerConfigProperties.put( - ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingProducerInterceptor.class.getName()); - } - return new DefaultKafkaProducerFactory<>(producerConfigProperties); - } - - /** - * The ConsumerFactory implementation is to produce new legacy instance for provided kafka properties defined - * into application.yml and replaces deserializer-value by JsonDeserializer. - * - * @return an instance of legacy consumer factory. - */ - @Bean - public ConsumerFactory legacyEventConsumerFactory() { - final Map consumerConfigProperties = kafkaProperties.buildConsumerProperties(NO_SSL); - consumerConfigProperties.put("spring.deserializer.value.delegate.class", JsonDeserializer.class); - if (tracingEnabled) { - consumerConfigProperties.put( - ConsumerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingConsumerInterceptor.class.getName()); - } - return new DefaultKafkaConsumerFactory<>(consumerConfigProperties); - } - - /** - * A legacy Kafka event template for executing high-level operations. The legacy producer factory ensure this. - * - * @return an instance of legacy Kafka template. - */ - @Bean - @Primary - public KafkaTemplate legacyEventKafkaTemplate() { - final KafkaTemplate kafkaTemplate = new KafkaTemplate<>(legacyEventProducerFactory()); - kafkaTemplate.setConsumerFactory(legacyEventConsumerFactory()); - if (tracingEnabled) { - kafkaTemplate.setObservationEnabled(true); - } - return kafkaTemplate; - } - - /** - * A legacy concurrent kafka listener container factory. - * - * @return instance of Concurrent kafka listener factory - */ - @Bean - public ConcurrentKafkaListenerContainerFactory legacyEventConcurrentKafkaListenerContainerFactory() { - final ConcurrentKafkaListenerContainerFactory containerFactory = - new ConcurrentKafkaListenerContainerFactory<>(); - containerFactory.setConsumerFactory(legacyEventConsumerFactory()); - containerFactory.getContainerProperties().setAuthExceptionRetryInterval(Duration.ofSeconds(10)); - if (tracingEnabled) { - containerFactory.getContainerProperties().setObservationEnabled(true); - } - return containerFactory; - } - - /** - * This sets the strategy for creating cloud Kafka producer instance from kafka properties defined into - * application.yml with CloudEventSerializer. - * - * @return cloud event producer instance. - */ - @Bean - public ProducerFactory cloudEventProducerFactory() { - final Map producerConfigProperties = kafkaProperties.buildProducerProperties(NO_SSL); - if (tracingEnabled) { - producerConfigProperties.put( - ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingProducerInterceptor.class.getName()); - } - return new DefaultKafkaProducerFactory<>(producerConfigProperties); - } - - /** - * The ConsumerFactory implementation to produce new legacy instance for provided kafka properties defined - * into application.yml having CloudEventDeserializer as deserializer-value. - * - * @return an instance of cloud consumer factory. - */ - @Bean - public ConsumerFactory cloudEventConsumerFactory() { - final Map consumerConfigProperties = kafkaProperties.buildConsumerProperties(NO_SSL); - if (tracingEnabled) { - consumerConfigProperties.put( - ConsumerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingConsumerInterceptor.class.getName()); - } - return new DefaultKafkaConsumerFactory<>(consumerConfigProperties); - } - - - /** - * A cloud Kafka event template for executing high-level operations. The cloud producer factory ensure this. - * - * @return an instance of cloud Kafka template. - */ - @Bean - public KafkaTemplate cloudEventKafkaTemplate() { - final KafkaTemplate kafkaTemplate = - new KafkaTemplate<>(cloudEventProducerFactory()); - kafkaTemplate.setConsumerFactory(cloudEventConsumerFactory()); - if (tracingEnabled) { - kafkaTemplate.setObservationEnabled(true); - } - return kafkaTemplate; - } - - /** - * A Concurrent CloudEvent kafka listener container factory. - * - * @return instance of Concurrent kafka listener factory - */ - @Bean - public ConcurrentKafkaListenerContainerFactory - cloudEventConcurrentKafkaListenerContainerFactory() { - final ConcurrentKafkaListenerContainerFactory containerFactory = - new ConcurrentKafkaListenerContainerFactory<>(); - containerFactory.setConsumerFactory(cloudEventConsumerFactory()); - containerFactory.getContainerProperties().setAuthExceptionRetryInterval(Duration.ofSeconds(10)); - if (tracingEnabled) { - containerFactory.getContainerProperties().setObservationEnabled(true); - } - return containerFactory; - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/DmiClientRequestException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/DmiClientRequestException.java deleted file mode 100644 index ab0fa68938..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/DmiClientRequestException.java +++ /dev/null @@ -1,54 +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.api.impl.exception; - -import lombok.Getter; -import org.onap.cps.ncmp.api.NcmpResponseStatus; - -/** - * Http Client Request exception from dmi service. - */ -@Getter -public class DmiClientRequestException extends NcmpException { - - private static final long serialVersionUID = 6659897770659834797L; - final NcmpResponseStatus ncmpResponseStatus; - final String message; - final String responseBodyAsString; - final int httpStatusCode; - - /** - * Constructor to form exception for dmi service response. - * - * @param httpStatusCode http response code from the client - * @param message response message from the client - * @param responseBodyAsString response body from the client - * @param ncmpResponseStatus ncmp status message and code - */ - public DmiClientRequestException(final int httpStatusCode, final String message, final String responseBodyAsString, - final NcmpResponseStatus ncmpResponseStatus) { - super(message, responseBodyAsString); - this.httpStatusCode = httpStatusCode; - this.message = message; - this.responseBodyAsString = responseBodyAsString; - this.ncmpResponseStatus = ncmpResponseStatus; - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/DmiRequestException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/DmiRequestException.java deleted file mode 100644 index d41ca70bca..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/DmiRequestException.java +++ /dev/null @@ -1,37 +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.api.impl.exception; - -/** - * Client Based Network CM Proxy exception. - */ -public class DmiRequestException extends NcmpException { - - /** - * Constructor. - * - * @param message the error message - * @param details the error details - */ - public DmiRequestException(final String message, final String details) { - super(message, details); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NcmpException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NcmpException.java deleted file mode 100644 index 2c75b5d992..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NcmpException.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021 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.exception; - -import lombok.Getter; - -/** - * Network CM Proxy exception. - */ -public class NcmpException extends RuntimeException { - - private static final long serialVersionUID = 1482619410918497467L; - - @Getter - final String details; - - /** - * Constructor. - * - * @param message the error message - * @param details the error details - */ - public NcmpException(final String message, final String details) { - super(message); - this.details = details; - } - -} - diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NcmpStartUpException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NcmpStartUpException.java deleted file mode 100644 index 7ac26f54fd..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NcmpStartUpException.java +++ /dev/null @@ -1,37 +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.api.impl.exception; - -/** - * NCMP start up exception. - */ -public class NcmpStartUpException extends NcmpException { - - /** - * Constructor. - * - * @param message the error message - * @param details the error details - */ - public NcmpStartUpException(final String message, final String details) { - super(message, details); - } -} \ No newline at end of file diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/ServerNcmpException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/ServerNcmpException.java deleted file mode 100644 index a03a2d3e6c..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/ServerNcmpException.java +++ /dev/null @@ -1,37 +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.api.impl.exception; - -/** - * Server Based Network CM Proxy exception. - */ -public class ServerNcmpException extends NcmpException { - - /** - * Constructor. - * - * @param message the error message - * @param details the error details - */ - public ServerNcmpException(final String message, final String details) { - super(message, details); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DataNodeHelper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DataNodeHelper.java deleted file mode 100644 index c032d1e8a4..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DataNodeHelper.java +++ /dev/null @@ -1,100 +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.api.impl.utils; - -import java.io.Serializable; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.onap.cps.spi.model.DataNode; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class DataNodeHelper { - - /** - * The nested DataNode object is being flattened. - * - * @param dataNode object. - * @return DataNode as stream. - */ - public static Stream flatten(final DataNode dataNode) { - return Stream.concat(Stream.of(dataNode), - dataNode.getChildDataNodes().stream().flatMap(DataNodeHelper::flatten)); - } - - /** - * The leaves for each DataNode is listed as map. - * - * @param dataNodes as collection - * @return list of map for the all leaves - */ - public static List> getDataNodeLeaves(final Collection dataNodes) { - return dataNodes.stream() - .flatMap(DataNodeHelper::flatten) - .map(DataNode::getLeaves) - .collect(Collectors.toList()); - } - - /** - * Extracts the mapping of cm handle id to status with details from nodes leaves. - * - * @param dataNodeLeaves as a list of map - * @return cm handle id to status and details mapping - */ - public static Map> cmHandleIdToStatusAndDetailsAsMap( - final List> dataNodeLeaves) { - return dataNodeLeaves.stream() - .filter(entryset -> entryset.values().contains("PENDING") - || entryset.values().contains("ACCEPTED") - || entryset.values().contains("REJECTED")) - .collect( - HashMap>::new, - (result, entry) -> { - final String cmHandleId = (String) entry.get("cmHandleId"); - final String status = (String) entry.get("status"); - final String details = (String) entry.get("details"); - - if (cmHandleId != null && status != null) { - result.put(cmHandleId, new HashMap<>()); - result.get(cmHandleId).put("status", status); - result.get(cmHandleId).put("details", details == null ? "" : details); - } - }, - HashMap::putAll - ); - } - - /** - * Extracts the mapping of cm handle id to status with details from data node collection. - * - * @param dataNodes as a collection - * @return cm handle id to status and details mapping - */ - public static Map> cmHandleIdToStatusAndDetailsAsMapFromDataNode( - final Collection dataNodes) { - return cmHandleIdToStatusAndDetailsAsMap(getDataNodeLeaves(dataNodes)); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceNameOrganizer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceNameOrganizer.java deleted file mode 100644 index 67880648bc..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceNameOrganizer.java +++ /dev/null @@ -1,64 +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.api.impl.utils; - -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; -import org.onap.cps.ncmp.impl.models.RequiredDmiService; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class DmiServiceNameOrganizer { - - /** - * organizes a map with dmi service name as key for cm handle with its properties. - * - * @param yangModelCmHandles list of cm handle model - */ - public static Map>> getDmiPropertiesPerCmHandleIdPerServiceName( - final Collection yangModelCmHandles) { - final Map>> dmiPropertiesPerCmHandleIdPerServiceName - = new HashMap<>(); - yangModelCmHandles.forEach(yangModelCmHandle -> { - final String dmiServiceName = yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA); - if (!dmiPropertiesPerCmHandleIdPerServiceName.containsKey(dmiServiceName)) { - final Map> cmHandleDmiPropertiesMap = new HashMap<>(); - cmHandleDmiPropertiesMap.put(yangModelCmHandle.getId(), - dmiPropertiesAsMap(yangModelCmHandle.getDmiProperties())); - dmiPropertiesPerCmHandleIdPerServiceName.put(dmiServiceName, cmHandleDmiPropertiesMap); - } else { - dmiPropertiesPerCmHandleIdPerServiceName.get(dmiServiceName) - .put(yangModelCmHandle.getId(), dmiPropertiesAsMap(yangModelCmHandle.getDmiProperties())); - } - }); - return dmiPropertiesPerCmHandleIdPerServiceName; - } - - private static Map dmiPropertiesAsMap(final List dmiProperties) { - return dmiProperties.stream().collect( - Collectors.toMap(YangModelCmHandle.Property::getName, YangModelCmHandle.Property::getValue)); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/EventDateTimeFormatter.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/EventDateTimeFormatter.java deleted file mode 100644 index 5dd6827126..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/EventDateTimeFormatter.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022-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.api.impl.utils; - -import java.time.OffsetDateTime; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import org.apache.commons.lang3.StringUtils; - -public interface EventDateTimeFormatter { - - String ISO_TIMESTAMP_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; - - DateTimeFormatter ISO_TIMESTAMP_FORMATTER = DateTimeFormatter.ofPattern(ISO_TIMESTAMP_PATTERN); - - /** - * Gets current date time. - * - * @return the current date time - */ - static String getCurrentIsoFormattedDateTime() { - return ZonedDateTime.now().format(ISO_TIMESTAMP_FORMATTER); - } - - static OffsetDateTime toIsoOffsetDateTime(final String dateTimestampAsString) { - return StringUtils.isNotBlank(dateTimestampAsString) - ? OffsetDateTime.parse(dateTimestampAsString, ISO_TIMESTAMP_FORMATTER) : null; - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/context/CpsApplicationContext.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/context/CpsApplicationContext.java deleted file mode 100644 index b14cf0d0db..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/context/CpsApplicationContext.java +++ /dev/null @@ -1,51 +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.api.impl.utils.context; - -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.stereotype.Component; - -@Component -public class CpsApplicationContext implements ApplicationContextAware { - - private static ApplicationContext applicationContext; - - /** - * Returns the spring managed cps bean instance of the given class type if it exists. - * Returns null otherwise. - * - * @param cpsBeanClass cps class type - * @return requested bean instance - */ - public static T getCpsBean(final Class cpsBeanClass) { - return applicationContext.getBean(cpsBeanClass); - } - - @Override - public void setApplicationContext(final ApplicationContext cpsApplicationContext) { - setCpsApplicationContext(cpsApplicationContext); - } - - private static synchronized void setCpsApplicationContext(final ApplicationContext cpsApplicationContext) { - CpsApplicationContext.applicationContext = cpsApplicationContext; - } -} \ No newline at end of file diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/url/builder/DmiServiceUrlTemplateBuilder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/url/builder/DmiServiceUrlTemplateBuilder.java deleted file mode 100644 index b89b7b3221..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/url/builder/DmiServiceUrlTemplateBuilder.java +++ /dev/null @@ -1,137 +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.api.impl.utils.url.builder; - -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import lombok.NoArgsConstructor; -import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.util.Strings; -import org.springframework.web.util.UriComponentsBuilder; - -@NoArgsConstructor -public class DmiServiceUrlTemplateBuilder { - - private final UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.newInstance(); - private static final String FIXED_PATH_SEGMENT = null; - private static final String VERSION_SEGMENT = "v1"; - private final Map pathSegments = new LinkedHashMap<>(); - private final Map queryParameters = new LinkedHashMap<>(); - - /** - * Static factory method to create a new instance of DmiServiceUrlTemplateBuilder. - * - * @return a new instance of DmiServiceUrlTemplateBuilder - */ - public static DmiServiceUrlTemplateBuilder newInstance() { - return new DmiServiceUrlTemplateBuilder(); - } - - /** - * Add a fixed pathSegment to the URL. - * - * @param pathSegment the path segment - * @return this builder instance - */ - public DmiServiceUrlTemplateBuilder fixedPathSegment(final String pathSegment) { - pathSegments.put(pathSegment, FIXED_PATH_SEGMENT); - return this; - } - - /** - * Add a variable pathSegment to the URL. - * Do NOT add { } braces. the builder will take care of that - * - * @param pathSegment the name of the variable path segment (with { and } - * @param value the value to be insert in teh URL for the given variable path segment - * @return this builder instance - */ - public DmiServiceUrlTemplateBuilder variablePathSegment(final String pathSegment, final String value) { - pathSegments.put(pathSegment, value); - return this; - } - - /** - * Add a query parameter to the URL. - * Do NOT encode as the builder wil take care of encoding - * - * @param queryParameterName the name of the variable - * @param queryParameterValue the value of the variable (only Strings are supported). - * - * @return this builder instance - */ - public DmiServiceUrlTemplateBuilder queryParameter(final String queryParameterName, - final String queryParameterValue) { - if (Strings.isNotBlank(queryParameterValue)) { - queryParameters.put(queryParameterName, queryParameterValue); - } - return this; - } - - /** - * Constructs a URL template with variables based on the accumulated path segments and query parameters. - * - * @param dmiServiceBaseUrl the base URL of the DMI service, e.g., "http://dmi-service.com". - * @param dmiBasePath the base path of the DMI service - * @return a UrlTemplateParameters instance containing the complete URL template and URL variables - */ - public UrlTemplateParameters createUrlTemplateParameters(final String dmiServiceBaseUrl, final String dmiBasePath) { - this.uriComponentsBuilder.pathSegment(dmiBasePath) - .pathSegment(VERSION_SEGMENT); - - final Map urlTemplateVariables = new HashMap<>(); - - pathSegments.forEach((pathSegmentName, variablePathValue) -> { - if (StringUtils.equals(variablePathValue, FIXED_PATH_SEGMENT)) { - this.uriComponentsBuilder.pathSegment(pathSegmentName); - } else { - this.uriComponentsBuilder.pathSegment("{" + pathSegmentName + "}"); - urlTemplateVariables.put(pathSegmentName, variablePathValue); - } - }); - - queryParameters.forEach((paramName, paramValue) -> { - this.uriComponentsBuilder.queryParam(paramName, "{" + paramName + "}"); - urlTemplateVariables.put(paramName, paramValue); - }); - - final String urlTemplate = dmiServiceBaseUrl + this.uriComponentsBuilder.build().toUriString(); - return new UrlTemplateParameters(urlTemplate, urlTemplateVariables); - } - - /** - * Constructs a URL for DMI health check based on the given base URL. - * - * @param dmiServiceBaseUrl the base URL of the DMI service, e.g., "http://dmi-service.com". - * @return a {@link UrlTemplateParameters} instance containing the complete URL template and empty URL variables, - * suitable for DMI health check. - */ - public UrlTemplateParameters createUrlTemplateParametersForHealthCheck(final String dmiServiceBaseUrl) { - this.uriComponentsBuilder.pathSegment("actuator") - .pathSegment("health"); - - final String urlTemplate = dmiServiceBaseUrl + this.uriComponentsBuilder.build().toUriString(); - return new UrlTemplateParameters(urlTemplate, Collections.emptyMap()); - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/url/builder/UrlTemplateParameters.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/url/builder/UrlTemplateParameters.java deleted file mode 100644 index edf56197b5..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/url/builder/UrlTemplateParameters.java +++ /dev/null @@ -1,30 +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.api.impl.utils.url.builder; - -import java.util.Map; - -/** - * Represents a URL template with associated variables for dynamic substitution. - * This record encapsulates a URL template string and a map of variables used for substitution within the template. - */ -public record UrlTemplateParameters(String urlTemplate, Map urlVariables) { -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistration.java index a5002e7909..44e2ebe320 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistration.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistration.java @@ -27,8 +27,8 @@ import java.util.Collections; import java.util.List; import lombok.Getter; import lombok.Setter; -import org.onap.cps.ncmp.api.impl.exception.DmiRequestException; -import org.onap.cps.ncmp.api.impl.exception.NcmpException; +import org.onap.cps.ncmp.api.exceptions.DmiRequestException; +import org.onap.cps.ncmp.api.exceptions.NcmpException; /** * Dmi Registry request object. diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/CpsApplicationContext.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/CpsApplicationContext.java new file mode 100644 index 0000000000..fbc31adcf3 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/CpsApplicationContext.java @@ -0,0 +1,51 @@ +/* + * ============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.config; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class CpsApplicationContext implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + /** + * Returns the spring managed cps bean instance of the given class type if it exists. + * Returns null otherwise. + * + * @param cpsBeanClass cps class type + * @return requested bean instance + */ + public static T getCpsBean(final Class cpsBeanClass) { + return applicationContext.getBean(cpsBeanClass); + } + + @Override + public void setApplicationContext(final ApplicationContext cpsApplicationContext) { + setCpsApplicationContext(cpsApplicationContext); + } + + private static synchronized void setCpsApplicationContext(final ApplicationContext cpsApplicationContext) { + CpsApplicationContext.applicationContext = cpsApplicationContext; + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/HttpClientConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/HttpClientConfiguration.java new file mode 100644 index 0000000000..583d4bb6ad --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/HttpClientConfiguration.java @@ -0,0 +1,72 @@ +/* + * ============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.config; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Getter +@Setter +@Configuration +@ConfigurationProperties(prefix = "ncmp.dmi.httpclient") +public class HttpClientConfiguration { + + private final DataServices dataServices = new DataServices(); + private final ModelServices modelServices = new ModelServices(); + private final HealthCheckServices healthCheckServices = new HealthCheckServices(); + + @Getter + @Setter + public static class DataServices extends ServiceConfig { + private String connectionProviderName = "dataConnectionPool"; + } + + @Getter + @Setter + public static class ModelServices extends ServiceConfig { + private String connectionProviderName = "modelConnectionPool"; + } + + @Getter + @Setter + public static class HealthCheckServices extends ServiceConfig { + private String connectionProviderName = "healthConnectionPool"; + private int maximumConnectionsTotal = 10; + private int pendingAcquireMaxCount = 5; + } + + /** + * Base configuration properties for all services. + */ + @Getter + @Setter + public static class ServiceConfig { + private String connectionProviderName = "cpsConnectionPool"; + private int maximumConnectionsTotal = 100; + private int pendingAcquireMaxCount = 50; + private Integer connectionTimeoutInSeconds = 30; + private long readTimeoutInSeconds = 30; + private long writeTimeoutInSeconds = 30; + private int maximumInMemorySizeInMegabytes = 1; + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/KafkaConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/KafkaConfig.java new file mode 100644 index 0000000000..3d3c3db482 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/KafkaConfig.java @@ -0,0 +1,198 @@ +/* + * ============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.config; + +import io.cloudevents.CloudEvent; +import io.opentelemetry.instrumentation.kafkaclients.v2_6.TracingConsumerInterceptor; +import io.opentelemetry.instrumentation.kafkaclients.v2_6.TracingProducerInterceptor; +import java.time.Duration; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.clients.producer.ProducerConfig; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.kafka.KafkaProperties; +import org.springframework.boot.ssl.SslBundles; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.kafka.annotation.EnableKafka; +import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; +import org.springframework.kafka.core.ConsumerFactory; +import org.springframework.kafka.core.DefaultKafkaConsumerFactory; +import org.springframework.kafka.core.DefaultKafkaProducerFactory; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.kafka.core.ProducerFactory; +import org.springframework.kafka.support.serializer.JsonDeserializer; +import org.springframework.kafka.support.serializer.JsonSerializer; + +/** + * kafka Configuration for legacy and cloud events. + * + * @param valid legacy event to be published over the wire. + */ +@Configuration +@EnableKafka +@RequiredArgsConstructor +public class KafkaConfig { + + private final KafkaProperties kafkaProperties; + + @Value("${cps.tracing.enabled:false}") + private boolean tracingEnabled; + + private static final SslBundles NO_SSL = null; + + /** + * This sets the strategy for creating legacy Kafka producer instance from kafka properties defined into + * application.yml and replaces value-serializer by JsonSerializer. + * + * @return legacy event producer instance. + */ + @Bean + public ProducerFactory legacyEventProducerFactory() { + final Map producerConfigProperties = kafkaProperties.buildProducerProperties(NO_SSL); + producerConfigProperties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class); + if (tracingEnabled) { + producerConfigProperties.put( + ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingProducerInterceptor.class.getName()); + } + return new DefaultKafkaProducerFactory<>(producerConfigProperties); + } + + /** + * The ConsumerFactory implementation is to produce new legacy instance for provided kafka properties defined + * into application.yml and replaces deserializer-value by JsonDeserializer. + * + * @return an instance of legacy consumer factory. + */ + @Bean + public ConsumerFactory legacyEventConsumerFactory() { + final Map consumerConfigProperties = kafkaProperties.buildConsumerProperties(NO_SSL); + consumerConfigProperties.put("spring.deserializer.value.delegate.class", JsonDeserializer.class); + if (tracingEnabled) { + consumerConfigProperties.put( + ConsumerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingConsumerInterceptor.class.getName()); + } + return new DefaultKafkaConsumerFactory<>(consumerConfigProperties); + } + + /** + * A legacy Kafka event template for executing high-level operations. The legacy producer factory ensure this. + * + * @return an instance of legacy Kafka template. + */ + @Bean + @Primary + public KafkaTemplate legacyEventKafkaTemplate() { + final KafkaTemplate kafkaTemplate = new KafkaTemplate<>(legacyEventProducerFactory()); + kafkaTemplate.setConsumerFactory(legacyEventConsumerFactory()); + if (tracingEnabled) { + kafkaTemplate.setObservationEnabled(true); + } + return kafkaTemplate; + } + + /** + * A legacy concurrent kafka listener container factory. + * + * @return instance of Concurrent kafka listener factory + */ + @Bean + public ConcurrentKafkaListenerContainerFactory legacyEventConcurrentKafkaListenerContainerFactory() { + final ConcurrentKafkaListenerContainerFactory containerFactory = + new ConcurrentKafkaListenerContainerFactory<>(); + containerFactory.setConsumerFactory(legacyEventConsumerFactory()); + containerFactory.getContainerProperties().setAuthExceptionRetryInterval(Duration.ofSeconds(10)); + if (tracingEnabled) { + containerFactory.getContainerProperties().setObservationEnabled(true); + } + return containerFactory; + } + + /** + * This sets the strategy for creating cloud Kafka producer instance from kafka properties defined into + * application.yml with CloudEventSerializer. + * + * @return cloud event producer instance. + */ + @Bean + public ProducerFactory cloudEventProducerFactory() { + final Map producerConfigProperties = kafkaProperties.buildProducerProperties(NO_SSL); + if (tracingEnabled) { + producerConfigProperties.put( + ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingProducerInterceptor.class.getName()); + } + return new DefaultKafkaProducerFactory<>(producerConfigProperties); + } + + /** + * The ConsumerFactory implementation to produce new legacy instance for provided kafka properties defined + * into application.yml having CloudEventDeserializer as deserializer-value. + * + * @return an instance of cloud consumer factory. + */ + @Bean + public ConsumerFactory cloudEventConsumerFactory() { + final Map consumerConfigProperties = kafkaProperties.buildConsumerProperties(NO_SSL); + if (tracingEnabled) { + consumerConfigProperties.put( + ConsumerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingConsumerInterceptor.class.getName()); + } + return new DefaultKafkaConsumerFactory<>(consumerConfigProperties); + } + + + /** + * A cloud Kafka event template for executing high-level operations. The cloud producer factory ensure this. + * + * @return an instance of cloud Kafka template. + */ + @Bean + public KafkaTemplate cloudEventKafkaTemplate() { + final KafkaTemplate kafkaTemplate = + new KafkaTemplate<>(cloudEventProducerFactory()); + kafkaTemplate.setConsumerFactory(cloudEventConsumerFactory()); + if (tracingEnabled) { + kafkaTemplate.setObservationEnabled(true); + } + return kafkaTemplate; + } + + /** + * A Concurrent CloudEvent kafka listener container factory. + * + * @return instance of Concurrent kafka listener factory + */ + @Bean + public ConcurrentKafkaListenerContainerFactory + cloudEventConcurrentKafkaListenerContainerFactory() { + final ConcurrentKafkaListenerContainerFactory containerFactory = + new ConcurrentKafkaListenerContainerFactory<>(); + containerFactory.setConsumerFactory(cloudEventConsumerFactory()); + containerFactory.getContainerProperties().setAuthExceptionRetryInterval(Duration.ofSeconds(10)); + if (tracingEnabled) { + containerFactory.getContainerProperties().setObservationEnabled(true); + } + return containerFactory; + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/OpenTelemetryConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/OpenTelemetryConfig.java new file mode 100644 index 0000000000..cff3187966 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/OpenTelemetryConfig.java @@ -0,0 +1,111 @@ +/* + * ============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.config; + +import io.micrometer.observation.ObservationPredicate; +import io.micrometer.observation.ObservationRegistry; +import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter; +import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; +import io.opentelemetry.sdk.extension.trace.jaeger.sampler.JaegerRemoteSampler; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import java.time.Duration; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.actuate.autoconfigure.observation.ObservationRegistryCustomizer; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.server.observation.ServerRequestObservationContext; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.PathMatcher; + +@Configuration +public class OpenTelemetryConfig { + + public static final int JAEGER_REMOTE_SAMPLER_POLLING_INTERVAL_IN_SECOND = 30; + + @Value("${spring.application.name:cps-application}") + private String serviceId; + + @Value("${cps.tracing.exporter.endpoint:http://onap-otel-collector:4317}") + private String tracingExporterEndpointUrl; + + @Value("${cps.tracing.sampler.jaeger_remote.endpoint:http://onap-otel-collector:14250}") + private String jaegerRemoteSamplerUrl; + + /** + * OTLP Exporter with Grpc exporter protocol. + */ + @Bean + @ConditionalOnExpression( + "${cps.tracing.enabled} && 'grpc'.equals('${cps.tracing.exporter.protocol}')") + public OtlpGrpcSpanExporter createOtlpExporterGrpc() { + return OtlpGrpcSpanExporter.builder().setEndpoint(tracingExporterEndpointUrl).build(); + } + + /** + * OTLP Exporter with HTTP exporter protocol. + */ + @Bean + @ConditionalOnExpression( + "${cps.tracing.enabled} && 'http'.equals('${cps.tracing.exporter.protocol}')") + public OtlpHttpSpanExporter createOtlpExporterHttp() { + return OtlpHttpSpanExporter.builder().setEndpoint(tracingExporterEndpointUrl).build(); + } + + /** + * Jaeger Remote Sampler. + */ + @Bean + @ConditionalOnProperty("cps.tracing.enabled") + public JaegerRemoteSampler createJaegerRemoteSampler() { + return JaegerRemoteSampler.builder() + .setEndpoint(jaegerRemoteSamplerUrl) + .setPollingInterval(Duration.ofSeconds(JAEGER_REMOTE_SAMPLER_POLLING_INTERVAL_IN_SECOND)) + .setInitialSampler(Sampler.alwaysOff()) + .setServiceName(serviceId) + .build(); + } + + /** + * Excluding /actuator/** endpoints. + */ + @Bean + @ConditionalOnProperty("cps.tracing.enabled") + ObservationRegistryCustomizer skipActuatorEndpointsFromObservation() { + final PathMatcher pathMatcher = new AntPathMatcher("/"); + return registry -> + registry.observationConfig().observationPredicate(observationPredicate(pathMatcher)); + } + + /** + * Excluding /actuator/** endpoints. + */ + static ObservationPredicate observationPredicate(final PathMatcher pathMatcher) { + return (name, context) -> { + if (context instanceof ServerRequestObservationContext observationContext) { + return !pathMatcher.match("/actuator/**", observationContext.getCarrier().getRequestURI()); + } else { + return true; + } + }; + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/InvalidTopicException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/InvalidTopicException.java deleted file mode 100644 index fcf2a28ccc..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/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.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-service/src/main/java/org/onap/cps/ncmp/exceptions/NcmpStartUpException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/NcmpStartUpException.java new file mode 100644 index 0000000000..7ffbe2e5cb --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/NcmpStartUpException.java @@ -0,0 +1,39 @@ +/* + * ============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.exceptions; + +import org.onap.cps.ncmp.api.exceptions.NcmpException; + +/** + * NCMP start up exception. + */ +public class NcmpStartUpException extends NcmpException { + + /** + * Constructor. + * + * @param message the error message + * @param details the error details + */ + public NcmpStartUpException(final String message, final String details) { + super(message, details); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/NoAlternateIdMatchFoundException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/NoAlternateIdMatchFoundException.java index 510a6f51a0..7c5fc3be2b 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/NoAlternateIdMatchFoundException.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/NoAlternateIdMatchFoundException.java @@ -21,7 +21,7 @@ package org.onap.cps.ncmp.exceptions; import java.io.Serial; -import org.onap.cps.ncmp.api.impl.exception.NcmpException; +import org.onap.cps.ncmp.api.exceptions.NcmpException; public class NoAlternateIdMatchFoundException extends NcmpException { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/PayloadTooLargeException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/PayloadTooLargeException.java deleted file mode 100644 index dc7057af79..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/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.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-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java index efe0335e8c..b902fe2767 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java @@ -37,15 +37,15 @@ import org.onap.cps.ncmp.api.NcmpResponseStatus; import org.onap.cps.ncmp.api.data.models.CmResourceAddress; import org.onap.cps.ncmp.api.data.models.DataOperationRequest; import org.onap.cps.ncmp.api.data.models.OperationType; -import org.onap.cps.ncmp.api.impl.client.DmiRestClient; -import org.onap.cps.ncmp.api.impl.config.DmiProperties; -import org.onap.cps.ncmp.api.impl.exception.DmiClientRequestException; -import org.onap.cps.ncmp.api.impl.utils.url.builder.DmiServiceUrlTemplateBuilder; -import org.onap.cps.ncmp.api.impl.utils.url.builder.UrlTemplateParameters; +import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException; import org.onap.cps.ncmp.impl.data.models.DmiDataOperation; import org.onap.cps.ncmp.impl.data.models.DmiDataOperationRequest; import org.onap.cps.ncmp.impl.data.models.DmiOperationCmHandle; import org.onap.cps.ncmp.impl.data.utils.DmiDataOperationsHelper; +import org.onap.cps.ncmp.impl.dmi.DmiProperties; +import org.onap.cps.ncmp.impl.dmi.DmiRestClient; +import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder; +import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters; import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpPassthroughResourceRequestHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpPassthroughResourceRequestHandler.java index be2dde2308..a21210c376 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpPassthroughResourceRequestHandler.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpPassthroughResourceRequestHandler.java @@ -32,7 +32,7 @@ import org.onap.cps.ncmp.api.data.models.CmResourceAddress; import org.onap.cps.ncmp.api.data.models.DataOperationRequest; import org.onap.cps.ncmp.api.data.models.DatastoreType; import org.onap.cps.ncmp.api.data.models.OperationType; -import org.onap.cps.ncmp.exceptions.PayloadTooLargeException; +import org.onap.cps.ncmp.api.exceptions.PayloadTooLargeException; import org.onap.cps.ncmp.utils.events.TopicValidator; import org.springframework.stereotype.Service; import reactor.core.publisher.Mono; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java index ab2f106449..3104be5539 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java @@ -39,10 +39,10 @@ import org.onap.cps.events.EventsPublisher; import org.onap.cps.ncmp.api.NcmpResponseStatus; import org.onap.cps.ncmp.api.data.models.DataOperationDefinition; import org.onap.cps.ncmp.api.data.models.DataOperationRequest; -import org.onap.cps.ncmp.api.impl.utils.DmiServiceNameOrganizer; -import org.onap.cps.ncmp.api.impl.utils.context.CpsApplicationContext; +import org.onap.cps.ncmp.config.CpsApplicationContext; import org.onap.cps.ncmp.impl.data.models.DmiDataOperation; import org.onap.cps.ncmp.impl.data.models.DmiOperationCmHandle; +import org.onap.cps.ncmp.impl.dmi.DmiServiceNameOrganizer; import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; import org.springframework.util.LinkedMultiValueMap; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java index 973a2a9b2d..3d1c5237d6 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java @@ -31,10 +31,10 @@ import org.onap.cps.ncmp.api.datajobs.models.DmiWriteOperation; import org.onap.cps.ncmp.api.datajobs.models.ProducerKey; import org.onap.cps.ncmp.api.datajobs.models.SubJobWriteRequest; import org.onap.cps.ncmp.api.datajobs.models.SubJobWriteResponse; -import org.onap.cps.ncmp.api.impl.client.DmiRestClient; -import org.onap.cps.ncmp.api.impl.config.DmiProperties; -import org.onap.cps.ncmp.api.impl.utils.url.builder.DmiServiceUrlTemplateBuilder; -import org.onap.cps.ncmp.api.impl.utils.url.builder.UrlTemplateParameters; +import org.onap.cps.ncmp.impl.dmi.DmiProperties; +import org.onap.cps.ncmp.impl.dmi.DmiRestClient; +import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder; +import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters; import org.onap.cps.ncmp.impl.models.RequiredDmiService; import org.onap.cps.utils.JsonObjectMapper; import org.springframework.http.ResponseEntity; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiProperties.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiProperties.java new file mode 100644 index 0000000000..2f60460da3 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiProperties.java @@ -0,0 +1,55 @@ +/* + * ============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.impl.dmi; + +import lombok.AccessLevel; +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Getter +@Component +public class DmiProperties { + @Value("${ncmp.dmi.auth.username}") + private String authUsername; + @Value("${ncmp.dmi.auth.password}") + private String authPassword; + @Getter(AccessLevel.NONE) + @Value("${ncmp.dmi.api.base-path}") + private String dmiBasePath; + @Value("${ncmp.dmi.auth.enabled}") + private boolean dmiBasicAuthEnabled; + + /** + * Removes both leading and trailing slashes if they are present. + * + * @return dmi base path without any slashes ("/") + */ + public String getDmiBasePath() { + if (dmiBasePath.startsWith("/")) { + dmiBasePath = dmiBasePath.substring(1); + } + if (dmiBasePath.endsWith("/")) { + dmiBasePath = dmiBasePath.substring(0, dmiBasePath.length() - 1); + } + return dmiBasePath; + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java new file mode 100644 index 0000000000..7ac85cbf84 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java @@ -0,0 +1,186 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021-2024 Nordix Foundation + * Modifications Copyright (C) 2022 Bell Canada + * ================================================================================ + * 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.impl.dmi; + +import static org.onap.cps.ncmp.api.NcmpResponseStatus.DMI_SERVICE_NOT_RESPONDING; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNABLE_TO_READ_RESOURCE_DATA; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR; +import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; +import static org.springframework.http.HttpStatus.REQUEST_TIMEOUT; + +import com.fasterxml.jackson.databind.JsonNode; +import java.util.Locale; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.data.models.OperationType; +import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException; +import org.onap.cps.ncmp.impl.models.RequiredDmiService; +import org.onap.cps.utils.JsonObjectMapper; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.client.HttpServerErrorException; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientRequestException; +import org.springframework.web.reactive.function.client.WebClientResponseException; +import reactor.core.publisher.Mono; + +@Component +@RequiredArgsConstructor +@Slf4j +public class DmiRestClient { + + private static final String NOT_SPECIFIED = ""; + private static final String NO_AUTHORIZATION = null; + + private final DmiProperties dmiProperties; + private final JsonObjectMapper jsonObjectMapper; + @Qualifier("dataServicesWebClient") + private final WebClient dataServicesWebClient; + @Qualifier("modelServicesWebClient") + private final WebClient modelServicesWebClient; + @Qualifier("healthChecksWebClient") + private final WebClient healthChecksWebClient; + + /** + * Sends a synchronous (blocking) POST operation to the DMI with a JSON body containing module references. + * + * @param requiredDmiService Determines if the required service is for a data or model operation. + * @param urlTemplateParameters The DMI resource URL template with variables. + * @param requestBodyAsJsonString JSON data body. + * @param operationType The type of operation being executed (for error reporting only). + * @param authorization Contents of the Authorization header, or null if not present. + * @return ResponseEntity containing the response from the DMI. + * @throws DmiClientRequestException If there is an error during the DMI request. + */ + public ResponseEntity synchronousPostOperationWithJsonData(final RequiredDmiService requiredDmiService, + final UrlTemplateParameters + urlTemplateParameters, + final String requestBodyAsJsonString, + final OperationType operationType, + final String authorization) { + final Mono> responseEntityMono = + asynchronousPostOperationWithJsonData(requiredDmiService, + urlTemplateParameters, + requestBodyAsJsonString, + operationType, + authorization); + return responseEntityMono.block(); + } + + /** + * Asynchronously performs an HTTP POST operation with the given JSON data. + * + * @param requiredDmiService The service object required for retrieving or configuring the WebClient. + * @param urlTemplateParameters The URL template with variables for the POST request. + * @param requestBodyAsJsonString The JSON string that will be sent as the request body. + * @param operationType An enumeration or object that holds information about the type of operation + * being performed. + * @param authorization The authorization token to be added to the request headers. + * @return A Mono emitting the response entity containing the server's response. + */ + public Mono> asynchronousPostOperationWithJsonData(final RequiredDmiService + requiredDmiService, + final UrlTemplateParameters + urlTemplateParameters, + final String requestBodyAsJsonString, + final OperationType operationType, + final String authorization) { + final WebClient webClient = getWebClient(requiredDmiService); + return webClient.post() + .uri(urlTemplateParameters.urlTemplate(), urlTemplateParameters.urlVariables()) + .headers(httpHeaders -> configureHttpHeaders(httpHeaders, authorization)) + .body(BodyInserters.fromValue(requestBodyAsJsonString)) + .retrieve() + .toEntity(Object.class) + .onErrorMap(throwable -> handleDmiClientException(throwable, operationType.getOperationName())); + } + + /** + * Retrieves the health status of the DMI plugin. + * This method performs an HTTP GET request to the DMI health check endpoint specified by the URL template + * parameters. If the response status code indicates a client error (4xx) or a server error (5xx), it logs a warning + * and returns an empty Mono. In case of an error during the request, it logs the exception and returns a default + * value of "NOT_SPECIFIED". If the response body contains a JSON node with a "status" field, the value of this + * field is returned. + * + * @param urlTemplateParameters the URL template parameters for the DMI health check endpoint + * @return a Mono emitting the health status as a String, or "NOT_SPECIFIED" if an error occurs + */ + public Mono getDmiHealthStatus(final UrlTemplateParameters urlTemplateParameters) { + return healthChecksWebClient.get() + .uri(urlTemplateParameters.urlTemplate(), urlTemplateParameters.urlVariables()) + .headers(httpHeaders -> configureHttpHeaders(httpHeaders, NO_AUTHORIZATION)) + .retrieve() + .bodyToMono(JsonNode.class) + .map(responseHealthStatus -> responseHealthStatus.path("status").asText()) + .onErrorResume(Exception.class, ex -> { + log.warn("Failed to retrieve health status from {}. Status: {}", + urlTemplateParameters.urlTemplate(), ex.getMessage()); + return Mono.empty(); + }) + .defaultIfEmpty(NOT_SPECIFIED); + } + + private WebClient getWebClient(final RequiredDmiService requiredDmiService) { + return requiredDmiService.equals(RequiredDmiService.DATA) ? dataServicesWebClient : modelServicesWebClient; + } + + private void configureHttpHeaders(final HttpHeaders httpHeaders, final String authorization) { + if (dmiProperties.isDmiBasicAuthEnabled()) { + httpHeaders.setBasicAuth(dmiProperties.getAuthUsername(), dmiProperties.getAuthPassword()); + } else if (authorization != null && authorization.toLowerCase(Locale.getDefault()).startsWith("bearer ")) { + httpHeaders.add(HttpHeaders.AUTHORIZATION, authorization); + } + } + + private DmiClientRequestException handleDmiClientException(final Throwable throwable, final String operationType) { + if (throwable instanceof WebClientResponseException webClientResponseException) { + if (webClientResponseException.getStatusCode().isSameCodeAs(REQUEST_TIMEOUT)) { + throw new DmiClientRequestException(webClientResponseException.getStatusCode().value(), + webClientResponseException.getMessage(), + jsonObjectMapper.asJsonString(webClientResponseException.getResponseBodyAsString()), + DMI_SERVICE_NOT_RESPONDING); + } + throw new DmiClientRequestException(webClientResponseException.getStatusCode().value(), + webClientResponseException.getMessage(), + jsonObjectMapper.asJsonString(webClientResponseException.getResponseBodyAsString()), + UNABLE_TO_READ_RESOURCE_DATA); + + } + final String exceptionMessage = "Unable to " + operationType + " resource data."; + if (throwable instanceof WebClientRequestException webClientRequestException) { + throw new DmiClientRequestException(HttpStatus.SERVICE_UNAVAILABLE.value(), + webClientRequestException.getMessage(), + exceptionMessage, DMI_SERVICE_NOT_RESPONDING); + } + if (throwable instanceof HttpServerErrorException httpServerErrorException) { + throw new DmiClientRequestException(httpServerErrorException.getStatusCode().value(), exceptionMessage, + httpServerErrorException.getResponseBodyAsString(), DMI_SERVICE_NOT_RESPONDING); + } + throw new DmiClientRequestException(INTERNAL_SERVER_ERROR.value(), exceptionMessage, throwable.getMessage(), + UNKNOWN_ERROR); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceNameOrganizer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceNameOrganizer.java new file mode 100644 index 0000000000..37e982d8cb --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceNameOrganizer.java @@ -0,0 +1,64 @@ +/* + * ============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.impl.dmi; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.ncmp.impl.models.RequiredDmiService; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class DmiServiceNameOrganizer { + + /** + * organizes a map with dmi service name as key for cm handle with its properties. + * + * @param yangModelCmHandles list of cm handle model + */ + public static Map>> getDmiPropertiesPerCmHandleIdPerServiceName( + final Collection yangModelCmHandles) { + final Map>> dmiPropertiesPerCmHandleIdPerServiceName + = new HashMap<>(); + yangModelCmHandles.forEach(yangModelCmHandle -> { + final String dmiServiceName = yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA); + if (!dmiPropertiesPerCmHandleIdPerServiceName.containsKey(dmiServiceName)) { + final Map> cmHandleDmiPropertiesMap = new HashMap<>(); + cmHandleDmiPropertiesMap.put(yangModelCmHandle.getId(), + dmiPropertiesAsMap(yangModelCmHandle.getDmiProperties())); + dmiPropertiesPerCmHandleIdPerServiceName.put(dmiServiceName, cmHandleDmiPropertiesMap); + } else { + dmiPropertiesPerCmHandleIdPerServiceName.get(dmiServiceName) + .put(yangModelCmHandle.getId(), dmiPropertiesAsMap(yangModelCmHandle.getDmiProperties())); + } + }); + return dmiPropertiesPerCmHandleIdPerServiceName; + } + + private static Map dmiPropertiesAsMap(final List dmiProperties) { + return dmiProperties.stream().collect( + Collectors.toMap(YangModelCmHandle.Property::getName, YangModelCmHandle.Property::getValue)); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilder.java new file mode 100644 index 0000000000..e7dbea83f2 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilder.java @@ -0,0 +1,137 @@ +/* + * ============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.impl.dmi; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.util.Strings; +import org.springframework.web.util.UriComponentsBuilder; + +@NoArgsConstructor +public class DmiServiceUrlTemplateBuilder { + + private final UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.newInstance(); + private static final String FIXED_PATH_SEGMENT = null; + private static final String VERSION_SEGMENT = "v1"; + private final Map pathSegments = new LinkedHashMap<>(); + private final Map queryParameters = new LinkedHashMap<>(); + + /** + * Static factory method to create a new instance of DmiServiceUrlTemplateBuilder. + * + * @return a new instance of DmiServiceUrlTemplateBuilder + */ + public static DmiServiceUrlTemplateBuilder newInstance() { + return new DmiServiceUrlTemplateBuilder(); + } + + /** + * Add a fixed pathSegment to the URL. + * + * @param pathSegment the path segment + * @return this builder instance + */ + public DmiServiceUrlTemplateBuilder fixedPathSegment(final String pathSegment) { + pathSegments.put(pathSegment, FIXED_PATH_SEGMENT); + return this; + } + + /** + * Add a variable pathSegment to the URL. + * Do NOT add { } braces. the builder will take care of that + * + * @param pathSegment the name of the variable path segment (with { and } + * @param value the value to be insert in teh URL for the given variable path segment + * @return this builder instance + */ + public DmiServiceUrlTemplateBuilder variablePathSegment(final String pathSegment, final String value) { + pathSegments.put(pathSegment, value); + return this; + } + + /** + * Add a query parameter to the URL. + * Do NOT encode as the builder wil take care of encoding + * + * @param queryParameterName the name of the variable + * @param queryParameterValue the value of the variable (only Strings are supported). + * + * @return this builder instance + */ + public DmiServiceUrlTemplateBuilder queryParameter(final String queryParameterName, + final String queryParameterValue) { + if (Strings.isNotBlank(queryParameterValue)) { + queryParameters.put(queryParameterName, queryParameterValue); + } + return this; + } + + /** + * Constructs a URL template with variables based on the accumulated path segments and query parameters. + * + * @param dmiServiceBaseUrl the base URL of the DMI service, e.g., "http://dmi-service.com". + * @param dmiBasePath the base path of the DMI service + * @return a UrlTemplateParameters instance containing the complete URL template and URL variables + */ + public UrlTemplateParameters createUrlTemplateParameters(final String dmiServiceBaseUrl, final String dmiBasePath) { + this.uriComponentsBuilder.pathSegment(dmiBasePath) + .pathSegment(VERSION_SEGMENT); + + final Map urlTemplateVariables = new HashMap<>(); + + pathSegments.forEach((pathSegmentName, variablePathValue) -> { + if (StringUtils.equals(variablePathValue, FIXED_PATH_SEGMENT)) { + this.uriComponentsBuilder.pathSegment(pathSegmentName); + } else { + this.uriComponentsBuilder.pathSegment("{" + pathSegmentName + "}"); + urlTemplateVariables.put(pathSegmentName, variablePathValue); + } + }); + + queryParameters.forEach((paramName, paramValue) -> { + this.uriComponentsBuilder.queryParam(paramName, "{" + paramName + "}"); + urlTemplateVariables.put(paramName, paramValue); + }); + + final String urlTemplate = dmiServiceBaseUrl + this.uriComponentsBuilder.build().toUriString(); + return new UrlTemplateParameters(urlTemplate, urlTemplateVariables); + } + + /** + * Constructs a URL for DMI health check based on the given base URL. + * + * @param dmiServiceBaseUrl the base URL of the DMI service, e.g., "http://dmi-service.com". + * @return a {@link UrlTemplateParameters} instance containing the complete URL template and empty URL variables, + * suitable for DMI health check. + */ + public UrlTemplateParameters createUrlTemplateParametersForHealthCheck(final String dmiServiceBaseUrl) { + this.uriComponentsBuilder.pathSegment("actuator") + .pathSegment("health"); + + final String urlTemplate = dmiServiceBaseUrl + this.uriComponentsBuilder.build().toUriString(); + return new UrlTemplateParameters(urlTemplate, Collections.emptyMap()); + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiWebClientConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiWebClientConfiguration.java new file mode 100644 index 0000000000..c176e40226 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiWebClientConfiguration.java @@ -0,0 +1,122 @@ +/* + * ============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.impl.dmi; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import io.netty.channel.ChannelOption; +import io.netty.handler.timeout.ReadTimeoutHandler; +import io.netty.handler.timeout.WriteTimeoutHandler; +import io.netty.resolver.DefaultAddressResolverGroup; +import java.time.Duration; +import java.util.concurrent.TimeUnit; +import lombok.RequiredArgsConstructor; +import org.onap.cps.ncmp.config.HttpClientConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.netty.http.client.HttpClient; +import reactor.netty.resources.ConnectionProvider; + +/** + * Configures and creates WebClient beans for various DMI services including data, model, and health check services. + * The configuration utilizes Netty-based HttpClient with custom connection settings, read and write timeouts, + * and initializes WebClient with these settings to ensure optimal performance and resource management. + */ +@Configuration +@RequiredArgsConstructor +public class DmiWebClientConfiguration { + + private final HttpClientConfiguration httpClientConfiguration; + private static final Duration DEFAULT_RESPONSE_TIMEOUT = Duration.ofSeconds(30); + + /** + * Configures and creates a web client bean for DMI data services. + * + * @param webClientBuilder The builder instance to create the WebClient. + * @return a WebClient instance configured for data services. + */ + @Bean + public WebClient dataServicesWebClient(final WebClient.Builder webClientBuilder) { + return configureWebClient(webClientBuilder, httpClientConfiguration.getDataServices()); + } + + /** + * Configures and creates a web client bean for DMI model services. + * + * @param webClientBuilder The builder instance to create the WebClient. + * @return a WebClient instance configured for model services. + */ + @Bean + public WebClient modelServicesWebClient(final WebClient.Builder webClientBuilder) { + return configureWebClient(webClientBuilder, httpClientConfiguration.getModelServices()); + } + + /** + * Configures and creates a web client bean for DMI health check services. + * + * @param webClientBuilder The builder instance to create the WebClient. + * @return a WebClient instance configured for health check services. + */ + @Bean + public WebClient healthChecksWebClient(final WebClient.Builder webClientBuilder) { + return configureWebClient(webClientBuilder, httpClientConfiguration.getHealthCheckServices()); + } + + private WebClient configureWebClient(final WebClient.Builder webClientBuilder, + final HttpClientConfiguration.ServiceConfig serviceConfig) { + final ConnectionProvider connectionProvider = getConnectionProvider(serviceConfig); + final HttpClient httpClient = createHttpClient(serviceConfig, connectionProvider); + return buildAndGetWebClient(webClientBuilder, httpClient, serviceConfig.getMaximumInMemorySizeInMegabytes()); + } + + private static HttpClient createHttpClient(final HttpClientConfiguration.ServiceConfig serviceConfig, + final ConnectionProvider connectionProvider) { + return HttpClient.create(connectionProvider) + .responseTimeout(DEFAULT_RESPONSE_TIMEOUT) + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, serviceConfig.getConnectionTimeoutInSeconds() * 1000) + .doOnConnected(connection -> connection.addHandlerLast(new ReadTimeoutHandler( + serviceConfig.getReadTimeoutInSeconds(), TimeUnit.SECONDS)).addHandlerLast( + new WriteTimeoutHandler(serviceConfig.getWriteTimeoutInSeconds(), TimeUnit.SECONDS))) + .resolver(DefaultAddressResolverGroup.INSTANCE) + .compress(true); + } + + @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE") + private static ConnectionProvider getConnectionProvider(final HttpClientConfiguration.ServiceConfig serviceConfig) { + return ConnectionProvider.builder(serviceConfig.getConnectionProviderName()) + .maxConnections(serviceConfig.getMaximumConnectionsTotal()) + .pendingAcquireMaxCount(serviceConfig.getPendingAcquireMaxCount()) + .build(); + } + + private WebClient buildAndGetWebClient(final WebClient.Builder webClientBuilder, final HttpClient httpClient, + final int maximumInMemorySizeInMegabytes) { + return webClientBuilder + .defaultHeaders(header -> header.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)) + .defaultHeaders(header -> header.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)) + .clientConnector(new ReactorClientHttpConnector(httpClient)) + .codecs(configurer -> configurer.defaultCodecs() + .maxInMemorySize(maximumInMemorySizeInMegabytes * 1024 * 1024)).build(); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/UrlTemplateParameters.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/UrlTemplateParameters.java new file mode 100644 index 0000000000..f51511116a --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/UrlTemplateParameters.java @@ -0,0 +1,30 @@ +/* + * ============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.impl.dmi; + +import java.util.Map; + +/** + * Represents a URL template with associated variables for dynamic substitution. + * This record encapsulates a URL template string and a map of variables used for substitution within the template. + */ +public record UrlTemplateParameters(String urlTemplate, Map urlVariables) { +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java index c1f89b3440..433c67f100 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java @@ -33,11 +33,11 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import lombok.RequiredArgsConstructor; -import org.onap.cps.ncmp.api.impl.client.DmiRestClient; -import org.onap.cps.ncmp.api.impl.config.DmiProperties; -import org.onap.cps.ncmp.api.impl.utils.url.builder.DmiServiceUrlTemplateBuilder; -import org.onap.cps.ncmp.api.impl.utils.url.builder.UrlTemplateParameters; import org.onap.cps.ncmp.api.inventory.models.YangResource; +import org.onap.cps.ncmp.impl.dmi.DmiProperties; +import org.onap.cps.ncmp.impl.dmi.DmiRestClient; +import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder; +import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; import org.onap.cps.ncmp.impl.models.DmiRequestBody; import org.onap.cps.spi.model.ModuleReference; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCreator.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCreator.java index 3ce6b91590..5137515758 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCreator.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCreator.java @@ -26,12 +26,12 @@ import lombok.NoArgsConstructor; import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.impl.utils.EventDateTimeFormatter; import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; import org.onap.cps.ncmp.events.lcm.v1.Event; import org.onap.cps.ncmp.events.lcm.v1.LcmEvent; import org.onap.cps.ncmp.events.lcm.v1.LcmEventHeader; import org.onap.cps.ncmp.events.lcm.v1.Values; +import org.onap.cps.ncmp.impl.utils.EventDateTimeFormatter; import org.springframework.stereotype.Component; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDog.java index 8be8ead44c..c81e9b7840 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDog.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDog.java @@ -24,10 +24,10 @@ import java.util.Collection; import java.util.Map; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.impl.client.DmiRestClient; -import org.onap.cps.ncmp.api.impl.utils.url.builder.DmiServiceUrlTemplateBuilder; -import org.onap.cps.ncmp.api.impl.utils.url.builder.UrlTemplateParameters; import org.onap.cps.ncmp.api.inventory.models.TrustLevel; +import org.onap.cps.ncmp.impl.dmi.DmiRestClient; +import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder; +import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters; import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.scheduling.annotation.Scheduled; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/EventDateTimeFormatter.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/EventDateTimeFormatter.java new file mode 100644 index 0000000000..9284c0fab7 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/EventDateTimeFormatter.java @@ -0,0 +1,47 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-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.impl.utils; + +import java.time.OffsetDateTime; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import org.apache.commons.lang3.StringUtils; + +public interface EventDateTimeFormatter { + + String ISO_TIMESTAMP_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; + + DateTimeFormatter ISO_TIMESTAMP_FORMATTER = DateTimeFormatter.ofPattern(ISO_TIMESTAMP_PATTERN); + + /** + * Gets current date time. + * + * @return the current date time + */ + static String getCurrentIsoFormattedDateTime() { + return ZonedDateTime.now().format(ISO_TIMESTAMP_FORMATTER); + } + + static OffsetDateTime toIsoOffsetDateTime(final String dateTimestampAsString) { + return StringUtils.isNotBlank(dateTimestampAsString) + ? OffsetDateTime.parse(dateTimestampAsString, ISO_TIMESTAMP_FORMATTER) : null; + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/AbstractModelLoader.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/AbstractModelLoader.java index 554501127c..6d51eb48b8 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/AbstractModelLoader.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/AbstractModelLoader.java @@ -33,7 +33,7 @@ import org.onap.cps.api.CpsAnchorService; import org.onap.cps.api.CpsDataService; import org.onap.cps.api.CpsDataspaceService; import org.onap.cps.api.CpsModuleService; -import org.onap.cps.ncmp.api.impl.exception.NcmpStartUpException; +import org.onap.cps.ncmp.exceptions.NcmpStartUpException; import org.onap.cps.spi.CascadeDeleteAllowed; import org.onap.cps.spi.exceptions.AlreadyDefinedException; import org.onap.cps.utils.JsonObjectMapper; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoader.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoader.java index 2592703449..780b240b6c 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoader.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoader.java @@ -30,7 +30,7 @@ import org.onap.cps.api.CpsDataService; import org.onap.cps.api.CpsDataspaceService; import org.onap.cps.api.CpsModuleService; import org.onap.cps.ncmp.api.data.models.DatastoreType; -import org.onap.cps.ncmp.api.impl.exception.NcmpStartUpException; +import org.onap.cps.ncmp.exceptions.NcmpStartUpException; import org.onap.cps.spi.exceptions.AlreadyDefinedException; import org.springframework.stereotype.Service; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpEvent.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpEvent.java index 67128bd159..8d3190eb00 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpEvent.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpEvent.java @@ -27,8 +27,8 @@ import java.util.Map; import java.util.UUID; import lombok.Builder; import org.apache.commons.lang3.StringUtils; -import org.onap.cps.ncmp.api.impl.utils.EventDateTimeFormatter; -import org.onap.cps.ncmp.api.impl.utils.context.CpsApplicationContext; +import org.onap.cps.ncmp.config.CpsApplicationContext; +import org.onap.cps.ncmp.impl.utils.EventDateTimeFormatter; import org.onap.cps.utils.JsonObjectMapper; @Builder diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/TopicValidator.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/TopicValidator.java index a7ad86cda5..07da7f76a0 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/TopicValidator.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/TopicValidator.java @@ -23,7 +23,7 @@ package org.onap.cps.ncmp.utils.events; import java.util.regex.Pattern; import lombok.AccessLevel; import lombok.NoArgsConstructor; -import org.onap.cps.ncmp.exceptions.InvalidTopicException; +import org.onap.cps.ncmp.api.exceptions.InvalidTopicException; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class TopicValidator { -- cgit