aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java39
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java23
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistence.java27
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistenceImpl.java38
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java138
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java5
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfig.java18
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy138
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy43
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncServiceSpec.groovy178
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasksSpec.groovy12
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfigSpec.groovy8
-rwxr-xr-xcps-ri/src/main/java/org/onap/cps/ri/CpsModulePersistenceServiceImpl.java23
-rw-r--r--cps-ri/src/main/java/org/onap/cps/ri/repository/ModuleReferenceQuery.java6
-rw-r--r--cps-ri/src/main/java/org/onap/cps/ri/repository/ModuleReferenceRepositoryImpl.java112
-rw-r--r--cps-ri/src/main/java/org/onap/cps/ri/repository/SchemaSetRepository.java13
-rw-r--r--cps-ri/src/main/java/org/onap/cps/ri/repository/SchemaSetYangResourceRepository.java9
-rw-r--r--cps-ri/src/main/java/org/onap/cps/ri/repository/YangResourceRepository.java10
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java53
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/impl/CpsAnchorServiceImpl.java7
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java34
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/impl/YangTextSchemaSourceSetCache.java9
-rw-r--r--cps-service/src/main/java/org/onap/cps/init/DbCleaner.java48
-rwxr-xr-xcps-service/src/main/java/org/onap/cps/spi/CpsModulePersistenceService.java35
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAnchorServiceImplSpec.groovy13
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy75
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/api/impl/YangTextSchemaSourceSetCacheSpec.groovy19
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/init/DbCleanerSpec.groovy38
-rw-r--r--docker-compose/docker-compose.yml11
-rw-r--r--docs/deployment.rst7
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy20
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/AnchorServiceIntegrationSpec.groovy15
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/DataspaceServiceIntegrationSpec.groovy2
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/ModuleServiceIntegrationSpec.groovy26
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpgradeSpec.groovy24
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/ModuleSyncWatchdogIntegrationSpec.groovy48
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/YangModulesSpec.groovy26
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/ModuleQueryPerfTest.groovy2
39 files changed, 467 insertions, 887 deletions
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 fc215c9c01..e7fd247a08 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
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2021-2024 Nordix Foundation
+ * Copyright (C) 2021-2025 Nordix Foundation
* Modifications Copyright (C) 2021 Pantheon.tech
* Modifications Copyright (C) 2021-2022 Bell Canada
* Modifications Copyright (C) 2023 TechMahindra Ltd.
@@ -138,17 +138,20 @@ public class CmHandleRegistrationService {
protected void processRemovedCmHandles(final DmiPluginRegistration dmiPluginRegistration,
final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) {
- final List<String> tobeRemovedCmHandleIds = dmiPluginRegistration.getRemovedCmHandles();
+ final List<String> toBeRemovedCmHandleIds = dmiPluginRegistration.getRemovedCmHandles();
+ if (toBeRemovedCmHandleIds.isEmpty()) {
+ return;
+ }
final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses =
- new ArrayList<>(tobeRemovedCmHandleIds.size());
+ new ArrayList<>(toBeRemovedCmHandleIds.size());
final Collection<YangModelCmHandle> yangModelCmHandles =
- inventoryPersistence.getYangModelCmHandles(tobeRemovedCmHandleIds);
+ inventoryPersistence.getYangModelCmHandles(toBeRemovedCmHandleIds);
updateCmHandleStateBatch(yangModelCmHandles, CmHandleState.DELETING);
final Set<String> notDeletedCmHandles = new HashSet<>();
- for (final List<String> tobeRemovedCmHandleBatch : Lists.partition(tobeRemovedCmHandleIds, DELETE_BATCH_SIZE)) {
+ for (final List<String> tobeRemovedCmHandleBatch : Lists.partition(toBeRemovedCmHandleIds, DELETE_BATCH_SIZE)) {
try {
- batchDeleteCmHandlesFromDbAndCaches(tobeRemovedCmHandleBatch);
+ deleteCmHandlesFromDbAndCaches(tobeRemovedCmHandleBatch);
tobeRemovedCmHandleBatch.forEach(cmHandleId ->
cmHandleRegistrationResponses.add(CmHandleRegistrationResponse.createSuccessResponse(cmHandleId)));
@@ -201,8 +204,9 @@ public class CmHandleRegistrationService {
protected void processUpdatedCmHandles(final DmiPluginRegistration dmiPluginRegistration,
final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) {
- dmiPluginRegistrationResponse.setUpdatedCmHandles(cmHandleRegistrationServicePropertyHandler
- .updateCmHandleProperties(dmiPluginRegistration.getUpdatedCmHandles()));
+ final List<CmHandleRegistrationResponse> updatedCmHandles = cmHandleRegistrationServicePropertyHandler
+ .updateCmHandleProperties(dmiPluginRegistration.getUpdatedCmHandles());
+ dmiPluginRegistrationResponse.setUpdatedCmHandles(updatedCmHandles);
}
protected void processUpgradedCmHandles(
@@ -275,7 +279,7 @@ public class CmHandleRegistrationService {
private CmHandleRegistrationResponse deleteCmHandleAndGetCmHandleRegistrationResponse(final String cmHandleId) {
try {
- deleteCmHandleFromDbAndCaches(cmHandleId);
+ deleteCmHandlesFromDbAndCaches(Collections.singletonList(cmHandleId));
return CmHandleRegistrationResponse.createSuccessResponse(cmHandleId);
} catch (final DataNodeNotFoundException dataNodeNotFoundException) {
log.error("Unable to find dataNode for cmHandleId : {} , caused by : {}",
@@ -298,16 +302,9 @@ public class CmHandleRegistrationService {
lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle);
}
- private void deleteCmHandleFromDbAndCaches(final String cmHandleId) {
- inventoryPersistence.deleteSchemaSetWithCascade(cmHandleId);
- inventoryPersistence.deleteDataNode(NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']");
- trustLevelManager.removeCmHandles(Collections.singleton(cmHandleId));
- removeDeletedCmHandleFromModuleSyncMap(cmHandleId);
- }
-
- private void batchDeleteCmHandlesFromDbAndCaches(final Collection<String> cmHandleIds) {
- inventoryPersistence.deleteSchemaSetsWithCascade(cmHandleIds);
+ private void deleteCmHandlesFromDbAndCaches(final Collection<String> cmHandleIds) {
inventoryPersistence.deleteDataNodes(mapCmHandleIdsToXpaths(cmHandleIds));
+ inventoryPersistence.deleteAnchors(cmHandleIds);
trustLevelManager.removeCmHandles(cmHandleIds);
cmHandleIds.forEach(this::removeDeletedCmHandleFromModuleSyncMap);
}
@@ -326,8 +323,11 @@ public class CmHandleRegistrationService {
private List<CmHandleRegistrationResponse> upgradeCmHandles(final Map<YangModelCmHandle, CmHandleState>
cmHandleStatePerCmHandle) {
+ if (cmHandleStatePerCmHandle.isEmpty()) {
+ return Collections.emptyList();
+ }
final List<String> cmHandleIds = getCmHandleIds(cmHandleStatePerCmHandle);
- log.info("Moving cm handles : {} into locked (for upgrade) state.", cmHandleIds);
+ log.info("Moving {} cm handles into locked (for upgrade) state: {} ", cmHandleIds.size(), cmHandleIds);
try {
lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle);
return CmHandleRegistrationResponse.createSuccessResponses(cmHandleIds);
@@ -384,5 +384,4 @@ public class CmHandleRegistrationService {
ncmpServiceCmHandle.getDataProducerIdentifier());
}
-
}
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 d566ae43cb..e7ec9cd13c 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
@@ -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.
* ================================================================================
@@ -62,26 +62,27 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv
private static final int CMHANDLE_BATCH_SIZE = 100;
private final CpsModuleService cpsModuleService;
- private final CpsAnchorService cpsAnchorService;
private final CpsValidator cpsValidator;
private final CmHandleQueryService cmHandleQueryService;
/**
* initialize an inventory persistence object.
*
- * @param jsonObjectMapper json mapper object
- * @param cpsDataService cps data service instance
- * @param cpsModuleService cps module service instance
- * @param cpsValidator cps validation service instance
- * @param cpsAnchorService cps anchor service instance
+ * @param cpsValidator cps validation service instance
+ * @param jsonObjectMapper json mapper object
+ * @param cpsAnchorService cps anchor service instance
+ * @param cpsModuleService cps module service instance
+ * @param cpsDataService cps data service instance
+ * @param cmHandleQueryService cm handle query service instance
*/
- public InventoryPersistenceImpl(final JsonObjectMapper jsonObjectMapper, final CpsDataService cpsDataService,
- final CpsModuleService cpsModuleService, final CpsValidator cpsValidator,
+ public InventoryPersistenceImpl(final CpsValidator cpsValidator,
+ final JsonObjectMapper jsonObjectMapper,
final CpsAnchorService cpsAnchorService,
+ final CpsModuleService cpsModuleService,
+ final CpsDataService cpsDataService,
final CmHandleQueryService cmHandleQueryService) {
- super(jsonObjectMapper, cpsDataService, cpsModuleService, cpsValidator);
+ super(jsonObjectMapper, cpsAnchorService, cpsDataService);
this.cpsModuleService = cpsModuleService;
- this.cpsAnchorService = cpsAnchorService;
this.cpsValidator = cpsValidator;
this.cmHandleQueryService = cmHandleQueryService;
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistence.java
index 714a7ca12f..f327edab17 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistence.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistence.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022-2023 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.
@@ -25,9 +25,6 @@ import java.util.Collection;
import org.onap.cps.api.model.DataNode;
import org.onap.cps.api.parameters.FetchDescendantsOption;
-/**
- * DmiRegistryConstants class to be strictly used for DMI Related constants only.
- */
public interface NcmpPersistence {
String NCMP_DATASPACE_NAME = "NCMP-Admin";
@@ -44,20 +41,6 @@ public interface NcmpPersistence {
void deleteListOrListElement(String listElementXpath);
/**
- * Method to delete a schema set.
- *
- * @param schemaSetName schema set name
- */
- void deleteSchemaSetWithCascade(String schemaSetName);
-
- /**
- * Method to delete multiple schema sets.
- *
- * @param schemaSetNames schema set names
- */
- void deleteSchemaSetsWithCascade(Collection<String> schemaSetNames);
-
- /**
* Get data node via xpath.
*
* @param xpath xpath
@@ -113,4 +96,12 @@ public interface NcmpPersistence {
* @param dataNodeXpaths data node xpaths
*/
void deleteDataNodes(Collection<String> dataNodeXpaths);
+
+ /**
+ * Deletes multiple anchors identified by their IDs.
+ *
+ * @param anchorIds ids of the anchors to be deleted
+ */
+ void deleteAnchors(Collection<String> anchorIds);
+
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistenceImpl.java
index 6092d8b3b9..2232d7ce12 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistenceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistenceImpl.java
@@ -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,31 +20,25 @@
package org.onap.cps.ncmp.impl.inventory;
-import static org.onap.cps.api.parameters.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED;
import static org.onap.cps.api.parameters.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS;
import io.micrometer.core.annotation.Timed;
import java.util.Collection;
import lombok.RequiredArgsConstructor;
-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.SchemaSetNotFoundException;
import org.onap.cps.api.model.DataNode;
import org.onap.cps.api.parameters.FetchDescendantsOption;
-import org.onap.cps.impl.utils.CpsValidator;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.stereotype.Component;
-@Slf4j
@RequiredArgsConstructor
@Component
public class NcmpPersistenceImpl implements NcmpPersistence {
protected final JsonObjectMapper jsonObjectMapper;
+ protected final CpsAnchorService cpsAnchorService;
protected final CpsDataService cpsDataService;
- private final CpsModuleService cpsModuleService;
- private final CpsValidator cpsValidator;
@Override
public void deleteListOrListElement(final String listElementXpath) {
@@ -53,27 +47,6 @@ public class NcmpPersistenceImpl implements NcmpPersistence {
}
@Override
- @Timed(value = "cps.ncmp.inventory.persistence.schemaset.delete",
- description = "Time taken to delete a schemaset")
- public void deleteSchemaSetWithCascade(final String schemaSetName) {
- try {
- cpsValidator.validateNameCharacters(schemaSetName);
- cpsModuleService.deleteSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName,
- CASCADE_DELETE_ALLOWED);
- } catch (final SchemaSetNotFoundException schemaSetNotFoundException) {
- log.warn("Schema set {} does not exist or already deleted", schemaSetName);
- }
- }
-
- @Override
- @Timed(value = "cps.ncmp.inventory.persistence.schemaset.delete.batch",
- description = "Time taken to delete multiple schemaset")
- public void deleteSchemaSetsWithCascade(final Collection<String> schemaSetNames) {
- cpsValidator.validateNameCharacters(schemaSetNames);
- cpsModuleService.deleteSchemaSetsWithCascade(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetNames);
- }
-
- @Override
@Timed(value = "cps.ncmp.inventory.persistence.datanode.get",
description = "Time taken to get a data node (from ncmp dmi registry)")
public Collection<DataNode> getDataNode(final String xpath) {
@@ -116,4 +89,9 @@ public class NcmpPersistenceImpl implements NcmpPersistence {
cpsDataService.deleteDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, dataNodeXpaths, NO_TIMESTAMP);
}
+ @Override
+ public void deleteAnchors(final Collection<String> anchorIds) {
+ cpsAnchorService.deleteAnchors(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, anchorIds);
+ }
+
}
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 994ca80287..e9f3d9b475 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
@@ -189,7 +189,7 @@ public class ModuleOperationsUtils {
.getLockReasonCategory()));
}
- public static String getUpgradedModuleSetTagFromLockReason(final CompositeState.LockReason lockReason) {
+ public 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 3f92dc73f0..9534cf35b1 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
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022-2024 Nordix Foundation
+ * Copyright (C) 2022-2025 Nordix Foundation
* Modifications Copyright (C) 2024 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -26,24 +26,18 @@ import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY
import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT;
import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME;
-import com.hazelcast.collection.ISet;
import java.time.OffsetDateTime;
import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.apache.logging.log4j.util.Strings;
import org.onap.cps.api.CpsAnchorService;
import org.onap.cps.api.CpsDataService;
import org.onap.cps.api.CpsModuleService;
-import org.onap.cps.api.exceptions.SchemaSetNotFoundException;
+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.api.parameters.CascadeDeleteAllowed;
-import org.onap.cps.ncmp.api.exceptions.NcmpException;
-import org.onap.cps.ncmp.api.inventory.models.CmHandleState;
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
import org.onap.cps.utils.ContentType;
import org.onap.cps.utils.JsonObjectMapper;
@@ -54,15 +48,11 @@ import org.springframework.stereotype.Service;
@RequiredArgsConstructor
public class ModuleSyncService {
- private static final Map<String, String> NO_NEW_MODULES = Collections.emptyMap();
-
private final DmiModelOperations dmiModelOperations;
private final CpsModuleService cpsModuleService;
private final CpsDataService cpsDataService;
private final CpsAnchorService cpsAnchorService;
private final JsonObjectMapper jsonObjectMapper;
- private final ISet<String> moduleSetTagsBeingProcessed;
- private final Map<String, ModuleDelta> privateModuleSetCache = new HashMap<>();
@AllArgsConstructor
private static final class ModuleDelta {
@@ -71,42 +61,16 @@ public class ModuleSyncService {
}
/**
- * This method creates a cm handle and initiates modules sync.
+ * Creates a CM handle and initiates the synchronization of modules to create a schema set and anchor.
*
* @param yangModelCmHandle the yang model of cm handle.
*/
public void syncAndCreateSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle) {
+ final String cmHandleId = yangModelCmHandle.getId();
final String moduleSetTag = yangModelCmHandle.getModuleSetTag();
- final ModuleDelta moduleDelta;
- boolean isNewModuleSetTag = Strings.isNotBlank(moduleSetTag);
- try {
- if (privateModuleSetCache.containsKey(moduleSetTag)) {
- moduleDelta = privateModuleSetCache.get(moduleSetTag);
- } else {
- if (isNewModuleSetTag) {
- if (moduleSetTagsBeingProcessed.add(moduleSetTag)) {
- log.info("Processing new module set tag {}", moduleSetTag);
- } else {
- isNewModuleSetTag = false;
- throw new NcmpException("Concurrent processing of module set tag " + moduleSetTag,
- moduleSetTag + " already being processed for cm handle " + yangModelCmHandle.getId());
- }
- }
- moduleDelta = getModuleDelta(yangModelCmHandle, moduleSetTag);
- }
- final String cmHandleId = yangModelCmHandle.getId();
- cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId,
- moduleDelta.newModuleNameToContentMap, moduleDelta.allModuleReferences);
- cpsAnchorService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, cmHandleId);
- if (isNewModuleSetTag) {
- final ModuleDelta noModuleDelta = new ModuleDelta(moduleDelta.allModuleReferences, NO_NEW_MODULES);
- privateModuleSetCache.put(moduleSetTag, noModuleDelta);
- }
- } finally {
- if (isNewModuleSetTag) {
- moduleSetTagsBeingProcessed.remove(moduleSetTag);
- }
- }
+ final String schemaSetName = getSchemaSetName(cmHandleId, moduleSetTag);
+ syncAndCreateSchemaSet(yangModelCmHandle, schemaSetName);
+ cpsAnchorService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName, cmHandleId);
}
/**
@@ -115,55 +79,61 @@ public class ModuleSyncService {
* @param yangModelCmHandle the yang model of cm handle.
*/
public void syncAndUpgradeSchemaSet(final YangModelCmHandle yangModelCmHandle) {
- final String upgradedModuleSetTag = ModuleOperationsUtils.getUpgradedModuleSetTagFromLockReason(
+ final String cmHandleId = yangModelCmHandle.getId();
+ final String sourceModuleSetTag = yangModelCmHandle.getModuleSetTag();
+ final String targetModuleSetTag = ModuleOperationsUtils.getTargetModuleSetTagFromLockReason(
yangModelCmHandle.getCompositeState().getLockReason());
- final ModuleDelta moduleDelta = getModuleDelta(yangModelCmHandle, upgradedModuleSetTag);
- cpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
- yangModelCmHandle.getId(), moduleDelta.newModuleNameToContentMap, moduleDelta.allModuleReferences);
- setCmHandleModuleSetTag(yangModelCmHandle, upgradedModuleSetTag);
+ if (sourceModuleSetTag.isEmpty() && targetModuleSetTag.isEmpty()) {
+ final ModuleDelta moduleDelta = getModuleDelta(yangModelCmHandle);
+ cpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
+ cmHandleId, moduleDelta.newModuleNameToContentMap, moduleDelta.allModuleReferences);
+ } else {
+ final String targetSchemaSetName = getSchemaSetName(cmHandleId, targetModuleSetTag);
+ syncAndCreateSchemaSet(yangModelCmHandle, targetSchemaSetName);
+ cpsAnchorService.updateAnchorSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId,
+ targetSchemaSetName);
+ setCmHandleModuleSetTag(yangModelCmHandle, targetModuleSetTag);
+ log.info("Upgrading schema set for CM handle ID: {}, Source Tag: {}, Target Tag: {}",
+ cmHandleId, sourceModuleSetTag, targetModuleSetTag);
+ }
}
- /**
- * Deletes the SchemaSet for schema set id if the SchemaSet Exists.
- *
- * @param schemaSetId the schema set id to be deleted
- */
- public void deleteSchemaSetIfExists(final String schemaSetId) {
- try {
- cpsModuleService.deleteSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetId,
- CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED);
- log.debug("SchemaSet for {} has been deleted. Ready to be recreated.", schemaSetId);
- } catch (final SchemaSetNotFoundException e) {
- log.debug("No SchemaSet for {}. Assuming CmHandle has not been previously Module Synced.", schemaSetId);
+ private void syncAndCreateSchemaSet(final YangModelCmHandle yangModelCmHandle, final String schemaSetName) {
+ if (isNewSchemaSet(schemaSetName)) {
+ final ModuleDelta moduleDelta = getModuleDelta(yangModelCmHandle);
+ try {
+ log.info("Creating Schema Set {} for CM Handle {}", schemaSetName, yangModelCmHandle.getId());
+ cpsModuleService.createSchemaSetFromModules(
+ NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
+ schemaSetName,
+ moduleDelta.newModuleNameToContentMap,
+ moduleDelta.allModuleReferences
+ );
+ log.info("Successfully created Schema Set {} for CM Handle {}",
+ schemaSetName, yangModelCmHandle.getId());
+ } catch (final AlreadyDefinedException | DuplicatedYangResourceException exception) {
+ log.warn("Schema Set {} already exists, no need to (re)create it for {}",
+ schemaSetName, yangModelCmHandle.getId());
+ }
}
}
- public void clearPrivateModuleSetCache() {
- privateModuleSetCache.clear();
+ private boolean isNewSchemaSet(final String schemaSetName) {
+ return !cpsModuleService.schemaSetExists(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName);
}
- private ModuleDelta getModuleDelta(final YangModelCmHandle yangModelCmHandle, final String targetModuleSetTag) {
- final Map<String, String> newYangResources;
- Collection<ModuleReference> allModuleReferences = getModuleReferencesByModuleSetTag(targetModuleSetTag);
- if (allModuleReferences.isEmpty()) {
- allModuleReferences = dmiModelOperations.getModuleReferences(yangModelCmHandle);
- newYangResources = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle,
- cpsModuleService.identifyNewModuleReferences(allModuleReferences));
- } else {
- log.info("Found other cm handle having same module set tag: {}", targetModuleSetTag);
- newYangResources = NO_NEW_MODULES;
- }
+ private ModuleDelta getModuleDelta(final YangModelCmHandle yangModelCmHandle) {
+ final Collection<ModuleReference> allModuleReferences =
+ dmiModelOperations.getModuleReferences(yangModelCmHandle);
+ final Collection<ModuleReference> newModuleReferences =
+ cpsModuleService.identifyNewModuleReferences(allModuleReferences);
+ final Map<String, String> newYangResources = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle,
+ newModuleReferences);
+ log.debug("Module delta calculated for CM handle ID: {}. All references: {}. New modules: {}",
+ yangModelCmHandle.getId(), allModuleReferences, newYangResources.keySet());
return new ModuleDelta(allModuleReferences, newYangResources);
}
- private Collection<ModuleReference> getModuleReferencesByModuleSetTag(final String moduleSetTag) {
- if (Strings.isBlank(moduleSetTag)) {
- return Collections.emptyList();
- }
- return cpsModuleService.getModuleReferencesByAttribute(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
- Map.of("module-set-tag", moduleSetTag), Map.of("cm-handle-state", CmHandleState.READY.name()));
- }
-
private void setCmHandleModuleSetTag(final YangModelCmHandle yangModelCmHandle, final String newModuleSetTag) {
final String jsonForUpdate = jsonObjectMapper.asJsonString(Map.of(
"cm-handles", Map.of("id", yangModelCmHandle.getId(), "module-set-tag", newModuleSetTag)));
@@ -171,4 +141,8 @@ public class ModuleSyncService {
jsonForUpdate, OffsetDateTime.now(), ContentType.JSON);
}
+ private static String getSchemaSetName(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 5f289c2c01..40404b719a 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
@@ -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.
@@ -109,13 +109,12 @@ public class ModuleSyncTasks {
if (inUpgrade) {
moduleSyncService.syncAndUpgradeSchemaSet(yangModelCmHandle);
} else {
- moduleSyncService.deleteSchemaSetIfExists(yangModelCmHandle.getId());
moduleSyncService.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle);
}
compositeState.setLockReason(null);
return CmHandleState.READY;
} catch (final Exception e) {
- log.warn("Processing of {} module failed due to 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;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfig.java
index d6ac242b30..c05944f66e 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfig.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfig.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.
@@ -20,13 +20,10 @@
package org.onap.cps.ncmp.impl.inventory.sync;
-import com.hazelcast.collection.ISet;
import com.hazelcast.config.MapConfig;
import com.hazelcast.config.QueueConfig;
-import com.hazelcast.config.SetConfig;
import com.hazelcast.map.IMap;
import java.util.concurrent.BlockingQueue;
-import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.impl.cache.HazelcastCacheConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -34,7 +31,6 @@ import org.springframework.context.annotation.Configuration;
/**
* Core infrastructure of the hazelcast distributed caches for Module Sync and Data Sync use cases.
*/
-@Slf4j
@Configuration
public class SynchronizationCacheConfig extends HazelcastCacheConfig {
@@ -45,8 +41,6 @@ public class SynchronizationCacheConfig extends HazelcastCacheConfig {
private static final MapConfig moduleSyncStartedConfig =
createMapConfigWithTimeToLiveInSeconds("moduleSyncStartedConfig", MODULE_SYNC_STARTED_TTL_SECS);
private static final MapConfig dataSyncSemaphoresConfig = createMapConfig("dataSyncSemaphoresConfig");
- private static final SetConfig moduleSetTagsBeingProcessedConfig
- = createSetConfig("moduleSetTagsBeingProcessedConfig");
/**
* Module Sync Distributed Queue Instance.
@@ -78,14 +72,4 @@ public class SynchronizationCacheConfig extends HazelcastCacheConfig {
return getOrCreateHazelcastInstance(dataSyncSemaphoresConfig).getMap("dataSyncSemaphores");
}
- /**
- * Collection of (new) module set tags being processed.
- * To prevent processing on multiple threads of same tag
- *
- * @return set of module set tags being processed
- */
- @Bean
- public ISet<String> moduleSetTagsBeingProcessed() {
- return getOrCreateHazelcastInstance(moduleSetTagsBeingProcessedConfig).getSet("moduleSetTagsBeingProcessed");
- }
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy
index ff190cc1ca..953e1c7d0e 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.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");
@@ -23,7 +23,10 @@ package org.onap.cps.ncmp.impl.inventory
import com.hazelcast.map.IMap
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.CpsException
+import org.onap.cps.api.exceptions.DataNodeNotFoundException
+import org.onap.cps.api.exceptions.DataValidationException
import org.onap.cps.ncmp.api.exceptions.DmiRequestException
import org.onap.cps.ncmp.api.inventory.DataStoreSyncState
import org.onap.cps.ncmp.api.inventory.models.CmHandleRegistrationResponse
@@ -36,11 +39,6 @@ import org.onap.cps.ncmp.api.inventory.models.CmHandleState
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import org.onap.cps.ncmp.impl.inventory.sync.lcm.LcmEventsCmHandleStateHandler
import org.onap.cps.ncmp.impl.inventory.trustlevel.TrustLevelManager
-import org.onap.cps.api.exceptions.AlreadyDefinedException
-import org.onap.cps.api.exceptions.CpsException
-import org.onap.cps.api.exceptions.DataNodeNotFoundException
-import org.onap.cps.api.exceptions.DataValidationException
-import org.onap.cps.api.exceptions.SchemaSetNotFoundException
import spock.lang.Specification
import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND
@@ -53,7 +51,6 @@ import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_D
class CmHandleRegistrationServiceSpec extends Specification {
def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'some-cm-handle-id')
- def mockCpsModuleService = Mock(CpsModuleService)
def mockNetworkCmProxyDataServicePropertyHandler = Mock(CmHandleRegistrationServicePropertyHandler)
def mockInventoryPersistence = Mock(InventoryPersistence)
def mockCmHandleQueries = Mock(CmHandleQueryService)
@@ -80,33 +77,43 @@ class CmHandleRegistrationServiceSpec extends Specification {
def dmiRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server')
dmiRegistration.setCreatedCmHandles([new NcmpServiceCmHandle(cmHandleId: 'cmhandle-1', publicProperties: ['publicProp1': 'value'], dmiProperties: [:])])
dmiRegistration.setUpdatedCmHandles([new NcmpServiceCmHandle(cmHandleId: 'cmhandle-2', publicProperties: ['publicProp1': 'value'], dmiProperties: [:])])
- dmiRegistration.setRemovedCmHandles(['cmhandle-2'])
- dmiRegistration.setUpgradedCmHandles(new UpgradedCmHandles(cmHandles: ['cmhandle-3'], moduleSetTag: 'some-module-set-tag'))
- and: 'cm handles are persisted'
+ dmiRegistration.setRemovedCmHandles(['cmhandle-3'])
+ dmiRegistration.setUpgradedCmHandles(new UpgradedCmHandles(cmHandles: ['cmhandle-4', 'cmhandle-5'], moduleSetTag: moduleSetTagForUpgrade))
+ and: 'cm handles 2,3 and 4 already exist in the inventory'
mockInventoryPersistence.getYangModelCmHandles(['cmhandle-2']) >> [new YangModelCmHandle()]
- mockInventoryPersistence.getYangModelCmHandle('cmhandle-3') >> new YangModelCmHandle(id: 'cmhandle-3', moduleSetTag: '', compositeState: new CompositeState(cmHandleState: CmHandleState.READY))
- and: 'cm handle is in READY state'
- mockCmHandleQueries.cmHandleHasState('cmhandle-3', CmHandleState.READY) >> true
- and: 'cm handles is present in in-progress map'
- mockModuleSyncStartedOnCmHandles.containsKey('cmhandle-2') >> true
+ mockInventoryPersistence.getYangModelCmHandles(['cmhandle-3']) >> [new YangModelCmHandle()]
+ mockInventoryPersistence.getYangModelCmHandle('cmhandle-4') >> new YangModelCmHandle(id: 'cmhandle-4', moduleSetTag: '', compositeState: new CompositeState(cmHandleState: CmHandleState.READY))
+ and: 'cm handle 5 also exist but already has the new module set tag (upgrade to)'
+ mockInventoryPersistence.getYangModelCmHandle('cmhandle-5') >> new YangModelCmHandle(id: 'cmhandle-5', moduleSetTag: moduleSetTagForUpgrade , compositeState: new CompositeState(cmHandleState: CmHandleState.READY))
+ and: 'all cm handles are in READY state'
+ mockCmHandleQueries.cmHandleHasState(_, CmHandleState.READY) >> true
+ and: 'cm handle to be removed is in progress map'
+ mockModuleSyncStartedOnCmHandles.containsKey('cmhandle-3') >> true
when: 'registration is processed'
- objectUnderTest.updateDmiRegistration(dmiRegistration)
+ def result = objectUnderTest.updateDmiRegistration(dmiRegistration)
then: 'cm-handles are removed first'
1 * objectUnderTest.processRemovedCmHandles(*_)
and: 'de-registered cm handle entry is removed from in progress map'
- 1 * mockModuleSyncStartedOnCmHandles.removeAsync('cmhandle-2')
- then: 'cm-handles are updated'
+ 1 * mockModuleSyncStartedOnCmHandles.removeAsync('cmhandle-3')
+ then: 'updated cm handles are processed by the property handler service'
1 * objectUnderTest.processUpdatedCmHandles(*_)
- 1 * mockNetworkCmProxyDataServicePropertyHandler.updateCmHandleProperties(*_) >> []
+ 1 * mockNetworkCmProxyDataServicePropertyHandler.updateCmHandleProperties(*_) >> [CmHandleRegistrationResponse.createSuccessResponse('cmhandle-2')]
then: 'cm-handles are upgraded'
1 * objectUnderTest.processUpgradedCmHandles(*_)
+ and: 'result contains the correct cm handles for each operation'
+ assert result.createdCmHandles.cmHandle == ['cmhandle-1']
+ assert result.updatedCmHandles.cmHandle == ['cmhandle-2']
+ assert result.removedCmHandles.cmHandle == ['cmhandle-3']
+ assert result.upgradedCmHandles.cmHandle as Set == ['cmhandle-4', 'cmhandle-5'] as Set
+ where: 'upgrade with and without module set tag'
+ moduleSetTagForUpgrade << ['some tag', '']
}
def 'DMI Registration upgrade operation with upgrade node state #scenario'() {
given: 'a registration with upgrade operation'
def dmiRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server')
dmiRegistration.setUpgradedCmHandles(new UpgradedCmHandles(cmHandles: ['cmhandle-3'], moduleSetTag: 'some-module-set-tag'))
- and: 'exception while checking cm handle state'
+ and: 'cm handle has the state #cmHandleState'
mockInventoryPersistence.getYangModelCmHandle('cmhandle-3') >> new YangModelCmHandle(id: 'cmhandle-3', moduleSetTag: '', compositeState: new CompositeState(cmHandleState: cmHandleState))
when: 'registration is processed'
def result = objectUnderTest.updateDmiRegistration(dmiRegistration)
@@ -134,6 +141,21 @@ class CmHandleRegistrationServiceSpec extends Specification {
'cm handle is invalid' | new DataValidationException('some error message', 'some error details') || '110'
}
+ def 'DMI Registration upgrade with exception while updating CM-handle state'() {
+ given: 'a registration with upgrade operation'
+ def dmiRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server')
+ dmiRegistration.setUpgradedCmHandles(new UpgradedCmHandles(cmHandles: ['cmhandle-3'], moduleSetTag: 'some-module-set-tag'))
+ and: 'cm handle has the state READY'
+ mockInventoryPersistence.getYangModelCmHandle('cmhandle-3') >> new YangModelCmHandle(id: 'cmhandle-3', moduleSetTag: '', compositeState: new CompositeState(cmHandleState: CmHandleState.READY))
+ and: 'exception will occur while updating cm handle state to LOCKED for upgrade'
+ mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_) >> { throw new RuntimeException() }
+ when: 'registration is processed'
+ def result = objectUnderTest.updateDmiRegistration(dmiRegistration)
+ then: 'upgrade operation contains expected error code'
+ assert result.upgradedCmHandles[0].status == Status.FAILURE
+ assert result.upgradedCmHandles[0].ncmpResponseStatus == UNKNOWN_ERROR
+ }
+
def 'Create CM-handle Validation: Registration with valid Service names: #scenario'() {
given: 'a registration '
def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: dmiPlugin, dmiModelPlugin: dmiModelPlugin,
@@ -276,18 +298,15 @@ class CmHandleRegistrationServiceSpec extends Specification {
assert response.updatedCmHandles.containsAll(updateOperationResponse)
}
- def 'Remove CmHandle Successfully: #scenario'() {
- given: 'a registration'
+ def 'Remove CmHandle Successfully'() {
+ given: 'a registration update to delete a cm handle'
def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server', removedCmHandles: ['cmhandle'])
- and: '#scenario'
- mockCpsModuleService.deleteSchemaSetsWithCascade(_, ['cmhandle']) >> { if (!schemaSetExist) { throw new SchemaSetNotFoundException('', '') } }
- when: 'registration is updated to delete cmhandle'
+ when: 'the registration is updated'
def response = objectUnderTest.updateDmiRegistration(dmiPluginRegistration)
- then: 'the cmHandle state is updated to "DELETING"'
- 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_) >>
- { args -> args[0].values()[0] == CmHandleState.DELETING }
- then: 'method to delete relevant schema set is called once'
- 1 * mockInventoryPersistence.deleteSchemaSetsWithCascade(_)
+ then: 'the cmHandle state is set to "DELETING"'
+ 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_) >> { args -> args[0].values()[0] == CmHandleState.DELETING }
+ then: 'method to delete anchors is called once'
+ 1 * mockInventoryPersistence.deleteAnchors(_)
and: 'method to delete relevant list/list element is called once'
1 * mockInventoryPersistence.deleteDataNodes(_)
and: 'successful response is received'
@@ -297,14 +316,7 @@ class CmHandleRegistrationServiceSpec extends Specification {
assert it.cmHandle == 'cmhandle'
}
and: 'the cmHandle state is updated to "DELETED"'
- 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_) >>
- { args -> args[0].values()[0] == CmHandleState.DELETED }
- and: 'No cm handles state updates for "upgraded cm handles"'
- 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch([:])
- where:
- scenario | schemaSetExist
- 'schema-set exists and can be deleted successfully' | true
- 'schema-set does not exist' | false
+ 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_) >> { args -> args[0].values()[0] == CmHandleState.DELETED }
}
def 'Remove CmHandle: Partial Success'() {
@@ -314,10 +326,11 @@ class CmHandleRegistrationServiceSpec extends Specification {
and: 'cm handles to be deleted in the progress map'
mockModuleSyncStartedOnCmHandles.containsKey("cmhandle1") >> true
mockModuleSyncStartedOnCmHandles.containsKey("cmhandle3") >> true
- and: 'cm-handle deletion fails on batch'
- mockInventoryPersistence.deleteDataNodes(_) >> { throw new RuntimeException("Failed") }
- and: 'cm-handle deletion is successful for 1st and 3rd; failed for 2nd'
- mockInventoryPersistence.deleteDataNode("/dmi-registry/cm-handles[@id='cmhandle2']") >> { throw new RuntimeException("Failed") }
+ and: 'delete fails for batch. Retry only fails for and cm handle 2'
+ mockInventoryPersistence.deleteDataNodes(_) >> { throw new RuntimeException("Batch Failed") }
+ >> { /* cm handle 1 is OK */ }
+ >> { throw new RuntimeException("Cm handle 2 Failed")}
+ >> { /* cm handle 3 is OK */ }
when: 'registration is updated to delete cmhandles'
def response = objectUnderTest.updateDmiRegistration(dmiPluginRegistration)
then: 'the cmHandle states are all updated to "DELETING"'
@@ -343,7 +356,7 @@ class CmHandleRegistrationServiceSpec extends Specification {
with(response.removedCmHandles[1]) {
assert it.status == Status.FAILURE
assert it.ncmpResponseStatus == UNKNOWN_ERROR
- assert it.errorText == 'Failed'
+ assert it.errorText == 'Cm handle 2 Failed'
assert it.cmHandle == 'cmhandle2'
}
and: 'the cmHandle state is updated to DELETED for 1st and 3rd'
@@ -351,40 +364,11 @@ class CmHandleRegistrationServiceSpec extends Specification {
assert it.size() == 2
assert it.every { entry -> entry.value == CmHandleState.DELETED }
})
- and: 'No cm handles state updates for "upgraded cm handles"'
- 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch([:])
- }
-
- def 'Remove CmHandle Error Handling: Schema Set Deletion failed'() {
- given: 'a registration'
- def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server',
- removedCmHandles: ['cmhandle'])
- and: 'schema set batch deletion failed with unknown error'
- mockInventoryPersistence.deleteSchemaSetsWithCascade(_) >> { throw new RuntimeException('Failed') }
- and: 'schema set single deletion failed with unknown error'
- mockInventoryPersistence.deleteSchemaSetWithCascade(_) >> { throw new RuntimeException('Failed') }
- when: 'registration is updated to delete cmhandle'
- def response = objectUnderTest.updateDmiRegistration(dmiPluginRegistration)
- then: 'no exception is thrown'
- noExceptionThrown()
- and: 'cm-handle is not deleted'
- 0 * mockInventoryPersistence.deleteDataNodes(_)
- and: 'the cmHandle state is not updated to "DELETED"'
- 0 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch([yangModelCmHandle: CmHandleState.DELETED])
- and: 'a failure response is received'
- assert response.removedCmHandles.size() == 1
- with(response.removedCmHandles[0]) {
- assert it.status == Status.FAILURE
- assert it.cmHandle == 'cmhandle'
- assert it.errorText == 'Failed'
- assert it.ncmpResponseStatus == UNKNOWN_ERROR
- }
}
def 'Remove CmHandle Error Handling: #scenario'() {
given: 'a registration'
- def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server',
- removedCmHandles: ['cmhandle'])
+ def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server', removedCmHandles: ['cmhandle'])
and: 'cm-handle deletion fails on batch'
mockInventoryPersistence.deleteDataNodes(_) >> { throw deleteListElementException }
and: 'cm-handle deletion fails on individual delete'
@@ -408,7 +392,7 @@ class CmHandleRegistrationServiceSpec extends Specification {
'an unexpected exception' | new RuntimeException('Failed') || UNKNOWN_ERROR | 'Failed'
}
- def 'Set Cm Handle Data Sync Enabled Flag where data sync flag is #scenario'() {
+ def 'Set Cm Handle Data Sync Enabled Flag where data sync flag is #scenario'() {
given: 'an existing cm handle composite state'
def compositeState = new CompositeState(cmHandleState: CmHandleState.READY, dataSyncEnabled: initialDataSyncEnabledFlag,
dataStores: CompositeState.DataStores.builder()
@@ -429,7 +413,7 @@ class CmHandleRegistrationServiceSpec extends Specification {
saveCmHandleStateExpectedNumberOfInvocations * mockInventoryPersistence.saveCmHandleState('some-cm-handle-id', compositeState)
where: 'the following data sync enabled flag is used'
scenario | dataSyncEnabledFlag | initialDataSyncEnabledFlag | initialDataSyncState || expectedDataStoreSyncState | deleteDataNodeExpectedNumberOfInvocation | saveCmHandleStateExpectedNumberOfInvocations
- 'enabled' | true | false | DataStoreSyncState.NONE_REQUESTED || DataStoreSyncState.UNSYNCHRONIZED | 0 | 1
+ 'enabled' | true | false | DataStoreSyncState.NONE_REQUESTED || DataStoreSyncState.UNSYNCHRONIZED | 0 | 1
'disabled' | false | true | DataStoreSyncState.UNSYNCHRONIZED || DataStoreSyncState.NONE_REQUESTED | 0 | 1
'disabled where sync-state is currently SYNCHRONIZED' | false | true | DataStoreSyncState.SYNCHRONIZED || DataStoreSyncState.NONE_REQUESTED | 1 | 1
'is set to existing flag state' | true | true | DataStoreSyncState.UNSYNCHRONIZED || DataStoreSyncState.UNSYNCHRONIZED | 0 | 0
@@ -448,6 +432,4 @@ class CmHandleRegistrationServiceSpec extends Specification {
0 * mockInventoryPersistence.saveCmHandleState(_, _)
}
-
-
}
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 619da70bf2..d8d92e99f5 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
@@ -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.
* ================================================================================
@@ -23,38 +23,36 @@
package org.onap.cps.ncmp.impl.inventory
import com.fasterxml.jackson.databind.ObjectMapper
+import java.time.OffsetDateTime
+import java.time.ZoneOffset
+import java.time.format.DateTimeFormatter
import org.onap.cps.api.CpsAnchorService
import org.onap.cps.api.CpsDataService
import org.onap.cps.api.CpsModuleService
import org.onap.cps.api.exceptions.DataNodeNotFoundException
import org.onap.cps.api.exceptions.DataValidationException
+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.CmHandleState
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import org.onap.cps.ncmp.impl.utils.YangDataConverter
-import org.onap.cps.api.parameters.CascadeDeleteAllowed
-import org.onap.cps.api.parameters.FetchDescendantsOption
-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.utils.ContentType
import org.onap.cps.utils.JsonObjectMapper
import spock.lang.Shared
import spock.lang.Specification
-import java.time.OffsetDateTime
-import java.time.ZoneOffset
-import java.time.format.DateTimeFormatter
-
+import static org.onap.cps.api.parameters.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
+import static org.onap.cps.api.parameters.FetchDescendantsOption.OMIT_DESCENDANTS
import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DATASPACE_NAME
import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR
import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT
import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NO_TIMESTAMP
-import static org.onap.cps.api.parameters.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
-import static org.onap.cps.api.parameters.FetchDescendantsOption.OMIT_DESCENDANTS
class InventoryPersistenceImplSpec extends Specification {
@@ -72,8 +70,7 @@ class InventoryPersistenceImplSpec extends Specification {
def mockYangDataConverter = Mock(YangDataConverter)
- def objectUnderTest = new InventoryPersistenceImpl(spiedJsonObjectMapper, mockCpsDataService, mockCpsModuleService,
- mockCpsValidator, mockCpsAnchorService, mockCmHandleQueries)
+ def objectUnderTest = new InventoryPersistenceImpl(mockCpsValidator, spiedJsonObjectMapper, mockCpsAnchorService, mockCpsModuleService, mockCpsDataService, mockCmHandleQueries)
def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
.format(OffsetDateTime.of(2022, 12, 31, 20, 30, 40, 1, ZoneOffset.UTC))
@@ -294,24 +291,6 @@ class InventoryPersistenceImplSpec extends Specification {
1 * mockCpsDataService.deleteListOrListElement(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,'sample xPath',null)
}
- def 'Delete schema set with a valid schema set name'() {
- when: 'the method to delete schema set is called with valid schema set name'
- objectUnderTest.deleteSchemaSetWithCascade('validSchemaSetName')
- then: 'the module service to delete schemaSet is invoked once'
- 1 * mockCpsModuleService.deleteSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'validSchemaSetName', CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED)
- and: 'the schema set name is validated'
- 1 * mockCpsValidator.validateNameCharacters('validSchemaSetName')
- }
-
- def 'Delete multiple schema sets with valid schema set names'() {
- when: 'the method to delete schema sets is called with valid schema set names'
- objectUnderTest.deleteSchemaSetsWithCascade(['validSchemaSetName1', 'validSchemaSetName2'])
- then: 'the module service to delete schema sets is invoked once'
- 1 * mockCpsModuleService.deleteSchemaSetsWithCascade(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, ['validSchemaSetName1', 'validSchemaSetName2'])
- and: 'the schema set names are validated'
- 1 * mockCpsValidator.validateNameCharacters(['validSchemaSetName1', 'validSchemaSetName2'])
- }
-
def 'Get data node via xPath'() {
when: 'the method to get data nodes is called'
objectUnderTest.getDataNode('sample xPath')
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 67cc4edd83..f8adfe5578 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
@@ -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.
@@ -20,20 +20,17 @@
package org.onap.cps.ncmp.impl.inventory.sync
-import com.hazelcast.collection.ISet
import org.onap.cps.api.CpsAnchorService
import org.onap.cps.api.CpsDataService
import org.onap.cps.api.CpsModuleService
-import org.onap.cps.ncmp.api.exceptions.NcmpException
+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.api.inventory.models.CompositeStateBuilder
import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle
import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService
import org.onap.cps.ncmp.api.inventory.models.CmHandleState
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
-import org.onap.cps.ncmp.impl.inventory.sync.ModuleSyncService.ModuleDelta
-import org.onap.cps.api.parameters.CascadeDeleteAllowed
-import org.onap.cps.api.exceptions.SchemaSetNotFoundException
-import org.onap.cps.api.model.ModuleReference
import org.onap.cps.utils.JsonObjectMapper
import spock.lang.Specification
@@ -48,18 +45,8 @@ class ModuleSyncServiceSpec extends Specification {
def mockCmHandleQueries = Mock(CmHandleQueryService)
def mockCpsDataService = Mock(CpsDataService)
def mockJsonObjectMapper = Mock(JsonObjectMapper)
- def mockModuleSetTagsBeingProcessed = Mock(ISet<String>);
- def objectUnderTest = new ModuleSyncService(mockDmiModelOperations, mockCpsModuleService, mockCpsDataService, mockCpsAnchorService, mockJsonObjectMapper, mockModuleSetTagsBeingProcessed)
-
- def expectedDataspaceName = NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
-
- def setup() {
- // Allow tags for al test except 'duplicate-processing-tag' to be added to processing semaphore
- mockModuleSetTagsBeingProcessed.add('new-tag') >> true
- mockModuleSetTagsBeingProcessed.add('same-tag') >> true
- mockModuleSetTagsBeingProcessed.add('cached-tag') >> true
- }
+ def objectUnderTest = new ModuleSyncService(mockDmiModelOperations, mockCpsModuleService, mockCpsDataService, mockCpsAnchorService, mockJsonObjectMapper)
def 'Sync models for a NEW cm handle using module set tags: #scenario.'() {
given: 'a cm handle to be synced'
@@ -71,26 +58,24 @@ class ModuleSyncServiceSpec extends Specification {
mockDmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, identifiedNewModuleReferences) >> newModuleNameContentToMap
and: 'the module service identifies #identifiedNewModuleReferences.size() new modules'
mockCpsModuleService.identifyNewModuleReferences(moduleReferences) >> identifiedNewModuleReferences
- and: 'the service returns a list of module references when queried with the specified attributes'
- mockCpsModuleService.getModuleReferencesByAttribute(*_) >> existingModuleReferences
when: 'module sync is triggered'
objectUnderTest.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle)
then: 'create schema set from module is invoked with correct parameters'
- 1 * mockCpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'ch-1', newModuleNameContentToMap, moduleReferences)
+ 1 * mockCpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, expectedSchemaSetName, newModuleNameContentToMap, moduleReferences)
and: 'anchor is created with the correct parameters'
- 1 * mockCpsAnchorService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'ch-1', 'ch-1')
+ 1 * mockCpsAnchorService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, expectedSchemaSetName, 'ch-1')
where: 'the following parameters are used'
- scenario | identifiedNewModuleReferences | newModuleNameContentToMap | moduleSetTag | existingModuleReferences
- 'one new module, new tag' | [new ModuleReference('module1', '1')] | [module1: 'some yang source'] | '' | []
- 'no new module, new tag' | [] | [:] | 'new-tag' | []
- 'same tag' | [] | [:] | 'same-tag' | [new ModuleReference('module1', '1'), new ModuleReference('module2', '2')]
+ scenario | identifiedNewModuleReferences | newModuleNameContentToMap | moduleSetTag | existingModuleReferences || expectedSchemaSetName
+ 'one new module, new tag' | [new ModuleReference('module1', '1')] | [module1: 'some yang source'] | '' | [] || 'ch-1'
+ 'no new module, new tag' | [] | [:] | 'new-tag' | [] || 'new-tag'
+ 'same tag' | [] | [:] | 'same-tag' | [new ModuleReference('module1', '1'), new ModuleReference('module2', '2')] || 'same-tag'
}
- def 'Attempt Sync models for a cm handle with exception and #scenario module set tag'() {
+ def 'Attempt Sync models for a cm handle with exception and #scenario module set tag.'() {
given: 'a cm handle to be synced'
def yangModelCmHandle = createAdvisedCmHandle(moduleSetTag)
- and: 'the service returns a list of module references when queried with the specified attributes'
- mockCpsModuleService.getModuleReferencesByAttribute(*_) >> [new ModuleReference('module1', '1')]
+ and: 'dmi returns no new yang resources'
+ mockDmiModelOperations.getNewYangResourcesFromDmi(*_) >> [:]
and: 'exception occurs when trying to store result'
def testException = new RuntimeException('test')
mockCpsModuleService.createSchemaSetFromModules(*_) >> { throw testException }
@@ -99,130 +84,75 @@ class ModuleSyncServiceSpec extends Specification {
then: 'the same exception is thrown up'
def exceptionThrown = thrown(Exception)
assert testException == exceptionThrown
- and: 'module set tag is removed from processing semaphores only when needed'
- expectedCallsToRemoveTag * mockModuleSetTagsBeingProcessed.remove('new-tag')
where: 'following module set tags are used'
- scenario | moduleSetTag || expectedCallsToRemoveTag
- 'with' | 'new-tag' || 1
- 'without' | ' ' || 0
- }
-
- def 'Sync models for a cm handle with previously cached module set tag.'() {
- given: 'a cm handle to be synced'
- def yangModelCmHandle = createAdvisedCmHandle('cached-tag')
- and: 'The module set tag exists in the private cache'
- def moduleReferences = [ new ModuleReference('module1','1') ]
- def cachedModuleDelta = new ModuleDelta(moduleReferences, [:])
- objectUnderTest.privateModuleSetCache.put('cached-tag', cachedModuleDelta)
- when: 'module sync is triggered'
- objectUnderTest.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle)
- then: 'create schema set from module is invoked with correct parameters'
- 1 * mockCpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'ch-1', [:], moduleReferences)
- and: 'anchor is created with the correct parameters'
- 1 * mockCpsAnchorService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'ch-1', 'ch-1')
+ scenario | moduleSetTag
+ 'with' | 'new-tag'
+ 'without' | ''
}
- def 'Attempt to sync using a module set tag already being processed by a different instance or thread.'() {
+ def 'Attempt Sync models for a cm handle with existing schema set (#exception).'() {
given: 'a cm handle to be synced'
- def yangModelCmHandle = createAdvisedCmHandle('duplicateTag')
- and: 'The module set tag already exists in the processing semaphore set'
- mockModuleSetTagsBeingProcessed.add('duplicate-processing-tag') > false
+ 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 exception }
when: 'module sync is triggered'
objectUnderTest.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle)
- then: 'a ncmp exception is thrown with the relevant details'
- def exceptionThrown = thrown(NcmpException)
- assert exceptionThrown.message.contains('duplicateTag')
- assert exceptionThrown.details.contains('duplicateTag')
- assert exceptionThrown.details.contains('ch-1')
+ then: 'no exception is thrown up'
+ noExceptionThrown()
+ where: 'following exceptions occur'
+ exception << [ AlreadyDefinedException.forSchemaSet('', '', null),
+ new DuplicatedYangResourceException('', '', null) ]
}
- def 'Upgrade model for an existing cm handle with Module Set Tag where the modules are #scenario'() {
- given: 'a cm handle being upgraded to module set tag: tag-1'
+ def 'Model upgrade without using Module Set Tags (legacy) where the modules are in database.'() {
+ given: 'a cm handle being upgraded without using module set tags'
def ncmpServiceCmHandle = new NcmpServiceCmHandle()
- ncmpServiceCmHandle.setCompositeState(new CompositeStateBuilder().withLockReason(MODULE_UPGRADE, 'Upgrade to ModuleSetTag: tag-1').build())
+ ncmpServiceCmHandle.setCompositeState(new CompositeStateBuilder().withLockReason(MODULE_UPGRADE, '').build())
def dmiServiceName = 'some service name'
ncmpServiceCmHandle.cmHandleId = 'upgraded-ch'
- def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, '', '', ncmpServiceCmHandle,'tag-1', '', '')
- and: 'some module references'
- def moduleReferences = [ new ModuleReference('module1','1') ]
+ 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(_, []) >> [:]
- and: 'none of these module references are new (unknown to the system)'
+ and: 'none of these module references are new (all already known to the system)'
mockCpsModuleService.identifyNewModuleReferences(_) >> []
- and: 'CPS-Core returns list of existing module resources for TBD'
- mockCpsModuleService.getYangResourcesModuleReferences(*_) >> [ new ModuleReference('module1','1') ]
- and: 'the service returns a list of module references when queried with the specified attributes'
- mockCpsModuleService.getModuleReferencesByAttribute(*_) >> existingModuleReferences
- and: 'the other cm handle is a state ready'
- mockCmHandleQueries.cmHandleHasState('otherId', CmHandleState.READY) >> true
when: 'module sync is triggered'
objectUnderTest.syncAndUpgradeSchemaSet(yangModelCmHandle)
then: 'update schema set from module is invoked for the upgraded cm handle'
1 * mockCpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'upgraded-ch', [:], moduleReferences)
- and: 'create schema set from module is not invoked for the upgraded cm handle'
- 0 * mockCpsModuleService.createSchemaSetFromModules(*_)
and: 'No anchor is created for the upgraded cm handle'
0 * mockCpsAnchorService.createAnchor(*_)
- where: 'the following parameters are used'
- scenario | existingModuleReferences
- 'new' | []
- 'in database' | [new ModuleReference('module1', '1')]
}
- def 'upgrade model for an existing cm handle'() {
+ def 'Model upgrade using to existing Module Set Tag'() {
given: 'a cm handle that is ready but locked for upgrade'
def ncmpServiceCmHandle = new NcmpServiceCmHandle()
- ncmpServiceCmHandle.setCompositeState(new CompositeStateBuilder()
- .withLockReason(MODULE_UPGRADE, 'Upgrade to ModuleSetTag: targetModuleSetTag').build())
+ ncmpServiceCmHandle.setCompositeState(new CompositeStateBuilder().withLockReason(MODULE_UPGRADE, 'Upgrade to ModuleSetTag: ' + tagTo).build())
ncmpServiceCmHandle.setCmHandleId('cmHandleId-1')
- def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle('some service name', '', '', ncmpServiceCmHandle, 'targetModuleSetTag', '', '')
+ def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle('some service name', '', '', ncmpServiceCmHandle, tagFrom, '', '')
mockCmHandleQueries.cmHandleHasState('cmHandleId-1', CmHandleState.READY) >> true
- and: 'the module service returns some module references'
- def moduleReferences = [new ModuleReference('module1', '1'), new ModuleReference('module2', '2')]
- mockCpsModuleService.getYangResourcesModuleReferences(*_)>> moduleReferences
- and: 'the service returns a list of module references when queried with the specified attributes'
- mockCpsModuleService.getModuleReferencesByAttribute(*_) >> moduleReferences
+ and: 'the module tag (schemaset) exists is #schemaExists'
+ 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
+ and: 'dmi returns no new yang resources'
+ mockDmiModelOperations.getNewYangResourcesFromDmi(*_) >> [:]
+ and: 'none of these module references are new (all already known to the system)'
+ expectedCallsToModuleService * mockCpsModuleService.identifyNewModuleReferences(_) >> []
when: 'module upgrade is triggered'
objectUnderTest.syncAndUpgradeSchemaSet(yangModelCmHandle)
- then: 'the upgrade is delegated to the module service (with the correct parameters)'
- 1 * mockCpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'cmHandleId-1', Collections.emptyMap(), moduleReferences)
- }
-
- def 'Delete Schema Set for CmHandle'() {
- when: 'delete schema set if exists is called'
- objectUnderTest.deleteSchemaSetIfExists('some-cmhandle-id')
- then: 'the module service is invoked to delete the correct schema set'
- 1 * mockCpsModuleService.deleteSchemaSet(expectedDataspaceName, 'some-cmhandle-id', CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED)
- }
-
- def 'Delete a non-existing Schema Set for CmHandle' () {
- given: 'the DB throws an exception because its Schema Set does not exist'
- mockCpsModuleService.deleteSchemaSet(*_) >> { throw new SchemaSetNotFoundException('some-dataspace-name', 'some-cmhandle-id') }
- when: 'delete schema set if exists is called'
- objectUnderTest.deleteSchemaSetIfExists('some-cmhandle-id')
- then: 'the exception from the DB is ignored; there are no exceptions'
- noExceptionThrown()
- }
-
- def 'Delete Schema Set for CmHandle with other exception' () {
- given: 'an exception other than SchemaSetNotFoundException is thrown'
- UnsupportedOperationException unsupportedOperationException = new UnsupportedOperationException();
- 1 * mockCpsModuleService.deleteSchemaSet(*_) >> { throw unsupportedOperationException }
- when: 'delete schema set if exists is called'
- objectUnderTest.deleteSchemaSetIfExists('some-cmhandle-id')
- then: 'an exception is thrown'
- def result = thrown(UnsupportedOperationException)
- result == unsupportedOperationException
- }
-
- def 'Clear module set cache.'() {
- given: 'something in the module set cache'
- objectUnderTest.privateModuleSetCache.put('test',new ModuleDelta([],[:]))
- when: 'the cache is cleared'
- objectUnderTest.clearPrivateModuleSetCache()
- then: 'the cache is empty'
- objectUnderTest.privateModuleSetCache.isEmpty()
+ then: 'the upgrade is delegated to the anchor service (with the correct parameters) except when new tag is blank'
+ expectedCallsToAnchorService * mockCpsAnchorService.updateAnchorSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'cmHandleId-1', tagTo)
+ where: 'with or without from tag'
+ scenario | schemaExists | tagFrom | tagTo || expectedCallsToDmi | expectedCallsToModuleService | expectedCallsToAnchorService
+ 'from no tag to existing tag' | true | '' | 'tagTo'|| 0 | 0 | 1
+ 'from tag to other existing tag' | true | 'oldTag' | 'tagTo'|| 0 | 0 | 1
+ 'to new tag' | false | 'oldTag' | 'tagTo'|| 1 | 1 | 1
+ 'to NO tag' | true | 'oldTag' | '' || 1 | 1 | 0
}
def createAdvisedCmHandle(moduleSetTag) {
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 556ed0b63c..92f4b38f31 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
@@ -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");
@@ -29,15 +29,16 @@ import com.hazelcast.config.Config
import com.hazelcast.core.Hazelcast
import com.hazelcast.instance.impl.HazelcastInstanceFactory
import com.hazelcast.map.IMap
+import org.onap.cps.api.exceptions.DataNodeNotFoundException
+import org.onap.cps.ncmp.api.inventory.models.CmHandleState
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.InventoryPersistence
-import org.onap.cps.ncmp.api.inventory.models.CmHandleState
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import org.onap.cps.ncmp.impl.inventory.sync.lcm.LcmEventsCmHandleStateHandler
-import org.onap.cps.api.exceptions.DataNodeNotFoundException
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
@@ -87,10 +88,7 @@ class ModuleSyncTasksSpec extends Specification {
mockInventoryPersistence.getYangModelCmHandle('cm-handle-2') >> cmHandle2
when: 'module sync poll is executed'
objectUnderTest.performModuleSync(['cm-handle-1', 'cm-handle-2'], batchCount)
- then: 'module sync service deletes schemas set of each cm handle if it already exists'
- 1 * mockModuleSyncService.deleteSchemaSetIfExists('cm-handle-1')
- 1 * mockModuleSyncService.deleteSchemaSetIfExists('cm-handle-2')
- and: 'module sync service is invoked for each cm handle'
+ 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' }
and: 'the state handler is called for the both cm handles'
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfigSpec.groovy
index 3213e5d442..7db9e5a870 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfigSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfigSpec.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.
@@ -20,7 +20,6 @@
package org.onap.cps.ncmp.impl.inventory.sync
-import com.hazelcast.collection.ISet
import com.hazelcast.config.Config
import com.hazelcast.core.Hazelcast
import com.hazelcast.map.IMap
@@ -45,9 +44,6 @@ class SynchronizationCacheConfigSpec extends Specification {
@Autowired
IMap<String, Boolean> dataSyncSemaphores
- @Autowired
- ISet<String> moduleSetTagsBeingProcessed
-
def cleanupSpec() {
Hazelcast.getHazelcastInstanceByName('cps-and-ncmp-hazelcast-instance-test-config').shutdown()
}
@@ -59,8 +55,6 @@ class SynchronizationCacheConfigSpec extends Specification {
assert null != moduleSyncStartedOnCmHandles
and: 'system is able to create an instance of a map to hold data sync semaphores'
assert null != dataSyncSemaphores
- and: 'system is able to create an instance of a set to hold module set tags being processed'
- assert null != moduleSetTagsBeingProcessed
and: 'there is only one instance with the correct name'
assert Hazelcast.allHazelcastInstances.size() == 1
assert Hazelcast.allHazelcastInstances.name[0] == 'cps-and-ncmp-hazelcast-instance-test-config'
diff --git a/cps-ri/src/main/java/org/onap/cps/ri/CpsModulePersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/ri/CpsModulePersistenceServiceImpl.java
index 023e76ef89..cf9fb021a6 100755
--- a/cps-ri/src/main/java/org/onap/cps/ri/CpsModulePersistenceServiceImpl.java
+++ b/cps-ri/src/main/java/org/onap/cps/ri/CpsModulePersistenceServiceImpl.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2020-2024 Nordix Foundation
+ * Copyright (C) 2020-2025 Nordix Foundation
* Modifications Copyright (C) 2020-2022 Bell Canada.
* Modifications Copyright (C) 2021 Pantheon.tech
* Modifications Copyright (C) 2022 TechMahindra Ltd.
@@ -174,6 +174,12 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
}
@Override
+ public boolean schemaSetExists(final String dataspaceName, final String schemaSetName) {
+ final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
+ return schemaSetRepository.existsByDataspaceAndName(dataspaceEntity, schemaSetName);
+ }
+
+ @Override
public Collection<SchemaSet> getSchemaSetsByDataspaceName(final String dataspaceName) {
final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
final List<SchemaSetEntity> schemaSetEntities = schemaSetRepository.findByDataspace(dataspaceEntity);
@@ -217,7 +223,6 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
schemaSetRepository.deleteByDataspaceAndNameIn(dataspaceEntity, schemaSetNames);
}
-
@Override
@Transactional
public void updateSchemaSetFromModules(final String dataspaceName, final String schemaSetName,
@@ -232,8 +237,9 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
@Override
@Transactional
- public void deleteUnusedYangResourceModules() {
- yangResourceRepository.deleteOrphans();
+ public void deleteAllUnusedYangModuleData() {
+ schemaSetRepository.deleteOrphanedSchemaSets();
+ yangResourceRepository.deleteOrphanedYangResources();
}
@Override
@@ -242,15 +248,6 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
return moduleReferenceRepository.identifyNewModuleReferences(moduleReferencesToCheck);
}
- @Override
- public Collection<ModuleReference> getModuleReferencesByAttribute(final String dataspaceName,
- final String anchorName,
- final Map<String, String> parentAttributes,
- final Map<String, String> childAttributes) {
- return moduleReferenceRepository.findModuleReferences(dataspaceName, anchorName, parentAttributes,
- childAttributes);
- }
-
private Set<YangResourceEntity> synchronizeYangResources(
final Map<String, String> moduleReferenceNameToContentMap) {
final Map<String, YangResourceEntity> checksumToEntityMap = moduleReferenceNameToContentMap.entrySet().stream()
diff --git a/cps-ri/src/main/java/org/onap/cps/ri/repository/ModuleReferenceQuery.java b/cps-ri/src/main/java/org/onap/cps/ri/repository/ModuleReferenceQuery.java
index 85d0e438cb..c91e8de48d 100644
--- a/cps-ri/src/main/java/org/onap/cps/ri/repository/ModuleReferenceQuery.java
+++ b/cps-ri/src/main/java/org/onap/cps/ri/repository/ModuleReferenceQuery.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.
@@ -21,7 +21,6 @@
package org.onap.cps.ri.repository;
import java.util.Collection;
-import java.util.Map;
import org.onap.cps.api.model.ModuleReference;
/**
@@ -31,7 +30,4 @@ public interface ModuleReferenceQuery {
Collection<ModuleReference> identifyNewModuleReferences(final Collection<ModuleReference> moduleReferencesToCheck);
- Collection<ModuleReference> findModuleReferences(final String dataspaceName, final String anchorName,
- final Map<String, String> parentAttributes,
- final Map<String, String> childAttributes);
}
diff --git a/cps-ri/src/main/java/org/onap/cps/ri/repository/ModuleReferenceRepositoryImpl.java b/cps-ri/src/main/java/org/onap/cps/ri/repository/ModuleReferenceRepositoryImpl.java
index b98696ca72..7611dcd8a5 100644
--- a/cps-ri/src/main/java/org/onap/cps/ri/repository/ModuleReferenceRepositoryImpl.java
+++ b/cps-ri/src/main/java/org/onap/cps/ri/repository/ModuleReferenceRepositoryImpl.java
@@ -1,6 +1,6 @@
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2022 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.
@@ -20,24 +20,18 @@
package org.onap.cps.ri.repository;
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
-import jakarta.persistence.Query;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
-import lombok.extern.slf4j.Slf4j;
import org.onap.cps.api.model.ModuleReference;
import org.springframework.transaction.annotation.Transactional;
-@Slf4j
@Transactional
@RequiredArgsConstructor
public class ModuleReferenceRepositoryImpl implements ModuleReferenceQuery {
@@ -70,104 +64,14 @@ public class ModuleReferenceRepositoryImpl implements ModuleReferenceQuery {
return identifyNewModuleReferencesForCmHandle(tempTableName);
}
- /**
- * Finds module references based on specified dataspace, anchor, and attribute filters.
- * This method constructs and executes a SQL query to retrieve module references. The query applies filters to
- * parent and child fragments using the provided attribute maps. The `parentAttributes` are used to filter
- * parent fragments, while `childAttributes` filter child fragments.
- *
- * @param dataspaceName the name of the dataspace to filter on.
- * @param anchorName the name of the anchor to filter on.
- * @param parentAttributes a map of attributes for filtering parent fragments.
- * @param childAttributes a map of attributes for filtering child fragments.
- * @return a collection of {@link ModuleReference} objects that match the specified filters.
- */
- @Transactional
- @SuppressWarnings("unchecked")
- @Override
- public Collection<ModuleReference> findModuleReferences(final String dataspaceName, final String anchorName,
- final Map<String, String> parentAttributes,
- final Map<String, String> childAttributes) {
-
- final String parentFragmentWhereClause = buildWhereClause(childAttributes, "parentFragment");
- final String childFragmentWhereClause = buildWhereClause(parentAttributes, "childFragment");
-
- final String moduleReferencesSqlQuery = buildModuleReferencesSqlQuery(parentFragmentWhereClause,
- childFragmentWhereClause);
-
- final Query query = entityManager.createNativeQuery(moduleReferencesSqlQuery);
- setQueryParameters(query, parentAttributes, childAttributes, anchorName, dataspaceName);
- return processQueryResults(query.getResultList());
- }
-
- private String buildWhereClause(final Map<String, String> attributes, final String alias) {
- return attributes.keySet().stream()
- .map(attributeName -> String.format("%s.attributes->>'%s' = ?", alias, attributeName))
- .collect(Collectors.joining(" AND "));
- }
-
- private void setQueryParameters(final Query query, final Map<String, String> parentAttributes,
- final Map<String, String> childAttributes, final String anchorName,
- final String dataspaceName) {
- final String childAttributeValue = childAttributes.entrySet().iterator().next().getValue();
- query.setParameter(1, childAttributeValue);
-
- final String parentAttributeValue = parentAttributes.entrySet().iterator().next().getValue();
- query.setParameter(2, parentAttributeValue);
-
- query.setParameter(3, anchorName);
- query.setParameter(4, dataspaceName);
- }
-
- @SuppressFBWarnings(value = "VA_FORMAT_STRING_USES_NEWLINE", justification = "no \n in string just in file format")
- private String buildModuleReferencesSqlQuery(final String parentFragmentClause, final String childFragmentClause) {
- return """
- WITH Fragment AS (
- SELECT childFragment.attributes->>'id' AS schema_set_name
- FROM fragment parentFragment
- JOIN fragment childFragment ON parentFragment.parent_id = childFragment.id
- JOIN anchor anchorInfo ON parentFragment.anchor_id = anchorInfo.id
- JOIN dataspace dataspaceInfo ON anchorInfo.dataspace_id = dataspaceInfo.id
- WHERE %s
- AND %s
- AND anchorInfo.name = ?
- AND dataspaceInfo.name = ?
- LIMIT 1
- ),
- SchemaSet AS (
- SELECT id
- FROM schema_set
- WHERE name = (SELECT schema_set_name FROM Fragment)
- )
- SELECT yangResource.module_name, yangResource.revision
- FROM yang_resource yangResource
- JOIN schema_set_yang_resources schemaSetYangResources
- ON yangResource.id = schemaSetYangResources.yang_resource_id
- WHERE schemaSetYangResources.schema_set_id = (SELECT id FROM SchemaSet);
- """.formatted(parentFragmentClause, childFragmentClause);
- }
-
- private Collection<ModuleReference> processQueryResults(final List<Object[]> queryResults) {
- if (queryResults.isEmpty()) {
- log.info("No module references found for the provided attributes.");
- return Collections.emptyList();
- }
- return queryResults.stream()
- .map(queryResult -> {
- final String name = (String) queryResult[0];
- final String revision = (String) queryResult[1];
- return new ModuleReference(name, revision);
- })
- .collect(Collectors.toList());
- }
-
private Collection<ModuleReference> identifyNewModuleReferencesForCmHandle(final String tempTableName) {
- final String sql = String.format(
- "SELECT %1$s.module_name, %1$s.revision"
- + " FROM %1$s LEFT JOIN yang_resource"
- + " ON yang_resource.module_name=%1$s.module_name"
- + " AND yang_resource.revision=%1$s.revision"
- + " WHERE yang_resource.module_name IS NULL;", tempTableName);
+ final String sql = """
+ SELECT %1$s.module_name, %1$s.revision
+ FROM %1$s
+ LEFT JOIN yang_resource
+ ON yang_resource.module_name=%1$s.module_name AND yang_resource.revision=%1$s.revision
+ WHERE yang_resource.module_name IS NULL;
+ """.formatted(tempTableName);
@SuppressWarnings("unchecked")
final List<Object[]> resultsAsObjects = entityManager.createNativeQuery(sql).getResultList();
diff --git a/cps-ri/src/main/java/org/onap/cps/ri/repository/SchemaSetRepository.java b/cps-ri/src/main/java/org/onap/cps/ri/repository/SchemaSetRepository.java
index 4e4948e601..b8dd7b755c 100644
--- a/cps-ri/src/main/java/org/onap/cps/ri/repository/SchemaSetRepository.java
+++ b/cps-ri/src/main/java/org/onap/cps/ri/repository/SchemaSetRepository.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* Copyright (C) 2020 Pantheon.tech
* Modifications Copyright (C) 2022 TechMahindra Ltd.
- * 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.
@@ -36,6 +36,8 @@ import org.springframework.stereotype.Repository;
@Repository
public interface SchemaSetRepository extends JpaRepository<SchemaSetEntity, Integer> {
+ boolean existsByDataspaceAndName(DataspaceEntity dataspaceEntity, String schemaSetName);
+
Optional<SchemaSetEntity> findByDataspaceAndName(DataspaceEntity dataspaceEntity, String schemaSetName);
/**
@@ -76,4 +78,13 @@ public interface SchemaSetRepository extends JpaRepository<SchemaSetEntity, Inte
deleteByDataspaceIdAndNameIn(dataspaceEntity.getId(), schemaSetNames);
}
+ /**
+ * Delete any schema set no longer used by any anchor.
+ */
+ @Modifying
+ @Query(value = """
+ DELETE FROM schema_set WHERE NOT EXISTS
+ (SELECT 1 FROM anchor WHERE anchor.schema_set_id = schema_set.id)
+ """, nativeQuery = true)
+ void deleteOrphanedSchemaSets();
}
diff --git a/cps-ri/src/main/java/org/onap/cps/ri/repository/SchemaSetYangResourceRepository.java b/cps-ri/src/main/java/org/onap/cps/ri/repository/SchemaSetYangResourceRepository.java
index 8350d5728c..410dcc2e26 100644
--- a/cps-ri/src/main/java/org/onap/cps/ri/repository/SchemaSetYangResourceRepository.java
+++ b/cps-ri/src/main/java/org/onap/cps/ri/repository/SchemaSetYangResourceRepository.java
@@ -1,6 +1,6 @@
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2021-2023 Nordix Foundation.
+ * Copyright (C) 2021-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,6 +24,13 @@ import java.util.List;
public interface SchemaSetYangResourceRepository {
+
+ /**
+ * Link yang resources (ids) with a schema set (id).
+ *
+ * @param schemaSetId the schema set id
+ * @param yangResourceIds list of yang resource ids
+ */
void insertSchemaSetIdYangResourceId(final Integer schemaSetId, final List<Integer> yangResourceIds);
}
diff --git a/cps-ri/src/main/java/org/onap/cps/ri/repository/YangResourceRepository.java b/cps-ri/src/main/java/org/onap/cps/ri/repository/YangResourceRepository.java
index 831766cc9a..628502f846 100644
--- a/cps-ri/src/main/java/org/onap/cps/ri/repository/YangResourceRepository.java
+++ b/cps-ri/src/main/java/org/onap/cps/ri/repository/YangResourceRepository.java
@@ -1,7 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2020 Pantheon.tech
- * Modifications Copyright (C) 2021-2024 Nordix Foundation
+ * Modifications Copyright (C) 2021-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.
@@ -92,7 +92,9 @@ public interface YangResourceRepository extends JpaRepository<YangResourceEntity
void deleteSchemaSetYangResourceForSchemaSetId(@Param("schemaSetId") int schemaSetId);
@Modifying
- @Query(value = "DELETE FROM yang_resource yr WHERE NOT EXISTS "
- + "(SELECT 1 FROM schema_set_yang_resources ssyr WHERE ssyr.yang_resource_id = yr.id)", nativeQuery = true)
- void deleteOrphans();
+ @Query(value = """
+ DELETE FROM yang_resource WHERE NOT EXISTS (SELECT 1 FROM schema_set_yang_resources
+ WHERE schema_set_yang_resources.yang_resource_id = yang_resource.id)
+ """, nativeQuery = true)
+ void deleteOrphanedYangResources();
}
diff --git a/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java b/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java
index e71b44c40f..81b6439efc 100644
--- a/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java
+++ b/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2020-2024 Nordix Foundation
+ * Copyright (C) 2020-2025 Nordix Foundation
* Modifications Copyright (C) 2020-2021 Pantheon.tech
* Modifications Copyright (C) 2022 TechMahindra Ltd.
* ================================================================================
@@ -58,6 +58,15 @@ public interface CpsModuleService {
Collection<ModuleReference> allModuleReferences);
/**
+ * Check if a schema set exist in the given dataspace.
+ *
+ * @param dataspaceName Dataspace name
+ * @param schemaSetName Schema set name
+ * @return boolean, true if a schema set with the given name exist in the given dataspace
+ */
+ boolean schemaSetExists(String dataspaceName, String schemaSetName);
+
+ /**
* Read schema set in the given dataspace.
*
* @param dataspaceName dataspace name
@@ -150,47 +159,13 @@ public interface CpsModuleService {
* The system will ignore the namespace of all module references.
*
* @param moduleReferencesToCheck the moduleReferencesToCheck
- * @returns collection of module references (namespace will be always blank)
- */
- Collection<ModuleReference> identifyNewModuleReferences(
- Collection<ModuleReference> moduleReferencesToCheck);
-
- /**
- * Retrieves module references based on the provided dataspace name, anchor name and attribute filters
- * for both parent and child fragments.
-
- * This method constructs and executes a SQL query to find module references from a database, using
- * the specified `dataspaceName`, `anchorName` and two sets of attribute filters: one for parent fragments
- * and one for child fragments. The method applies these filters to identify the appropriate fragments
- * and schema sets, and then retrieves the corresponding module references.
-
- * The SQL query is dynamically built based on the provided attribute filters:
- * - The `parentAttributes` map is used to filter the parent fragments. The entries in this map are
- * converted into a WHERE clause for the parent fragments.
- * - The `childAttributes` map is used to filter the child fragments. This is applied to the child fragments
- * after filtering the parent fragments.
- *
- * @param dataspaceName the name of the dataspace to filter on. It is used to locate the relevant dataspace
- * in the database.
- * @param anchorName the name of the anchor to filter on. It is used to locate the relevant anchor within
- * the dataspace.
- * @param parentAttributes a map of attributes to filter parent fragments. Each entry in this map represents
- * an attribute key-value pair used in the WHERE clause for parent fragments.
- * @param childAttributes a map of attributes to filter child fragments. Each entry in this map represents
- * an attribute key-value pair used in the WHERE clause for child fragments.
- * @return a collection of {@link ModuleReference} objects that match the given criteria.
- * Each {@code ModuleReference} contains information about a module's name and revision.
- * @implNote The method assumes that both `parentAttributes` and `childAttributes` maps contain at least
- * one entry. The first entry from `parentAttributes` is used to filter parent fragments,
- * and the first entry from `childAttributes` is used to filter child fragments.
+ * @return collection of module references (namespace will be always blank)
*/
- Collection<ModuleReference> getModuleReferencesByAttribute(final String dataspaceName, final String anchorName,
- final Map<String, String> parentAttributes,
- final Map<String, String> childAttributes);
+ Collection<ModuleReference> identifyNewModuleReferences(Collection<ModuleReference> moduleReferencesToCheck);
/**
- * Remove any Yang Resource Modules from the DB that are no longer referenced by any schema set.
+ * Remove any Yang Resource Modules and Schema Sets from the DB that are no longer referenced by any anchor.
*/
- void deleteUnusedYangResourceModules();
+ void deleteAllUnusedYangModuleData();
}
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsAnchorServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsAnchorServiceImpl.java
index 1bd2b6af56..2a2ddc6c11 100644
--- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsAnchorServiceImpl.java
+++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsAnchorServiceImpl.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.
@@ -39,7 +39,7 @@ public class CpsAnchorServiceImpl implements CpsAnchorService {
@Override
public void createAnchor(final String dataspaceName, final String schemaSetName, final String anchorName) {
- cpsValidator.validateNameCharacters(dataspaceName, schemaSetName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
cpsAdminPersistenceService.createAnchor(dataspaceName, schemaSetName, anchorName);
}
@@ -64,7 +64,7 @@ public class CpsAnchorServiceImpl implements CpsAnchorService {
@Override
public Collection<Anchor> getAnchorsBySchemaSetName(final String dataspaceName, final String schemaSetName) {
- cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+ cpsValidator.validateNameCharacters(dataspaceName);
return cpsAdminPersistenceService.getAnchorsBySchemaSetName(dataspaceName, schemaSetName);
}
@@ -72,7 +72,6 @@ public class CpsAnchorServiceImpl implements CpsAnchorService {
public Collection<Anchor> getAnchorsBySchemaSetNames(final String dataspaceName,
final Collection<String> schemaSetNames) {
cpsValidator.validateNameCharacters(dataspaceName);
- cpsValidator.validateNameCharacters(schemaSetNames);
return cpsAdminPersistenceService.getAnchorsBySchemaSetNames(dataspaceName, schemaSetNames);
}
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
index 9f5c0a3853..6740262bcc 100644
--- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
+++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2020-2024 Nordix Foundation
+ * Copyright (C) 2020-2025 Nordix Foundation
* Modifications Copyright (C) 2020-2021 Pantheon.tech
* Modifications Copyright (C) 2022 Bell Canada
* Modifications Copyright (C) 2022 TechMahindra Ltd
@@ -58,7 +58,7 @@ public class CpsModuleServiceImpl implements CpsModuleService {
description = "Time taken to create (and store) a schemaset")
public void createSchemaSet(final String dataspaceName, final String schemaSetName,
final Map<String, String> yangResourcesNameToContentMap) {
- cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+ cpsValidator.validateNameCharacters(dataspaceName);
cpsModulePersistenceService.storeSchemaSet(dataspaceName, schemaSetName, yangResourcesNameToContentMap);
final YangTextSchemaSourceSet yangTextSchemaSourceSet =
timedYangTextSchemaSourceSetBuilder.getYangTextSchemaSourceSet(yangResourcesNameToContentMap);
@@ -69,14 +69,20 @@ public class CpsModuleServiceImpl implements CpsModuleService {
public void createSchemaSetFromModules(final String dataspaceName, final String schemaSetName,
final Map<String, String> newModuleNameToContentMap,
final Collection<ModuleReference> allModuleReferences) {
- cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+ cpsValidator.validateNameCharacters(dataspaceName);
cpsModulePersistenceService.storeSchemaSetFromModules(dataspaceName, schemaSetName,
newModuleNameToContentMap, allModuleReferences);
}
@Override
+ public boolean schemaSetExists(final String dataspaceName, final String schemaSetName) {
+ cpsValidator.validateNameCharacters(dataspaceName);
+ return cpsModulePersistenceService.schemaSetExists(dataspaceName, schemaSetName);
+ }
+
+ @Override
public SchemaSet getSchemaSet(final String dataspaceName, final String schemaSetName) {
- cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+ cpsValidator.validateNameCharacters(dataspaceName);
final var yangTextSchemaSourceSet = yangTextSchemaSourceSetCache
.get(dataspaceName, schemaSetName);
return SchemaSet.builder().name(schemaSetName).dataspaceName(dataspaceName)
@@ -96,7 +102,7 @@ public class CpsModuleServiceImpl implements CpsModuleService {
@Transactional
public void deleteSchemaSet(final String dataspaceName, final String schemaSetName,
final CascadeDeleteAllowed cascadeDeleteAllowed) {
- cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+ cpsValidator.validateNameCharacters(dataspaceName);
final Collection<Anchor> anchors = cpsAnchorService.getAnchorsBySchemaSetName(dataspaceName, schemaSetName);
if (!anchors.isEmpty() && isCascadeDeleteProhibited(cascadeDeleteAllowed)) {
throw new SchemaSetInUseException(dataspaceName, schemaSetName);
@@ -112,7 +118,6 @@ public class CpsModuleServiceImpl implements CpsModuleService {
@Transactional
public void deleteSchemaSetsWithCascade(final String dataspaceName, final Collection<String> schemaSetNames) {
cpsValidator.validateNameCharacters(dataspaceName);
- cpsValidator.validateNameCharacters(schemaSetNames);
final Collection<String> anchorNames =
cpsAnchorService.getAnchorsBySchemaSetNames(dataspaceName, schemaSetNames)
.stream().map(Anchor::getName).collect(Collectors.toSet());
@@ -127,7 +132,7 @@ public class CpsModuleServiceImpl implements CpsModuleService {
public void upgradeSchemaSetFromModules(final String dataspaceName, final String schemaSetName,
final Map<String, String> newModuleNameToContentMap,
final Collection<ModuleReference> allModuleReferences) {
- cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+ cpsValidator.validateNameCharacters(dataspaceName);
cpsModulePersistenceService.updateSchemaSetFromModules(dataspaceName, schemaSetName,
newModuleNameToContentMap, allModuleReferences);
yangTextSchemaSourceSetCache.removeFromCache(dataspaceName, schemaSetName);
@@ -169,20 +174,9 @@ public class CpsModuleServiceImpl implements CpsModuleService {
return cpsModulePersistenceService.identifyNewModuleReferences(moduleReferencesToCheck);
}
- @Timed(value = "cps.module.service.module.reference.query.by.attribute",
- description = "Time taken to query list of module references by attribute (e.g moduleSetTag)")
- @Override
- public Collection<ModuleReference> getModuleReferencesByAttribute(final String dataspaceName,
- final String anchorName,
- final Map<String, String> parentAttributes,
- final Map<String, String> childAttributes) {
- return cpsModulePersistenceService.getModuleReferencesByAttribute(dataspaceName, anchorName, parentAttributes,
- childAttributes);
- }
-
@Override
- public void deleteUnusedYangResourceModules() {
- cpsModulePersistenceService.deleteUnusedYangResourceModules();
+ public void deleteAllUnusedYangModuleData() {
+ cpsModulePersistenceService.deleteAllUnusedYangModuleData();
}
private boolean isCascadeDeleteProhibited(final CascadeDeleteAllowed cascadeDeleteAllowed) {
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/YangTextSchemaSourceSetCache.java b/cps-service/src/main/java/org/onap/cps/api/impl/YangTextSchemaSourceSetCache.java
index 8b85dfca32..b893bcea09 100644
--- a/cps-service/src/main/java/org/onap/cps/api/impl/YangTextSchemaSourceSetCache.java
+++ b/cps-service/src/main/java/org/onap/cps/api/impl/YangTextSchemaSourceSetCache.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* Copyright (C) 2021 Pantheon.tech
* Modifications Copyright (C) 2022 Bell Canada
- * Modifications Copyright (C) 2022-2023 Nordix Foundation
+ * Modifications 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.
@@ -60,7 +60,7 @@ public class YangTextSchemaSourceSetCache {
*/
@Cacheable(key = "#p0.concat('-').concat(#p1)")
public YangTextSchemaSourceSet get(final String dataspaceName, final String schemaSetName) {
- cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+ cpsValidator.validateNameCharacters(dataspaceName);
final Map<String, String> yangResourceNameToContent =
cpsModulePersistenceService.getYangSchemaResources(dataspaceName, schemaSetName);
return YangTextSchemaSourceSetBuilder.of(yangResourceNameToContent);
@@ -78,7 +78,7 @@ public class YangTextSchemaSourceSetCache {
@CanIgnoreReturnValue
public YangTextSchemaSourceSet updateCache(final String dataspaceName, final String schemaSetName,
final YangTextSchemaSourceSet yangTextSchemaSourceSet) {
- cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+ cpsValidator.validateNameCharacters(dataspaceName);
yangSchemaCacheCounter.incrementAndGet();
return yangTextSchemaSourceSet;
}
@@ -91,9 +91,8 @@ public class YangTextSchemaSourceSetCache {
*/
@CacheEvict(key = "#p0.concat('-').concat(#p1)")
public void removeFromCache(final String dataspaceName, final String schemaSetName) {
- cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+ cpsValidator.validateNameCharacters(dataspaceName);
yangSchemaCacheCounter.decrementAndGet();
- // Spring provides implementation for removing object from cache
}
}
diff --git a/cps-service/src/main/java/org/onap/cps/init/DbCleaner.java b/cps-service/src/main/java/org/onap/cps/init/DbCleaner.java
deleted file mode 100644
index 6bd3e1f204..0000000000
--- a/cps-service/src/main/java/org/onap/cps/init/DbCleaner.java
+++ /dev/null
@@ -1,48 +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.init;
-
-import java.util.concurrent.TimeUnit;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.api.CpsModuleService;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Service;
-
-@Slf4j
-@RequiredArgsConstructor
-@Service
-public class DbCleaner {
-
- private final CpsModuleService cpsModuleService;
-
- /**
- * This method will clean up the db during application start up.
- * It wil run once and currently only removes unused yang resource modules.
- *
- */
- @Scheduled(initialDelay = 1, timeUnit = TimeUnit.SECONDS)
- public void cleanDbAtStartUp() {
- log.info("CPS Application started, commencing DB clean up");
- cpsModuleService.deleteUnusedYangResourceModules();
- log.info("DB clean up completed");
- }
-}
diff --git a/cps-service/src/main/java/org/onap/cps/spi/CpsModulePersistenceService.java b/cps-service/src/main/java/org/onap/cps/spi/CpsModulePersistenceService.java
index 4cfc287a5d..b1f8aad88f 100755
--- a/cps-service/src/main/java/org/onap/cps/spi/CpsModulePersistenceService.java
+++ b/cps-service/src/main/java/org/onap/cps/spi/CpsModulePersistenceService.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2020-2024 Nordix Foundation
+ * Copyright (C) 2020-2025 Nordix Foundation
* Modifications Copyright (C) 2020-2022 Bell Canada.
* Modifications Copyright (C) 2022 TechMahindra Ltd.
* ================================================================================
@@ -65,6 +65,14 @@ public interface CpsModulePersistenceService {
final Map<String, String> newModuleNameToContentMap,
final Collection<ModuleReference> allModuleReferences);
+ /**
+ * Checks whether a schema set exists in the specified dataspace.
+ *
+ * @param dataspaceName dataspace name
+ * @param schemaSetName schema set name
+ * @return {@code true} if the schema set exists in the given dataspace; {@code false} otherwise
+ */
+ boolean schemaSetExists(String dataspaceName, String schemaSetName);
/**
* Get all schema sets for a given dataspace.
@@ -138,35 +146,18 @@ public interface CpsModulePersistenceService {
String moduleName, String moduleRevision);
/**
- * Remove unused Yang Resource Modules.
+ * Remove any unused Yang Resource Modules and Schema Sets.
*/
- void deleteUnusedYangResourceModules();
+ void deleteAllUnusedYangModuleData();
/**
* Identify new module references from those returned by a node compared to what is in CPS already.
* The system will ignore the namespace of all module references.
*
* @param moduleReferencesToCheck the module references ot check
- * @returns Collection of {@link ModuleReference} (namespace will be always blank)
- *
- */
- Collection<ModuleReference> identifyNewModuleReferences(
- Collection<ModuleReference> moduleReferencesToCheck);
-
- /**
- * Retrieves module references based on the specified dataspace, anchor, and attribute filters.
-
- * Constructs and executes a SQL query to find module references by applying filters for parent and child fragments.
- * Uses `parentAttributes` for filtering parent fragments and `childAttributes` for filtering child fragments.
+ * @return Collection of {@link ModuleReference} (namespace will be always blank)
*
- * @param dataspaceName the name of the dataspace to filter on.
- * @param anchorName the name of the anchor to filter on.
- * @param parentAttributes a map of attributes for filtering parent fragments.
- * @param childAttributes a map of attributes for filtering child fragments.
- * @return a collection of {@link ModuleReference} objects matching the criteria.
*/
- Collection<ModuleReference> getModuleReferencesByAttribute(final String dataspaceName, final String anchorName,
- final Map<String, String> parentAttributes,
- final Map<String, String> childAttributes);
+ Collection<ModuleReference> identifyNewModuleReferences(Collection<ModuleReference> moduleReferencesToCheck);
}
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAnchorServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAnchorServiceImplSpec.groovy
index e8617d445d..223ae71987 100644
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAnchorServiceImplSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAnchorServiceImplSpec.groovy
@@ -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.
@@ -40,8 +40,8 @@ class CpsAnchorServiceImplSpec extends Specification {
objectUnderTest.createAnchor('someDataspace', 'someSchemaSet', 'someAnchorName')
then: 'the persistence service method is invoked with same parameters'
1 * mockCpsAdminPersistenceService.createAnchor('someDataspace', 'someSchemaSet', 'someAnchorName')
- and: 'the CpsValidator is called on the dataspaceName, schemaSetName and anchorName'
- 1 * mockCpsValidator.validateNameCharacters('someDataspace', 'someSchemaSet', 'someAnchorName')
+ and: 'the CpsValidator is called on the dataspaceName and anchorName'
+ 1 * mockCpsValidator.validateNameCharacters('someDataspace', 'someAnchorName')
}
def 'Retrieve all anchors for dataspace.'() {
@@ -64,8 +64,8 @@ class CpsAnchorServiceImplSpec extends Specification {
def result = objectUnderTest.getAnchorsBySchemaSetName('someDataspace', 'someSchemaSet')
then: 'the collection provided by persistence service is returned as result'
result == anchors
- and: 'the CpsValidator is called on the dataspaceName, schemaSetName'
- 1 * mockCpsValidator.validateNameCharacters('someDataspace', 'someSchemaSet')
+ and: 'the CpsValidator is called on the dataspaceName'
+ 1 * mockCpsValidator.validateNameCharacters('someDataspace')
}
def 'Retrieve all anchors for multiple schema-sets.'() {
@@ -76,9 +76,8 @@ class CpsAnchorServiceImplSpec extends Specification {
def result = objectUnderTest.getAnchorsBySchemaSetNames('someDataspace', ['schemaSet1', 'schemaSet2'])
then: 'the collection provided by persistence service is returned as result'
result == anchors
- and: 'the CpsValidator is called on the dataspace name and schema-set names'
+ and: 'the CpsValidator is called on the dataspace name'
1 * mockCpsValidator.validateNameCharacters('someDataspace')
- 1 * mockCpsValidator.validateNameCharacters(_)
}
def 'Retrieve anchor for dataspace and provided anchor name.'() {
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy
index 97b9f7fffd..d1101fc248 100644
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2020-2024 Nordix Foundation
+ * Copyright (C) 2020-2025 Nordix Foundation
* Modifications Copyright (C) 2020-2021 Pantheon.tech
* Modifications Copyright (C) 2020-2022 Bell Canada.
* Modifications Copyright (C) 2022 TechMahindra Ltd.
@@ -54,23 +54,23 @@ class CpsModuleServiceImplSpec extends Specification {
def 'Create schema set.'() {
when: 'Create schema set method is invoked'
- objectUnderTest.createSchemaSet('someDataspace', 'someSchemaSet', [:])
+ objectUnderTest.createSchemaSet('someDataspace', 'schemaSetName@with Special!Characters', [:])
then: 'Parameters are validated and processing is delegated to persistence service'
- 1 * mockCpsModulePersistenceService.storeSchemaSet('someDataspace', 'someSchemaSet', [:])
- and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
- 1 * mockCpsValidator.validateNameCharacters('someDataspace', 'someSchemaSet')
+ 1 * mockCpsModulePersistenceService.storeSchemaSet('someDataspace', 'schemaSetName@with Special!Characters', [:])
+ and: 'the CpsValidator is called on the dataspaceName'
+ 1 * mockCpsValidator.validateNameCharacters('someDataspace')
}
def 'Create schema set from new modules and existing modules.'() {
given: 'a list of existing modules module reference'
- def moduleReferenceForExistingModule = new ModuleReference('test', '2021-10-12','test.org')
+ def moduleReferenceForExistingModule = new ModuleReference('test', '2021-10-12', 'test.org')
def listOfExistingModulesModuleReference = [moduleReferenceForExistingModule]
when: 'create schema set from modules method is invoked'
objectUnderTest.createSchemaSetFromModules('someDataspaceName', 'someSchemaSetName', [newModule: 'newContent'], listOfExistingModulesModuleReference)
then: 'processing is delegated to persistence service'
1 * mockCpsModulePersistenceService.storeSchemaSetFromModules('someDataspaceName', 'someSchemaSetName', [newModule: 'newContent'], listOfExistingModulesModuleReference)
- and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
- 1 * mockCpsValidator.validateNameCharacters('someDataspaceName', 'someSchemaSetName')
+ and: 'the CpsValidator is called on the dataspaceName'
+ 1 * mockCpsValidator.validateNameCharacters('someDataspaceName')
}
def 'Create schema set from invalid resources'() {
@@ -100,15 +100,15 @@ class CpsModuleServiceImplSpec extends Specification {
given: 'an already present schema set'
def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang')
and: 'yang resource cache returns the expected schema set'
- mockYangTextSchemaSourceSetCache.get('someDataspace', 'someSchemaSet') >> YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap)
+ mockYangTextSchemaSourceSetCache.get('someDataspace', 'schemaSetName@with Special!Characters') >> YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap)
when: 'get schema set method is invoked'
- def result = objectUnderTest.getSchemaSet('someDataspace', 'someSchemaSet')
+ def result = objectUnderTest.getSchemaSet('someDataspace', 'schemaSetName@with Special!Characters')
then: 'the correct schema set is returned'
- result.getName().contains('someSchemaSet')
+ result.getName().contains('schemaSetName@with Special!Characters')
result.getDataspaceName().contains('someDataspace')
result.getModuleReferences().contains(new ModuleReference('stores', '2020-09-15', 'org:onap:ccsdk:sample'))
- and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
- 1 * mockCpsValidator.validateNameCharacters('someDataspace', 'someSchemaSet')
+ and: 'the CpsValidator is called on the dataspaceName'
+ 1 * mockCpsValidator.validateNameCharacters('someDataspace')
}
def 'Get schema sets by dataspace name.'() {
@@ -142,8 +142,8 @@ class CpsModuleServiceImplSpec extends Specification {
1 * mockCpsModulePersistenceService.deleteSchemaSet('my-dataspace', 'my-schemaset')
and: 'schema set will be removed from the cache'
1 * mockYangTextSchemaSourceSetCache.removeFromCache('my-dataspace', 'my-schemaset')
- and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
- 1 * mockCpsValidator.validateNameCharacters('my-dataspace', _)
+ and: 'the CpsValidator is called on the dataspaceName'
+ 1 * mockCpsValidator.validateNameCharacters('my-dataspace')
where: 'following parameters are used'
numberOfAnchors << [0, 3]
}
@@ -159,8 +159,8 @@ class CpsModuleServiceImplSpec extends Specification {
1 * mockCpsModulePersistenceService.deleteSchemaSet('my-dataspace', 'my-schemaset')
and: 'schema set will be removed from the cache'
1 * mockYangTextSchemaSourceSetCache.removeFromCache('my-dataspace', 'my-schemaset')
- and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
- 1 * mockCpsValidator.validateNameCharacters('my-dataspace', 'my-schemaset')
+ and: 'the CpsValidator is called on the dataspaceName'
+ 1 * mockCpsValidator.validateNameCharacters('my-dataspace')
}
def 'Delete schema-set when cascade is prohibited and schema-set has anchors.'() {
@@ -185,17 +185,15 @@ class CpsModuleServiceImplSpec extends Specification {
2 * mockYangTextSchemaSourceSetCache.removeFromCache('my-dataspace', _)
and: 'the CpsValidator is called on the dataspaceName'
1 * mockCpsValidator.validateNameCharacters('my-dataspace')
- and: 'the CpsValidator is called on the schemaSetNames'
- 1 * mockCpsValidator.validateNameCharacters(_)
where: 'following parameters are used'
numberOfAnchors << [0, 3]
}
def 'Upgrade existing schema set'() {
when: 'schema set update is requested'
- objectUnderTest.upgradeSchemaSetFromModules('my-dataspace', 'my-schemaset', [:], moduleReferences)
+ objectUnderTest.upgradeSchemaSetFromModules('my-dataspace', 'my-schemaset', [:], moduleReferences)
then: 'no exception is thrown '
- noExceptionThrown()
+ noExceptionThrown()
}
def 'Get all yang resources module references.'() {
@@ -206,7 +204,7 @@ class CpsModuleServiceImplSpec extends Specification {
def result = objectUnderTest.getYangResourceModuleReferences('someDataspaceName')
then: 'the list provided by persistence service is returned as result'
result == moduleReferences
- and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
+ and: 'the CpsValidator is called on the dataspaceName'
1 * mockCpsValidator.validateNameCharacters('someDataspaceName')
}
@@ -218,7 +216,7 @@ class CpsModuleServiceImplSpec extends Specification {
def result = objectUnderTest.getYangResourcesModuleReferences('someDataspaceName', 'someAnchorName')
then: 'the list provided by persistence service is returned as result'
result == moduleReferences
- and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
+ and: 'the CpsValidator is called on the dataspaceName and anchorName'
1 * mockCpsValidator.validateNameCharacters('someDataspaceName', 'someAnchorName')
}
@@ -231,22 +229,6 @@ class CpsModuleServiceImplSpec extends Specification {
1 * mockCpsModulePersistenceService.identifyNewModuleReferences(moduleReferencesToCheck)
}
- def 'Get module references when queried by attributes'() {
- given: 'a valid dataspace name and anchor name'
- def dataspaceName = 'someDataspace'
- def anchorName = 'someAnchor'
- and: 'a set of parent attributes and child attributes used for filtering'
- def parentAttributes = ['some-property-key1': 'some-property-val1']
- def childAttributes = ['some-property-key2': 'some-property-val2']
- and: 'a list of expected module references returned by the persistence service'
- def expectedModuleReferences = [new ModuleReference(moduleName: 'some-name', revision: 'some-revision')]
- mockCpsModulePersistenceService.getModuleReferencesByAttribute(dataspaceName, anchorName, parentAttributes, childAttributes) >> expectedModuleReferences
- when: 'the method is invoked to retrieve module references by attributes'
- def actualModuleReferences = objectUnderTest.getModuleReferencesByAttribute(dataspaceName, anchorName, parentAttributes, childAttributes)
- then: 'the retrieved module references should match the expected module references'
- assert actualModuleReferences == expectedModuleReferences
- }
-
def 'Getting module definitions with module name'() {
given: 'module persistence service returns module definitions for module name'
@@ -270,11 +252,18 @@ class CpsModuleServiceImplSpec extends Specification {
1 * mockCpsValidator.validateNameCharacters('some-dataspace-name', 'some-anchor-name')
}
- def 'Delete unused yang resource modules.'() {
- when: 'deleting unused yang resource modules'
- objectUnderTest.deleteUnusedYangResourceModules()
+ def 'Delete all unused yang module data.'() {
+ when: 'deleting unused yang module data'
+ objectUnderTest.deleteAllUnusedYangModuleData()
then: 'it is delegated to the module persistence service'
- 1 * mockCpsModulePersistenceService.deleteUnusedYangResourceModules()
+ 1 * mockCpsModulePersistenceService.deleteAllUnusedYangModuleData()
+ }
+
+ def 'Schema set exists.'() {
+ when: 'checking if schema set exists'
+ objectUnderTest.schemaSetExists('some-dataspace-name', 'some-schema-set-name')
+ then: 'the call is delegated to the module persistence service'
+ 1 * mockCpsModulePersistenceService.schemaSetExists('some-dataspace-name', 'some-schema-set-name')
}
def getModuleReferences() {
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/YangTextSchemaSourceSetCacheSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/YangTextSchemaSourceSetCacheSpec.groovy
index 189e28521b..5b9d11f439 100644
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/YangTextSchemaSourceSetCacheSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/YangTextSchemaSourceSetCacheSpec.groovy
@@ -1,7 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2022 Bell Canada
- * Modifications Copyright (C) 2022 Nordix Foundation
+ * Modifications 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.
@@ -77,8 +77,8 @@ class YangTextSchemaSourceSetCacheSpec extends Specification {
assert cachedValue.getModuleReferences() == expectedYangTextSchemaSourceSet.getModuleReferences()
and: 'the response is as expected'
assert result.getModuleReferences() == expectedYangTextSchemaSourceSet.getModuleReferences()
- and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
- 1 * mockCpsValidator.validateNameCharacters('my-dataspace', 'my-schemaset')
+ and: 'the CpsValidator is called on the dataspaceName'
+ 1 * mockCpsValidator.validateNameCharacters('my-dataspace')
}
def 'Cache Hit: Respond from cache'() {
@@ -104,8 +104,8 @@ class YangTextSchemaSourceSetCacheSpec extends Specification {
then: 'cached value is same as expected'
def cachedValue = getCachedValue('my-dataspace', 'my-schemaset')
cachedValue.getModuleReferences() == yangTextSchemaSourceSet.getModuleReferences()
- and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
- 1 * mockCpsValidator.validateNameCharacters('my-dataspace', 'my-schemaset')
+ and: 'the CpsValidator is called on the dataspaceName'
+ 1 * mockCpsValidator.validateNameCharacters('my-dataspace')
}
def 'Cache Evict:with invalid #scenario'() {
@@ -119,8 +119,8 @@ class YangTextSchemaSourceSetCacheSpec extends Specification {
objectUnderTest.removeFromCache('my-dataspace', 'my-schemaset')
then: 'cached does not have value'
assert getCachedValue('my-dataspace', 'my-schemaset') == null
- and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
- 1 * mockCpsValidator.validateNameCharacters('my-dataspace', 'my-schemaset')
+ and: 'the CpsValidator is called on the dataspaceName'
+ 1 * mockCpsValidator.validateNameCharacters('my-dataspace')
}
def 'Cache Evict: remove when does not exist'() {
@@ -130,8 +130,8 @@ class YangTextSchemaSourceSetCacheSpec extends Specification {
objectUnderTest.removeFromCache('my-dataspace', 'my-schemaset')
then: 'cached does not have value'
assert getCachedValue('my-dataspace', 'my-schemaset') == null
- and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
- 1 * mockCpsValidator.validateNameCharacters('my-dataspace', 'my-schemaset')
+ and: 'the CpsValidator is called on the dataspaceName'
+ 1 * mockCpsValidator.validateNameCharacters('my-dataspace')
}
def getCachedValue(dataSpace, schemaSet) {
@@ -142,5 +142,4 @@ class YangTextSchemaSourceSetCacheSpec extends Specification {
return new String("${dataSpace}-${schemaSet}")
}
-
}
diff --git a/cps-service/src/test/groovy/org/onap/cps/init/DbCleanerSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/init/DbCleanerSpec.groovy
deleted file mode 100644
index 5106d29fa5..0000000000
--- a/cps-service/src/test/groovy/org/onap/cps/init/DbCleanerSpec.groovy
+++ /dev/null
@@ -1,38 +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.init
-
-import org.onap.cps.api.CpsModuleService
-import spock.lang.Specification
-
-class DbCleanerSpec extends Specification {
-
- def mockCpsModuleService = Mock(CpsModuleService)
-
- def objectUnderTest = new DbCleaner(mockCpsModuleService)
-
- def 'DB clean up.'() {
- when: 'scheduled method is triggered'
- objectUnderTest.cleanDbAtStartUp()
- then: 'the unused yang resource modules are deleted'
- 1 * mockCpsModuleService.deleteUnusedYangResourceModules()
- }
-}
diff --git a/docker-compose/docker-compose.yml b/docker-compose/docker-compose.yml
index 1eae8f6a65..4263329eed 100644
--- a/docker-compose/docker-compose.yml
+++ b/docker-compose/docker-compose.yml
@@ -1,7 +1,7 @@
# ============LICENSE_START=======================================================
# Copyright (c) 2020 Pantheon.tech.
# Modifications Copyright (C) 2021 Bell Canada.
-# Modifications Copyright (C) 2022-2024 Nordix Foundation.
+# Modifications 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.
@@ -51,6 +51,8 @@ services:
image: ${DOCKER_REPO:-nexus3.onap.org:10003}/onap/cps-and-ncmp:${CPS_VERSION:-latest}
ports:
- ${CPS_PORT_RANGE:-8698-8699}:8080
+ ### DEBUG: Uncomment next line to enable java debugging (ensure 'ports' aligns with 'deploy')
+ ### - ${CPS_CORE_DEBUG_PORT:-5005}:5005-
environment:
CPS_USERNAME: ${CPS_CORE_USERNAME:-cpsuser}
CPS_PASSWORD: ${CPS_CORE_PASSWORD:-cpsr0cks!}
@@ -66,9 +68,9 @@ services:
ONAP_OTEL_EXPORTER_ENDPOINT: http://jaeger-service:4317
POLICY_SERVICE_ENABLED: 'false'
POLICY_SERVICE_DEFAULT_DECISION: 'deny from env'
- JAVA_TOOL_OPTIONS: "-XX:InitialRAMPercentage=75.0 -XX:MaxRAMPercentage=75.0"
+ ####JAVA_TOOL_OPTIONS: "-XX:InitialRAMPercentage=75.0 -XX:MaxRAMPercentage=75.0"
### DEBUG: Uncomment next line to enable java debugging
- ### DEBUG: JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
+ ### JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
restart: unless-stopped
depends_on:
- dbpostgresql
@@ -79,9 +81,6 @@ services:
limits:
cpus: '3'
memory: 2G
- ### DEBUG: Uncomment next 2 lines to enable java debugging (ensure 'ports' aligns with 'deploy')
- ### DEBUG ports:
- ### DEBUG - ${CPS_CORE_DEBUG_PORT:-5005}:5005
nginx:
container_name: ${NGINX_CONTAINER_NAME:-nginx-loadbalancer}
diff --git a/docs/deployment.rst b/docs/deployment.rst
index 2a17e30a16..940bc50923 100644
--- a/docs/deployment.rst
+++ b/docs/deployment.rst
@@ -1,6 +1,6 @@
.. This work is licensed under a Creative Commons Attribution 4.0 International License.
.. http://creativecommons.org/licenses/by/4.0
-.. Copyright (C) 2021-2024 Nordix Foundation
+.. Copyright (C) 2021-2025 Nordix Foundation
.. Modifications Copyright (C) 2021 Bell Canada.
.. DO NOT CHANGE THIS LABEL FOR RELEASE NOTES - EVEN THOUGH IT GIVES A WARNING
@@ -354,10 +354,7 @@ Below are the list of distributed datastructures that we have.
+--------------+------------------------------------+-----------------------------------------------------------+
| cps-ncmp | cmNotificationSubscriptionCache | Stores and tracks cm notification subscription requests. |
+--------------+------------------------------------+-----------------------------------------------------------+
-| cps-ncmp | moduleSetTagsBeingProcessed | Track module set tags which are processed to prevent |
-| | | multiple threads working with same tag. |
-+--------------+------------------------------------+-----------------------------------------------------------+
| cps-ncmp | cpsAndNcmpLock | Cps and NCMP distributed lock for various use cases. |
+--------------+------------------------------------+-----------------------------------------------------------+
-Total number of caches : 8
+Total number of caches : 7
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
index fa65d9d873..f3cca801e7 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2023-2024 Nordix Foundation
+ * Copyright (C) 2023-2025 Nordix Foundation
* Modifications Copyright (C) 2024-2025 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the 'License');
@@ -21,7 +21,6 @@
package org.onap.cps.integration.base
-import com.hazelcast.collection.ISet
import com.hazelcast.map.IMap
import okhttp3.mockwebserver.MockWebServer
import org.onap.cps.api.CpsAnchorService
@@ -29,24 +28,23 @@ import org.onap.cps.api.CpsDataService
import org.onap.cps.api.CpsDataspaceService
import org.onap.cps.api.CpsModuleService
import org.onap.cps.api.CpsQueryService
+import org.onap.cps.api.exceptions.DataspaceNotFoundException
+import org.onap.cps.api.model.DataNode
import org.onap.cps.integration.DatabaseTestContainer
import org.onap.cps.integration.KafkaTestContainer
-import org.onap.cps.ncmp.impl.NetworkCmProxyInventoryFacadeImpl
+import org.onap.cps.ncmp.api.inventory.models.CmHandleState
import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration
import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle
+import org.onap.cps.ncmp.impl.NetworkCmProxyInventoryFacadeImpl
import org.onap.cps.ncmp.impl.data.NetworkCmProxyFacade
import org.onap.cps.ncmp.impl.data.NetworkCmProxyQueryService
import org.onap.cps.ncmp.impl.inventory.InventoryPersistence
import org.onap.cps.ncmp.impl.inventory.ParameterizedCmHandleQueryService
-import org.onap.cps.ncmp.api.inventory.models.CmHandleState
import org.onap.cps.ncmp.impl.inventory.sync.ModuleSyncService
import org.onap.cps.ncmp.impl.inventory.sync.ModuleSyncWatchdog
import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher
import org.onap.cps.ri.repository.DataspaceRepository
import org.onap.cps.ri.utils.SessionManager
-import org.onap.cps.api.exceptions.DataspaceNotFoundException
-import org.onap.cps.api.model.DataNode
-import static org.onap.cps.utils.ContentType.*
import org.onap.cps.utils.JsonObjectMapper
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
@@ -136,9 +134,6 @@ abstract class CpsIntegrationSpecBase extends Specification {
@Autowired
AlternateIdMatcher alternateIdMatcher
- @Autowired
- ISet<String> moduleSetTagsBeingProcessed
-
@Value('${ncmp.policy-executor.server.port:8080}')
private String policyServerPort;
@@ -158,7 +153,7 @@ abstract class CpsIntegrationSpecBase extends Specification {
static NO_ALTERNATE_ID = ''
static GENERAL_TEST_DATASPACE = 'generalTestDataspace'
static BOOKSTORE_SCHEMA_SET = 'bookstoreSchemaSet'
- static MODULE_SYNC_WAIT_TIME_IN_SECONDS = 10
+ static MODULE_SYNC_WAIT_TIME_IN_SECONDS = 2
static initialized = false
def now = OffsetDateTime.now()
@@ -167,6 +162,7 @@ abstract class CpsIntegrationSpecBase extends Specification {
if (!initialized) {
cpsDataspaceService.createDataspace(GENERAL_TEST_DATASPACE)
createStandardBookStoreSchemaSet(GENERAL_TEST_DATASPACE)
+ cpsAnchorService.createAnchor(GENERAL_TEST_DATASPACE, BOOKSTORE_SCHEMA_SET, 'owner-of-bookstore-schema-set-do-not-delete')
initialized = true
}
mockDmiServer1.setDispatcher(dmiDispatcher1)
@@ -186,7 +182,7 @@ abstract class CpsIntegrationSpecBase extends Specification {
mockDmiServer1.shutdown()
mockDmiServer2.shutdown()
mockPolicyServer.shutdown()
- moduleSetTagsBeingProcessed.clear()
+ cpsModuleService.deleteAllUnusedYangModuleData()
}
def static readResourceDataFile(filename) {
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/AnchorServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/AnchorServiceIntegrationSpec.groovy
index 257f10b58b..2bd5a4a1be 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/AnchorServiceIntegrationSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/AnchorServiceIntegrationSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2023-2024 Nordix Foundation
+ * Copyright (C) 2023-2025 Nordix Foundation
* Modifications Copyright (C) 2024 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the 'License');
@@ -22,7 +22,6 @@
package org.onap.cps.integration.functional.cps
import java.time.OffsetDateTime
-
import org.onap.cps.api.CpsAnchorService
import org.onap.cps.integration.base.FunctionalSpecBase
import org.onap.cps.api.parameters.FetchDescendantsOption
@@ -60,17 +59,17 @@ class AnchorServiceIntegrationSpec extends FunctionalSpecBase {
and: '1 anchor with "other" schema set is created'
createStandardBookStoreSchemaSet(GENERAL_TEST_DATASPACE, 'otherSchemaSet')
objectUnderTest.createAnchor(GENERAL_TEST_DATASPACE, 'otherSchemaSet', 'anchor3')
- then: 'there are 3 anchors in the general test database'
- assert objectUnderTest.getAnchors(GENERAL_TEST_DATASPACE).size() == 3
- and: 'there are 2 anchors associated with bookstore schema set'
- assert objectUnderTest.getAnchorsBySchemaSetName(GENERAL_TEST_DATASPACE, BOOKSTORE_SCHEMA_SET).size() == 2
+ then: 'there are 4 anchors in the general test database'
+ assert objectUnderTest.getAnchors(GENERAL_TEST_DATASPACE).size() == 4
+ and: 'there are 3 anchors associated with bookstore schema set'
+ assert objectUnderTest.getAnchorsBySchemaSetName(GENERAL_TEST_DATASPACE, BOOKSTORE_SCHEMA_SET).size() == 3
and: 'there is 1 anchor associated with other schema set'
assert objectUnderTest.getAnchorsBySchemaSetName(GENERAL_TEST_DATASPACE, 'otherSchemaSet').size() == 1
}
def 'Querying anchor(name)s (depends on previous test!).'() {
- expect: 'there are now 3 anchors using the "stores" module (both schema sets use the same modules) '
- assert objectUnderTest.queryAnchorNames(GENERAL_TEST_DATASPACE, ['stores', 'bookstore-types']).size() == 3
+ expect: 'there are now 4 anchors using the "stores" module (both schema sets use the same modules) '
+ assert objectUnderTest.queryAnchorNames(GENERAL_TEST_DATASPACE, ['stores', 'bookstore-types']).size() == 4
and: 'there are no anchors using both "stores" and a "unused-model"'
assert objectUnderTest.queryAnchorNames(GENERAL_TEST_DATASPACE, ['stores', 'unused-model']).size() == 0
}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/DataspaceServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/DataspaceServiceIntegrationSpec.groovy
index 6cd7f21df3..178b0227ca 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/DataspaceServiceIntegrationSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/DataspaceServiceIntegrationSpec.groovy
@@ -32,7 +32,7 @@ class DataspaceServiceIntegrationSpec extends FunctionalSpecBase {
def setup() { objectUnderTest = cpsDataspaceService }
- def cleanup() { cpsModuleService.deleteUnusedYangResourceModules() }
+ def cleanup() { cpsModuleService.deleteAllUnusedYangModuleData() }
def 'Dataspace CRUD operations.'() {
when: 'a dataspace is created'
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/ModuleServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/ModuleServiceIntegrationSpec.groovy
index efdd71d5f4..d8010875c1 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/ModuleServiceIntegrationSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/ModuleServiceIntegrationSpec.groovy
@@ -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.
@@ -41,17 +41,17 @@ class ModuleServiceIntegrationSpec extends FunctionalSpecBase {
private static def bookStoreTypesModuleReference = new ModuleReference('bookstore-types','2024-01-30')
private static def bookStoreTypesModuleReferenceWithNamespace = new ModuleReference('bookstore-types','2024-01-30', 'org:onap:cps:types:sample')
static def NEW_RESOURCE_REVISION = '2023-05-10'
- static def NEW_RESOURCE_CONTENT = 'module test_module {\n' +
- ' yang-version 1.1;\n' +
- ' namespace "org:onap:ccsdk:sample";\n' +
- '\n' +
- ' prefix book-store;\n' +
- '\n' +
- ' revision "2023-05-10" {\n' +
- ' description\n' +
- ' "Sample Model";\n' +
- ' }' +
- '}'
+ static def NEW_RESOURCE_CONTENT = """
+ module test_module {
+ yang-version 1.1;
+ namespace "org:onap:ccsdk:sample";
+ prefix book-store;
+ revision "2023-05-10" {
+ description
+ "Sample Model";
+ }
+ }
+ """
def newYangResourcesNameToContentMap = [:]
def moduleReferences = []
@@ -61,7 +61,7 @@ class ModuleServiceIntegrationSpec extends FunctionalSpecBase {
def setup() { objectUnderTest = cpsModuleService }
- def cleanup() { objectUnderTest.deleteUnusedYangResourceModules() }
+ def cleanup() { objectUnderTest.deleteAllUnusedYangModuleData() }
/*
C R E A T E S C H E M A S E T U S E - C A S E S
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpgradeSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpgradeSpec.groovy
index 11a4f2c6a7..28714fd123 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpgradeSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpgradeSpec.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.
@@ -21,12 +21,12 @@
package org.onap.cps.integration.functional.ncmp
import org.onap.cps.integration.base.CpsIntegrationSpecBase
-import org.onap.cps.ncmp.impl.NetworkCmProxyInventoryFacadeImpl
import org.onap.cps.ncmp.api.inventory.models.CmHandleRegistrationResponse
-import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration
-import org.onap.cps.ncmp.api.inventory.models.UpgradedCmHandles
import org.onap.cps.ncmp.api.inventory.models.CmHandleState
+import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration
import org.onap.cps.ncmp.api.inventory.models.LockReasonCategory
+import org.onap.cps.ncmp.api.inventory.models.UpgradedCmHandles
+import org.onap.cps.ncmp.impl.NetworkCmProxyInventoryFacadeImpl
import spock.util.concurrent.PollingConditions
class CmHandleUpgradeSpec extends CpsIntegrationSpecBase {
@@ -38,10 +38,9 @@ class CmHandleUpgradeSpec extends CpsIntegrationSpecBase {
def setup() {
objectUnderTest = networkCmProxyInventoryFacade
- moduleSyncService.clearPrivateModuleSetCache()
}
- def 'Upgrade CM-handle with new moduleSetTag or no moduleSetTag.'() {
+ def 'Upgrade CM-handle with and without (new) module set tags.'() {
given: 'a CM-handle is created with expected initial modules: M1 and M2'
dmiDispatcher1.moduleNamesPerCmHandleId[cmHandleId] = ['M1', 'M2']
registerCmHandle(DMI1_URL, cmHandleId, initialModuleSetTag)
@@ -78,15 +77,16 @@ class CmHandleUpgradeSpec extends CpsIntegrationSpecBase {
and: 'CM-handle has expected updated modules: M1 and M3'
assert ['M1', 'M3'] == objectUnderTest.getYangResourcesModuleReferences(cmHandleId).moduleName.sort()
- cleanup: 'deregister CM-handle'
+ cleanup: 'deregister CM-handle and remove all associated module resources'
deregisterCmHandle(DMI1_URL, cmHandleId)
+ cpsModuleService.deleteAllUnusedYangModuleData()
where: 'following module set tags are used'
initialModuleSetTag | updatedModuleSetTag
NO_MODULE_SET_TAG | NO_MODULE_SET_TAG
- NO_MODULE_SET_TAG | 'new'
- 'initial' | NO_MODULE_SET_TAG
- 'initial' | 'new'
+ NO_MODULE_SET_TAG | 'new@set'
+ 'initial set' | NO_MODULE_SET_TAG
+ 'initial set' | 'new@set'
}
def 'Upgrade CM-handle with existing moduleSetTag.'() {
@@ -127,8 +127,8 @@ class CmHandleUpgradeSpec extends CpsIntegrationSpecBase {
where:
initialModuleSetTag | updatedModuleSetTag
- NO_MODULE_SET_TAG | 'moduleSet2'
- 'moduleSet1' | 'moduleSet2'
+ NO_MODULE_SET_TAG | 'module@Set2'
+ 'module@Set1' | 'module@Set2'
}
def 'Skip upgrade of CM-handle with same moduleSetTag as before.'() {
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/ModuleSyncWatchdogIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/ModuleSyncWatchdogIntegrationSpec.groovy
index a6e56ab22d..43db9b208e 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/ModuleSyncWatchdogIntegrationSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/ModuleSyncWatchdogIntegrationSpec.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.
@@ -21,15 +21,16 @@
package org.onap.cps.integration.functional.ncmp
import io.micrometer.core.instrument.MeterRegistry
+import spock.lang.Ignore
+
+import java.util.concurrent.Executors
+import java.util.concurrent.TimeUnit
import org.onap.cps.integration.base.CpsIntegrationSpecBase
import org.onap.cps.ncmp.impl.inventory.sync.ModuleSyncWatchdog
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.util.StopWatch
import spock.util.concurrent.PollingConditions
-import java.util.concurrent.Executors
-import java.util.concurrent.TimeUnit
-
class ModuleSyncWatchdogIntegrationSpec extends CpsIntegrationSpecBase {
ModuleSyncWatchdog objectUnderTest
@@ -46,7 +47,6 @@ class ModuleSyncWatchdogIntegrationSpec extends CpsIntegrationSpecBase {
def cleanup() {
try {
- deregisterSequenceOfCmHandles(DMI1_URL, PARALLEL_SYNC_SAMPLE_SIZE, 1)
moduleSyncWorkQueue.clear()
} finally {
executorService.shutdownNow()
@@ -54,14 +54,21 @@ class ModuleSyncWatchdogIntegrationSpec extends CpsIntegrationSpecBase {
}
def 'Watchdog is disabled for test.'() {
- given:
+ given: 'some cm handles are registered'
registerSequenceOfCmHandlesWithManyModuleReferencesButDoNotWaitForReady(DMI1_URL, NO_MODULE_SET_TAG, PARALLEL_SYNC_SAMPLE_SIZE, 1)
when: 'wait a while but less then the initial delay of 10 minutes'
Thread.sleep(3000)
then: 'the work queue remains empty'
assert moduleSyncWorkQueue.isEmpty()
+ cleanup: 'remove advised cm handles'
+ deregisterSequenceOfCmHandles(DMI1_URL, PARALLEL_SYNC_SAMPLE_SIZE, 1)
}
+ @Ignore
+ /** this test has intermittent failures, due to timeouts.
+ * Ignored but left here as it might be valuable to further optimization investigations.
+ **/
+
def 'CPS-2478 Highlight (and improve) module sync inefficiencies.'() {
given: 'register 250 cm handles with module set tag cps-2478-A'
def numberOfTags = 2
@@ -78,34 +85,32 @@ class ModuleSyncWatchdogIntegrationSpec extends CpsIntegrationSpecBase {
when: 'sync all advised cm handles'
objectUnderTest.moduleSyncAdvisedCmHandles()
Thread.sleep(100)
- then: 'retry until all schema sets are stored in db (1 schema set for each cm handle)'
+ then: 'retry until both schema sets are stored in db (1 schema set for each module set tag)'
def dbSchemaSetStorageTimer = meterRegistry.get('cps.module.persistence.schemaset.store').timer()
new PollingConditions().within(10, () -> {
objectUnderTest.moduleSyncAdvisedCmHandles()
Thread.sleep(100)
- assert dbSchemaSetStorageTimer.count() >= 500
+ assert dbSchemaSetStorageTimer.count() == 2
})
then: 'wait till at least 5 batches of state updates are done (often more because of retries of locked cm handles)'
def dbStateUpdateTimer = meterRegistry.get('cps.ncmp.cmhandle.state.update.batch').timer()
new PollingConditions().within(10, () -> {
assert dbStateUpdateTimer.count() >= minimumBatches
})
- and: 'the db has been queried for tags exactly 2 times.'
- def dbModuleQueriesTimer = meterRegistry.get('cps.module.service.module.reference.query.by.attribute').timer()
- assert dbModuleQueriesTimer.count() == 2
- and: 'exactly 2 calls to DMI to get module references'
+ and: 'one call to DMI per module set tag to get module references (may be more due to parallel processing of batches)'
def dmiModuleRetrievalTimer = meterRegistry.get('cps.ncmp.inventory.module.references.from.dmi').timer()
- assert dmiModuleRetrievalTimer.count() == 2
+ assert dmiModuleRetrievalTimer.count() >= numberOfTags && dmiModuleRetrievalTimer.count() <= minimumBatches
+
and: 'log the relevant instrumentation'
- logInstrumentation(dbModuleQueriesTimer, 'query module references')
logInstrumentation(dmiModuleRetrievalTimer, 'get modules from DMI ')
logInstrumentation(dbSchemaSetStorageTimer, 'store schema sets ')
logInstrumentation(dbStateUpdateTimer, 'batch state updates ')
- cleanup: 'remove all cm handles'
+ cleanup: 'remove all test cm handles'
// To properly measure performance the sample-size should be increased to 20,000 cm handles or higher (10,000 per tag)
def stopWatch = new StopWatch()
stopWatch.start()
deregisterSequenceOfCmHandles(DMI1_URL, totalCmHandles, 1)
+ cpsModuleService.deleteAllUnusedYangModuleData()
stopWatch.stop()
println "*** CPS-2478, Deletion of $totalCmHandles cm handles took ${stopWatch.getTotalTimeMillis()} milliseconds"
}
@@ -122,6 +127,8 @@ class ModuleSyncWatchdogIntegrationSpec extends CpsIntegrationSpecBase {
Thread.sleep(50)
then: 'the queue size is exactly the sample size'
assert moduleSyncWorkQueue.size() == PARALLEL_SYNC_SAMPLE_SIZE
+ cleanup: 'remove all test cm handles'
+ deregisterSequenceOfCmHandles(DMI1_URL, PARALLEL_SYNC_SAMPLE_SIZE, 1)
}
def 'Populate module sync work queue on two parallel threads with a slight difference in start time.'() {
@@ -136,6 +143,8 @@ class ModuleSyncWatchdogIntegrationSpec extends CpsIntegrationSpecBase {
Thread.sleep(50)
then: 'the queue size is exactly the sample size'
assert moduleSyncWorkQueue.size() == PARALLEL_SYNC_SAMPLE_SIZE
+ cleanup: 'remove all test cm handles'
+ deregisterSequenceOfCmHandles(DMI1_URL, PARALLEL_SYNC_SAMPLE_SIZE, 1)
}
def logInstrumentation(timer, description) {
@@ -151,15 +160,6 @@ class ModuleSyncWatchdogIntegrationSpec extends CpsIntegrationSpecBase {
}
}
- def populateQueueWithoutDelayCallable = () -> {
- try {
- objectUnderTest.populateWorkQueueIfNeeded()
- return 'task acquired the lock first'
- } catch (InterruptedException e) {
- e.printStackTrace()
- }
- }
-
def populateQueueWithDelay = () -> {
try {
Thread.sleep(10)
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/YangModulesSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/YangModulesSpec.groovy
index 4492e3d183..e01af55c35 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/YangModulesSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/YangModulesSpec.groovy
@@ -38,14 +38,16 @@ class YangModulesSpec extends CpsIntegrationSpecBase {
def setup() {
dmiDispatcher1.moduleNamesPerCmHandleId['ch-1'] = ['M1', 'M2']
dmiDispatcher1.moduleNamesPerCmHandleId['ch-2'] = ['M1', 'M3']
+ dmiDispatcher1.moduleNamesPerCmHandleId['ch-3'] = ['M4']
registerCmHandle(DMI1_URL, 'ch-1', NO_MODULE_SET_TAG, 'alt-1')
registerCmHandle(DMI1_URL, 'ch-2', NO_MODULE_SET_TAG, 'alt-2')
+ registerCmHandle(DMI1_URL, 'ch-3', 'my-module-set-tag', 'alt-3')
// Note DMI dispatcher is not configured to return modules for this handle, so module sync will fail
registerCmHandleWithoutWaitForReady(DMI1_URL, 'not-ready-id', NO_MODULE_SET_TAG, NO_ALTERNATE_ID)
}
def cleanup() {
- deregisterCmHandles(DMI1_URL, ['ch-1', 'ch-2', 'not-ready-id'])
+ deregisterCmHandles(DMI1_URL, ['ch-1', 'ch-2', 'ch-3', 'not-ready-id'])
}
def 'Get yang module references returns expected modules with #scenario.'() {
@@ -56,11 +58,12 @@ class YangModulesSpec extends CpsIntegrationSpecBase {
.andExpect(jsonPath('$[*].moduleName', containsInAnyOrder(expectedModuleNames.toArray())))
.andExpect(jsonPath('$[*].revision', everyItem(equalTo('2024-01-01'))))
where: 'following scenarios are applied'
- scenario | cmHandleReference || expectedModuleNames
- 'cm-handle id' | 'ch-1' || ['M1', 'M2']
- 'alternate id' | 'alt-2' || ['M1', 'M3']
- 'not ready CM handle' | 'not-ready-id' || []
- 'non-existing CM handle' | 'non-existing' || []
+ scenario | cmHandleReference || expectedModuleNames
+ 'cm-handle id' | 'ch-1' || ['M1', 'M2']
+ 'alternate id' | 'alt-2' || ['M1', 'M3']
+ 'CM handle with module set tag' | 'ch-3' || ['M4']
+ 'not ready CM handle' | 'not-ready-id' || []
+ 'non-existing CM handle' | 'non-existing' || []
}
def 'Get yang module definitions returns expected modules with #scenario.'() {
@@ -72,11 +75,12 @@ class YangModulesSpec extends CpsIntegrationSpecBase {
.andExpect(jsonPath('$[*].revision', everyItem(equalTo('2024-01-01'))))
.andExpect(jsonPath('$[*].content', not(is(emptyString()))))
where: 'following scenarios are applied'
- scenario | cmHandleReference || expectedModuleNames
- 'cm-handle id' | 'ch-1' || ['M1', 'M2']
- 'alternate id' | 'alt-2' || ['M1', 'M3']
- 'not ready CM handle' | 'not-ready-id' || []
- 'non-existing CM handle' | 'non-existing' || []
+ scenario | cmHandleReference || expectedModuleNames
+ 'cm-handle id' | 'ch-1' || ['M1', 'M2']
+ 'alternate id' | 'alt-2' || ['M1', 'M3']
+ 'CM handle with module set tag' | 'ch-3' || ['M4']
+ 'not ready CM handle' | 'not-ready-id' || []
+ 'non-existing CM handle' | 'non-existing' || []
}
def 'Get yang module definition for specific module with #scenario.'() {
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/ModuleQueryPerfTest.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/ModuleQueryPerfTest.groovy
index b239a78d71..613f760b0c 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/ModuleQueryPerfTest.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/ModuleQueryPerfTest.groovy
@@ -100,7 +100,7 @@ class ModuleQueryPerfTest extends CpsPerfTestBase {
cpsModuleService.deleteSchemaSetsWithCascade(CPS_PERFORMANCE_TEST_DATASPACE, (i..i+100).collect {SCHEMA_SET_PREFIX + it})
}
cpsModuleService.deleteSchemaSetsWithCascade(CPS_PERFORMANCE_TEST_DATASPACE, [SCHEMA_SET_PREFIX + '0'])
- cpsModuleService.deleteUnusedYangResourceModules()
+ cpsModuleService.deleteAllUnusedYangModuleData()
}
// This makes a Yang module of approximately target length in bytes by padding the description field with many '*'