diff options
Diffstat (limited to 'cps-ncmp-service/src')
41 files changed, 408 insertions, 665 deletions
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cache/HazelcastCacheConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cache/HazelcastCacheConfig.java index 75007e2e35..1a7ef758d8 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cache/HazelcastCacheConfig.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cache/HazelcastCacheConfig.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================== - * Copyright (C) 2023-2024 Nordix Foundation + * Copyright (C) 2023-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,6 @@ import com.hazelcast.config.MapConfig; import com.hazelcast.config.NamedConfig; import com.hazelcast.config.NearCacheConfig; import com.hazelcast.config.QueueConfig; -import com.hazelcast.config.RestEndpointGroup; import com.hazelcast.config.SetConfig; import com.hazelcast.core.Hazelcast; import com.hazelcast.core.HazelcastInstance; @@ -61,7 +60,6 @@ public class HazelcastCacheConfig { config.setClusterName(clusterName); config.setClassLoader(Dataspace.class.getClassLoader()); configureDataStructures(namedConfig, config); - exposeClusterInformation(config); updateDiscoveryMode(config); return config; } @@ -130,9 +128,4 @@ public class HazelcastCacheConfig { } } - protected void exposeClusterInformation(final Config config) { - config.getNetworkConfig().getRestApiConfig().setEnabled(true) - .enableGroups(RestEndpointGroup.HEALTH_CHECK, RestEndpointGroup.CLUSTER_READ); - } - } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiInEventProducer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiInEventProducer.java index c62916f05c..232803a941 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiInEventProducer.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiInEventProducer.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2024 Nordix Foundation + * Copyright (C) 2024-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,14 +20,14 @@ package org.onap.cps.ncmp.impl.cmnotificationsubscription.dmi; +import static org.onap.cps.ncmp.events.NcmpEventDataSchema.SUBSCRIPTIONS_V1; + import io.cloudevents.CloudEvent; -import io.cloudevents.core.builder.CloudEventBuilder; -import java.net.URI; -import java.util.UUID; +import java.util.Map; import lombok.RequiredArgsConstructor; import org.onap.cps.events.EventsPublisher; import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_dmi.DmiInEvent; -import org.onap.cps.utils.JsonObjectMapper; +import org.onap.cps.ncmp.utils.events.NcmpEvent; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; @@ -38,7 +38,6 @@ import org.springframework.stereotype.Component; public class DmiInEventProducer { private final EventsPublisher<CloudEvent> eventsPublisher; - private final JsonObjectMapper jsonObjectMapper; @Value("${app.ncmp.avc.cm-subscription-dmi-in}") private String dmiInEventTopic; @@ -58,13 +57,15 @@ public class DmiInEventProducer { } - private CloudEvent buildAndGetDmiInEventAsCloudEvent(final String subscriptionId, - final String dmiPluginName, final String eventType, final DmiInEvent dmiInEvent) { - return CloudEventBuilder.v1().withId(UUID.randomUUID().toString()).withType(eventType) - .withSource(URI.create("NCMP")) - .withDataSchema(URI.create("org.onap.ncmp.dmi.cm.subscription:1.0.0")) - .withExtension("correlationid", subscriptionId.concat("#").concat(dmiPluginName)) - .withData(jsonObjectMapper.asJsonBytes(dmiInEvent)).build(); + private CloudEvent buildAndGetDmiInEventAsCloudEvent(final String subscriptionId, final String dmiPluginName, + final String eventType, final DmiInEvent dmiInEvent) { + return NcmpEvent.builder() + .type(eventType) + .dataSchema(SUBSCRIPTIONS_V1.getDataSchema()) + .extensions(Map.of("correlationid", String.join("#", subscriptionId, dmiPluginName))) + .data(dmiInEvent) + .build() + .asCloudEvent(); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducer.java index 3371d59f7a..8cfb3ad563 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducer.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducer.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2024 Nordix Foundation + * Copyright (C) 2024-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,11 +20,10 @@ package org.onap.cps.ncmp.impl.cmnotificationsubscription.ncmp; +import static org.onap.cps.ncmp.events.NcmpEventDataSchema.SUBSCRIPTIONS_V1; + import io.cloudevents.CloudEvent; -import io.cloudevents.core.builder.CloudEventBuilder; -import java.net.URI; import java.util.Map; -import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -35,7 +34,7 @@ import lombok.extern.slf4j.Slf4j; import org.onap.cps.events.EventsPublisher; import org.onap.cps.ncmp.impl.cmnotificationsubscription.cache.DmiCacheHandler; import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.NcmpOutEvent; -import org.onap.cps.utils.JsonObjectMapper; +import org.onap.cps.ncmp.utils.events.NcmpEvent; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; @@ -53,7 +52,6 @@ public class NcmpOutEventProducer { private Integer dmiOutEventTimeoutInMs; private final EventsPublisher<CloudEvent> eventsPublisher; - private final JsonObjectMapper jsonObjectMapper; private final NcmpOutEventMapper ncmpOutEventMapper; private final DmiCacheHandler dmiCacheHandler; private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); @@ -91,49 +89,48 @@ public class NcmpOutEventProducer { } } + /** + * Get an NCMP out event as cloud event. + * + * @param subscriptionId subscription id + * @param eventType event type + * @param ncmpOutEvent cm notification subscription NCMP out event + * @return cm notification subscription NCMP out event as cloud event + */ + public static CloudEvent buildAndGetNcmpOutEventAsCloudEvent( + final String subscriptionId, final String eventType, final NcmpOutEvent ncmpOutEvent) { + + return NcmpEvent.builder() + .type(eventType) + .dataSchema(SUBSCRIPTIONS_V1.getDataSchema()) + .extensions(Map.of("correlationid", subscriptionId)) + .data(ncmpOutEvent) + .build() + .asCloudEvent(); + } + private ScheduledFuture<?> scheduleAndPublishNcmpOutEvent(final String subscriptionId, final String eventType) { final NcmpOutEventPublishingTask ncmpOutEventPublishingTask = new NcmpOutEventPublishingTask(ncmpOutEventTopic, subscriptionId, eventType, eventsPublisher, - jsonObjectMapper, ncmpOutEventMapper, dmiCacheHandler); + ncmpOutEventMapper, dmiCacheHandler); return scheduledExecutorService.schedule(ncmpOutEventPublishingTask, dmiOutEventTimeoutInMs, TimeUnit.MILLISECONDS); } private void cancelScheduledTask(final String taskKey) { - final ScheduledFuture<?> scheduledFuture = scheduledTasksPerSubscriptionIdAndEventType.get(taskKey); if (scheduledFuture != null) { scheduledFuture.cancel(true); scheduledTasksPerSubscriptionIdAndEventType.remove(taskKey); } - } - private void publishNcmpOutEventNow(final String subscriptionId, final String eventType, final NcmpOutEvent ncmpOutEvent) { final CloudEvent ncmpOutEventAsCloudEvent = - buildAndGetNcmpOutEventAsCloudEvent(jsonObjectMapper, subscriptionId, eventType, ncmpOutEvent); + buildAndGetNcmpOutEventAsCloudEvent(subscriptionId, eventType, ncmpOutEvent); eventsPublisher.publishCloudEvent(ncmpOutEventTopic, subscriptionId, ncmpOutEventAsCloudEvent); dmiCacheHandler.removeAcceptedAndRejectedDmiSubscriptionEntries(subscriptionId); } - /** - * Get an NCMP out event as cloud event. - * - * @param jsonObjectMapper JSON object mapper - * @param subscriptionId subscription id - * @param eventType event type - * @param ncmpOutEvent cm notification subscription NCMP out event - * @return cm notification subscription NCMP out event as cloud event - */ - public static CloudEvent buildAndGetNcmpOutEventAsCloudEvent(final JsonObjectMapper jsonObjectMapper, - final String subscriptionId, final String eventType, final NcmpOutEvent ncmpOutEvent) { - - return CloudEventBuilder.v1().withId(UUID.randomUUID().toString()).withType(eventType) - .withSource(URI.create("NCMP")).withDataSchema(URI.create("org.onap.ncmp.cm.subscription:1.0.0")) - .withExtension("correlationid", subscriptionId) - .withData(jsonObjectMapper.asJsonBytes(ncmpOutEvent)).build(); - } - } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventPublishingTask.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventPublishingTask.java index f8f253d275..e9d6d78429 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventPublishingTask.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventPublishingTask.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2024 Nordix Foundation + * Copyright (C) 2024-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,6 @@ import org.onap.cps.events.EventsPublisher; import org.onap.cps.ncmp.impl.cmnotificationsubscription.cache.DmiCacheHandler; import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.DmiCmSubscriptionDetails; import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.NcmpOutEvent; -import org.onap.cps.utils.JsonObjectMapper; @Slf4j @RequiredArgsConstructor @@ -40,7 +39,6 @@ public class NcmpOutEventPublishingTask implements Runnable { private final String subscriptionId; private final String eventType; private final EventsPublisher<CloudEvent> eventsPublisher; - private final JsonObjectMapper jsonObjectMapper; private final NcmpOutEventMapper ncmpOutEventMapper; private final DmiCacheHandler dmiCacheHandler; @@ -55,8 +53,7 @@ public class NcmpOutEventPublishingTask implements Runnable { final NcmpOutEvent ncmpOutEvent = ncmpOutEventMapper.toNcmpOutEvent(subscriptionId, dmiSubscriptionsPerDmi); eventsPublisher.publishCloudEvent(topicName, subscriptionId, - buildAndGetNcmpOutEventAsCloudEvent(jsonObjectMapper, subscriptionId, eventType, - ncmpOutEvent)); + buildAndGetNcmpOutEventAsCloudEvent(subscriptionId, eventType, ncmpOutEvent)); dmiCacheHandler.removeAcceptedAndRejectedDmiSubscriptionEntries(subscriptionId); } } 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 189239ceb2..7cb1c44526 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 @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2024 Nordix Foundation + * Copyright (C) 2021-2025 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,7 +34,6 @@ import java.util.Set; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.onap.cps.api.exceptions.CpsException; -import org.onap.cps.api.exceptions.DataValidationException; 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; @@ -79,7 +78,7 @@ public class DmiDataOperations { * This method fetches the resource data from the operational data store for a given CM handle * identifier on the specified resource using the DMI client. * - * @param cmResourceAddress Target datastore, CM handle, and resource identifier. + * @param cmResourceAddress Target datastore, CM handle reference, and resource identifier. * @param options Options query string. * @param topic Topic name for triggering asynchronous responses. * @param requestId Request ID for asynchronous responses. @@ -94,7 +93,8 @@ public class DmiDataOperations { final String topic, final String requestId, final String authorization) { - final YangModelCmHandle yangModelCmHandle = resolveYangModelCmHandleFromCmHandleReference(cmResourceAddress); + final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle( + cmResourceAddress.resolveCmHandleReferenceToId()); final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState(); validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState); final String jsonRequestBody = getDmiRequestBody(READ, requestId, null, null, yangModelCmHandle); @@ -157,22 +157,22 @@ public class DmiDataOperations { * This method creates the resource data from pass-through running data store for given cm handle * identifier on given resource using dmi client. * - * @param cmHandleId network resource identifier - * @param resourceId resource identifier - * @param operationType operation enum - * @param requestData the request data - * @param dataType data type - * @param authorization contents of Authorization header, or null if not present + * @param cmHandleReference network resource identifier + * @param resourceId resource identifier + * @param operationType operation enum + * @param requestData the request data + * @param dataType data type + * @param authorization contents of Authorization header, or null if not present * @return {@code ResponseEntity} response entity */ - public ResponseEntity<Object> writeResourceDataPassThroughRunningFromDmi(final String cmHandleId, + public ResponseEntity<Object> writeResourceDataPassThroughRunningFromDmi(final String cmHandleReference, final String resourceId, final OperationType operationType, final String requestData, final String dataType, final String authorization) { final CmResourceAddress cmResourceAddress = - new CmResourceAddress(PASSTHROUGH_RUNNING.getDatastoreName(), cmHandleId, resourceId); + new CmResourceAddress(PASSTHROUGH_RUNNING.getDatastoreName(), cmHandleReference, resourceId); final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmResourceAddress.resolveCmHandleReferenceToId()); @@ -281,16 +281,6 @@ public class DmiDataOperations { }).subscribe(); } - private YangModelCmHandle resolveYangModelCmHandleFromCmHandleReference(final CmResourceAddress cmResourceAddress) { - String cmHandleId = cmResourceAddress.getCmHandleReference(); - try { - return getYangModelCmHandle(cmHandleId); - } catch (final DataValidationException ignored) { - cmHandleId = cmResourceAddress.resolveCmHandleReferenceToId(); - return getYangModelCmHandle(cmHandleId); - } - } - private String createDmiDataOperationRequestAsJsonString( final List<DmiDataOperation> dmiDataOperationRequestBodies) { final DmiDataOperationRequest dmiDataOperationRequest = DmiDataOperationRequest.builder() diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DataOperationEventCreator.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DataOperationEventCreator.java index d74abb9935..14e2eda2d2 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DataOperationEventCreator.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DataOperationEventCreator.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation + * Copyright (C) 2023-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,8 @@ package org.onap.cps.ncmp.impl.data.utils; +import static org.onap.cps.ncmp.events.NcmpEventDataSchema.BATCH_RESPONSE_V1; + import io.cloudevents.CloudEvent; import java.util.ArrayList; import java.util.HashMap; @@ -27,7 +29,6 @@ import java.util.List; import java.util.Map; import lombok.AccessLevel; import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.NcmpResponseStatus; import org.onap.cps.ncmp.events.async1_0_0.Data; import org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent; @@ -36,7 +37,6 @@ import org.onap.cps.ncmp.impl.data.models.DmiDataOperation; import org.onap.cps.ncmp.utils.events.NcmpEvent; import org.springframework.util.MultiValueMap; -@Slf4j @NoArgsConstructor(access = AccessLevel.PRIVATE) public class DataOperationEventCreator { @@ -57,8 +57,13 @@ public class DataOperationEventCreator { final Data data = createPayloadFromDataOperationResponses(cmHandleIdsPerResponseCodesPerOperation); dataOperationEvent.setData(data); final Map<String, String> extensions = createDataOperationExtensions(requestId, clientTopic); - return NcmpEvent.builder().type(DataOperationEvent.class.getName()) - .data(dataOperationEvent).extensions(extensions).build().asCloudEvent(); + return NcmpEvent.builder() + .type(DataOperationEvent.class.getName()) + .data(dataOperationEvent) + .dataSchema(BATCH_RESPONSE_V1.getDataSchema()) + .extensions(extensions) + .build() + .asCloudEvent(); } private static Data createPayloadFromDataOperationResponses(final MultiValueMap<DmiDataOperation, 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 a118d53e7e..d74863a710 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 @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2024 Nordix Foundation + * Copyright (C) 2024-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -79,8 +79,11 @@ public class DmiSubJobRequestHandler { jsonObjectMapper.asJsonString(subJobWriteRequest), OperationType.CREATE, authorization); - final SubJobWriteResponse subJobWriteResponse = jsonObjectMapper - .convertToValueType(responseEntity.getBody(), SubJobWriteResponse.class); + final Map<String, String> responseAsKeyValuePairs = jsonObjectMapper + .convertToValueType(responseEntity.getBody(), Map.class); + final String subJobId = responseAsKeyValuePairs.get("subJobId"); + final SubJobWriteResponse subJobWriteResponse = new SubJobWriteResponse(subJobId, + producerKey.dmiServiceName(), producerKey.dataProducerIdentifier()); log.debug("Sub job write response: {}", subJobWriteResponse); subJobWriteResponses.add(subJobWriteResponse); }); 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 index a177272dff..ccda476081 100644 --- 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 @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2024 Nordix Foundation + * Copyright (C) 2021-2025 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -150,7 +150,7 @@ public class DmiRestClient { * * @param urlTemplateParameters The URL template parameters for the DMI data job status endpoint. * @param authorization The authorization token to be added to the request headers. - * @return A Mono emitting the status of the data job as a String. + * @return A Mono emitting the status of the data job in JSON format. * @throws DmiClientRequestException If there is an error during the DMI request. */ public Mono<String> getDataJobStatus(final UrlTemplateParameters urlTemplateParameters, @@ -160,8 +160,7 @@ public class DmiRestClient { .uri(urlTemplateParameters.urlTemplate(), urlTemplateParameters.urlVariables()) .headers(httpHeaders -> configureHttpHeaders(httpHeaders, authorization)) .retrieve() - .bodyToMono(JsonNode.class) - .map(jsonNode -> jsonNode.path("status").asText()) + .bodyToMono(String.class) .onErrorMap(throwable -> handleDmiClientException(throwable, OperationType.READ.getOperationName())); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java index 9447f13b68..f1f71dc57c 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation + * Copyright (C) 2022-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -110,12 +110,4 @@ public interface CmHandleQueryService { Collection<String> getCmHandleReferencesByDmiPluginIdentifier(String dmiPluginIdentifier, boolean outputAlternateId); - /** - * Get map of cmHandle references by DMI plugin identifier. - * - * @param dmiPluginIdentifier DMI plugin identifier - * @return map of cmHandle references key:CmHandleId Value:AlternateId - */ - Map<String, String> getCmHandleReferencesMapByDmiPluginIdentifier(String dmiPluginIdentifier); - } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java index 59d0f9704e..770ada0a5f 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation + * Copyright (C) 2022-2025 Nordix Foundation * Modifications Copyright (C) 2023 TechMahindra Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,9 +28,9 @@ import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.onap.cps.api.CpsDataService; @@ -38,7 +38,6 @@ import org.onap.cps.api.CpsQueryService; import org.onap.cps.api.model.DataNode; import org.onap.cps.api.parameters.FetchDescendantsOption; import org.onap.cps.cpspath.parser.CpsPathUtil; -import org.onap.cps.impl.utils.CpsValidator; import org.onap.cps.ncmp.api.inventory.DataStoreSyncState; import org.onap.cps.ncmp.api.inventory.models.CmHandleState; import org.onap.cps.ncmp.api.inventory.models.TrustLevel; @@ -46,6 +45,7 @@ import org.onap.cps.ncmp.impl.inventory.models.ModelledDmiServiceLeaves; import org.onap.cps.ncmp.impl.inventory.models.PropertyType; import org.onap.cps.ncmp.impl.inventory.trustlevel.TrustLevelCacheConfig; import org.onap.cps.ncmp.impl.utils.YangDataConverter; +import org.onap.cps.utils.CpsValidator; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @@ -90,7 +90,8 @@ public class CmHandleQueryServiceImpl implements CmHandleQueryService { @Override public Collection<String> queryCmHandleIdsByState(final CmHandleState cmHandleState) { final Collection<DataNode> cmHandlesAsDataNodes = - queryNcmpRegistryByCpsPath("//state[@cm-handle-state='" + cmHandleState + "']", OMIT_DESCENDANTS); + queryNcmpRegistryByCpsPath("//state[@cm-handle-state='" + cmHandleState + "']", + OMIT_DESCENDANTS); return cmHandlesAsDataNodes.stream() .map(DataNode::getXpath) .map(YangDataConverter::extractCmHandleIdFromXpath) @@ -106,7 +107,7 @@ public class CmHandleQueryServiceImpl implements CmHandleQueryService { @Override public Collection<DataNode> queryCmHandleAncestorsByCpsPath(final String cpsPath, - final FetchDescendantsOption fetchDescendantsOption) { + final FetchDescendantsOption fetchDescendantsOption) { if (CpsPathUtil.getCpsPathQuery(cpsPath).getXpathPrefix().endsWith("/cm-handles")) { return queryNcmpRegistryByCpsPath(cpsPath, fetchDescendantsOption); } @@ -128,84 +129,60 @@ public class CmHandleQueryServiceImpl implements CmHandleQueryService { @Override public Collection<String> getCmHandleReferencesByDmiPluginIdentifier(final String dmiPluginIdentifier, - final boolean outputAlternateId) { + final boolean outputAlternateId) { final Collection<String> cmHandleReferences = new HashSet<>(); for (final ModelledDmiServiceLeaves modelledDmiServiceLeaf : ModelledDmiServiceLeaves.values()) { - for (final DataNode cmHandleAsDataNode: getCmHandlesByDmiPluginIdentifierAndDmiProperty( - dmiPluginIdentifier, - modelledDmiServiceLeaf.getLeafName())) { - if (outputAlternateId) { - cmHandleReferences.add(cmHandleAsDataNode.getLeaves().get(ALTERNATE_ID).toString()); - } else { - cmHandleReferences.add(cmHandleAsDataNode.getLeaves().get("id").toString()); - } - } + cmHandleReferences.addAll(getIdsByDmiPluginIdentifierAndDmiProperty( + dmiPluginIdentifier, modelledDmiServiceLeaf.getLeafName(), outputAlternateId)); } return cmHandleReferences; } - @Override - public Map<String, String> getCmHandleReferencesMapByDmiPluginIdentifier(final String dmiPluginIdentifier) { - final Map<String, String> cmHandleReferencesMap = new HashMap<>(); - for (final ModelledDmiServiceLeaves modelledDmiServiceLeaf : ModelledDmiServiceLeaves.values()) { - for (final DataNode cmHandleAsDataNode: getCmHandlesByDmiPluginIdentifierAndDmiProperty( - dmiPluginIdentifier, - modelledDmiServiceLeaf.getLeafName())) { - cmHandleReferencesMap.put(cmHandleAsDataNode.getLeaves().get("id").toString(), - cmHandleAsDataNode.getLeaves().get(ALTERNATE_ID).toString()); - } - } - return cmHandleReferencesMap; - } - private Collection<String> getCmHandleReferencesByTrustLevel(final TrustLevel targetTrustLevel, final boolean outputAlternateId) { final Collection<String> selectedCmHandleReferences = new HashSet<>(); - for (final Map.Entry<String, TrustLevel> mapEntry : trustLevelPerDmiPlugin.entrySet()) { final String dmiPluginIdentifier = mapEntry.getKey(); final TrustLevel dmiTrustLevel = mapEntry.getValue(); - final Map<String, String> candidateCmHandleReferences = - getCmHandleReferencesMapByDmiPluginIdentifier(dmiPluginIdentifier); - for (final Map.Entry<String, String> candidateCmHandleReference : candidateCmHandleReferences.entrySet()) { - final TrustLevel candidateCmHandleTrustLevel = - trustLevelPerCmHandleId.get(candidateCmHandleReference.getKey()); + final Collection<String> candidateCmHandleIds = getCmHandleReferencesByDmiPluginIdentifier( + dmiPluginIdentifier, false); + for (final String candidateCmHandleId : candidateCmHandleIds) { + final TrustLevel candidateCmHandleTrustLevel = trustLevelPerCmHandleId.get(candidateCmHandleId); final TrustLevel effectiveTrustlevel = - candidateCmHandleTrustLevel.getEffectiveTrustLevel(dmiTrustLevel); + candidateCmHandleTrustLevel.getEffectiveTrustLevel(dmiTrustLevel); if (targetTrustLevel.equals(effectiveTrustlevel)) { - if (outputAlternateId) { - selectedCmHandleReferences.add(candidateCmHandleReference.getValue()); - } else { - selectedCmHandleReferences.add(candidateCmHandleReference.getKey()); - } + selectedCmHandleReferences.add(candidateCmHandleId); } } } + if (outputAlternateId) { + return getAlternateIdsByCmHandleIds(selectedCmHandleReferences); + } return selectedCmHandleReferences; } private Collection<String> collectCmHandleReferencesFromDataNodes(final Collection<DataNode> dataNodes, - final boolean outputAlternateId) { + final boolean outputAlternateId) { if (outputAlternateId) { return dataNodes.stream().map(dataNode -> - (String) dataNode.getLeaves().get(ALTERNATE_ID)).collect(Collectors.toSet()); + (String) dataNode.getLeaves().get(ALTERNATE_ID)).collect(Collectors.toSet()); } else { return dataNodes.stream().map(dataNode -> - (String) dataNode.getLeaves().get("id")).collect(Collectors.toSet()); + (String) dataNode.getLeaves().get("id")).collect(Collectors.toSet()); } } private Collection<String> queryCmHandleAnyProperties( - final Map<String, String> propertyQueryPairs, - final PropertyType propertyType, final boolean outputAlternateId) { + final Map<String, String> propertyQueryPairs, + final PropertyType propertyType, final boolean outputAlternateId) { if (propertyQueryPairs.isEmpty()) { return Collections.emptySet(); } Collection<String> cmHandleReferences = null; for (final Map.Entry<String, String> publicPropertyQueryPair : propertyQueryPairs.entrySet()) { final String cpsPath = DESCENDANT_PATH + propertyType.getYangContainerName() + "[@name=\"" - + publicPropertyQueryPair.getKey() - + "\" and @value=\"" + publicPropertyQueryPair.getValue() + "\"]"; + + publicPropertyQueryPair.getKey() + + "\" and @value=\"" + publicPropertyQueryPair.getValue() + "\"]"; final Collection<DataNode> dataNodes = queryCmHandleAncestorsByCpsPath(cpsPath, OMIT_DESCENDANTS); @@ -223,17 +200,35 @@ public class CmHandleQueryServiceImpl implements CmHandleQueryService { return cmHandleReferences; } - private Collection<DataNode> getCmHandlesByDmiPluginIdentifierAndDmiProperty(final String dmiPluginIdentifier, - final String dmiProperty) { - return cpsQueryService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@" + dmiProperty + "='" + dmiPluginIdentifier + "']", - OMIT_DESCENDANTS); + private Set<String> getIdsByDmiPluginIdentifierAndDmiProperty(final String dmiPluginIdentifier, + final String dmiProperty, + final boolean outputAlternateId) { + final String attributeName = outputAlternateId ? ALTERNATE_ID : "id"; + final String cpsPath = String.format("%s/cm-handles[@%s='%s']/@%s", + NCMP_DMI_REGISTRY_PARENT, dmiProperty, dmiPluginIdentifier, attributeName); + return cpsQueryService.queryDataLeaf(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, cpsPath, String.class); + } + + private Collection<String> getAlternateIdsByCmHandleIds(final Collection<String> cmHandleIds) { + + final String cpsPath = NCMP_DMI_REGISTRY_PARENT + "/cm-handles[" + + createFormattedQueryString(cmHandleIds) + "]/@alternate-id"; + + return cpsQueryService.queryDataLeaf(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, cpsPath, String.class); + } + + private String createFormattedQueryString(final Collection<String> cmHandleIds) { + return cmHandleIds.stream() + .map(cmHandleId -> "@id='" + cmHandleId + "'") + .collect(Collectors.joining(" or ")); } + private DataNode getCmHandleState(final String cmHandleId) { cpsValidator.validateNameCharacters(cmHandleId); final String xpath = NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']/state"; return cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, xpath, OMIT_DESCENDANTS).iterator().next(); } -} + +}
\ No newline at end of file diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java index e7ec9cd13c..e145c62921 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java @@ -45,13 +45,13 @@ import org.onap.cps.api.model.DataNode; import org.onap.cps.api.model.ModuleDefinition; import org.onap.cps.api.model.ModuleReference; import org.onap.cps.api.parameters.FetchDescendantsOption; -import org.onap.cps.impl.utils.CpsValidator; import org.onap.cps.ncmp.api.exceptions.CmHandleNotFoundException; import org.onap.cps.ncmp.api.inventory.models.CompositeState; import org.onap.cps.ncmp.api.inventory.models.CompositeStateBuilder; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; import org.onap.cps.ncmp.impl.utils.YangDataConverter; import org.onap.cps.utils.ContentType; +import org.onap.cps.utils.CpsValidator; import org.onap.cps.utils.JsonObjectMapper; import org.springframework.stereotype.Component; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java index 428c6f6491..4c1032efad 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation + * Copyright (C) 2022-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -62,13 +62,13 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan @Override public Collection<String> queryCmHandleReferenceIds( - final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, - final boolean outputAlternateId) { + final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, + final boolean outputAlternateId) { return executeQueries(cmHandleQueryServiceParameters, outputAlternateId, - this::executeCpsPathQuery, - this::queryCmHandlesByPublicProperties, - this::executeModuleNameQuery, - this::queryCmHandlesByTrustLevel); + this::executeCpsPathQuery, + this::queryCmHandlesByPublicProperties, + this::executeModuleNameQuery, + this::queryCmHandlesByTrustLevel); } @Override @@ -84,7 +84,7 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan @Override public Collection<NcmpServiceCmHandle> queryCmHandles( - final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { + final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) { if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) { return getAllCmHandles(); @@ -111,15 +111,11 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan } final String dmiPluginIdentifierValue = dmiPropertyQueryPairs - .get(PropertyType.DMI_PLUGIN.getYangContainerName()); + .get(PropertyType.DMI_PLUGIN.getYangContainerName()); + + return cmHandleQueryService.getCmHandleReferencesByDmiPluginIdentifier( + dmiPluginIdentifierValue, outputAlternateId); - if (outputAlternateId) { - return - cmHandleQueryService.getCmHandleReferencesMapByDmiPluginIdentifier(dmiPluginIdentifierValue).values(); - } else { - return cmHandleQueryService.getCmHandleReferencesByDmiPluginIdentifier(dmiPluginIdentifierValue, - outputAlternateId); - } } private Collection<String> queryCmHandlesByPrivateProperties( @@ -175,7 +171,7 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan private Collection<String> executeCpsPathQuery( final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, final boolean outputAlternateId) { final Map<String, String> cpsPathCondition - = getCpsPathCondition(cmHandleQueryServiceParameters.getCmHandleQueryParameters()); + = getCpsPathCondition(cmHandleQueryServiceParameters.getCmHandleQueryParameters()); if (!validateCpsPathConditionProperties(cpsPathCondition)) { return Collections.emptySet(); } @@ -185,8 +181,8 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan } try { cpsPathQueryResult = collectCmHandleReferencesFromDataNodes( - cmHandleQueryService.queryCmHandleAncestorsByCpsPath(cpsPathCondition.get("cpsPath"), OMIT_DESCENDANTS), - outputAlternateId); + cmHandleQueryService.queryCmHandleAncestorsByCpsPath(cpsPathCondition.get("cpsPath"), + OMIT_DESCENDANTS), outputAlternateId); } catch (final PathParsingException pathParsingException) { throw new DataValidationException(pathParsingException.getMessage(), pathParsingException.getDetails(), pathParsingException); @@ -211,7 +207,7 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan } private Map<String, String> getPropertyPairs(final List<ConditionProperties> conditionProperties, - final String queryProperty) { + final String queryProperty) { final Map<String, String> result = new HashMap<>(); getConditions(conditionProperties, queryProperty).forEach(result::putAll); return result; @@ -229,18 +225,18 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan private Collection<String> getAllCmHandleReferences(final boolean outputAlternateId) { final DataNode dataNode = inventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT, DIRECT_CHILDREN_ONLY) - .iterator().next(); + .iterator().next(); return collectCmHandleReferencesFromDataNodes(dataNode.getChildDataNodes(), outputAlternateId); } private Collection<NcmpServiceCmHandle> getNcmpServiceCmHandles(final Collection<String> cmHandleIds) { final Collection<YangModelCmHandle> yangModelcmHandles - = inventoryPersistence.getYangModelCmHandles(cmHandleIds); + = inventoryPersistence.getYangModelCmHandles(cmHandleIds); final Collection<NcmpServiceCmHandle> ncmpServiceCmHandles = new ArrayList<>(yangModelcmHandles.size()); yangModelcmHandles.forEach(yangModelcmHandle -> - ncmpServiceCmHandles.add(YangDataConverter.toNcmpServiceCmHandle(yangModelcmHandle)) + ncmpServiceCmHandles.add(YangDataConverter.toNcmpServiceCmHandle(yangModelcmHandle)) ); return ncmpServiceCmHandles; } @@ -252,15 +248,15 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan private Collection<String> executeQueries(final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, final boolean outputAlternateId, final BiFunction<CmHandleQueryServiceParameters, Boolean, - Collection<String>>... queryFunctions) { + Collection<String>>... queryFunctions) { if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) { return getAllCmHandleReferences(outputAlternateId); } Collection<String> combinedQueryResult = NO_QUERY_TO_EXECUTE; for (final BiFunction<CmHandleQueryServiceParameters, Boolean, - Collection<String>> queryFunction : queryFunctions) { + Collection<String>> queryFunction : queryFunctions) { final Collection<String> queryResult = queryFunction.apply(cmHandleQueryServiceParameters, - outputAlternateId); + outputAlternateId); if (noEntriesFoundCanStopQuerying(queryResult)) { return Collections.emptySet(); } @@ -288,13 +284,13 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan } private Collection<String> collectCmHandleReferencesFromDataNodes(final Collection<DataNode> dataNodes, - final boolean outputAlternateId) { + final boolean outputAlternateId) { if (outputAlternateId) { return dataNodes.stream().map(dataNode -> - (String) dataNode.getLeaves().get("alternate-id")).collect(Collectors.toSet()); + (String) dataNode.getLeaves().get("alternate-id")).collect(Collectors.toSet()); } else { return dataNodes.stream().map(dataNode -> - (String) dataNode.getLeaves().get("id")).collect(Collectors.toSet()); + (String) dataNode.getLeaves().get("id")).collect(Collectors.toSet()); } } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/AsyncTaskExecutor.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/AsyncTaskExecutor.java deleted file mode 100644 index 80bc4ab69f..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/AsyncTaskExecutor.java +++ /dev/null @@ -1,77 +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.impl.inventory.sync; - -import static java.util.concurrent.TimeUnit.MILLISECONDS; - -import jakarta.annotation.PostConstruct; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeoutException; -import java.util.function.Supplier; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -@Slf4j -@Service -public class AsyncTaskExecutor { - - @Value("${ncmp.modules-sync-watchdog.async-executor.parallelism-level:10}") - @Getter - private int asyncTaskParallelismLevel; - private ExecutorService executorService; - private static final int DEFAULT_PARALLELISM_LEVEL = 10; - - /** - * Set up executor service with thread-pool size as per configuration parameter. - * If modules-sync-watchdog.async-executor.parallelism-level not set a default of 10 threads will be applied. - */ - @PostConstruct - public void setupThreadPool() { - executorService = Executors.newWorkStealingPool( - asyncTaskParallelismLevel == 0 ? DEFAULT_PARALLELISM_LEVEL : asyncTaskParallelismLevel); - } - - /** - * Execute supplied task asynchronously. - * - * @param taskSupplier functional method is get() task need to executed asynchronously - * @param timeOutInMillis the task timeout value in milliseconds - */ - public void executeTask(final Supplier<Object> taskSupplier, final long timeOutInMillis) { - CompletableFuture.supplyAsync(taskSupplier::get, executorService) - .orTimeout(timeOutInMillis, MILLISECONDS) - .whenCompleteAsync(this::handleTaskCompletion); - } - - private void handleTaskCompletion(final Object response, final Throwable throwable) { - if (throwable != null) { - if (throwable instanceof TimeoutException) { - log.error("Async task didn't complete within the required time.", throwable); - } else { - log.error("Watchdog async batch failed.", throwable); - } - } - } -} 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 1e24671f8d..2cc4375447 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 @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2024 Nordix Foundation + * Copyright (C) 2021-2025 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -61,13 +61,14 @@ public class DmiModelOperations { * Retrieves module references. * * @param yangModelCmHandle the yang model cm handle + * @param targetModuleSetTag module set tag to send to dmi * @return module references */ @Timed(value = "cps.ncmp.inventory.module.references.from.dmi", description = "Time taken to get all module references for a cm handle from dmi") - public List<ModuleReference> getModuleReferences(final YangModelCmHandle yangModelCmHandle) { - final DmiRequestBody dmiRequestBody = DmiRequestBody.builder() - .moduleSetTag(yangModelCmHandle.getModuleSetTag()).build(); + public List<ModuleReference> getModuleReferences(final YangModelCmHandle yangModelCmHandle, + final String targetModuleSetTag) { + final DmiRequestBody dmiRequestBody = DmiRequestBody.builder().moduleSetTag(targetModuleSetTag).build(); dmiRequestBody.asDmiProperties(yangModelCmHandle.getDmiProperties()); final ResponseEntity<Object> dmiFetchModulesResponseEntity = getResourceFromDmiWithJsonData( yangModelCmHandle.resolveDmiServiceName(MODEL), @@ -79,18 +80,20 @@ public class DmiModelOperations { * Retrieve yang resources from dmi for any modules that CPS-NCMP hasn't cached before. * * @param yangModelCmHandle the yangModelCmHandle + * @param targetModuleSetTag module set tag to send to dmi * @param newModuleReferences the unknown module references * @return yang resources as map of module name to yang(re)source */ @Timed(value = "cps.ncmp.inventory.yang.resources.from.dmi", description = "Time taken to get list of yang resources from dmi") public Map<String, String> getNewYangResourcesFromDmi(final YangModelCmHandle yangModelCmHandle, + final String targetModuleSetTag, final Collection<ModuleReference> newModuleReferences) { if (newModuleReferences.isEmpty()) { return Collections.emptyMap(); } final String jsonWithDataAndDmiProperties = getRequestBodyToFetchYangResources(newModuleReferences, - yangModelCmHandle.getDmiProperties(), yangModelCmHandle.getModuleSetTag()); + yangModelCmHandle.getDmiProperties(), targetModuleSetTag); final ResponseEntity<Object> responseEntity = getResourceFromDmiWithJsonData( yangModelCmHandle.resolveDmiServiceName(MODEL), jsonWithDataAndDmiProperties, @@ -123,13 +126,13 @@ public class DmiModelOperations { private static String getRequestBodyToFetchYangResources(final Collection<ModuleReference> newModuleReferences, final List<YangModelCmHandle.Property> dmiProperties, - final String moduleSetTag) { + final String targetModuleSetTag) { final JsonArray moduleReferencesAsJson = getModuleReferencesAsJson(newModuleReferences); final JsonObject data = new JsonObject(); data.add("modules", moduleReferencesAsJson); final JsonObject jsonRequestObject = new JsonObject(); - if (!moduleSetTag.isEmpty()) { - jsonRequestObject.addProperty("moduleSetTag", moduleSetTag); + if (!targetModuleSetTag.isEmpty()) { + jsonRequestObject.addProperty("moduleSetTag", targetModuleSetTag); } jsonRequestObject.add("data", data); jsonRequestObject.add("cmHandleProperties", toJsonObject(dmiProperties)); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java index e9f3d9b475..80e41652ee 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation + * Copyright (C) 2022-2025 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -189,7 +189,12 @@ public class ModuleOperationsUtils { .getLockReasonCategory())); } - public static String getTargetModuleSetTagFromLockReason(final CompositeState.LockReason lockReason) { + public static String getTargetModuleSetTagForUpgrade(final YangModelCmHandle yangModelCmHandle) { + final CompositeState.LockReason lockReason = yangModelCmHandle.getCompositeState().getLockReason(); + return getTargetModuleSetTagFromLockReason(lockReason); + } + + private static String getTargetModuleSetTagFromLockReason(final CompositeState.LockReason lockReason) { return getLockedCompositeStateDetails(lockReason).getOrDefault(MODULE_SET_TAG_KEY, ""); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java index 6c1dc731c6..79f5496eb7 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java @@ -36,7 +36,6 @@ import org.onap.cps.api.CpsAnchorService; import org.onap.cps.api.CpsDataService; import org.onap.cps.api.CpsModuleService; import org.onap.cps.api.exceptions.AlreadyDefinedException; -import org.onap.cps.api.exceptions.DuplicatedYangResourceException; import org.onap.cps.api.model.ModuleReference; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; import org.onap.cps.utils.ContentType; @@ -57,7 +56,7 @@ public class ModuleSyncService { @AllArgsConstructor private static final class ModuleDelta { Collection<ModuleReference> allModuleReferences; - Map<String, String> newModuleNameToContentMap; + Map<String, String> newYangResourceContentPerName; } /** @@ -67,14 +66,14 @@ public class ModuleSyncService { */ public void syncAndCreateSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle) { final String cmHandleId = yangModelCmHandle.getId(); - final String moduleSetTag = yangModelCmHandle.getModuleSetTag(); - final String schemaSetName = getSchemaSetName(cmHandleId, moduleSetTag); - syncAndCreateSchemaSet(yangModelCmHandle, schemaSetName); + final String targetModuleSetTag = yangModelCmHandle.getModuleSetTag(); + final String schemaSetName = getSchemaSetNameForModuleSetTag(cmHandleId, targetModuleSetTag); + syncAndCreateSchemaSet(yangModelCmHandle, schemaSetName, targetModuleSetTag); try { cpsAnchorService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName, cmHandleId); } catch (final AlreadyDefinedException alreadyDefinedException) { - log.warn("Ignoring (anchor) already exist exception for {}. Exception details: ", - yangModelCmHandle.getId(), alreadyDefinedException); + log.warn("Ignoring (Anchor) already exists exception for {}. Exception details: {}", cmHandleId, + alreadyDefinedException.getDetails()); } } @@ -86,46 +85,40 @@ public class ModuleSyncService { public void syncAndUpgradeSchemaSet(final YangModelCmHandle yangModelCmHandle) { final String cmHandleId = yangModelCmHandle.getId(); final String sourceModuleSetTag = yangModelCmHandle.getModuleSetTag(); - final String targetModuleSetTag = ModuleOperationsUtils.getTargetModuleSetTagFromLockReason( - yangModelCmHandle.getCompositeState().getLockReason()); + final String targetModuleSetTag = ModuleOperationsUtils.getTargetModuleSetTagForUpgrade(yangModelCmHandle); + final String schemaSetName = getSchemaSetNameForModuleSetTag(cmHandleId, targetModuleSetTag); if (sourceModuleSetTag.isEmpty() && targetModuleSetTag.isEmpty()) { - final ModuleDelta moduleDelta = getModuleDelta(yangModelCmHandle); + final ModuleDelta moduleDelta = getModuleDelta(yangModelCmHandle, targetModuleSetTag); cpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, - cmHandleId, moduleDelta.newModuleNameToContentMap, moduleDelta.allModuleReferences); + schemaSetName, moduleDelta.newYangResourceContentPerName, moduleDelta.allModuleReferences); } else { - final String targetSchemaSetName = getSchemaSetName(cmHandleId, targetModuleSetTag); - syncAndCreateSchemaSet(yangModelCmHandle, targetSchemaSetName); - cpsAnchorService.updateAnchorSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, - targetSchemaSetName); + syncAndCreateSchemaSet(yangModelCmHandle, schemaSetName, targetModuleSetTag); + cpsAnchorService.updateAnchorSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, schemaSetName); setCmHandleModuleSetTag(yangModelCmHandle, targetModuleSetTag); log.info("Upgrading schema set for CM handle ID: {}, Source Tag: {}, Target Tag: {}", cmHandleId, sourceModuleSetTag, targetModuleSetTag); } } - private void syncAndCreateSchemaSet(final YangModelCmHandle yangModelCmHandle, final String schemaSetName) { + private void syncAndCreateSchemaSet(final YangModelCmHandle yangModelCmHandle, + final String schemaSetName, + final String targetModuleSetTag) { if (isNewSchemaSet(schemaSetName)) { - final ModuleDelta moduleDelta = getModuleDelta(yangModelCmHandle); + final String cmHandleId = yangModelCmHandle.getId(); + final ModuleDelta moduleDelta = getModuleDelta(yangModelCmHandle, targetModuleSetTag); try { - log.info("Creating Schema Set {} for CM Handle {}", schemaSetName, yangModelCmHandle.getId()); + log.info("Creating Schema Set {} for CM Handle {}", schemaSetName, cmHandleId); cpsModuleService.createSchemaSetFromModules( NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName, - moduleDelta.newModuleNameToContentMap, + moduleDelta.newYangResourceContentPerName, moduleDelta.allModuleReferences ); log.info("Successfully created Schema Set {} for CM Handle {}", schemaSetName, yangModelCmHandle.getId()); } catch (final AlreadyDefinedException alreadyDefinedException) { - log.warn("Ignoring already exist (schema set) exception for {}. Exception details: ", - yangModelCmHandle.getId(), alreadyDefinedException); - } catch (final DuplicatedYangResourceException duplicatedYangResourceException) { - log.warn("Duplicate Yang Resource {} creation for {}. " - + "CM Handle will be LOCKED (for retry). Exception details: ", - duplicatedYangResourceException.getName(), - yangModelCmHandle.getId(), - duplicatedYangResourceException); - throw duplicatedYangResourceException; + log.warn("Ignoring (Schema Set) already exists exception for {}. Exception details: {}", cmHandleId, + alreadyDefinedException.getDetails()); } } } @@ -134,16 +127,17 @@ public class ModuleSyncService { return !cpsModuleService.schemaSetExists(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName); } - private ModuleDelta getModuleDelta(final YangModelCmHandle yangModelCmHandle) { + private ModuleDelta getModuleDelta(final YangModelCmHandle yangModelCmHandle, + final String targetModuleSetTag) { final Collection<ModuleReference> allModuleReferences = - dmiModelOperations.getModuleReferences(yangModelCmHandle); + dmiModelOperations.getModuleReferences(yangModelCmHandle, targetModuleSetTag); final Collection<ModuleReference> newModuleReferences = cpsModuleService.identifyNewModuleReferences(allModuleReferences); - final Map<String, String> newYangResources = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, - newModuleReferences); + final Map<String, String> newYangResourceContentPerName = + dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, targetModuleSetTag, newModuleReferences); log.debug("Module delta calculated for CM handle ID: {}. All references: {}. New modules: {}", - yangModelCmHandle.getId(), allModuleReferences, newYangResources.keySet()); - return new ModuleDelta(allModuleReferences, newYangResources); + yangModelCmHandle.getId(), allModuleReferences, newYangResourceContentPerName.keySet()); + return new ModuleDelta(allModuleReferences, newYangResourceContentPerName); } private void setCmHandleModuleSetTag(final YangModelCmHandle yangModelCmHandle, final String newModuleSetTag) { @@ -153,7 +147,7 @@ public class ModuleSyncService { jsonForUpdate, OffsetDateTime.now(), ContentType.JSON); } - private static String getSchemaSetName(final String cmHandleId, final String moduleSetTag) { + private static String getSchemaSetNameForModuleSetTag(final String cmHandleId, final String moduleSetTag) { return moduleSetTag.isEmpty() ? cmHandleId : moduleSetTag; } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java index b63496753e..f8f023e0f8 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java @@ -24,8 +24,6 @@ import com.hazelcast.map.IMap; import java.util.Collection; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.atomic.AtomicInteger; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.exceptions.DataNodeNotFoundException; @@ -51,12 +49,8 @@ public class ModuleSyncTasks { * Perform module sync on a batch of cm handles. * * @param cmHandleIds a batch of cm handle ids to perform module sync on - * @param batchCounter the number of batches currently being processed, will be decreased when - * task is finished or fails - * @return completed future to handle post-processing */ - public CompletableFuture<Void> performModuleSync(final Collection<String> cmHandleIds, - final AtomicInteger batchCounter) { + public void performModuleSync(final Collection<String> cmHandleIds) { final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle = new HashMap<>(cmHandleIds.size()); try { for (final String cmHandleId : cmHandleIds) { @@ -74,11 +68,8 @@ public class ModuleSyncTasks { } } } finally { - batchCounter.getAndDecrement(); lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle); - log.info("Processing module sync batch finished. {} batch(es) active.", batchCounter.get()); } - return CompletableFuture.completedFuture(null); } /** @@ -114,7 +105,7 @@ public class ModuleSyncTasks { compositeState.setLockReason(null); return CmHandleState.READY; } catch (final Exception e) { - log.warn("Processing of {} failed,reason : ", yangModelCmHandle.getId(), e); + log.warn("Processing of {} failed, reason: {}.", yangModelCmHandle.getId(), e.getMessage()); final LockReasonCategory lockReasonCategory = inUpgrade ? LockReasonCategory.MODULE_UPGRADE_FAILED : LockReasonCategory.MODULE_SYNC_FAILED; @@ -124,8 +115,8 @@ public class ModuleSyncTasks { } private void removeResetCmHandleFromModuleSyncMap(final String resetCmHandleId) { - moduleSyncStartedOnCmHandles.removeAsync(resetCmHandleId); - log.info("{} will be removed asynchronously from in progress map", resetCmHandleId); + moduleSyncStartedOnCmHandles.delete(resetCmHandleId); + log.info("{} removed from in progress map", resetCmHandleId); } private static boolean isCmHandleInAdvisedState(final YangModelCmHandle yangModelCmHandle) { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdog.java index 32e1c49f17..6eefedb633 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdog.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdog.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation + * Copyright (C) 2022-2025 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,13 +27,9 @@ import com.hazelcast.map.IMap; import java.util.Collection; import java.util.HashSet; import java.util.concurrent.BlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; -import org.onap.cps.ncmp.impl.utils.Sleeper; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @@ -46,16 +42,10 @@ public class ModuleSyncWatchdog { private final BlockingQueue<String> moduleSyncWorkQueue; private final IMap<String, Object> moduleSyncStartedOnCmHandles; private final ModuleSyncTasks moduleSyncTasks; - private final AsyncTaskExecutor asyncTaskExecutor; private final IMap<String, String> cpsAndNcmpLock; - private final Sleeper sleeper; private static final int MODULE_SYNC_BATCH_SIZE = 100; - private static final long PREVENT_CPU_BURN_WAIT_TIME_MILLIS = 10; private static final String VALUE_FOR_HAZELCAST_IN_PROGRESS_MAP = "Started"; - private static final long ASYNC_TASK_TIMEOUT_IN_MILLISECONDS = TimeUnit.MINUTES.toMillis(5); - @Getter - private AtomicInteger batchCounter = new AtomicInteger(1); /** * Check DB for any cm handles in 'ADVISED' state. @@ -69,18 +59,11 @@ public class ModuleSyncWatchdog { log.debug("Processing module sync watchdog waking up."); populateWorkQueueIfNeeded(); while (!moduleSyncWorkQueue.isEmpty()) { - if (batchCounter.get() <= asyncTaskExecutor.getAsyncTaskParallelismLevel()) { - final Collection<String> nextBatch = prepareNextBatch(); - log.info("Processing module sync batch of {}. {} batch(es) active.", - nextBatch.size(), batchCounter.get()); - if (!nextBatch.isEmpty()) { - asyncTaskExecutor.executeTask(() -> - moduleSyncTasks.performModuleSync(nextBatch, batchCounter), - ASYNC_TASK_TIMEOUT_IN_MILLISECONDS); - batchCounter.getAndIncrement(); - } - } else { - preventBusyWait(); + final Collection<String> nextBatch = prepareNextBatch(); + if (!nextBatch.isEmpty()) { + log.info("Processing module sync batch of {}. 1 batch(es) active.", nextBatch.size()); + moduleSyncTasks.performModuleSync(nextBatch); + log.info("Processing module sync batch finished. 0 batch(es) active."); } } } @@ -153,13 +136,4 @@ public class ModuleSyncWatchdog { log.info("nextBatch size : {}", nextBatch.size()); return nextBatch; } - - private void preventBusyWait() { - try { - log.debug("Busy waiting now"); - sleeper.haveALittleRest(PREVENT_CPU_BURN_WAIT_TIME_MILLIS); - } catch (final InterruptedException e) { - Thread.currentThread().interrupt(); - } - } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumer.java index efcbb78ace..44befab574 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumer.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumer.java @@ -27,11 +27,13 @@ import org.apache.kafka.clients.consumer.ConsumerRecord; import org.onap.cps.ncmp.api.inventory.models.TrustLevel; import org.onap.cps.ncmp.events.trustlevel.DeviceTrustLevel; import org.onap.cps.ncmp.utils.events.CloudEventMapper; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Component; @Component @RequiredArgsConstructor +@ConditionalOnProperty(name = "notification.enabled", havingValue = "true", matchIfMissing = true) public class DeviceTrustLevelMessageConsumer { private static final String CLOUD_EVENT_ID_HEADER_NAME = "ce_id"; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java index f68bb3b543..692bf5caee 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java @@ -193,14 +193,14 @@ public class TrustLevelManager { final TrustLevel newEffectiveTrustLevel) { if (oldEffectiveTrustLevel.equals(newEffectiveTrustLevel)) { log.debug("The Cm Handle: {} has already the same trust level: {}", notificationCandidateCmHandleId, - newEffectiveTrustLevel); + newEffectiveTrustLevel); } else { log.info("The trust level for Cm Handle: {} is now: {} ", notificationCandidateCmHandleId, - newEffectiveTrustLevel); + newEffectiveTrustLevel); cmAvcEventPublisher.publishAvcEvent(notificationCandidateCmHandleId, - AVC_CHANGED_ATTRIBUTE_NAME, - oldEffectiveTrustLevel.name(), - newEffectiveTrustLevel.name()); + AVC_CHANGED_ATTRIBUTE_NAME, + oldEffectiveTrustLevel.name(), + newEffectiveTrustLevel.name()); } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java index b97da2977a..750a5050f2 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2024 Nordix Foundation + * Copyright (C) 2024-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ import org.onap.cps.ncmp.api.exceptions.CmHandleNotFoundException; import org.onap.cps.ncmp.exceptions.NoAlternateIdMatchFoundException; import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; +import org.onap.cps.utils.CpsValidator; import org.springframework.stereotype.Service; @Service @@ -33,6 +34,7 @@ import org.springframework.stereotype.Service; public class AlternateIdMatcher { private final InventoryPersistence inventoryPersistence; + private final CpsValidator cpsValidator; /** * Get yang model cm handle that matches longest alternate id by removing elements @@ -64,11 +66,22 @@ public class AlternateIdMatcher { * @return cm handle id string */ public String getCmHandleId(final String cmHandleReference) { + if (cpsValidator.isValidName(cmHandleReference)) { + return getCmHandleIdTryingStandardIdFirst(cmHandleReference); + } + return getCmHandleIdByAlternateId(cmHandleReference); + } + + private String getCmHandleIdByAlternateId(final String cmHandleReference) { + // Please note: because of cm handle id validation rules this case does NOT need to try by (standard) id + return inventoryPersistence.getYangModelCmHandleByAlternateId(cmHandleReference).getId(); + } + + private String getCmHandleIdTryingStandardIdFirst(final String cmHandleReference) { if (inventoryPersistence.isExistingCmHandleId(cmHandleReference)) { return cmHandleReference; - } else { - return inventoryPersistence.getYangModelCmHandleByAlternateId(cmHandleReference).getId(); } + return inventoryPersistence.getYangModelCmHandleByAlternateId(cmHandleReference).getId(); } private String getParentPath(final String path, final String separator) { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/Sleeper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/Sleeper.java deleted file mode 100644 index 7a02fa06e0..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/Sleeper.java +++ /dev/null @@ -1,35 +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.impl.utils; - -import java.util.concurrent.TimeUnit; -import org.springframework.stereotype.Service; - -/** - * This class is to extract out sleep functionality so the interrupted exception handling can - * be covered with a test (e.g. using spy on Sleeper) and help to get to 100% code coverage. - */ -@Service -public class Sleeper { - public void haveALittleRest(final long timeInMillis) throws InterruptedException { - TimeUnit.MILLISECONDS.sleep(timeInMillis); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/CmAvcEventPublisher.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/CmAvcEventPublisher.java index 2a9717cc1a..2bb35864d3 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/CmAvcEventPublisher.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/CmAvcEventPublisher.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation + * Copyright (C) 2023-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,8 @@ package org.onap.cps.ncmp.utils.events; +import static org.onap.cps.ncmp.events.NcmpEventDataSchema.INVENTORY_EVENTS_V1; + import io.cloudevents.CloudEvent; import java.util.Collections; import java.util.HashMap; @@ -38,8 +40,8 @@ public class CmAvcEventPublisher { private final EventsPublisher<CloudEvent> eventsPublisher; - @Value("${app.ncmp.avc.cm-events-topic}") - private String avcTopic; + @Value("${app.ncmp.avc.inventory-events-topic}") + private String ncmpInventoryEventsTopicName; /** * Publish attribute value change event. @@ -51,11 +53,15 @@ public class CmAvcEventPublisher { final AvcEvent avcEvent = buildAvcEvent(attributeName, oldAttributeValue, newAttributeValue); final Map<String, String> extensions = createAvcEventExtensions(eventKey); - final CloudEvent avcCloudEvent = - NcmpEvent.builder().type(AvcEvent.class.getTypeName()) - .data(avcEvent).extensions(extensions).build().asCloudEvent(); + final CloudEvent avcCloudEvent = NcmpEvent.builder() + .type(AvcEvent.class.getTypeName()) + .dataSchema(INVENTORY_EVENTS_V1.getDataSchema()) + .data(avcEvent) + .extensions(extensions) + .build() + .asCloudEvent(); - eventsPublisher.publishCloudEvent(avcTopic, eventKey, avcCloudEvent); + eventsPublisher.publishCloudEvent(ncmpInventoryEventsTopicName, eventKey, avcCloudEvent); } private AvcEvent buildAvcEvent(final String attributeName, @@ -78,4 +84,4 @@ public class CmAvcEventPublisher { extensions.put("correlationid", eventKey); return extensions; } -} +}
\ No newline at end of file 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 8d3190eb00..6db962c068 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 @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation + * Copyright (C) 2023-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,12 +34,11 @@ import org.onap.cps.utils.JsonObjectMapper; @Builder public class NcmpEvent { + private String dataSchema; private Object data; private Map<String, String> extensions; private String type; @Builder.Default - private static final String CLOUD_EVENT_SPEC_VERSION_V1 = "1.0.0"; - @Builder.Default private static final String CLOUD_EVENT_SOURCE = "NCMP"; /** @@ -53,7 +52,7 @@ public class NcmpEvent { .withId(UUID.randomUUID().toString()) .withSource(URI.create(CLOUD_EVENT_SOURCE)) .withType(type) - .withDataSchema(URI.create("urn:cps:" + type + ":" + CLOUD_EVENT_SPEC_VERSION_V1)) + .withDataSchema(URI.create(dataSchema)) .withTime(EventDateTimeFormatter.toIsoOffsetDateTime( EventDateTimeFormatter.getCurrentIsoFormattedDateTime())) .withData(jsonObjectMapper.asJsonBytes(data)); diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cache/HazelcastCacheConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cache/HazelcastCacheConfigSpec.groovy index c08ff75a44..0026d7c4e6 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cache/HazelcastCacheConfigSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cache/HazelcastCacheConfigSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation + * Copyright (C) 2023-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,8 +20,7 @@ package org.onap.cps.ncmp.impl.cache -import com.hazelcast.config.Config -import com.hazelcast.config.RestEndpointGroup + import com.hazelcast.core.Hazelcast import spock.lang.Specification @@ -60,17 +59,4 @@ class HazelcastCacheConfigSpec extends Specification { 'Set Config' | HazelcastCacheConfig.createSetConfig('my set config') || false | false | true } - def 'Verify Hazelcast Cluster Information'() { - given: 'a test configuration' - def testConfig = new Config() - when: 'cluster information is exposed' - objectUnderTest.exposeClusterInformation(testConfig) - then: 'REST api configs are enabled' - assert testConfig.networkConfig.restApiConfig.enabled - and: 'only health check and cluster read are enabled' - def enabledGroups = testConfig.networkConfig.restApiConfig.enabledGroups - assert enabledGroups.size() == 2 - assert enabledGroups.containsAll([RestEndpointGroup.CLUSTER_READ, RestEndpointGroup.HEALTH_CHECK]) - } - } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiInEventProducerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiInEventProducerSpec.groovy index 34fa4549f5..3bf4c2c160 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiInEventProducerSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiInEventProducerSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (c) 2024 Nordix Foundation. + * Copyright (c) 2024-2025 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,19 +23,23 @@ package org.onap.cps.ncmp.impl.cmnotificationsubscription.dmi import com.fasterxml.jackson.databind.ObjectMapper import io.cloudevents.CloudEvent import org.onap.cps.events.EventsPublisher +import org.onap.cps.ncmp.config.CpsApplicationContext import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_dmi.CmHandle import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_dmi.Data import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_dmi.DmiInEvent import org.onap.cps.ncmp.utils.events.CloudEventMapper import org.onap.cps.utils.JsonObjectMapper +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.context.ContextConfiguration import spock.lang.Specification +@SpringBootTest(classes = [ObjectMapper, JsonObjectMapper]) +@ContextConfiguration(classes = [CpsApplicationContext]) class DmiInEventProducerSpec extends Specification { def mockEventsPublisher = Mock(EventsPublisher) - def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper()) - def objectUnderTest = new DmiInEventProducer(mockEventsPublisher, jsonObjectMapper) + def objectUnderTest = new DmiInEventProducer(mockEventsPublisher) def 'Create and Publish Cm Notification Subscription DMI In Event'() { given: 'a cm subscription for a dmi plugin' diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducerSpec.groovy index afa2e9874e..fde7e182d0 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducerSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducerSpec.groovy @@ -1,23 +1,47 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2025 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.cmnotificationsubscription.ncmp import com.fasterxml.jackson.databind.ObjectMapper import io.cloudevents.CloudEvent import org.onap.cps.events.EventsPublisher +import org.onap.cps.ncmp.config.CpsApplicationContext import org.onap.cps.ncmp.impl.cmnotificationsubscription.cache.DmiCacheHandler import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.Data import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.NcmpOutEvent import org.onap.cps.ncmp.utils.events.CloudEventMapper import org.onap.cps.utils.JsonObjectMapper +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.context.ContextConfiguration import spock.lang.Specification +@SpringBootTest(classes = [ObjectMapper, JsonObjectMapper]) +@ContextConfiguration(classes = [CpsApplicationContext]) class NcmpOutEventProducerSpec extends Specification { def mockEventsPublisher = Mock(EventsPublisher) - def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper()) def mockNcmpOutEventMapper = Mock(NcmpOutEventMapper) def mockDmiCacheHandler = Mock(DmiCacheHandler) - def objectUnderTest = new NcmpOutEventProducer(mockEventsPublisher, jsonObjectMapper, mockNcmpOutEventMapper, mockDmiCacheHandler) + def objectUnderTest = new NcmpOutEventProducer(mockEventsPublisher, mockNcmpOutEventMapper, mockDmiCacheHandler) def 'Create and #scenario Cm Notification Subscription NCMP out event'() { given: 'a cm subscription response for the client' @@ -102,5 +126,4 @@ class NcmpOutEventProducerSpec extends Specification { 0 * mockEventsPublisher.publishCloudEvent(*_) } - } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy index 01a08e7bb5..3dd2eabe21 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2024 Nordix Foundation + * Copyright (C) 2021-2025 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,8 +22,6 @@ package org.onap.cps.ncmp.impl.data import com.fasterxml.jackson.databind.ObjectMapper -import org.onap.cps.api.exceptions.DataNodeNotFoundException -import org.onap.cps.api.exceptions.DataValidationException import org.onap.cps.events.EventsPublisher import org.onap.cps.ncmp.api.data.models.CmResourceAddress import org.onap.cps.ncmp.api.data.models.DataOperationRequest @@ -86,6 +84,7 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec { def 'call get resource data for #expectedDataStore from DMI without topic #scenario.'() { given: 'a cm handle for #cmHandleId' + alternateIdMatcher.getCmHandleId(cmHandleId) >> cmHandleId mockYangModelCmHandleRetrieval(dmiProperties) and: 'a positive response from DMI service when it is called with the expected parameters' def responseFromDmi = Mono.just(new ResponseEntity<Object>('{some-key:some-value}', HttpStatus.OK)) @@ -206,33 +205,6 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec { CmHandleState.ADVISED || true } - def 'Resolving cm handle references with cm handle id.'() { - given: 'a resource address with a cm handle id' - def cmResourceAddress = new CmResourceAddress('some store', 'cm-handle-id', 'some resource') - and: 'the given cm handle id is available in the inventory' - mockInventoryPersistence.getYangModelCmHandle('cm-handle-id') >> yangModelCmHandle - expect: 'resolving the cm handle id returns the cm handle' - assert objectUnderTest.resolveYangModelCmHandleFromCmHandleReference(cmResourceAddress) == yangModelCmHandle - } - - def 'Resolving cm handle references with alternate id #scenario.'() { - given: 'a resource with a alternate id' - def cmResourceAddress = new CmResourceAddress('some store', alternateId, 'some resource') - and: 'the alternate id cannot be found in the inventory directly and that results in an exception' - mockInventoryPersistence.getYangModelCmHandle(alternateId) >> { throw errorThrownDuringCmHandleIdSearch } - and: 'the alternate id can be matched to a cm handle id' - alternateIdMatcher.getCmHandleId(alternateId) >> 'cm-handle-id' - and: 'that cm handle id is available in the inventory' - mockInventoryPersistence.getYangModelCmHandle('cm-handle-id') >> yangModelCmHandle - expect: 'resolving that cm handle id returns the cm handle' - assert objectUnderTest.resolveYangModelCmHandleFromCmHandleReference(cmResourceAddress) == yangModelCmHandle - where: 'the following alternate ids are used' - scenario | alternateId | errorThrownDuringCmHandleIdSearch - 'alternate id with no special characters' | 'alternate-id' | new DataNodeNotFoundException('','') - 'alternate id with special characters' | 'alternate#id' | new DataValidationException('','') - } - - def extractDataValue(actualDataOperationCloudEvent) { return toTargetEvent(actualDataOperationCloudEvent, DataOperationEvent).data.responses[0] } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandlerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandlerSpec.groovy index 041fbd95ee..93362f23be 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandlerSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandlerSpec.groovy @@ -29,12 +29,13 @@ class DmiSubJobRequestHandlerSpec extends Specification { def dmiWriteOperationsPerProducerKey = [new ProducerKey('dmi1', 'prod1'): [dmiWriteOperation]] def authorization = 'my authorization header' and: 'the dmi rest client will return a response (for the correct parameters)' - def responseEntity = new ResponseEntity<>(new SubJobWriteResponse('my-sub-job-id', 'dmi1', 'prod1'), HttpStatus.OK) + def responseAsKeyValuePairs = [subJobId:'my-sub-job-id'] + def responseEntity = new ResponseEntity<>(responseAsKeyValuePairs, HttpStatus.OK) def expectedJson = '{"destination":"d1","dataAcceptType":"t1","dataContentType":"t2","dataProducerId":"prod1","dataJobId":"some-job-id","data":[{"path":"p","op":"operation","moduleSetTag":"tag","value":null,"operationId":"o1","privateProperties":{}}]}' mockDmiRestClient.synchronousPostOperationWithJsonData(RequiredDmiService.DATA, _, expectedJson, OperationType.CREATE, authorization) >> responseEntity when: 'sending request to DMI invoked' objectUnderTest.sendRequestsToDmi(authorization, dataJobId, dataJobMetadata, dmiWriteOperationsPerProducerKey) then: 'the result contains the expected sub-job id' - assert responseEntity.body.subJobId == 'my-sub-job-id' + assert responseEntity.body.get('subJobId') == 'my-sub-job-id' } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientSpec.groovy index 4d47ef14a0..c968a32b3c 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2024 Nordix Foundation + * Copyright (C) 2021-2025 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -168,13 +168,12 @@ class DmiRestClientSpec extends Specification { def 'DMI GET Operation for DMI Data Service '() { given: 'the Data web client returns a valid response entity for the expected parameters' mockDataServicesWebClient.get() >> mockRequestBody - def jsonNode = jsonObjectMapper.convertJsonString('{"status":"some status"}', JsonNode.class) - ((ObjectNode) jsonNode).put('status', 'some status') - mockResponse.bodyToMono(JsonNode.class) >> Mono.just(jsonNode) + def result = '{"status":"some status"}' + mockResponse.bodyToMono(String.class) >> Mono.just(result) when: 'GET operation is invoked for Data Service' def response = objectUnderTest.getDataJobStatus(urlTemplateParameters, NO_AUTH_HEADER).block() then: 'the response equals to the expected value' - assert response == 'some status' + assert response == '{"status":"some status"}' } def 'Get data job result from DMI.'() { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy index 811e4ea526..6e6116e409 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation + * Copyright (C) 2022-2025 Nordix Foundation * Modifications Copyright (C) 2023 TechMahindra Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,7 +26,7 @@ import com.hazelcast.core.Hazelcast import com.hazelcast.instance.impl.HazelcastInstanceFactory import org.onap.cps.api.CpsDataService import org.onap.cps.api.CpsQueryService -import org.onap.cps.impl.utils.CpsValidator +import org.onap.cps.utils.CpsValidator import org.onap.cps.ncmp.api.inventory.DataStoreSyncState import org.onap.cps.ncmp.api.inventory.models.TrustLevel import org.onap.cps.ncmp.api.inventory.models.CmHandleState @@ -86,21 +86,21 @@ class CmHandleQueryServiceImplSpec extends Specification { } def 'Query cm handles on trust level'() { - given: 'query properties for trust level COMPLETE' - def trustLevelPropertyQueryPairs = ['trustLevel' : TrustLevel.COMPLETE.toString()] + given: 'query properties for #trustLevel' + def trustLevelPropertyQueryPairs = ['trustLevel' : trustLevel.toString()] and: 'the dmi cache has been initialised and "knows" about my-dmi-plugin-identifier' - trustLevelPerDmiPlugin.put('my-dmi-plugin-identifier', TrustLevel.COMPLETE) + trustLevelPerDmiPlugin.put('my-dmi-plugin-identifier', trustLevel) and: 'the DataNodes queried for a given cpsPath are returned from the persistence service' mockResponses() when: 'the query is run' def result = objectUnderTest.queryCmHandlesByTrustLevel(trustLevelPropertyQueryPairs, outputAlternateId) then: 'the result contain trusted cmHandle reference' - assert result.size() == 1 - assert result[0] == expectedCmHandleReference + assert result as Set == expectedCmHandleReference as Set where: 'the following data is used' - senario | outputAlternateId | expectedCmHandleReference - 'output cmHandleId' | false | 'PNFDemo' - 'output AlternateId' | true | 'alt-PNFDemo' + senario | outputAlternateId | expectedCmHandleReference | trustLevel || resultSize + 'output cmHandleId for trustLevel Complete' | false | ['PNFDemo'] | TrustLevel.COMPLETE || 1 + 'output alternateId for trustLevel Complete'| true | ['alt-PNFDemo'] | TrustLevel.COMPLETE || 1 + 'output alternateIds for trustLevel None' | true | ['alt-PNFDemo2', 'alt-PNFDemo', 'alt-PNFDemo4']| TrustLevel.NONE || 3 } def 'Query CmHandles using empty public properties query pair.'() { @@ -143,8 +143,8 @@ class CmHandleQueryServiceImplSpec extends Specification { def cmHandleState = state and: 'the persistence service returns a list of data nodes' mockCpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - NCMP_DMI_REGISTRY_PARENT + '/cm-handles[@id=\'some-cm-handle\']/state', - OMIT_DESCENDANTS) >> [new DataNode(leaves: ['cm-handle-state': 'READY'])] + NCMP_DMI_REGISTRY_PARENT + '/cm-handles[@id=\'some-cm-handle\']/state', + OMIT_DESCENDANTS) >> [new DataNode(leaves: ['cm-handle-state': 'READY'])] when: 'cm handles are compared by state' def result = objectUnderTest.cmHandleHasState('some-cm-handle', cmHandleState) then: 'the returned result matches the expected result from the persistence service' @@ -160,8 +160,8 @@ class CmHandleQueryServiceImplSpec extends Specification { def cmHandleState = CmHandleState.READY and: 'cps data service returns a list of data nodes' mockCpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - NCMP_DMI_REGISTRY_PARENT + '/cm-handles[@id=\'some-cm-handle\']/state', - OMIT_DESCENDANTS) >> [new DataNode(leaves: ['cm-handle-state': 'READY'])] + NCMP_DMI_REGISTRY_PARENT + '/cm-handles[@id=\'some-cm-handle\']/state', + OMIT_DESCENDANTS) >> [new DataNode(leaves: ['cm-handle-state': 'READY'])] when: 'cm handles are fetched by state and id' def result = objectUnderTest.getCmHandleState('some-cm-handle') then: 'the returned result is a list of data nodes returned by cps data service' @@ -200,8 +200,8 @@ class CmHandleQueryServiceImplSpec extends Specification { def cpsPath = "//cm-handles[@alternate-id='1']" and: 'cps data service returns a valid data node' mockCpsQueryService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - cpsPath, INCLUDE_ALL_DESCENDANTS) - >> Arrays.asList(cmHandleDataNode) + cpsPath, INCLUDE_ALL_DESCENDANTS) + >> Arrays.asList(cmHandleDataNode) when: 'get cm handles by cps path is invoked' def result = objectUnderTest.queryCmHandleAncestorsByCpsPath(cpsPath, INCLUDE_ALL_DESCENDANTS) then: 'the returned result is a list of data nodes returned by cps data service' @@ -223,18 +223,8 @@ class CmHandleQueryServiceImplSpec extends Specification { 'output is for cm handle ids' | false || ['PNFDemo', 'PNFDemo2', 'PNFDemo4'] } - def 'Get all alternateIds by dmi plugin identifier'() { - given: 'the DataNodes queried for a given cpsPath are returned from the persistence service.' - mockResponses() - when: 'cm Handles are fetched for a given dmi plugin identifier' - def result = objectUnderTest.getCmHandleReferencesMapByDmiPluginIdentifier('my-dmi-plugin-identifier').values() - then: 'result is the correct size' - assert result.size() == 3 - and: 'result contains the correct alternate Ids' - assert result.containsAll('alt-PNFDemo', 'alt-PNFDemo2', 'alt-PNFDemo4') - } - void mockResponses() { + mockCpsQueryService.queryDataNodes(_, _, '//public-properties[@name=\"Contact\" and @value=\"newemailforstore@bookstore.com\"]/ancestor::cm-handles', _) >> [pnfDemo, pnfDemo2, pnfDemo4] mockCpsQueryService.queryDataNodes(_, _, '//public-properties[@name=\"wont_match\" and @value=\"wont_match\"]/ancestor::cm-handles', _) >> [] mockCpsQueryService.queryDataNodes(_, _, '//public-properties[@name=\"Contact2\" and @value=\"newemailforstore2@bookstore.com\"]/ancestor::cm-handles', _) >> [pnfDemo4] @@ -244,6 +234,16 @@ class CmHandleQueryServiceImplSpec extends Specification { mockCpsQueryService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@dmi-service-name=\'my-dmi-plugin-identifier\']', OMIT_DESCENDANTS) >> [pnfDemo, pnfDemo2] mockCpsQueryService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@dmi-data-service-name=\'my-dmi-plugin-identifier\']', OMIT_DESCENDANTS) >> [pnfDemo, pnfDemo4] mockCpsQueryService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@dmi-model-service-name=\'my-dmi-plugin-identifier\']', OMIT_DESCENDANTS) >> [pnfDemo2, pnfDemo4] + + mockCpsQueryService.queryDataLeaf(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@dmi-service-name=\'my-dmi-plugin-identifier\']/@id', _) >> [pnfDemo.getLeaves().get('id'), pnfDemo2.getLeaves().get('id')] + mockCpsQueryService.queryDataLeaf(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@dmi-data-service-name=\'my-dmi-plugin-identifier\']/@id', _) >> [pnfDemo.getLeaves().get('id'), pnfDemo4.getLeaves().get('id')] + mockCpsQueryService.queryDataLeaf(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@dmi-model-service-name=\'my-dmi-plugin-identifier\']/@id', _) >> [pnfDemo2.getLeaves().get('id'), pnfDemo4.getLeaves().get('id')] + + mockCpsQueryService.queryDataLeaf(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@dmi-service-name=\'my-dmi-plugin-identifier\']/@alternate-id', _) >> [pnfDemo.getLeaves().get('alternate-id'), pnfDemo2.getLeaves().get('alternate-id')] + mockCpsQueryService.queryDataLeaf(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@dmi-data-service-name=\'my-dmi-plugin-identifier\']/@alternate-id', _) >> [pnfDemo.getLeaves().get('alternate-id'), pnfDemo4.getLeaves().get('alternate-id')] + mockCpsQueryService.queryDataLeaf(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@dmi-model-service-name=\'my-dmi-plugin-identifier\']/@alternate-id', _) >> [pnfDemo2.getLeaves().get('alternate-id'), pnfDemo4.getLeaves().get('alternate-id')] + mockCpsQueryService.queryDataLeaf(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@id=\'PNFDemo\']/@alternate-id', _) >> [pnfDemo.getLeaves().get('alternate-id')] + mockCpsQueryService.queryDataLeaf(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@id=\'PNFDemo2\' or @id=\'PNFDemo\' or @id=\'PNFDemo4\']/@alternate-id', _) >> [pnfDemo2.getLeaves().get('alternate-id'), pnfDemo.getLeaves().get('alternate-id'), pnfDemo4.getLeaves().get('alternate-id')] } def static createDataNode(dataNodeId) { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy index d8d92e99f5..0ed9dd8aae 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy @@ -35,7 +35,7 @@ import org.onap.cps.api.model.DataNode import org.onap.cps.api.model.ModuleDefinition import org.onap.cps.api.model.ModuleReference import org.onap.cps.api.parameters.FetchDescendantsOption -import org.onap.cps.impl.utils.CpsValidator +import org.onap.cps.utils.CpsValidator import org.onap.cps.ncmp.api.exceptions.CmHandleNotFoundException import org.onap.cps.ncmp.api.inventory.models.CompositeState import org.onap.cps.ncmp.api.inventory.models.CmHandleState diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceSpec.groovy index bf6ea36d65..7ba2bdf1e3 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation + * Copyright (C) 2022-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -206,7 +206,7 @@ class ParameterizedCmHandleQueryServiceSpec extends Specification { def conditionProperties = createConditionProperties('cmHandleWithDmiPlugin', [['some-key': 'some-value']]) cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties]) and: 'the inventoryPersistence returns different CmHandleIds' - partiallyMockedCmHandleQueries.getCmHandleReferencesMapByDmiPluginIdentifier(*_) >> [:] + partiallyMockedCmHandleQueries.getCmHandleReferencesByDmiPluginIdentifier(_,_) >> [] when: 'the query executed' def result = objectUnderTestWithPartiallyMockedQueries.queryCmHandleIdsForInventory(cmHandleQueryParameters, true) then: 'the expected number of results are returned.' diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/AsyncTaskExecutorSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/AsyncTaskExecutorSpec.groovy deleted file mode 100644 index 751c97a4d0..0000000000 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/AsyncTaskExecutorSpec.groovy +++ /dev/null @@ -1,63 +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.impl.inventory.sync - - -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest -import spock.lang.Specification - -import java.util.concurrent.TimeoutException -import java.util.function.Supplier - -@SpringBootTest(classes = AsyncTaskExecutor) -class AsyncTaskExecutorSpec extends Specification { - - @Autowired - AsyncTaskExecutor objectUnderTest - def mockTaskSupplier = Mock(Supplier<Object>) - - def 'Parallelism level configuration.'() { - expect: 'Parallelism level is configured with the correct value' - assert objectUnderTest.getAsyncTaskParallelismLevel() == 3 - } - - def 'Task completion with #caseDescriptor.'() { - when: 'task completion is handled' - def irrelevantResponse = null - objectUnderTest.handleTaskCompletion(irrelevantResponse, exception); - then: 'any exception is swallowed by the task completion (logged)' - noExceptionThrown() - where: 'following cases are tested' - caseDescriptor | exception - 'no exception' | null - 'time out exception' | new TimeoutException("time-out") - 'unexpected exception' | new Exception("some exception") - } - - def 'Task execution.'() { - when: 'a task is submitted for execution' - objectUnderTest.executeTask(() -> mockTaskSupplier, 0) - then: 'the task submission is successful' - noExceptionThrown() - } - -} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperationsSpec.groovy index 714555958a..302e43f170 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperationsSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperationsSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2024 Nordix Foundation + * Copyright (C) 2021-2025 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,14 +21,11 @@ package org.onap.cps.ncmp.impl.inventory.sync -import com.fasterxml.jackson.core.JsonProcessingException -import com.fasterxml.jackson.databind.ObjectMapper import org.onap.cps.ncmp.impl.dmi.DmiOperationsBaseSpec import org.onap.cps.ncmp.impl.dmi.DmiProperties import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters import org.onap.cps.api.model.ModuleReference 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.HttpStatus @@ -40,9 +37,12 @@ import static org.onap.cps.ncmp.api.data.models.OperationType.READ import static org.onap.cps.ncmp.impl.models.RequiredDmiService.MODEL @SpringBootTest -@ContextConfiguration(classes = [DmiProperties, DmiModelOperations]) +@ContextConfiguration(classes = [DmiProperties, DmiModelOperations, JsonObjectMapper]) class DmiModelOperationsSpec extends DmiOperationsBaseSpec { + def NO_AUTH_HEADER = null + def NO_MODULE_SET_TAG = '' + def expectedModulesUrlTemplateWithVariables = new UrlTemplateParameters('myServiceName/dmi/v1/ch/{cmHandleId}/modules', ['cmHandleId': cmHandleId]) def expectedModuleResourcesUrlTemplateWithVariables = new UrlTemplateParameters('myServiceName/dmi/v1/ch/{cmHandleId}/moduleResources', ['cmHandleId': cmHandleId]) @@ -52,11 +52,6 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { @Autowired DmiModelOperations objectUnderTest - @SpringBean - JsonObjectMapper spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper())) - - def NO_AUTH_HEADER = null - def 'Retrieving module references.'() { given: 'a cm handle' mockYangModelCmHandleRetrieval([]) @@ -65,7 +60,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { def responseFromDmi = new ResponseEntity([schemas: moduleReferencesAsLisOfMaps], HttpStatus.OK) mockDmiRestClient.synchronousPostOperationWithJsonData(MODEL, expectedModulesUrlTemplateWithVariables, '{"cmHandleProperties":{},"moduleSetTag":""}', READ, NO_AUTH_HEADER) >> responseFromDmi when: 'get module references is called' - def result = objectUnderTest.getModuleReferences(yangModelCmHandle) + def result = objectUnderTest.getModuleReferences(yangModelCmHandle, NO_MODULE_SET_TAG) then: 'the result consists of expected module references' assert result == [new ModuleReference(moduleName: 'mod1', revision: 'A'), new ModuleReference(moduleName: 'mod2', revision: 'X')] } @@ -78,7 +73,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { def responseFromDmi = new ResponseEntity(bodyAsMap, HttpStatus.NO_CONTENT) mockDmiRestClient.synchronousPostOperationWithJsonData(*_) >> responseFromDmi when: 'get module references is called' - def result = objectUnderTest.getModuleReferences(yangModelCmHandle) + def result = objectUnderTest.getModuleReferences(yangModelCmHandle, NO_MODULE_SET_TAG) then: 'the result is empty' assert result == [] where: 'the DMI response body has the following content' @@ -97,7 +92,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { mockDmiRestClient.synchronousPostOperationWithJsonData(MODEL, expectedModulesUrlTemplateWithVariables, '{"cmHandleProperties":' + expectedAdditionalPropertiesInRequest + ',"moduleSetTag":""}', READ, NO_AUTH_HEADER) >> responseFromDmi when: 'a get module references is called' - def result = objectUnderTest.getModuleReferences(yangModelCmHandle) + def result = objectUnderTest.getModuleReferences(yangModelCmHandle, NO_MODULE_SET_TAG) then: 'the result is the response from DMI service' assert result == [] where: 'the following DMI properties are used' @@ -116,7 +111,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { mockDmiRestClient.synchronousPostOperationWithJsonData(MODEL, expectedModuleResourcesUrlTemplateWithVariables, '{"data":{"modules":[' + expectedModuleReferencesInRequest + ']},"cmHandleProperties":{}}', READ, NO_AUTH_HEADER) >> responseFromDmi when: 'get new yang resources from DMI service' - def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, newModuleReferences) + def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, NO_MODULE_SET_TAG, newModuleReferences) then: 'the result has the 2 expected yang (re)sources (order is not guaranteed)' assert result.size() == 2 assert result.get('mod1') == 'some yang source' @@ -131,7 +126,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { def responseFromDmi = new ResponseEntity(responseFromDmiBody, HttpStatus.NO_CONTENT) mockDmiRestClient.synchronousPostOperationWithJsonData(*_) >> responseFromDmi when: 'get new yang resources from DMI service' - def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, newModuleReferences) + def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, NO_MODULE_SET_TAG, newModuleReferences) then: 'the result is empty' assert result == [:] where: 'the DMI response body has the following content' @@ -149,7 +144,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { '{"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' - def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, newModuleReferences) + def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, NO_MODULE_SET_TAG, newModuleReferences) then: 'the result is the response from DMI service' assert result == [mod1:'some yang source'] where: 'the following DMI properties are used' @@ -166,7 +161,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { mockDmiRestClient.synchronousPostOperationWithJsonData(MODEL, expectedModuleResourcesUrlTemplateWithVariables, '{' + 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) + def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, moduleSetTag, newModuleReferences) then: 'the result is the response from DMI service' assert result == [mod1:'some yang source'] where: 'the following Module Set Tags are used' @@ -180,7 +175,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { given: 'a cm handle' mockYangModelCmHandleRetrieval([]) when: 'a get new yang resources from DMI is called with no module references' - def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, []) + def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, NO_MODULE_SET_TAG, []) then: 'no resources are returned' assert result == [:] and: 'no request is sent to DMI' @@ -191,21 +186,35 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { given: 'a cm handle' mockYangModelCmHandleRetrieval(null) when: 'a get new yang resources from DMI is called' - objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, [new ModuleReference('mod1', 'A')]) + objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, NO_MODULE_SET_TAG, [new ModuleReference('mod1', 'A')]) then: 'a null pointer is thrown (we might need to address this later)' thrown(NullPointerException) } - def 'Retrieving module references with Json processing exception.'() { - given: 'a cm handle' - mockYangModelCmHandleRetrieval([]) - and: 'a Json processing exception occurs' - spiedJsonObjectMapper.asJsonString(_) >> {throw (new JsonProcessingException('parsing error'))} - when: 'a DMI operation is executed' - objectUnderTest.getModuleReferences(yangModelCmHandle) - then: 'an ncmp exception is thrown' - def exceptionThrown = thrown(JsonProcessingException) - and: 'the message indicates a parsing error' - exceptionThrown.message.toLowerCase().contains('parsing error') + def 'Retrieving module references forwards the new module set tag to DMI during CM-handle upgrade.'() { + given: 'a cm handle with an existing module set tag' + mockYangModelCmHandleRetrieval([], 'OLD-TAG') + when: 'get module references is called' + objectUnderTest.getModuleReferences(yangModelCmHandle, 'NEW-TAG') + then: 'a request was sent to DMI with the NEW module set tag in the body' + 1 * mockDmiRestClient.synchronousPostOperationWithJsonData(*_) >> { args -> + def requestBodyAsJson = args[2] as String + assert requestBodyAsJson.contains('"moduleSetTag":"NEW-TAG"') + return new ResponseEntity([schemas: [[moduleName: 'mod1', revision: 'A'], [moduleName: 'mod2', revision: 'X']]], HttpStatus.OK) + } + } + + def 'Retrieving yang resources forwards the new module set tag to DMI during CM-handle upgrade.'() { + given: 'a cm handle with an existing module set tag' + mockYangModelCmHandleRetrieval([], 'OLD-TAG') + when: 'get new yang resources from DMI service' + objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, 'NEW-TAG', newModuleReferences) + then: 'a request was sent to DMI with the NEW module set tag in the body' + 1 * mockDmiRestClient.synchronousPostOperationWithJsonData(*_) >> { args -> + def requestBodyAsJson = args[2] as String + assert requestBodyAsJson.contains('"moduleSetTag":"NEW-TAG"') + return new ResponseEntity([[moduleName: 'mod1', revision: 'A', yangSource: 'some yang source'], + [moduleName: 'mod2', revision: 'X', yangSource: 'other yang source']], HttpStatus.OK) + } } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncServiceSpec.groovy index 868609e282..b4837f7bab 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncServiceSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncServiceSpec.groovy @@ -39,6 +39,8 @@ import static org.onap.cps.ncmp.api.inventory.models.LockReasonCategory.MODULE_U class ModuleSyncServiceSpec extends Specification { + def NO_MODULE_SET_TAG = '' + def mockCpsModuleService = Mock(CpsModuleService) def mockDmiModelOperations = Mock(DmiModelOperations) def mockCpsAnchorService = Mock(CpsAnchorService) @@ -53,9 +55,9 @@ class ModuleSyncServiceSpec extends Specification { def yangModelCmHandle = createAdvisedCmHandle(moduleSetTag) and: 'DMI operations returns some module references' def moduleReferences = [ new ModuleReference('module1','1'), new ModuleReference('module2','2') ] - mockDmiModelOperations.getModuleReferences(yangModelCmHandle) >> moduleReferences + mockDmiModelOperations.getModuleReferences(yangModelCmHandle, moduleSetTag) >> moduleReferences and: 'DMI-Plugin returns resource(s) for "new" module(s)' - mockDmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, identifiedNewModuleReferences) >> newModuleNameContentToMap + mockDmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, moduleSetTag, identifiedNewModuleReferences) >> newModuleNameContentToMap and: 'the module service identifies #identifiedNewModuleReferences.size() new modules' mockCpsModuleService.identifyNewModuleReferences(moduleReferences) >> identifiedNewModuleReferences when: 'module sync is triggered' @@ -140,8 +142,8 @@ class ModuleSyncServiceSpec extends Specification { def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, '', '', ncmpServiceCmHandle,'', '', '') and: 'DMI operations returns some module references for upgraded cm handle' def moduleReferences = [ new ModuleReference('module1','1') ] - mockDmiModelOperations.getModuleReferences(yangModelCmHandle) >> moduleReferences - mockDmiModelOperations.getNewYangResourcesFromDmi(_, []) >> [:] + mockDmiModelOperations.getModuleReferences(yangModelCmHandle, NO_MODULE_SET_TAG) >> moduleReferences + mockDmiModelOperations.getNewYangResourcesFromDmi(_, NO_MODULE_SET_TAG, []) >> [:] and: 'none of these module references are new (all already known to the system)' mockCpsModuleService.identifyNewModuleReferences(_) >> [] when: 'module sync is triggered' @@ -163,7 +165,7 @@ class ModuleSyncServiceSpec extends Specification { mockCpsModuleService.schemaSetExists(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, tagTo) >> schemaExists and: 'DMI operations returns some module references for upgraded cm handle' def moduleReferences = [ new ModuleReference('module1','1') ] - expectedCallsToDmi * mockDmiModelOperations.getModuleReferences(yangModelCmHandle) >> moduleReferences + expectedCallsToDmi * mockDmiModelOperations.getModuleReferences(yangModelCmHandle, tagTo) >> moduleReferences and: 'dmi returns no new yang resources' mockDmiModelOperations.getNewYangResourcesFromDmi(*_) >> [:] and: 'none of these module references are new (all already known to the system)' diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasksSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasksSpec.groovy index 92f4b38f31..a2f38c89eb 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasksSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasksSpec.groovy @@ -39,8 +39,6 @@ import org.onap.cps.ncmp.impl.inventory.sync.lcm.LcmEventsCmHandleStateHandler import org.slf4j.LoggerFactory import spock.lang.Specification -import java.util.concurrent.atomic.AtomicInteger - import static org.onap.cps.ncmp.api.inventory.models.LockReasonCategory.MODULE_SYNC_FAILED import static org.onap.cps.ncmp.api.inventory.models.LockReasonCategory.MODULE_UPGRADE import static org.onap.cps.ncmp.api.inventory.models.LockReasonCategory.MODULE_UPGRADE_FAILED @@ -70,8 +68,6 @@ class ModuleSyncTasksSpec extends Specification { .getOrCreateHazelcastInstance(new Config('hazelcastInstanceName')) .getMap('mapInstanceName') - def batchCount = new AtomicInteger(5) - def objectUnderTest = new ModuleSyncTasks(mockInventoryPersistence, mockSyncUtils, mockModuleSyncService, mockLcmEventsCmHandleStateHandler, moduleSyncStartedOnCmHandles) @@ -87,7 +83,7 @@ class ModuleSyncTasksSpec extends Specification { mockInventoryPersistence.getYangModelCmHandle('cm-handle-1') >> cmHandle1 mockInventoryPersistence.getYangModelCmHandle('cm-handle-2') >> cmHandle2 when: 'module sync poll is executed' - objectUnderTest.performModuleSync(['cm-handle-1', 'cm-handle-2'], batchCount) + objectUnderTest.performModuleSync(['cm-handle-1', 'cm-handle-2']) then: 'module sync service is invoked for each cm handle' 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(_) >> { args -> assert args[0].id == 'cm-handle-1' } 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(_) >> { args -> assert args[0].id == 'cm-handle-2' } @@ -95,8 +91,6 @@ class ModuleSyncTasksSpec extends Specification { 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_) >> { args -> assertBatch(args, ['cm-handle-1', 'cm-handle-2'], CmHandleState.READY) } - and: 'batch count is decremented by one' - assert batchCount.get() == 4 } def 'Handle CM handle failure during #scenario and log MODULE_UPGRADE lock reason'() { @@ -108,15 +102,13 @@ class ModuleSyncTasksSpec extends Specification { mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(_) >> { throw new Exception('some exception') } mockModuleSyncService.syncAndUpgradeSchemaSet(_) >> { throw new Exception('some exception') } when: 'module sync is executed' - objectUnderTest.performModuleSync(['cm-handle'], batchCount) + objectUnderTest.performModuleSync(['cm-handle']) then: 'lock reason is updated with number of attempts' 1 * mockSyncUtils.updateLockReasonWithAttempts(_, expectedLockReasonCategory, 'some exception') and: 'the state handler is called to update the state to LOCKED' 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_) >> { args -> assertBatch(args, ['cm-handle'], CmHandleState.LOCKED) } - and: 'batch count is decremented by one' - assert batchCount.get() == 4 where: scenario | lockReasonCategory | lockReasonDetails || expectedLockReasonCategory 'module sync' | MODULE_SYNC_FAILED | 'some lock details' || MODULE_SYNC_FAILED @@ -132,7 +124,7 @@ class ModuleSyncTasksSpec extends Specification { and: 'a cm handle in advised state' mockInventoryPersistence.getYangModelCmHandle('cm-handle-3') >> cmHandleByIdAndState('cm-handle-3', CmHandleState.ADVISED) when: 'module sync poll is executed' - objectUnderTest.performModuleSync(['cm-handle-1', 'cm-handle-2', 'cm-handle-3'], batchCount) + objectUnderTest.performModuleSync(['cm-handle-1', 'cm-handle-2', 'cm-handle-3']) then: 'no exception is thrown' noExceptionThrown() and: 'the deleted cm-handle did not sync' @@ -176,7 +168,7 @@ class ModuleSyncTasksSpec extends Specification { and: 'entry in progress map for other cm handle' moduleSyncStartedOnCmHandles.put('other-cm-handle', 'started') when: 'module sync poll is executed' - objectUnderTest.performModuleSync(['cm-handle-1'], batchCount) + objectUnderTest.performModuleSync(['cm-handle-1']) then: 'module sync service is invoked for cm handle' 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(_) >> { args -> assert args[0].id == 'cm-handle-1' } and: 'the entry for other cm handle is still in the progress map' @@ -192,7 +184,7 @@ class ModuleSyncTasksSpec extends Specification { def loggingEvent = getLoggingEvent() assert loggingEvent.level == Level.INFO and: 'the log indicates the cm handle entry is removed successfully' - assert loggingEvent.formattedMessage == 'ch-1 will be removed asynchronously from in progress map' + assert loggingEvent.formattedMessage == 'ch-1 removed from in progress map' } def 'Sync and upgrade CM handle if in upgrade state for #scenario'() { @@ -201,7 +193,7 @@ class ModuleSyncTasksSpec extends Specification { cmHandle.compositeState.setLockReason(CompositeState.LockReason.builder().lockReasonCategory(lockReasonCategory).build()) mockInventoryPersistence.getYangModelCmHandle('cm-handle') >> cmHandle when: 'module sync is executed' - objectUnderTest.performModuleSync(['cm-handle'], batchCount) + objectUnderTest.performModuleSync(['cm-handle']) then: 'the module sync service should attempt to sync and upgrade the CM handle' 1 * mockModuleSyncService.syncAndUpgradeSchemaSet(_) >> { args -> assert args[0].id == 'cm-handle' diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy index a9b88c2d3b..68aa6a1b6a 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation + * Copyright (C) 2022-2025 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,14 +22,10 @@ package org.onap.cps.ncmp.impl.inventory.sync import com.hazelcast.map.IMap +import java.util.concurrent.ArrayBlockingQueue import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle -import org.onap.cps.ncmp.impl.utils.Sleeper -import org.onap.cps.api.model.DataNode import spock.lang.Specification -import java.util.concurrent.ArrayBlockingQueue -import java.util.concurrent.locks.Lock - class ModuleSyncWatchdogSpec extends Specification { def mockModuleOperationsUtils = Mock(ModuleOperationsUtils) @@ -42,17 +38,9 @@ class ModuleSyncWatchdogSpec extends Specification { def mockModuleSyncTasks = Mock(ModuleSyncTasks) - def spiedAsyncTaskExecutor = Spy(AsyncTaskExecutor) - def mockCpsAndNcmpLock = Mock(IMap<String,String>) - def spiedSleeper = Spy(Sleeper) - - def objectUnderTest = new ModuleSyncWatchdog(mockModuleOperationsUtils, moduleSyncWorkQueue , mockModuleSyncStartedOnCmHandles, mockModuleSyncTasks, spiedAsyncTaskExecutor, mockCpsAndNcmpLock, spiedSleeper) - - void setup() { - spiedAsyncTaskExecutor.setupThreadPool() - } + def objectUnderTest = new ModuleSyncWatchdog(mockModuleOperationsUtils, moduleSyncWorkQueue , mockModuleSyncStartedOnCmHandles, mockModuleSyncTasks, mockCpsAndNcmpLock) def 'Module sync advised cm handles with #scenario.'() { given: 'module sync utilities returns #numberOfAdvisedCmHandles advised cm handles' @@ -61,12 +49,10 @@ class ModuleSyncWatchdogSpec extends Specification { mockModuleOperationsUtils.getCmHandlesThatFailedModelSyncOrUpgrade() >> [] and: 'the work queue can be locked' mockCpsAndNcmpLock.tryLock('workQueueLock') >> true - and: 'the executor has enough available threads' - spiedAsyncTaskExecutor.getAsyncTaskParallelismLevel() >> 3 when: ' module sync is started' objectUnderTest.moduleSyncAdvisedCmHandles() then: 'it performs #expectedNumberOfTaskExecutions tasks' - expectedNumberOfTaskExecutions * spiedAsyncTaskExecutor.executeTask(*_) + expectedNumberOfTaskExecutions * mockModuleSyncTasks.performModuleSync(*_) and: 'the executing thread is unlocked' 1 * mockCpsAndNcmpLock.unlock('workQueueLock') where: 'the following parameter are used' @@ -84,12 +70,10 @@ class ModuleSyncWatchdogSpec extends Specification { mockModuleOperationsUtils.getAdvisedCmHandleIds() >> createCmHandleIds(1) and: 'the work queue can be locked' mockCpsAndNcmpLock.tryLock('workQueueLock') >> true - and: 'the executor first has no threads but has one thread on the second attempt' - spiedAsyncTaskExecutor.getAsyncTaskParallelismLevel() >>> [ 0, 1 ] when: ' module sync is started' objectUnderTest.moduleSyncAdvisedCmHandles() then: 'it performs one task' - 1 * spiedAsyncTaskExecutor.executeTask(*_) + 1 * mockModuleSyncTasks.performModuleSync(*_) } def 'Module sync advised cm handle already handled by other thread.'() { @@ -97,27 +81,21 @@ class ModuleSyncWatchdogSpec extends Specification { mockModuleOperationsUtils.getAdvisedCmHandleIds() >> createCmHandleIds(1) and: 'the work queue can be locked' mockCpsAndNcmpLock.tryLock('workQueueLock') >> true - and: 'the executor has a thread available' - spiedAsyncTaskExecutor.getAsyncTaskParallelismLevel() >> 1 and: 'the semaphore cache indicates the cm handle is already being processed' mockModuleSyncStartedOnCmHandles.putIfAbsent(*_) >> 'Started' - when: ' module sync is started' + when: 'module sync is started' objectUnderTest.moduleSyncAdvisedCmHandles() then: 'it does NOT execute a task to process the (empty) batch' - 0 * spiedAsyncTaskExecutor.executeTask(*_) + 0 * mockModuleSyncTasks.performModuleSync(*_) } def 'Module sync with previous cm handle(s) left in work queue.'() { given: 'there is still a cm handle in the queue' moduleSyncWorkQueue.offer('ch-1') - and: 'sync utilities returns many advise cm handles' - mockModuleOperationsUtils.getAdvisedCmHandleIds() >> createCmHandleIds(500) - and: 'the executor has plenty threads available' - spiedAsyncTaskExecutor.getAsyncTaskParallelismLevel() >> 10 - when: ' module sync is started' + when: 'module sync is started' objectUnderTest.moduleSyncAdvisedCmHandles() then: 'it does executes only one task to process the remaining handle in the queue' - 1 * spiedAsyncTaskExecutor.executeTask(*_) + 1 * mockModuleSyncTasks.performModuleSync(*_) } def 'Reset failed cm handles.'() { @@ -147,15 +125,6 @@ class ModuleSyncWatchdogSpec extends Specification { true || false || 1 } - def 'Sleeper gets interrupted.'() { - given: 'sleeper gets interrupted' - spiedSleeper.haveALittleRest(_) >> { throw new InterruptedException() } - when: 'the watchdog attempts to sleep to save cpu cycles' - objectUnderTest.preventBusyWait() - then: 'no exception is thrown' - noExceptionThrown() - } - def createCmHandleIds(numberOfCmHandles) { return (numberOfCmHandles > 0) ? (1..numberOfCmHandles).collect { 'ch-'+it } : [] } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/AlternateIdMatcherSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/AlternateIdMatcherSpec.groovy index a6d21afd30..b59dd1a55f 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/AlternateIdMatcherSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/AlternateIdMatcherSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2024 Nordix Foundation + * Copyright (C) 2024-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. @@ -24,12 +24,18 @@ import org.onap.cps.ncmp.api.exceptions.CmHandleNotFoundException import org.onap.cps.ncmp.exceptions.NoAlternateIdMatchFoundException import org.onap.cps.ncmp.impl.inventory.InventoryPersistence import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle +import org.onap.cps.utils.CpsValidatorImpl +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.context.ContextConfiguration import spock.lang.Specification +@SpringBootTest +@ContextConfiguration(classes = [InventoryPersistence]) class AlternateIdMatcherSpec extends Specification { def mockInventoryPersistence = Mock(InventoryPersistence) - def objectUnderTest = new AlternateIdMatcher(mockInventoryPersistence) + + def objectUnderTest = new AlternateIdMatcher(mockInventoryPersistence, new CpsValidatorImpl()) def setup() { given: 'cm handle in the registry with alternate id /a/b' @@ -68,17 +74,22 @@ class AlternateIdMatcherSpec extends Specification { 'no match at all' | '/x/y' } - def 'Get cmHandle id from passed cmHandleReference (cmHandleId scenario)' () { - when: 'a cmHandleCmReference is passed in' + def 'Get cm handle id from a cm handle reference that is a #scenario id.' () { + given: 'inventory persistence service confirms the reference exists as an id or not (#isExistingCmHandleId)' + mockInventoryPersistence.isExistingCmHandleId(cmHandleReference) >> isExistingCmHandleId + when: 'getting a cm handle id from the reference' def result = objectUnderTest.getCmHandleId(cmHandleReference) - then: 'the inventory persistence service returns a cm handle (or not)' - mockInventoryPersistence.isExistingCmHandleId(cmHandleReference) >> existingCmHandleIdResponse - mockInventoryPersistence.getYangModelCmHandleByAlternateId(cmHandleReference) >> alternateIdGetResponse - and: 'correct result is returned' - assert result == cmHandleReference + then: 'a call to find the cm handle by alternate id is only made when needed' + if (isExistingCmHandleId) { + 0 * mockInventoryPersistence.getYangModelCmHandleByAlternateId(*_) + } else { + 1 * mockInventoryPersistence.getYangModelCmHandleByAlternateId(cmHandleReference) >> new YangModelCmHandle(id: 'ch-id-2') + } + and: 'the expected cm handle id is returned' + assert result == expectedCmHandleId where: 'the following parameters are used' - cmHandleReference | existingCmHandleIdResponse | alternateIdGetResponse - 'ch-1' | true | '' - 'alt-1' | false | new YangModelCmHandle(id: 'alt-1') + scenario | cmHandleReference | isExistingCmHandleId || expectedCmHandleId + 'standard' | 'ch-id-1' | true || 'ch-id-1' + 'alternate' | 'alt-id=1' | false || 'ch-id-2' } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/MessagingBaseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/MessagingBaseSpec.groovy index 377a1a6637..d38d5442f2 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/MessagingBaseSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/MessagingBaseSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (c) 2023 Nordix Foundation. + * Copyright (c) 2023-2025 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,8 +29,7 @@ import org.springframework.kafka.core.KafkaTemplate import org.springframework.kafka.support.serializer.JsonSerializer import org.springframework.test.context.DynamicPropertyRegistry import org.springframework.test.context.DynamicPropertySource -import org.testcontainers.containers.KafkaContainer -import org.testcontainers.utility.DockerImageName +import org.testcontainers.kafka.ConfluentKafkaContainer import spock.lang.Specification class MessagingBaseSpec extends Specification { @@ -43,7 +42,7 @@ class MessagingBaseSpec extends Specification { kafkaTestContainer.stop() } - static kafkaTestContainer = new KafkaContainer(DockerImageName.parse('registry.nordix.org/onaptest/confluentinc/cp-kafka:6.2.1').asCompatibleSubstituteFor('confluentinc/cp-kafka')) + static kafkaTestContainer = new ConfluentKafkaContainer("confluentinc/cp-kafka:7.8.0") def legacyEventKafkaTemplate = new KafkaTemplate<>(new DefaultKafkaProducerFactory<String, String>(eventProducerConfigProperties(JsonSerializer))) diff --git a/cps-ncmp-service/src/test/resources/application.yml b/cps-ncmp-service/src/test/resources/application.yml index 12db639633..3276ceb534 100644 --- a/cps-ncmp-service/src/test/resources/application.yml +++ b/cps-ncmp-service/src/test/resources/application.yml @@ -77,10 +77,6 @@ ncmp: trust-level: dmi-availability-watchdog-ms: 30000 - modules-sync-watchdog: - async-executor: - parallelism-level: 3 - policy-executor: enabled: true defaultDecision: "some default decision" |