summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsourabh_sourabh <sourabh.sourabh@est.tech>2024-05-27 18:28:10 +0100
committerSourabh Sourabh <sourabh.sourabh@est.tech>2024-06-06 15:54:57 +0000
commit43d0451a27311e4154536a66cb22eb4d68a21e7a (patch)
treeeaef3f668b77ed49849410b21d7542ab912aee34
parentd7fa9601a1409ee3a156ac2f6a6ec11853989cd7 (diff)
#1: Dedicated web client instance is assigned for data, model and health services
- Switched web client instance based on dmi service type (like data or model) - 3 diff. beans are configured for data, model and health dmi service. - Added configurable properties for data and model. - Hard coded properties are assigned for health service. Issue-ID: CPS-2231 Change-Id: I39fb739c07c41430dae43509fe29ece5306b7d71 Signed-off-by: sourabh_sourabh <sourabh.sourabh@est.tech>
-rw-r--r--cps-application/src/main/resources/application.yml17
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java85
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfiguration.java85
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/HttpClientConfiguration.java38
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java18
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/async/DataOperationEventConsumerSpec.groovy4
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy121
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfigurationSpec.groovy30
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/HttpClientConfigurationSpec.groovy40
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy16
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy19
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/context/CpsApplicationContextSpec.groovy20
-rw-r--r--cps-ncmp-service/src/test/resources/application.yml8
14 files changed, 340 insertions, 163 deletions
diff --git a/cps-application/src/main/resources/application.yml b/cps-application/src/main/resources/application.yml
index 9c8c1ecd5f..4f08bb61a0 100644
--- a/cps-application/src/main/resources/application.yml
+++ b/cps-application/src/main/resources/application.yml
@@ -189,11 +189,18 @@ logging:
ncmp:
dmi:
httpclient:
- connectionTimeoutInSeconds: 30
- readTimeoutInSeconds: 30
- writeTimeoutInSeconds: 30
- maximumConnectionsTotal: 100
- maximumInMemorySizeInMegabytes: 16
+ data-services:
+ connectionTimeoutInSeconds: 30
+ readTimeoutInSeconds: 30
+ writeTimeoutInSeconds: 30
+ maximumConnectionsTotal: 100
+ maximumInMemorySizeInMegabytes: 16
+ model-services:
+ connectionTimeoutInSeconds: 30
+ readTimeoutInSeconds: 30
+ writeTimeoutInSeconds: 30
+ maximumConnectionsTotal: 100
+ maximumInMemorySizeInMegabytes: 16
auth:
username: ${DMI_USERNAME:cpsuser}
password: ${DMI_PASSWORD:cpsr0cks!}
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
index ef48c43d2a..7878c5d0ba 100644
--- 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
@@ -26,6 +26,7 @@ import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNABLE_TO_READ_RESOURCE_D
import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
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.net.URI;
@@ -37,7 +38,9 @@ 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.exception.InvalidDmiResourceUrlException;
import org.onap.cps.ncmp.api.impl.operations.OperationType;
+import org.onap.cps.ncmp.api.impl.operations.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;
@@ -45,6 +48,7 @@ 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;
@Component
@@ -55,31 +59,43 @@ public class DmiRestClient {
private static final String HEALTH_CHECK_URL_EXTENSION = "/actuator/health";
private static final String NOT_SPECIFIED = "";
private static final String NO_AUTHORIZATION = null;
- private final WebClient webClient;
+
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 POST operation to DMI with json body containing module references.
+ * Sends a POST operation to the DMI with a JSON body containing module references.
*
- * @param dmiResourceUrl dmi resource url
- * @param requestBodyAsJsonString json data body
- * @param operationType the type of operation being executed (for error reporting only)
- * @param authorization contents of Authorization header, or null if not present
- * @return response entity of type String
+ * @param requiredDmiService Determines if the required service is for a data or model operation.
+ * @param dmiUrl The DMI resource URL.
+ * @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<Object> postOperationWithJsonData(final String dmiResourceUrl,
+ public ResponseEntity<Object> postOperationWithJsonData(final RequiredDmiService requiredDmiService,
+ final String dmiUrl,
final String requestBodyAsJsonString,
final OperationType operationType,
final String authorization) {
+ final WebClient webClient = requiredDmiService.equals(RequiredDmiService.DATA)
+ ? dataServicesWebClient : modelServicesWebClient;
try {
- return ResponseEntity.ok(webClient.post().uri(toUri(dmiResourceUrl))
+ return webClient.post()
+ .uri(toUri(dmiUrl))
.headers(httpHeaders -> configureHttpHeaders(httpHeaders, authorization))
.body(BodyInserters.fromValue(requestBodyAsJsonString))
.retrieve()
- .bodyToMono(Object.class)
+ .toEntity(Object.class)
.onErrorMap(httpError -> handleDmiClientException(httpError, operationType.getOperationName()))
- .block());
+ .block();
} catch (final HttpServerErrorException e) {
throw handleDmiClientException(e, operationType.getOperationName());
}
@@ -88,31 +104,31 @@ public class DmiRestClient {
/**
* Get DMI plugin health status.
*
- * @param dmiPluginBaseUrl the base URL of the dmi-plugin
- * @return plugin health status ("UP" is all OK, "" (not-specified) in case of any exception)
+ * @param dmiUrl the base URL of the dmi-plugin
+ * @return plugin health status ("UP" is all OK, "" (not-specified) in case of any exception)
*/
- public String getDmiHealthStatus(final String dmiPluginBaseUrl) {
+ public String getDmiHealthStatus(final String dmiUrl) {
try {
- final JsonNode responseHealthStatus = webClient.get()
- .uri(toUri(dmiPluginBaseUrl + HEALTH_CHECK_URL_EXTENSION))
+ final URI dmiHealthCheckUri = toUri(dmiUrl + HEALTH_CHECK_URL_EXTENSION);
+ final JsonNode responseHealthStatus = healthChecksWebClient.get()
+ .uri(dmiHealthCheckUri)
.headers(httpHeaders -> configureHttpHeaders(httpHeaders, NO_AUTHORIZATION))
.retrieve()
.bodyToMono(JsonNode.class).block();
return responseHealthStatus == null ? NOT_SPECIFIED :
- responseHealthStatus.get("status").asText();
+ responseHealthStatus.path("status").asText();
} catch (final Exception e) {
- log.warn("Failed to retrieve health status from {}. Error Message: {}", dmiPluginBaseUrl, e.getMessage());
+ log.warn("Failed to retrieve health status from {}. Error Message: {}", dmiUrl, e.getMessage());
return NOT_SPECIFIED;
}
}
- private HttpHeaders configureHttpHeaders(final HttpHeaders httpHeaders, final String authorization) {
+ 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);
}
- return httpHeaders;
}
private static URI toUri(final String dmiResourceUrl) {
@@ -123,22 +139,31 @@ public class DmiRestClient {
}
}
- private DmiClientRequestException handleDmiClientException(final Throwable e, final String operationType) {
- final String exceptionMessage = "Unable to " + operationType + " resource data.";
- if (e instanceof WebClientResponseException wcre) {
- if (wcre.getStatusCode().isSameCodeAs(HttpStatus.REQUEST_TIMEOUT)) {
- throw new DmiClientRequestException(wcre.getStatusCode().value(), wcre.getMessage(),
- jsonObjectMapper.asJsonString(wcre.getResponseBodyAsString()), DMI_SERVICE_NOT_RESPONDING);
+ 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(wcre.getStatusCode().value(), wcre.getMessage(),
- jsonObjectMapper.asJsonString(wcre.getResponseBodyAsString()), UNABLE_TO_READ_RESOURCE_DATA);
+ throw new DmiClientRequestException(webClientResponseException.getStatusCode().value(),
+ webClientResponseException.getMessage(),
+ jsonObjectMapper.asJsonString(webClientResponseException.getResponseBodyAsString()),
+ UNABLE_TO_READ_RESOURCE_DATA);
}
- if (e instanceof HttpServerErrorException httpServerErrorException) {
+ 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, e.getMessage(),
+ 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/DmiWebClientConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfiguration.java
index 2e84f7f69f..2c0b702627 100644
--- 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
@@ -34,6 +34,10 @@ import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.http.client.HttpClient;
import reactor.netty.resources.ConnectionProvider;
+/**
+ * Configures and creates a WebClient bean that triggers an initialization (warmup) of the host name resolver and
+ * loads the necessary native libraries to avoid the extra time needed to load resources for first request.
+ */
@Configuration
@RequiredArgsConstructor
public class DmiWebClientConfiguration {
@@ -41,30 +45,83 @@ public class DmiWebClientConfiguration {
private final HttpClientConfiguration httpClientConfiguration;
/**
- * Configures and create a WebClient bean that triggers an initialization (warmup) of the host name resolver and
- * loads the necessary native libraries to avoid the extra time needed to load resources for first request.
+ * Configures and create a WebClient bean for DMI data service.
+ *
+ * @return a WebClient instance for data services.
+ */
+ @Bean
+ public WebClient dataServicesWebClient() {
+ final HttpClientConfiguration.DataServices httpClientConfiguration
+ = this.httpClientConfiguration.getDataServices();
+
+ final HttpClient httpClient = createHttpClient("dataConnectionPool",
+ httpClientConfiguration.getMaximumConnectionsTotal(),
+ httpClientConfiguration.getConnectionTimeoutInSeconds(),
+ httpClientConfiguration.getReadTimeoutInSeconds(),
+ httpClientConfiguration.getWriteTimeoutInSeconds());
+ return buildAndGetWebClient(httpClient, httpClientConfiguration.getMaximumInMemorySizeInMegabytes());
+ }
+
+ /**
+ * Configures and creates a WebClient bean for DMI model service.
+ *
+ * @return a WebClient instance for model services.
+ */
+ @Bean
+ public WebClient modelServicesWebClient() {
+ final HttpClientConfiguration.ModelServices httpClientConfiguration
+ = this.httpClientConfiguration.getModelServices();
+
+ final HttpClient httpClient = createHttpClient("modelConnectionPool",
+ httpClientConfiguration.getMaximumConnectionsTotal(),
+ httpClientConfiguration.getConnectionTimeoutInSeconds(),
+ httpClientConfiguration.getReadTimeoutInSeconds(),
+ httpClientConfiguration.getWriteTimeoutInSeconds());
+ return buildAndGetWebClient(httpClient, httpClientConfiguration.getMaximumInMemorySizeInMegabytes());
+ }
+
+ /**
+ * Configures and creates a WebClient bean for DMI health service.
*
- * @return a WebClient instance.
+ * @return a WebClient instance for health checks.
*/
@Bean
- public WebClient webClient() {
- final ConnectionProvider dmiWebClientConnectionProvider = ConnectionProvider.create(
- "dmiWebClientConnectionPool", httpClientConfiguration.getMaximumConnectionsTotal());
+ public WebClient healthChecksWebClient() {
+ final HttpClientConfiguration.HealthCheckServices httpClientConfiguration
+ = this.httpClientConfiguration.getHealthCheckServices();
+
+ final HttpClient httpClient = createHttpClient("healthConnectionPool",
+ httpClientConfiguration.getMaximumConnectionsTotal(),
+ httpClientConfiguration.getConnectionTimeoutInSeconds(),
+ httpClientConfiguration.getReadTimeoutInSeconds(),
+ httpClientConfiguration.getWriteTimeoutInSeconds());
+ return buildAndGetWebClient(httpClient, httpClientConfiguration.getMaximumInMemorySizeInMegabytes());
+ }
+
+ private static HttpClient createHttpClient(final String connectionProviderName,
+ final Integer maximumConnectionsTotal,
+ final Integer connectionTimeoutInSeconds,
+ final Integer readTimeoutInSeconds,
+ final Integer writeTimeoutInSeconds) {
+ final ConnectionProvider dmiWebClientConnectionProvider = ConnectionProvider.create(connectionProviderName,
+ maximumConnectionsTotal);
final HttpClient httpClient = HttpClient.create(dmiWebClientConnectionProvider)
- .option(ChannelOption.CONNECT_TIMEOUT_MILLIS,
- httpClientConfiguration.getConnectionTimeoutInSeconds() * 1000)
- .doOnConnected(connection -> connection.addHandlerLast(new ReadTimeoutHandler(
- httpClientConfiguration.getReadTimeoutInSeconds(), TimeUnit.SECONDS))
- .addHandlerLast(new WriteTimeoutHandler(
- httpClientConfiguration.getWriteTimeoutInSeconds(), TimeUnit.SECONDS)));
+ .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectionTimeoutInSeconds * 1000)
+ .doOnConnected(connection -> connection.addHandlerLast(new ReadTimeoutHandler(readTimeoutInSeconds,
+ TimeUnit.SECONDS)).addHandlerLast(new WriteTimeoutHandler(writeTimeoutInSeconds,
+ TimeUnit.SECONDS)));
httpClient.warmup().block();
+ return httpClient;
+ }
+
+ private static WebClient buildAndGetWebClient(final HttpClient httpClient,
+ final Integer maximumInMemorySizeInMegabytes) {
return WebClient.builder()
.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(
- httpClientConfiguration.getMaximumInMemorySizeInMegabytes() * 1024 * 1024))
- .build();
+ 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
index d2521d9d1e..62432f6cae 100644
--- 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
@@ -30,9 +30,37 @@ import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "ncmp.dmi.httpclient")
public class HttpClientConfiguration {
- private Integer maximumConnectionsTotal = 100;
- private Integer connectionTimeoutInSeconds = 30;
- private Integer readTimeoutInSeconds = 30;
- private Integer writeTimeoutInSeconds = 30;
- private Integer maximumInMemorySizeInMegabytes = 1;
+
+ private final DataServices dataServices = new DataServices();
+ private final ModelServices modelServices = new ModelServices();
+ private final HealthCheckServices healthCheckServices = new HealthCheckServices();
+
+ @Getter
+ @Setter
+ public static class DataServices {
+ private Integer maximumConnectionsTotal = 100;
+ private Integer connectionTimeoutInSeconds = 30;
+ private Integer readTimeoutInSeconds = 30;
+ private Integer writeTimeoutInSeconds = 30;
+ private Integer maximumInMemorySizeInMegabytes = 1;
+ }
+
+ @Getter
+ @Setter
+ public static class ModelServices {
+ private Integer maximumConnectionsTotal = 100;
+ private Integer connectionTimeoutInSeconds = 30;
+ private Integer readTimeoutInSeconds = 30;
+ private Integer writeTimeoutInSeconds = 30;
+ private Integer maximumInMemorySizeInMegabytes = 1;
+ }
+
+ @Getter
+ public static class HealthCheckServices {
+ private final Integer maximumConnectionsTotal = 10;
+ private final Integer connectionTimeoutInSeconds = 30;
+ private final Integer readTimeoutInSeconds = 30;
+ private final Integer writeTimeoutInSeconds = 30;
+ private final Integer maximumInMemorySizeInMegabytes = 1;
+ }
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
index 6370879094..978855569a 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
@@ -23,6 +23,7 @@ package org.onap.cps.ncmp.api.impl.operations;
import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING;
import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ;
+import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.DATA;
import io.micrometer.core.annotation.Timed;
import java.util.Collection;
@@ -87,13 +88,9 @@ public class DmiDataOperations {
final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState();
validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState);
final String jsonRequestBody = getDmiRequestBody(READ, requestId, null, null, yangModelCmHandle);
-
- final String dmiUrl = getDmiResourceDataUrl(cmResourceAddress.datastoreName(),
- yangModelCmHandle,
- cmResourceAddress.resourceIdentifier(),
- optionsParamInQuery,
- topicParamInQuery);
- return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonRequestBody, READ, authorization);
+ final String dmiUrl = getDmiResourceDataUrl(cmResourceAddress.datastoreName(), yangModelCmHandle,
+ cmResourceAddress.resourceIdentifier(), optionsParamInQuery, topicParamInQuery);
+ return dmiRestClient.postOperationWithJsonData(DATA, dmiUrl, jsonRequestBody, READ, authorization);
}
/**
@@ -114,7 +111,7 @@ public class DmiDataOperations {
final String jsonRequestBody = getDmiRequestBody(READ, requestId, null, null, yangModelCmHandle);
final String dmiUrl = getDmiResourceDataUrl(datastoreName, yangModelCmHandle, "/", null, null);
- return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonRequestBody, READ, null);
+ return dmiRestClient.postOperationWithJsonData(DATA, dmiUrl, jsonRequestBody, READ, null);
}
/**
@@ -171,7 +168,7 @@ public class DmiDataOperations {
yangModelCmHandle);
final String dmiUrl = getDmiResourceDataUrl(PASSTHROUGH_RUNNING.getDatastoreName(),
yangModelCmHandle, resourceId, null, null);
- return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonRequestBody, operationType, authorization);
+ return dmiRestClient.postOperationWithJsonData(DATA, dmiUrl, jsonRequestBody, operationType, authorization);
}
private YangModelCmHandle getYangModelCmHandle(final String cmHandleId) {
@@ -251,7 +248,8 @@ public class DmiDataOperations {
.operations(dmiDataOperationRequestBodies).build();
final String dmiDataOperationRequestAsJsonString = jsonObjectMapper.asJsonString(dmiDataOperationRequest);
try {
- dmiRestClient.postOperationWithJsonData(dmiUrl, dmiDataOperationRequestAsJsonString, READ, authorization);
+ dmiRestClient.postOperationWithJsonData(DATA, dmiUrl, dmiDataOperationRequestAsJsonString, READ,
+ authorization);
} catch (final DmiClientRequestException e) {
handleTaskCompletionException(e, dmiUrl, dmiDataOperationRequestBodies);
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java
index 78d27b54b6..77dfcb7a20 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java
@@ -111,7 +111,7 @@ public class DmiModelOperations {
.variablePathSegment("cmHandleId", cmHandle)
.variablePathSegment("resourceName", resourceName)
.build(dmiServiceName, dmiProperties.getDmiBasePath());
- return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonRequestBody, OperationType.READ, null);
+ return dmiRestClient.postOperationWithJsonData(MODEL, dmiUrl, jsonRequestBody, OperationType.READ, null);
}
private static String getRequestBodyToFetchYangResources(final Collection<ModuleReference> newModuleReferences,
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/async/DataOperationEventConsumerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/async/DataOperationEventConsumerSpec.groovy
index 369b496ca7..b095f904a3 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/async/DataOperationEventConsumerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/async/DataOperationEventConsumerSpec.groovy
@@ -20,6 +20,8 @@
package org.onap.cps.ncmp.api.impl.async
+import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent
+
import com.fasterxml.jackson.databind.ObjectMapper
import io.cloudevents.CloudEvent
import io.cloudevents.kafka.CloudEventDeserializer
@@ -42,8 +44,6 @@ import org.springframework.test.annotation.DirtiesContext
import org.testcontainers.spock.Testcontainers
import java.time.Duration
-import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent
-
@SpringBootTest(classes = [EventsPublisher, DataOperationEventConsumer, RecordFilterStrategies, JsonObjectMapper, ObjectMapper])
@Testcontainers
@DirtiesContext
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy
index d2dce06b04..2c22127738 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy
@@ -21,9 +21,11 @@
package org.onap.cps.ncmp.api.impl.client
-import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ
-import static org.onap.cps.ncmp.api.impl.operations.OperationType.PATCH
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR
import static org.onap.cps.ncmp.api.impl.operations.OperationType.CREATE
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.PATCH
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ
+import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.DATA
import static org.springframework.http.HttpStatus.SERVICE_UNAVAILABLE
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
@@ -31,109 +33,102 @@ import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNABLE_TO_READ_RESOURCE_D
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.node.ObjectNode
-import org.onap.cps.ncmp.api.impl.config.DmiWebClientConfiguration
-import org.onap.cps.ncmp.api.impl.exception.InvalidDmiResourceUrlException
import org.onap.cps.ncmp.api.impl.exception.DmiClientRequestException
+import org.onap.cps.ncmp.api.impl.exception.InvalidDmiResourceUrlException
+import org.onap.cps.ncmp.api.impl.config.DmiProperties
import org.onap.cps.ncmp.utils.TestUtils
import org.onap.cps.utils.JsonObjectMapper
-import org.spockframework.spring.SpringBean
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.HttpHeaders
+import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
-import org.springframework.test.context.ContextConfiguration
import org.springframework.web.client.HttpServerErrorException
import org.springframework.web.reactive.function.client.WebClient
+import org.springframework.web.reactive.function.client.WebClientResponseException
+import org.springframework.web.reactive.function.client.WebClientRequestException
import reactor.core.publisher.Mono
import spock.lang.Specification
-import org.springframework.web.reactive.function.client.WebClientResponseException
-import org.onap.cps.ncmp.api.impl.config.DmiProperties
-@SpringBootTest
-@ContextConfiguration(classes = [DmiProperties, DmiRestClient, ObjectMapper])
class DmiRestClientSpec extends Specification {
static final NO_AUTH_HEADER = null
- static final BASIC_AUTH_HEADER = 'Basic c29tZS11c2VyOnNvbWUtcGFzc3dvcmQ='
+ static final BASIC_AUTH_HEADER = 'Basic c29tZSB1c2VyOnNvbWUgcGFzc3dvcmQ='
static final BEARER_AUTH_HEADER = 'Bearer my-bearer-token'
- @Autowired
- DmiProperties dmiProperties
+ def mockDataServicesWebClient = Mock(WebClient)
+ def mockModelServicesWebClient = Mock(WebClient)
+ def mockHealthChecksWebClient = Mock(WebClient)
- @Autowired
- DmiRestClient objectUnderTest
+ def mockRequestBody = Mock(WebClient.RequestBodyUriSpec)
+ def mockResponse = Mock(WebClient.ResponseSpec)
- @SpringBean
- WebClient mockWebClient = Mock(WebClient);
+ def responseBody = [message: 'Success']
+ def mockDmiProperties = Mock(DmiProperties)
- @SpringBean
JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
- def mockRequestBodyUriSpec = Mock(WebClient.RequestBodyUriSpec)
- def mockResponseSpec = Mock(WebClient.ResponseSpec)
- def mockResponseEntity = Mock(ResponseEntity)
+ DmiRestClient objectUnderTest = new DmiRestClient(mockDmiProperties, jsonObjectMapper, mockDataServicesWebClient, mockModelServicesWebClient, mockHealthChecksWebClient)
def setup() {
- mockRequestBodyUriSpec.uri(_) >> mockRequestBodyUriSpec
- mockRequestBodyUriSpec.headers(_) >> mockRequestBodyUriSpec
- mockRequestBodyUriSpec.retrieve() >> mockResponseSpec
+ mockRequestBody.uri(_) >> mockRequestBody
+ mockRequestBody.headers(_) >> mockRequestBody
+ mockRequestBody.body(_) >> mockRequestBody
+ mockRequestBody.retrieve() >> mockResponse
}
- def 'DMI POST operation with JSON.'() {
+ def 'DMI POST Operation with JSON for status #httpStatusCode'() {
given: 'the web client returns a valid response entity for the expected parameters'
- mockWebClient.post() >> mockRequestBodyUriSpec
- mockRequestBodyUriSpec.body(_) >> mockRequestBodyUriSpec
- def monoSpec = Mono.just(mockResponseEntity)
- mockResponseSpec.bodyToMono(Object.class) >> monoSpec
- monoSpec.block() >> mockResponseEntity
+ mockDataServicesWebClient.post() >> mockRequestBody
+ mockResponse.toEntity(Object.class) >> Mono.just(new ResponseEntity<>(responseBody, httpStatusCode))
when: 'POST operation is invoked'
- def response = objectUnderTest.postOperationWithJsonData('/my/url', 'some json', READ, null)
+ def response = objectUnderTest.postOperationWithJsonData(DATA, '/my/url', 'some json', READ, NO_AUTH_HEADER)
then: 'the output of the method is equal to the output from the test template'
- assert response.statusCode.value() == 200
- assert response.hasBody()
+ assert response.statusCode == httpStatusCode
+ assert response.body == responseBody
+ where: 'the following status codes are used'
+ httpStatusCode << [HttpStatus.OK, HttpStatus.CREATED, HttpStatus.ACCEPTED]
}
def 'Failing DMI POST operation for server error'() {
given: 'the web client throws an exception'
- mockWebClient.post() >> { throw new HttpServerErrorException(SERVICE_UNAVAILABLE, null, null, null) }
+ mockDataServicesWebClient.post() >> { throw new HttpServerErrorException(SERVICE_UNAVAILABLE, null, null, null) }
when: 'POST operation is invoked'
- objectUnderTest.postOperationWithJsonData('/some', 'some json', READ, null)
+ objectUnderTest.postOperationWithJsonData(DATA, '/some', 'some json', READ, NO_AUTH_HEADER)
then: 'a http client exception is thrown'
def thrown = thrown(DmiClientRequestException)
and: 'the exception has the relevant details from the error response'
- assert thrown.ncmpResponseStatus.code == '102'
- assert thrown.httpStatusCode == 503
+ thrown.ncmpResponseStatus.code == '102'
+ thrown.httpStatusCode == 503
}
def 'Failing DMI POST operation due to invalid dmi resource url.'() {
when: 'POST operation is invoked with invalid dmi resource url'
- objectUnderTest.postOperationWithJsonData('/invalid dmi url', null, null, null)
+ objectUnderTest.postOperationWithJsonData(DATA, '/invalid dmi url', null, null, NO_AUTH_HEADER)
then: 'invalid dmi resource url exception is thrown'
def thrown = thrown(InvalidDmiResourceUrlException)
and: 'the exception has the relevant details from the error response'
- assert thrown.httpStatus == 400
- assert thrown.message == 'Invalid dmi resource url: /invalid dmi url'
+ thrown.httpStatus == 400
+ thrown.message == 'Invalid dmi resource url: /invalid dmi url'
where: 'the following operations are executed'
operation << [CREATE, READ, PATCH]
}
def 'Dmi service sends client error response when #scenario'() {
given: 'the web client unable to return response entity but error'
- mockWebClient.post() >> mockRequestBodyUriSpec
- mockRequestBodyUriSpec.body(_) >> mockRequestBodyUriSpec
- def monoSpec = Mono.error(new WebClientResponseException('message', httpStatusCode, null, null, null, null))
- mockResponseSpec.bodyToMono(Object.class) >> monoSpec
+ mockDataServicesWebClient.post() >> mockRequestBody
+ mockResponse.toEntity(Object.class) >> Mono.error(exceptionType)
when: 'POST operation is invoked'
- objectUnderTest.postOperationWithJsonData('/my/url', 'some json', READ, null)
+ objectUnderTest.postOperationWithJsonData(DATA, '/my/url', 'some json', READ, NO_AUTH_HEADER)
then: 'a http client exception is thrown'
def thrown = thrown(DmiClientRequestException)
and: 'the exception has the relevant details from the error response'
- assert thrown.ncmpResponseStatus.code == expectedNcmpResponseStatusCode
+ assert thrown.ncmpResponseStatus == expectedNcmpResponseStatusCode
assert thrown.httpStatusCode == httpStatusCode
where: 'the following errors occur'
- scenario | httpStatusCode | expectedNcmpResponseStatusCode
- 'dmi request timeout' | 408 | DMI_SERVICE_NOT_RESPONDING.code
- 'other error code' | 500 | UNABLE_TO_READ_RESOURCE_DATA.code
+ scenario | httpStatusCode | exceptionType || expectedNcmpResponseStatusCode
+ 'dmi service unavailable' | 503 | new WebClientRequestException(new RuntimeException('some-error'), null, null, new HttpHeaders()) || DMI_SERVICE_NOT_RESPONDING
+ 'dmi request timeout' | 408 | new WebClientResponseException('message', httpStatusCode, 'statusText', null, null, null) || DMI_SERVICE_NOT_RESPONDING
+ 'dmi server error' | 500 | new WebClientResponseException('message', httpStatusCode, 'statusText', null, null, null) || UNABLE_TO_READ_RESOURCE_DATA
+ 'unknown error' | 500 | new Throwable('message') || UNKNOWN_ERROR
}
def 'Dmi trust level is determined by spring boot health status'() {
@@ -141,19 +136,18 @@ class DmiRestClientSpec extends Specification {
def dmiPluginHealthCheckResponseJsonData = TestUtils.getResourceFileContent('dmiPluginHealthCheckResponse.json')
def jsonNode = jsonObjectMapper.convertJsonString(dmiPluginHealthCheckResponseJsonData, JsonNode.class)
((ObjectNode) jsonNode).put('status', 'my status')
- def monoResponse = Mono.just(jsonNode)
- mockWebClient.get() >> mockRequestBodyUriSpec
- mockResponseSpec.bodyToMono(_) >> monoResponse
- monoResponse.block() >> jsonNode
+ mockHealthChecksWebClient.get() >> mockRequestBody
+ mockResponse.bodyToMono(JsonNode.class) >> Mono.just(jsonNode)
when: 'get trust level of the dmi plugin'
def result = objectUnderTest.getDmiHealthStatus('some/url')
- then: 'the status value from the json is return'
+ then: 'the status value from the json is returned'
assert result == 'my status'
}
def 'Failing to get dmi plugin health status #scenario'() {
given: 'rest template with #scenario'
- mockWebClient.get() >> healthStatusResponse
+ mockHealthChecksWebClient.get() >> mockRequestBody
+ mockResponse.bodyToMono(_) >> healthStatusResponse
when: 'attempt to get health status of the dmi plugin'
def result = objectUnderTest.getDmiHealthStatus('some url')
then: 'result will be empty'
@@ -161,15 +155,18 @@ class DmiRestClientSpec extends Specification {
where: 'the following responses are used'
scenario | healthStatusResponse
'null' | null
- 'exception' | {throw new Exception()}
+ 'exception' | { throw new Exception() }
}
def 'DMI auth header #scenario'() {
when: 'Specific dmi properties are provided'
- dmiProperties.dmiBasicAuthEnabled = authEnabled
+ mockDmiProperties.dmiBasicAuthEnabled >> authEnabled
+ mockDmiProperties.authUsername >> 'some user'
+ mockDmiProperties.authPassword >> 'some password'
then: 'http headers to conditionally have Authorization header'
- def authHeaderValues = objectUnderTest.configureHttpHeaders(new HttpHeaders(), ncmpAuthHeader).getOrEmpty('Authorization')
- def outputAuthHeader = (authHeaderValues == null ? null : authHeaderValues[0])
+ def httpHeaders = new HttpHeaders()
+ objectUnderTest.configureHttpHeaders(httpHeaders, ncmpAuthHeader)
+ def outputAuthHeader = (httpHeaders.Authorization == null ? null : httpHeaders.Authorization[0])
assert outputAuthHeader == expectedAuthHeader
where: 'the following configurations are used'
scenario | authEnabled | ncmpAuthHeader || expectedAuthHeader
@@ -179,4 +176,4 @@ class DmiRestClientSpec extends Specification {
'DMI basic auth disabled, with NCMP bearer token' | false | BEARER_AUTH_HEADER || BEARER_AUTH_HEADER
'DMI basic auth disabled, with NCMP basic auth' | false | BASIC_AUTH_HEADER || NO_AUTH_HEADER
}
-}
+} \ No newline at end of file
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfigurationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfigurationSpec.groovy
index ee7ab3f28d..05ecaa11b1 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfigurationSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfigurationSpec.groovy
@@ -29,7 +29,7 @@ import spock.lang.Specification
@SpringBootTest
@ContextConfiguration(classes = [HttpClientConfiguration])
-@TestPropertySource(properties = ['ncmp.dmi.httpclient.connectionTimeoutInSeconds=1', 'ncmp.dmi.httpclient.maximumInMemorySizeInMegabytes=1'])
+@TestPropertySource(properties = ['ncmp.dmi.httpclient.data-services.connectionTimeoutInSeconds=1', 'ncmp.dmi.httpclient.model-services.maximumInMemorySizeInMegabytes=1'])
@EnableConfigurationProperties
class DmiWebClientConfigurationSpec extends Specification {
@@ -42,11 +42,27 @@ class DmiWebClientConfigurationSpec extends Specification {
new DmiWebClientConfiguration(httpClientConfiguration) != null
}
- def 'Creating a WebClient instance.'() {
- given: 'WebClient configuration invoked'
- def webClientInstance = objectUnderTest.webClient()
- expect: 'the system can create an instance'
- assert webClientInstance != null
- assert webClientInstance instanceof WebClient
+ def 'Creating a web client instance data service.'() {
+ given: 'Web client configuration is invoked'
+ def dataServicesWebClient = objectUnderTest.dataServicesWebClient()
+ expect: 'the system can create an instance for data service'
+ assert dataServicesWebClient != null
+ assert dataServicesWebClient instanceof WebClient
+ }
+
+ def 'Creating a web client instance model service.'() {
+ given: 'Web client configuration invoked'
+ def modelServicesWebClient = objectUnderTest.modelServicesWebClient()
+ expect: 'the system can create an instance for model service'
+ assert modelServicesWebClient != null
+ assert modelServicesWebClient instanceof WebClient
+ }
+
+ def 'Creating a web client instance health service.'() {
+ given: 'Web client configuration invoked'
+ def healthChecksWebClient = objectUnderTest.healthChecksWebClient()
+ expect: 'the system can create an instance for health service'
+ assert healthChecksWebClient != null
+ assert healthChecksWebClient instanceof WebClient
}
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/HttpClientConfigurationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/HttpClientConfigurationSpec.groovy
index 4ede360e68..b7ced23828 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/HttpClientConfigurationSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/HttpClientConfigurationSpec.groovy
@@ -30,18 +30,42 @@ import spock.lang.Specification
@SpringBootTest
@ContextConfiguration(classes = [HttpClientConfiguration])
@EnableConfigurationProperties(HttpClientConfiguration.class)
-@TestPropertySource(properties = ["ncmp.dmi.httpclient.readTimeoutInSeconds=123", "ncmp.dmi.httpclient.maximumConnectionsTotal=200"])
+@TestPropertySource(properties = ["ncmp.dmi.httpclient.data-services.readTimeoutInSeconds=789", "ncmp.dmi.httpclient.model-services.maximumConnectionsTotal=111"])
class HttpClientConfigurationSpec extends Specification {
@Autowired
private HttpClientConfiguration httpClientConfiguration
- def 'Test HttpClientConfiguration properties with custom and default values'() {
- expect: 'properties are populated correctly'
- assert httpClientConfiguration.connectionTimeoutInSeconds == 123
- assert httpClientConfiguration.readTimeoutInSeconds == 123
- assert httpClientConfiguration.writeTimeoutInSeconds == 30
- assert httpClientConfiguration.maximumConnectionsTotal == 200
- assert httpClientConfiguration.maximumInMemorySizeInMegabytes == 16
+ def 'Test http client configuration properties of data with custom and default values'() {
+ expect: 'properties are populated correctly for data'
+ with(httpClientConfiguration.dataServices) {
+ assert connectionTimeoutInSeconds == 123
+ assert readTimeoutInSeconds == 789
+ assert writeTimeoutInSeconds == 30
+ assert maximumConnectionsTotal == 100
+ assert maximumInMemorySizeInMegabytes == 7
+ }
+ }
+
+ def 'Test http client configuration properties of model with custom and default values'() {
+ expect: 'properties are populated correctly for model'
+ with(httpClientConfiguration.modelServices) {
+ assert connectionTimeoutInSeconds == 456
+ assert readTimeoutInSeconds == 30
+ assert writeTimeoutInSeconds == 30
+ assert maximumConnectionsTotal == 111
+ assert maximumInMemorySizeInMegabytes == 8
+ }
+ }
+
+ def 'Test http client configuration properties of health with default values'() {
+ expect: 'properties are populated correctly for health'
+ with(httpClientConfiguration.healthCheckServices) {
+ assert connectionTimeoutInSeconds == 30
+ assert readTimeoutInSeconds == 30
+ assert writeTimeoutInSeconds == 30
+ assert maximumConnectionsTotal == 10
+ assert maximumInMemorySizeInMegabytes == 1
+ }
}
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy
index a84e1348e0..ad3f85c84a 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy
@@ -21,15 +21,14 @@
package org.onap.cps.ncmp.api.impl.operations
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
-
-import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR
import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent
import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL
import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING
import static org.onap.cps.ncmp.api.impl.operations.OperationType.CREATE
import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ
import static org.onap.cps.ncmp.api.impl.operations.OperationType.UPDATE
+import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.DATA
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR
import com.fasterxml.jackson.databind.ObjectMapper
import org.onap.cps.events.EventsPublisher
@@ -40,6 +39,7 @@ import org.onap.cps.ncmp.api.models.DataOperationRequest
import org.onap.cps.ncmp.api.models.CmResourceAddress
import org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent
import org.onap.cps.ncmp.utils.TestUtils
+import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
import org.onap.cps.utils.JsonObjectMapper
import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
@@ -77,7 +77,7 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
def responseFromDmi = new ResponseEntity<Object>(HttpStatus.OK)
def expectedUrl = "${dmiServiceBaseUrl}${expectedDatastoreInUrl}?resourceIdentifier=${resourceIdentifier}${expectedOptionsInUrl}"
def expectedJson = '{"operation":"read","cmHandleProperties":' + expectedProperties + ',"moduleSetTag":""}'
- mockDmiRestClient.postOperationWithJsonData(expectedUrl, expectedJson, READ, NO_AUTH_HEADER) >> responseFromDmi
+ mockDmiRestClient.postOperationWithJsonData(DATA, expectedUrl, expectedJson, READ, NO_AUTH_HEADER) >> responseFromDmi
when: 'get resource data is invoked'
def cmResourceAddress = new CmResourceAddress(dataStore.datastoreName, cmHandleId, resourceIdentifier)
def result = objectUnderTest.getResourceDataFromDmi(cmResourceAddress, options, NO_TOPIC, NO_REQUEST_ID, NO_AUTH_HEADER)
@@ -103,11 +103,11 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
def responseFromDmi = new ResponseEntity<Object>(HttpStatus.ACCEPTED)
def expectedDmiBatchResourceDataUrl = "someServiceName/dmi/v1/data?requestId=requestId&topic=my-topic-name"
def expectedBatchRequestAsJson = '{"operations":[{"operation":"read","operationId":"operational-14","datastore":"ncmp-datastore:passthrough-operational","options":"some option","resourceIdentifier":"some resource identifier","cmHandles":[{"id":"some-cm-handle","moduleSetTag":"","cmHandleProperties":{"prop1":"val1"}}]}]}'
- mockDmiRestClient.postOperationWithJsonData(expectedDmiBatchResourceDataUrl, _, READ.operationName, NO_AUTH_HEADER) >> responseFromDmi
+ mockDmiRestClient.postOperationWithJsonData(DATA, expectedDmiBatchResourceDataUrl, _, READ, NO_AUTH_HEADER) >> responseFromDmi
when: 'get resource data for group of cm handles are invoked'
objectUnderTest.requestResourceDataFromDmi('my-topic-name', dataOperationRequest, 'requestId', NO_AUTH_HEADER)
then: 'the post operation was called and ncmp generated dmi request body json args'
- 1 * mockDmiRestClient.postOperationWithJsonData(expectedDmiBatchResourceDataUrl, expectedBatchRequestAsJson, READ, NO_AUTH_HEADER)
+ 1 * mockDmiRestClient.postOperationWithJsonData(DATA, expectedDmiBatchResourceDataUrl, expectedBatchRequestAsJson, READ, NO_AUTH_HEADER)
}
def 'Execute (async) data operation from DMI service with Exception.'() {
@@ -139,7 +139,7 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
def responseFromDmi = new ResponseEntity<Object>(HttpStatus.OK)
def expectedUrl = dmiServiceBaseUrl + "passthrough-operational?resourceIdentifier=/"
def expectedJson = '{"operation":"read","cmHandleProperties":{"prop1":"val1"},"moduleSetTag":"my-module-set-tag"}'
- mockDmiRestClient.postOperationWithJsonData(expectedUrl, expectedJson, READ, null) >> responseFromDmi
+ mockDmiRestClient.postOperationWithJsonData(DATA, expectedUrl, expectedJson, READ, null) >> responseFromDmi
when: 'get resource data is invoked'
def result = objectUnderTest.getResourceDataFromDmi( PASSTHROUGH_OPERATIONAL.datastoreName, cmHandleId, NO_REQUEST_ID)
then: 'the result is the response from the DMI service'
@@ -153,7 +153,7 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
def expectedUrl = "${dmiServiceBaseUrl}passthrough-running?resourceIdentifier=${resourceIdentifier}"
def expectedJson = '{"operation":"' + expectedOperationInUrl + '","dataType":"some data type","data":"requestData","cmHandleProperties":{"prop1":"val1"},"moduleSetTag":""}'
def responseFromDmi = new ResponseEntity<Object>(HttpStatus.OK)
- mockDmiRestClient.postOperationWithJsonData(expectedUrl, expectedJson, operation, NO_AUTH_HEADER) >> responseFromDmi
+ mockDmiRestClient.postOperationWithJsonData(DATA, expectedUrl, expectedJson, operation, NO_AUTH_HEADER) >> responseFromDmi
when: 'write resource method is invoked'
def result = objectUnderTest.writeResourceDataPassThroughRunningFromDmi(cmHandleId, 'parent/child', operation, 'requestData', 'some data type', NO_AUTH_HEADER)
then: 'the result is the response from the DMI service'
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy
index de5e15e504..db7f26f5f1 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy
@@ -21,6 +21,9 @@
package org.onap.cps.ncmp.api.impl.operations
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ
+import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.MODEL
+
import com.fasterxml.jackson.core.JsonProcessingException
import com.fasterxml.jackson.databind.ObjectMapper
import org.onap.cps.ncmp.api.impl.config.DmiProperties
@@ -34,8 +37,6 @@ import org.springframework.http.ResponseEntity
import org.springframework.test.context.ContextConfiguration
import spock.lang.Shared
-import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ
-
@SpringBootTest
@ContextConfiguration(classes = [DmiProperties, DmiModelOperations])
class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
@@ -58,7 +59,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
def moduleReferencesAsLisOfMaps = [[moduleName: 'mod1', revision: 'A'], [moduleName: 'mod2', revision: 'X']]
def expectedUrl = "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/modules"
def responseFromDmi = new ResponseEntity([schemas: moduleReferencesAsLisOfMaps], HttpStatus.OK)
- mockDmiRestClient.postOperationWithJsonData(expectedUrl, '{"cmHandleProperties":{},"moduleSetTag":""}', READ, NO_AUTH_HEADER) >> responseFromDmi
+ mockDmiRestClient.postOperationWithJsonData(MODEL, expectedUrl, '{"cmHandleProperties":{},"moduleSetTag":""}', READ, NO_AUTH_HEADER) >> responseFromDmi
when: 'get module references is called'
def result = objectUnderTest.getModuleReferences(yangModelCmHandle)
then: 'the result consists of expected module references'
@@ -89,7 +90,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
mockYangModelCmHandleRetrieval(dmiProperties)
and: 'a positive response from DMI service when it is called with tha expected parameters'
def responseFromDmi = new ResponseEntity<String>(HttpStatus.OK)
- mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/modules",
+ mockDmiRestClient.postOperationWithJsonData(MODEL, "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/modules",
'{"cmHandleProperties":' + expectedAdditionalPropertiesInRequest + ',"moduleSetTag":""}', READ, NO_AUTH_HEADER) >> responseFromDmi
when: 'a get module references is called'
def result = objectUnderTest.getModuleReferences(yangModelCmHandle)
@@ -108,7 +109,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
def responseFromDmi = new ResponseEntity([[moduleName: 'mod1', revision: 'A', yangSource: 'some yang source'],
[moduleName: 'mod2', revision: 'C', yangSource: 'other yang source']], HttpStatus.OK)
def expectedModuleReferencesInRequest = '{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}'
- mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
+ mockDmiRestClient.postOperationWithJsonData(MODEL, "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
'{"data":{"modules":[' + expectedModuleReferencesInRequest + ']},"cmHandleProperties":{}}', READ, NO_AUTH_HEADER) >> responseFromDmi
when: 'get new yang resources from DMI service'
def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, newModuleReferences)
@@ -140,7 +141,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
mockYangModelCmHandleRetrieval(dmiProperties)
and: 'a positive response from DMI service when it is called with the expected moduleSetTag, modules and properties'
def responseFromDmi = new ResponseEntity<>([[moduleName: 'mod1', revision: 'A', yangSource: 'some yang source']], HttpStatus.OK)
- mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
+ mockDmiRestClient.postOperationWithJsonData(MODEL, "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
'{"data":{"modules":[{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}]},"cmHandleProperties":' + expectedAdditionalPropertiesInRequest + '}',
READ, NO_AUTH_HEADER) >> responseFromDmi
when: 'get new yang resources from DMI service'
@@ -158,9 +159,9 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
mockYangModelCmHandleRetrieval([], moduleSetTag)
and: 'a positive response from DMI service when it is called with the expected moduleSetTag'
def responseFromDmi = new ResponseEntity<>([[moduleName: 'mod1', revision: 'A', yangSource: 'some yang source']], HttpStatus.OK)
- mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
- '{' + expectedModuleSetTagInRequest + '"data":{"modules":[{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}]},"cmHandleProperties":{}}',
- READ, NO_AUTH_HEADER) >> responseFromDmi
+ mockDmiRestClient.postOperationWithJsonData(MODEL, "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
+ '{' + expectedModuleSetTagInRequest + '"data":{"modules":[{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}]},"cmHandleProperties":{}}',
+ READ, NO_AUTH_HEADER) >> responseFromDmi
when: 'get new yang resources from DMI service'
def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, newModuleReferences)
then: 'the result is the response from DMI service'
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/context/CpsApplicationContextSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/context/CpsApplicationContextSpec.groovy
index b7fa449251..ee117160c1 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/context/CpsApplicationContextSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/context/CpsApplicationContextSpec.groovy
@@ -1,3 +1,23 @@
+/*
+ * ============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.utils.context
import com.fasterxml.jackson.databind.ObjectMapper
diff --git a/cps-ncmp-service/src/test/resources/application.yml b/cps-ncmp-service/src/test/resources/application.yml
index 2a93f40816..e35f471005 100644
--- a/cps-ncmp-service/src/test/resources/application.yml
+++ b/cps-ncmp-service/src/test/resources/application.yml
@@ -37,8 +37,12 @@ app:
ncmp:
dmi:
httpclient:
- connectionTimeoutInSeconds: 123
- maximumInMemorySizeInMegabytes: 16
+ data-services:
+ connectionTimeoutInSeconds: 123
+ maximumInMemorySizeInMegabytes: 7
+ model-services:
+ connectionTimeoutInSeconds: 456
+ maximumInMemorySizeInMegabytes: 8
auth:
username: some-user
password: some-password