aboutsummaryrefslogtreecommitdiffstats
path: root/cps-ncmp-service
diff options
context:
space:
mode:
Diffstat (limited to 'cps-ncmp-service')
-rw-r--r--cps-ncmp-service/pom.xml2
-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/datajobs/DmiSubJobRequestHandler.java9
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java3
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandler.java6
-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/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.java68
-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/TrustLevelManager.java10
-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.java14
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CmHandleRegistrationResponseSpec.groovy11
-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/datajobs/DmiSubJobRequestHandlerSpec.groovy5
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy2
-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/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.groovy44
-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/utils/events/MessagingBaseSpec.groovy7
-rw-r--r--cps-ncmp-service/src/test/resources/application.yml4
28 files changed, 199 insertions, 415 deletions
diff --git a/cps-ncmp-service/pom.xml b/cps-ncmp-service/pom.xml
index eb0aed1e7c..70e0b4f8f4 100644
--- a/cps-ncmp-service/pom.xml
+++ b/cps-ncmp-service/pom.xml
@@ -27,7 +27,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.6.0-SNAPSHOT</version>
+ <version>3.6.1-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
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/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/inventory/CmHandleQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java
index 59d0f9704e..ae913ddfe7 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
@@ -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;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java
index e7fd247a08..75c52f3c60 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java
@@ -23,7 +23,6 @@
package org.onap.cps.ncmp.impl.inventory;
-import static org.onap.cps.ncmp.api.NcmpResponseStatus.ALTERNATE_ID_ALREADY_ASSOCIATED;
import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND;
import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_READY;
import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_ALREADY_EXIST;
@@ -347,7 +346,7 @@ public class CmHandleRegistrationService {
final Collection<String> rejectedCmHandleIds = alternateIdChecker
.getIdsOfCmHandlesWithRejectedAlternateId(cmHandlesToBeCreated, AlternateIdChecker.Operation.CREATE);
cmHandleRegistrationResponses.addAll(CmHandleRegistrationResponse.createFailureResponses(
- rejectedCmHandleIds, ALTERNATE_ID_ALREADY_ASSOCIATED));
+ rejectedCmHandleIds, CM_HANDLE_ALREADY_EXIST));
return rejectedCmHandleIds;
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandler.java
index 86d1d70ab3..3415793478 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandler.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandler.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
* Modifications Copyright (C) 2024 TechMahindra Ltd.
* ================================================================================
@@ -22,8 +22,8 @@
package org.onap.cps.ncmp.impl.inventory;
-import static org.onap.cps.ncmp.api.NcmpResponseStatus.ALTERNATE_ID_ALREADY_ASSOCIATED;
import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_ALREADY_EXIST;
import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID;
import static org.onap.cps.ncmp.impl.inventory.CmHandleRegistrationServicePropertyHandler.PropertyType.DMI_PROPERTY;
import static org.onap.cps.ncmp.impl.inventory.CmHandleRegistrationServicePropertyHandler.PropertyType.PUBLIC_PROPERTY;
@@ -81,7 +81,7 @@ public class CmHandleRegistrationServicePropertyHandler {
final Collection<String> rejectedCmHandleIds = alternateIdChecker
.getIdsOfCmHandlesWithRejectedAlternateId(updatedNcmpServiceCmHandles, AlternateIdChecker.Operation.UPDATE);
final List<CmHandleRegistrationResponse> failureResponses =
- CmHandleRegistrationResponse.createFailureResponses(rejectedCmHandleIds, ALTERNATE_ID_ALREADY_ASSOCIATED);
+ CmHandleRegistrationResponse.createFailureResponses(rejectedCmHandleIds, CM_HANDLE_ALREADY_EXIST);
final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses = new ArrayList<>(failureResponses);
for (final NcmpServiceCmHandle updatedNcmpServiceCmHandle : updatedNcmpServiceCmHandles) {
final String cmHandleId = updatedNcmpServiceCmHandle.getCmHandleId();
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/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 041daa0927..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
@@ -35,6 +35,7 @@ import lombok.extern.slf4j.Slf4j;
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.model.ModuleReference;
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
import org.onap.cps.utils.ContentType;
@@ -55,7 +56,7 @@ public class ModuleSyncService {
@AllArgsConstructor
private static final class ModuleDelta {
Collection<ModuleReference> allModuleReferences;
- Map<String, String> newModuleNameToContentMap;
+ Map<String, String> newYangResourceContentPerName;
}
/**
@@ -65,10 +66,15 @@ 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);
- cpsAnchorService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName, cmHandleId);
+ 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 exists exception for {}. Exception details: {}", cmHandleId,
+ alreadyDefinedException.getDetails());
+ }
}
/**
@@ -79,34 +85,41 @@ 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);
- log.info("Creating Schema Set {} for CM Handle {}", schemaSetName, yangModelCmHandle.getId());
- cpsModuleService.createSchemaSetFromModules(
+ final String cmHandleId = yangModelCmHandle.getId();
+ final ModuleDelta moduleDelta = getModuleDelta(yangModelCmHandle, targetModuleSetTag);
+ try {
+ 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());
+ );
+ log.info("Successfully created Schema Set {} for CM Handle {}", schemaSetName,
+ yangModelCmHandle.getId());
+ } catch (final AlreadyDefinedException alreadyDefinedException) {
+ log.warn("Ignoring (Schema Set) already exists exception for {}. Exception details: {}", cmHandleId,
+ alreadyDefinedException.getDetails());
+ }
}
}
@@ -114,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) {
@@ -133,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 40404b719a..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.getMessage());
+ 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/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/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..bdc7899724 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.
@@ -38,8 +38,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.
@@ -52,10 +52,10 @@ public class CmAvcEventPublisher {
final Map<String, String> extensions = createAvcEventExtensions(eventKey);
final CloudEvent avcCloudEvent =
- NcmpEvent.builder().type(AvcEvent.class.getTypeName())
- .data(avcEvent).extensions(extensions).build().asCloudEvent();
+ NcmpEvent.builder().type(AvcEvent.class.getTypeName())
+ .data(avcEvent).extensions(extensions).build().asCloudEvent();
- eventsPublisher.publishCloudEvent(avcTopic, eventKey, avcCloudEvent);
+ eventsPublisher.publishCloudEvent(ncmpInventoryEventsTopicName, eventKey, avcCloudEvent);
}
private AvcEvent buildAvcEvent(final String attributeName,
@@ -78,4 +78,4 @@ public class CmAvcEventPublisher {
extensions.put("correlationid", eventKey);
return extensions;
}
-}
+} \ No newline at end of file
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CmHandleRegistrationResponseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CmHandleRegistrationResponseSpec.groovy
index 055a6e7448..c49af0f01b 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CmHandleRegistrationResponseSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CmHandleRegistrationResponseSpec.groovy
@@ -1,7 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2022 Bell Canada
- * Modifications Copyright (C) 2023-2024 Nordix Foundation
+ * Modifications 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.
@@ -26,7 +26,6 @@ import spock.lang.Specification
import java.util.stream.Collectors
-import static org.onap.cps.ncmp.api.NcmpResponseStatus.ALTERNATE_ID_ALREADY_ASSOCIATED
import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_ALREADY_EXIST
import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR
@@ -89,14 +88,14 @@ class CmHandleRegistrationResponseSpec extends Specification {
}
def 'Failed cm-handle registration based on cm handle id and registration error'() {
- when: 'the failure response is created with "alternate id already associated" error code for 1 cm handle'
+ when: 'the failure response is created with "cm-handle already exists" error code for 1 cm handle'
def cmHandleRegistrationResponses =
- CmHandleRegistrationResponse.createFailureResponses(['ch 1'], ALTERNATE_ID_ALREADY_ASSOCIATED)
+ CmHandleRegistrationResponse.createFailureResponses(['ch 1'], CM_HANDLE_ALREADY_EXIST)
then: 'the response with expected values'
assert cmHandleRegistrationResponses[0].cmHandle == 'ch 1'
assert cmHandleRegistrationResponses[0].status == Status.FAILURE
- assert cmHandleRegistrationResponses[0].ncmpResponseStatus == ALTERNATE_ID_ALREADY_ASSOCIATED
- assert cmHandleRegistrationResponses[0].errorText == 'alternate id already associated'
+ assert cmHandleRegistrationResponses[0].ncmpResponseStatus == CM_HANDLE_ALREADY_EXIST
+ assert cmHandleRegistrationResponses[0].errorText == 'cm-handle already exists'
}
}
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/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/inventory/CmHandleQueryServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy
index 811e4ea526..1cbdc7beca 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
@@ -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
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/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 7881375762..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'
@@ -90,21 +92,45 @@ class ModuleSyncServiceSpec extends Specification {
'without' | ''
}
- def 'Attempt Sync models for a cm handle with existing schema set (#originalException).'() {
+ def 'Sync models for a cm handle with already defined exception upon schema set creation.'() {
+ given: 'a cm handle to be synced'
+ def yangModelCmHandle = createAdvisedCmHandle('existing tag')
+ and: 'dmi returns no new yang resources'
+ mockDmiModelOperations.getNewYangResourcesFromDmi(*_) >> [:]
+ and: 'already defined exception occurs when creating schema (existing)'
+ mockCpsModuleService.createSchemaSetFromModules(*_) >> { throw AlreadyDefinedException.forSchemaSet('', '', null) }
+ when: 'module sync is triggered'
+ objectUnderTest.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle)
+ then: 'the exception is ignored'
+ noExceptionThrown()
+ }
+
+ def 'Sync models for a cm handle with already defined exception upon anchor set creation.'() {
given: 'a cm handle to be synced'
def yangModelCmHandle = createAdvisedCmHandle('existing tag')
and: 'dmi returns no new yang resources'
mockDmiModelOperations.getNewYangResourcesFromDmi(*_) >> [:]
and: 'already defined exception occurs when creating schema (existing)'
+ mockCpsAnchorService.createAnchor(*_) >> { throw AlreadyDefinedException.forAnchor('', '', null) }
+ when: 'module sync is triggered'
+ objectUnderTest.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle)
+ then: 'the exception is ignored'
+ noExceptionThrown()
+ }
+
+ def 'Attempt Sync models for a cm handle with duplicate yang resources exception).'() {
+ given: 'a cm handle to be synced'
+ def yangModelCmHandle = createAdvisedCmHandle('existing tag')
+ and: 'dmi returns no new yang resources'
+ mockDmiModelOperations.getNewYangResourcesFromDmi(*_) >> [:]
+ and: 'duplicate yang resource exception occurs when creating schema'
+ def originalException = new DuplicatedYangResourceException('', '', null)
mockCpsModuleService.createSchemaSetFromModules(*_) >> { throw originalException }
when: 'module sync is triggered'
objectUnderTest.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle)
then: 'same exception is thrown up'
def thrownException = thrown(Exception)
assert thrownException == originalException
- where: 'following exceptions occur'
- originalException << [AlreadyDefinedException.forSchemaSet('', '', null),
- new DuplicatedYangResourceException('', '', null) ]
}
def 'Model upgrade without using Module Set Tags (legacy) where the modules are in database.'() {
@@ -116,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'
@@ -139,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/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"