From a05ca3d3152de44ac3078e2455834dedb5789b1b Mon Sep 17 00:00:00 2001 From: ToineSiebelink Date: Tue, 27 Aug 2024 14:56:44 +0100 Subject: Invoke Policy Executor and handle not-allowed response - Execute Policy Executor REST request - Act (and log) on response from Policy Executor - Add dispatcher(mock) in integration test FWK - Add integration test for allow/non allowed and no authorization use cases - disabled PolicyExecution feature by default (only enabled for testware) Issue-ID: CPS-2247 Change-Id: I111ba9ba89cc91649b63b20f88414aa33721dbeb Signed-off-by: ToineSiebelink Signed-off-by: mpriyank --- .../api/exceptions/PolicyExecutorException.java | 42 +++++++ .../onap/cps/ncmp/impl/data/DmiDataOperations.java | 3 +- .../impl/data/policyexecutor/PolicyExecutor.java | 122 ++++++++++++++++++-- .../utils/http/RestServiceUrlTemplateBuilder.java | 6 +- .../cps/ncmp/config/DmiHttpClientConfigSpec.groovy | 2 +- .../PolicyExecutorHttpClientConfigSpec.groovy | 2 +- .../data/PolicyExecutorConfigurationSpec.groovy | 45 ++++++++ .../cps/ncmp/impl/data/PolicyExecutorSpec.groovy | 124 ++++++++++++++++----- .../cps/ncmp/utils/WebClientBuilderTestConfig.java | 40 +++++++ .../src/test/resources/application.yml | 4 +- 10 files changed, 342 insertions(+), 48 deletions(-) create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/PolicyExecutorException.java create mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorConfigurationSpec.groovy create mode 100644 cps-ncmp-service/src/test/java/org/onap/cps/ncmp/utils/WebClientBuilderTestConfig.java (limited to 'cps-ncmp-service/src') diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/PolicyExecutorException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/PolicyExecutorException.java new file mode 100644 index 0000000000..333c12271b --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/PolicyExecutorException.java @@ -0,0 +1,42 @@ +/* + * ============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; + +import lombok.Getter; + +/** + * Exception to be used when policy execution fails or does not allow to proceed. + */ +@Getter +public class PolicyExecutorException extends NcmpException { + + private static final long serialVersionUID = 6659897770659834798L; + + /** + * Constructor to form exception for policy executor responses. + * + * @param message response message + * @param details response details + */ + public PolicyExecutorException(final String message, final String details) { + super(message, details); + } +} 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 0cedeae0a4..e49ba665c9 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 @@ -139,8 +139,7 @@ public class DmiDataOperations { final String requestId, final String authorization) { - final Set cmHandlesIds - = getDistinctCmHandleIds(dataOperationRequest); + final Set cmHandlesIds = getDistinctCmHandleIds(dataOperationRequest); final Collection yangModelCmHandles = inventoryPersistence.getYangModelCmHandles(cmHandlesIds); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutor.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutor.java index 8e7620ccea..89b48f3755 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutor.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutor.java @@ -20,12 +20,26 @@ package org.onap.cps.ncmp.impl.data.policyexecutor; +import com.fasterxml.jackson.databind.JsonNode; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.data.models.OperationType; +import org.onap.cps.ncmp.api.exceptions.PolicyExecutorException; +import org.onap.cps.ncmp.api.exceptions.ServerNcmpException; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.ncmp.impl.utils.http.RestServiceUrlTemplateBuilder; +import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; @Slf4j @Service @@ -41,7 +55,8 @@ public class PolicyExecutor { @Value("${ncmp.policy-executor.server.port:8080}") private String serverPort; - private static final String PAYLOAD_TYPE_PREFIX = "cm_"; + @Qualifier("policyExecutorWebClient") + private final WebClient policyExecutorWebClient; /** * Use the Policy Executor to check permission for a cm write operation. @@ -58,17 +73,102 @@ public class PolicyExecutor { final String authorization, final String resourceIdentifier, final String changeRequestAsJson) { + log.trace("Policy Executor Enabled: {}", enabled); if (enabled) { - final String payloadType = PAYLOAD_TYPE_PREFIX + operationType.getOperationName(); - log.info("Policy Executor Enabled"); - log.info("Address : {}", serverAddress); - log.info("Port : {}", serverPort); - log.info("Authorization : {}", authorization); - log.info("Payload Type : {}", payloadType); - log.info("Target FDN : {}", yangModelCmHandle.getAlternateId()); - log.info("CM Handle Id : {}", yangModelCmHandle.getId()); - log.info("Resource Identifier : {}", resourceIdentifier); - log.info("Change Request (json) : {}", changeRequestAsJson); + final ResponseEntity responseEntity = + getPolicyExecutorResponse(yangModelCmHandle, operationType, authorization, resourceIdentifier, + changeRequestAsJson); + + if (responseEntity == null) { + log.warn("No valid response from policy, ignored"); + return; + } + + if (responseEntity.getStatusCode().is2xxSuccessful()) { + if (responseEntity.getBody() == null) { + log.warn("No valid response body from policy, ignored"); + return; + } + processResponse(responseEntity.getBody()); + } else { + log.warn("Policy Executor invocation failed with status {}", + responseEntity.getStatusCode().value()); + throw new ServerNcmpException("Policy Executor invocation failed", "HTTP status code: " + + responseEntity.getStatusCode().value()); + } + } + } + + private Map getSingleRequestAsMap(final YangModelCmHandle yangModelCmHandle, + final OperationType operationType, + final String resourceIdentifier, + final String changeRequestAsJson) { + final Map data = new HashMap<>(4); + data.put("cmHandleId", yangModelCmHandle.getId()); + data.put("resourceIdentifier", resourceIdentifier); + data.put("targetIdentifier", yangModelCmHandle.getAlternateId()); + if (!OperationType.DELETE.equals(operationType)) { + data.put("cmChangeRequest", changeRequestAsJson); + } + + final Map request = new HashMap<>(2); + request.put("schema", getAssociatedPolicyDataSchemaName(operationType)); + request.put("data", data); + return request; + } + + private static String getAssociatedPolicyDataSchemaName(final OperationType operationType) { + return "urn:cps:org.onap.cps.ncmp.policy-executor.ncmp-" + operationType.getOperationName() + "-schema:1.0.0"; + } + + private Object createBodyAsObject(final List requests) { + final Map bodyAsMap = new HashMap<>(2); + bodyAsMap.put("decisionType", "allow"); + bodyAsMap.put("requests", requests); + return bodyAsMap; + } + + private ResponseEntity getPolicyExecutorResponse(final YangModelCmHandle yangModelCmHandle, + final OperationType operationType, + final String authorization, + final String resourceIdentifier, + final String changeRequestAsJson) { + final String serviceBaseUrl = serverAddress + ":" + serverPort; + + final Map requestAsMap = getSingleRequestAsMap(yangModelCmHandle, + operationType, + resourceIdentifier, + changeRequestAsJson); + + final Object bodyAsObject = createBodyAsObject(Collections.singletonList(requestAsMap)); + + final UrlTemplateParameters urlTemplateParameters = RestServiceUrlTemplateBuilder.newInstance() + .fixedPathSegment("execute") + .createUrlTemplateParameters(serviceBaseUrl, ""); + + return policyExecutorWebClient.post() + .uri(urlTemplateParameters.urlTemplate(), urlTemplateParameters.urlVariables()) + .header(HttpHeaders.AUTHORIZATION, authorization) + .body(BodyInserters.fromValue(bodyAsObject)) + .retrieve() + .toEntity(JsonNode.class) + .block(); + } + + private static void processResponse(final JsonNode responseBody) { + final String decisionId = responseBody.path("decisionId").asText("unknown id"); + log.trace("Policy Executor Decision ID: {} ", decisionId); + final String decision = responseBody.path("decision").asText("unknown"); + if ("allow".equals(decision)) { + log.trace("Policy Executor allows the operation"); + } else { + log.warn("Policy Executor decision: {}", decision); + final String details = responseBody.path("message").asText(); + log.warn("Policy Executor message: {}", details); + final String message = "Policy Executor did not allow request. Decision #" + + decisionId + " : " + decision; + throw new PolicyExecutorException(message, details); } } + } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/RestServiceUrlTemplateBuilder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/RestServiceUrlTemplateBuilder.java index fafb09007d..c850ca94a0 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/RestServiceUrlTemplateBuilder.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/RestServiceUrlTemplateBuilder.java @@ -96,9 +96,7 @@ public class RestServiceUrlTemplateBuilder { * @return a UrlTemplateParameters instance containing the complete URL template and URL variables */ public UrlTemplateParameters createUrlTemplateParameters(final String serviceBaseUrl, final String basePath) { - this.uriComponentsBuilder.pathSegment(basePath) - .pathSegment(VERSION_SEGMENT); - + this.uriComponentsBuilder.pathSegment(basePath).pathSegment(VERSION_SEGMENT); final Map urlTemplateVariables = new HashMap<>(); pathSegments.forEach((pathSegmentName, variablePathValue) -> { @@ -120,7 +118,7 @@ public class RestServiceUrlTemplateBuilder { } /** - * Constructs a URL for DMI health check based on the given base URL. + * Constructs a URL for a spring actuator health check based on the given base URL. * * @param serviceBaseUrl the base URL of the service, e.g., "http://dmi-service.com". * @return a {@link UrlTemplateParameters} instance containing the complete URL template and empty URL variables, diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/DmiHttpClientConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/DmiHttpClientConfigSpec.groovy index e0ae204c8d..23f5edd890 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/DmiHttpClientConfigSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/DmiHttpClientConfigSpec.groovy @@ -29,7 +29,7 @@ import spock.lang.Specification @SpringBootTest @ContextConfiguration(classes = [DmiHttpClientConfig]) -@EnableConfigurationProperties(DmiHttpClientConfig) +@EnableConfigurationProperties class DmiHttpClientConfigSpec extends Specification { @Autowired diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfigSpec.groovy index 1946a452b1..ca71c345c1 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfigSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfigSpec.groovy @@ -34,7 +34,7 @@ class PolicyExecutorHttpClientConfigSpec extends Specification { @Autowired PolicyExecutorHttpClientConfig policyExecutorHttpClientConfig - def 'Test http client configuration properties of data with custom and default values'() { + def 'Http client configuration properties for policy executor http client.'() { expect: 'properties are populated correctly for all services' with(policyExecutorHttpClientConfig.allServices) { assert maximumInMemorySizeInMegabytes == 31 diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorConfigurationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorConfigurationSpec.groovy new file mode 100644 index 0000000000..c086eab810 --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorConfigurationSpec.groovy @@ -0,0 +1,45 @@ +/* + * ============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.data + +import org.onap.cps.ncmp.config.PolicyExecutorHttpClientConfig +import org.onap.cps.ncmp.impl.data.policyexecutor.PolicyExecutor +import org.onap.cps.ncmp.impl.policyexecutor.PolicyExecutorWebClientConfiguration +import org.onap.cps.ncmp.utils.WebClientBuilderTestConfig +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.context.ContextConfiguration +import spock.lang.Specification + +@SpringBootTest +@ContextConfiguration(classes = [PolicyExecutor, PolicyExecutorWebClientConfiguration, PolicyExecutorHttpClientConfig, WebClientBuilderTestConfig ]) +class PolicyExecutorConfigurationSpec extends Specification { + + @Autowired + PolicyExecutor objectUnderTest + + def 'Policy executor configuration properties.'() { + expect: 'properties used from application.yml' + assert objectUnderTest.enabled + assert objectUnderTest.serverAddress == 'http://localhost' + assert objectUnderTest.serverPort == '8785' + } +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorSpec.groovy index 4b09afa2ae..a5776676dc 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorSpec.groovy @@ -1,69 +1,139 @@ +/* + * ============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.data import ch.qos.logback.classic.Level import ch.qos.logback.classic.Logger import ch.qos.logback.classic.spi.ILoggingEvent import ch.qos.logback.core.read.ListAppender +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.ObjectMapper +import org.onap.cps.ncmp.api.exceptions.PolicyExecutorException +import org.onap.cps.ncmp.api.exceptions.ServerNcmpException import org.onap.cps.ncmp.impl.data.policyexecutor.PolicyExecutor import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle import org.slf4j.LoggerFactory -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.test.context.ContextConfiguration +import org.springframework.http.HttpStatus +import org.springframework.http.ResponseEntity +import org.springframework.web.reactive.function.client.WebClient +import reactor.core.publisher.Mono import spock.lang.Specification +import static org.onap.cps.ncmp.api.data.models.OperationType.CREATE +import static org.onap.cps.ncmp.api.data.models.OperationType.DELETE import static org.onap.cps.ncmp.api.data.models.OperationType.PATCH +import static org.onap.cps.ncmp.api.data.models.OperationType.UPDATE -@SpringBootTest -@ContextConfiguration(classes = [PolicyExecutor]) class PolicyExecutorSpec extends Specification { - @Autowired - PolicyExecutor objectUnderTest + def mockWebClient = Mock(WebClient) + def mockRequestBodyUriSpec = Mock(WebClient.RequestBodyUriSpec) + def mockResponseSpec = Mock(WebClient.ResponseSpec) + + PolicyExecutor objectUnderTest = new PolicyExecutor(mockWebClient) def logAppender = Spy(ListAppender) + ObjectMapper objectMapper = new ObjectMapper() + def setup() { setupLogger() + objectUnderTest.enabled = true + mockWebClient.post() >> mockRequestBodyUriSpec + mockRequestBodyUriSpec.uri(*_) >> mockRequestBodyUriSpec + mockRequestBodyUriSpec.header(*_) >> mockRequestBodyUriSpec + mockRequestBodyUriSpec.body(*_) >> mockRequestBodyUriSpec + mockRequestBodyUriSpec.retrieve() >> mockResponseSpec } def cleanup() { ((Logger) LoggerFactory.getLogger(PolicyExecutor)).detachAndStopAllAppenders() } - def 'Configuration properties.'() { - expect: 'properties used from application.yml' - assert objectUnderTest.enabled - assert objectUnderTest.serverAddress == 'http://localhost' - assert objectUnderTest.serverPort == '8785' + def 'Permission check with allow response.'() { + given: 'allow response' + mockResponse([decision:'allow'], HttpStatus.OK) + when: 'permission is checked for an operation' + objectUnderTest.checkPermission(new YangModelCmHandle(), operationType, 'my credentials','my resource','my change') + then: 'system logs the operation is allowed' + assert getLogEntry(2) == 'Policy Executor allows the operation' + and: 'no exception occurs' + noExceptionThrown() + where: 'all write operations are tested' + operationType << [ CREATE, DELETE, PATCH, UPDATE ] + } + + def 'Permission check with other response (not allowed).'() { + given: 'other response' + mockResponse([decision:'other', decisionId:123, message:'I dont like Mondays' ], HttpStatus.OK) + when: 'permission is checked for an operation' + objectUnderTest.checkPermission(new YangModelCmHandle(), PATCH, 'my credentials','my resource','my change') + then: 'Policy Executor exception is thrown' + def thrownException = thrown(PolicyExecutorException) + assert thrownException.message == 'Policy Executor did not allow request. Decision #123 : other' + assert thrownException.details == 'I dont like Mondays' + } + + def 'Permission check with non 2xx response.'() { + given: 'other response' + mockResponse([], HttpStatus.I_AM_A_TEAPOT) + when: 'permission is checked for an operation' + objectUnderTest.checkPermission(new YangModelCmHandle(), PATCH, 'my credentials','my resource','my change') + then: 'Server Ncmp exception is thrown' + def thrownException = thrown(ServerNcmpException) + assert thrownException.message == 'Policy Executor invocation failed' + assert thrownException.details == 'HTTP status code: 418' } - def 'Permission check logging.'() { + def 'Permission check with invalid response from Policy Executor.'() { + given: 'invalid response from Policy executor' + mockResponseSpec.toEntity(*_) >> invalidResponse when: 'permission is checked for an operation' - def yangModelCmHandle = new YangModelCmHandle(id:'ch-1', alternateId:'fdn1') - objectUnderTest.checkPermission(yangModelCmHandle, PATCH, 'my credentials','my resource','my change') - then: 'correct details are logged ' - assert getLogEntry(0) == 'Policy Executor Enabled' - assert getLogEntry(3).contains('my credentials') - assert getLogEntry(4).contains('cm_patch') - assert getLogEntry(5).contains('fdn1') - assert getLogEntry(6).contains('ch-1') - assert getLogEntry(7).contains('my resource') - assert getLogEntry(8).contains('my change') + objectUnderTest.checkPermission(new YangModelCmHandle(), CREATE, 'my credentials','my resource','my change') + then: 'system logs the expected message' + assert getLogEntry(1) == expectedMessage + where: 'following invalid responses are received' + invalidResponse || expectedMessage + Mono.empty() || 'No valid response from policy, ignored' + Mono.just(new ResponseEntity<>(null, HttpStatus.OK)) || 'No valid response body from policy, ignored' } - def 'Permission check with feature disabled.'() { + def 'Permission check feature disabled.'() { given: 'feature is disabled' objectUnderTest.enabled = false when: 'permission is checked for an operation' objectUnderTest.checkPermission(new YangModelCmHandle(), PATCH, 'my credentials','my resource','my change') - then: 'nothing is logged' - assert logAppender.list.isEmpty() + then: 'system logs that the feature not enabled' + assert getLogEntry(0) == 'Policy Executor Enabled: false' + } + + def mockResponse(mockResponseAsMap, httpStatus) { + JsonNode jsonNode = objectMapper.readTree(objectMapper.writeValueAsString(mockResponseAsMap)) + def mono = Mono.just(new ResponseEntity<>(jsonNode, httpStatus)) + mockResponseSpec.toEntity(*_) >> mono } def setupLogger() { def logger = LoggerFactory.getLogger(PolicyExecutor) - logger.setLevel(Level.DEBUG) + logger.setLevel(Level.TRACE) logger.addAppender(logAppender) logAppender.start() } diff --git a/cps-ncmp-service/src/test/java/org/onap/cps/ncmp/utils/WebClientBuilderTestConfig.java b/cps-ncmp-service/src/test/java/org/onap/cps/ncmp/utils/WebClientBuilderTestConfig.java new file mode 100644 index 0000000000..2f6b270076 --- /dev/null +++ b/cps-ncmp-service/src/test/java/org/onap/cps/ncmp/utils/WebClientBuilderTestConfig.java @@ -0,0 +1,40 @@ +/* + * ============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.utils; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.web.reactive.function.client.WebClient; + +@TestConfiguration +public class WebClientBuilderTestConfig { + + /** + * Configures and creates a web client builder bean to make it accessible for the Spring Boot Test Context. + * + * @return a WebClient Builder instance. + */ + @Bean + public WebClient.Builder webClientBuilder() { + return WebClient.builder(); + } + +} diff --git a/cps-ncmp-service/src/test/resources/application.yml b/cps-ncmp-service/src/test/resources/application.yml index 72d074ab5f..c76831da74 100644 --- a/cps-ncmp-service/src/test/resources/application.yml +++ b/cps-ncmp-service/src/test/resources/application.yml @@ -84,8 +84,8 @@ ncmp: policy-executor: enabled: true server: - address: "http://localhost" - port: "8785" + address: http://localhost + port: 8785 httpclient: all-services: maximumInMemorySizeInMegabytes: 31 -- cgit 1.2.3-korg