aboutsummaryrefslogtreecommitdiffstats
path: root/cps-ncmp-service/src
diff options
context:
space:
mode:
Diffstat (limited to 'cps-ncmp-service/src')
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cache/HazelcastCacheConfig.java9
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiInEventProducer.java27
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducer.java55
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventPublishingTask.java7
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java34
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DataOperationEventCreator.java15
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java9
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java7
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java10
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java103
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java54
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/AsyncTaskExecutor.java77
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java19
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java9
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java64
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java17
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdog.java38
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumer.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java10
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java19
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/Sleeper.java35
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/CmAvcEventPublisher.java22
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpEvent.java7
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cache/HazelcastCacheConfigSpec.groovy18
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiInEventProducerSpec.groovy10
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducerSpec.groovy29
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy32
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandlerSpec.groovy5
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientSpec.groovy9
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy54
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceSpec.groovy4
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/AsyncTaskExecutorSpec.groovy63
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperationsSpec.groovy69
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncServiceSpec.groovy12
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasksSpec.groovy20
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy49
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/AlternateIdMatcherSpec.groovy35
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/MessagingBaseSpec.groovy7
-rw-r--r--cps-ncmp-service/src/test/resources/application.yml4
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"