diff options
Diffstat (limited to 'cps-ncmp-service/src')
88 files changed, 1384 insertions, 932 deletions
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NcmpEventResponseCode.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NcmpResponseStatus.java index 3b11249838..b9c834c559 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NcmpEventResponseCode.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NcmpResponseStatus.java @@ -23,7 +23,7 @@ package org.onap.cps.ncmp.api; import lombok.Getter; @Getter -public enum NcmpEventResponseCode { +public enum NcmpResponseStatus { SUCCESS("0", "Successfully applied changes"), SUCCESSFULLY_APPLIED_SUBSCRIPTION("1", "successfully applied subscription"), @@ -33,13 +33,16 @@ public enum NcmpEventResponseCode { UNABLE_TO_READ_RESOURCE_DATA("103", "dmi plugin service is not able to read resource data"), PARTIALLY_APPLIED_SUBSCRIPTION("104", "partially applied subscription"), SUBSCRIPTION_NOT_APPLICABLE("105", "subscription not applicable for all cm handles"), - SUBSCRIPTION_PENDING("106", "subscription pending for all cm handles"); + SUBSCRIPTION_PENDING("106", "subscription pending for all cm handles"), + UNKNOWN_ERROR("108", "Unknown error"), + CM_HANDLE_ALREADY_EXIST("109", "cm-handle already exists"), + CM_HANDLE_INVALID_ID("110", "cm-handle has an invalid character(s) in id"); - private final String statusCode; - private final String statusMessage; + private final String code; + private final String message; - NcmpEventResponseCode(final String statusCode, final String statusMessage) { - this.statusCode = statusCode; - this.statusMessage = statusMessage; + NcmpResponseStatus(final String code, final String message) { + this.code = code; + this.message = message; } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java index a65e3c4be1..e7ffaa624f 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java @@ -25,8 +25,8 @@ package org.onap.cps.ncmp.api; import java.util.Collection; import java.util.Map; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState; import org.onap.cps.ncmp.api.impl.operations.OperationType; -import org.onap.cps.ncmp.api.inventory.CompositeState; import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters; import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters; import org.onap.cps.ncmp.api.models.DataOperationRequest; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java index 1d390f8d16..7475cdd4a3 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java @@ -20,6 +20,7 @@ package org.onap.cps.ncmp.api.impl; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.HAS_ALL_MODULES; import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.HAS_ALL_PROPERTIES; import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.WITH_CPS_PATH; @@ -41,12 +42,12 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.cpspath.parser.PathParsingException; import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; +import org.onap.cps.ncmp.api.impl.inventory.enums.PropertyType; import org.onap.cps.ncmp.api.impl.utils.InventoryQueryConditions; import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CmHandleQueries; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; -import org.onap.cps.ncmp.api.inventory.enums.PropertyType; import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.onap.cps.spi.exceptions.DataValidationException; @@ -156,7 +157,8 @@ public class NetworkCmProxyCmHandleQueryServiceImpl implements NetworkCmProxyCmH } try { cpsPathQueryResult = collectCmHandleIdsFromDataNodes( - cmHandleQueries.queryCmHandleDataNodesByCpsPath(cpsPathCondition.get("cpsPath"), OMIT_DESCENDANTS)); + cmHandleQueries.queryCmHandleAncestorsByCpsPath( + cpsPathCondition.get("cpsPath"), OMIT_DESCENDANTS)); } catch (final PathParsingException pathParsingException) { throw new DataValidationException(pathParsingException.getMessage(), pathParsingException.getDetails(), pathParsingException); @@ -198,12 +200,12 @@ public class NetworkCmProxyCmHandleQueryServiceImpl implements NetworkCmProxyCmH } private Collection<NcmpServiceCmHandle> getAllCmHandles() { - final DataNode dataNode = inventoryPersistence.getDataNode("/dmi-registry").iterator().next(); + final DataNode dataNode = inventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT).iterator().next(); return dataNode.getChildDataNodes().stream().map(this::createNcmpServiceCmHandle).collect(Collectors.toSet()); } private Collection<String> getAllCmHandleIds() { - final DataNode dataNode = inventoryPersistence.getDataNode("/dmi-registry", DIRECT_CHILDREN_ONLY) + final DataNode dataNode = inventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT, DIRECT_CHILDREN_ONLY) .iterator().next(); return collectCmHandleIdsFromDataNodes(dataNode.getChildDataNodes()); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java index ea2f72fef7..692a9f2a94 100755 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java @@ -24,11 +24,18 @@ package org.onap.cps.ncmp.api.impl; -import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_READY; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_ALREADY_EXIST; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID; +import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.MODULE_UPGRADE; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateCmHandleQueryParameters; import com.google.common.collect.Lists; import com.hazelcast.map.IMap; +import java.text.MessageFormat; import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.Collection; @@ -44,26 +51,28 @@ import org.onap.cps.api.CpsDataService; import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService; import org.onap.cps.ncmp.api.NetworkCmProxyDataService; import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState; +import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder; +import org.onap.cps.ncmp.api.impl.inventory.CompositeStateUtils; +import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations; import org.onap.cps.ncmp.api.impl.operations.OperationType; +import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel; import org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions; import org.onap.cps.ncmp.api.impl.utils.InventoryQueryConditions; import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CmHandleQueries; -import org.onap.cps.ncmp.api.inventory.CmHandleState; -import org.onap.cps.ncmp.api.inventory.CompositeState; -import org.onap.cps.ncmp.api.inventory.CompositeStateUtils; -import org.onap.cps.ncmp.api.inventory.DataStoreSyncState; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters; import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters; import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse; -import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError; import org.onap.cps.ncmp.api.models.DataOperationRequest; import org.onap.cps.ncmp.api.models.DmiPluginRegistration; import org.onap.cps.ncmp.api.models.DmiPluginRegistrationResponse; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; +import org.onap.cps.ncmp.api.models.UpgradedCmHandles; import org.onap.cps.spi.FetchDescendantsOption; import org.onap.cps.spi.exceptions.AlreadyDefinedException; import org.onap.cps.spi.exceptions.CpsException; @@ -90,6 +99,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService private final LcmEventsCmHandleStateHandler lcmEventsCmHandleStateHandler; private final CpsDataService cpsDataService; private final IMap<String, Object> moduleSyncStartedOnCmHandles; + private final IMap<String, TrustLevel> trustLevelPerDmiPlugin; @Override public DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule( @@ -99,18 +109,26 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService if (!dmiPluginRegistration.getRemovedCmHandles().isEmpty()) { dmiPluginRegistrationResponse.setRemovedCmHandles( - parseAndRemoveCmHandlesInDmiRegistration(dmiPluginRegistration.getRemovedCmHandles())); + parseAndProcessDeletedCmHandlesInRegistration(dmiPluginRegistration.getRemovedCmHandles())); } if (!dmiPluginRegistration.getCreatedCmHandles().isEmpty()) { dmiPluginRegistrationResponse.setCreatedCmHandles( - parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(dmiPluginRegistration)); + parseAndProcessCreatedCmHandlesInRegistration(dmiPluginRegistration)); } if (!dmiPluginRegistration.getUpdatedCmHandles().isEmpty()) { dmiPluginRegistrationResponse.setUpdatedCmHandles( networkCmProxyDataServicePropertyHandler .updateCmHandleProperties(dmiPluginRegistration.getUpdatedCmHandles())); } + if (dmiPluginRegistration.getUpgradedCmHandles() != null + && !dmiPluginRegistration.getUpgradedCmHandles().getCmHandles().isEmpty()) { + dmiPluginRegistrationResponse.setUpgradedCmHandles( + parseAndProcessUpgradedCmHandlesInRegistration(dmiPluginRegistration)); + } + + setTrustLevelPerDmiPlugin(dmiPluginRegistration); + return dmiPluginRegistrationResponse; } @@ -204,8 +222,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService */ @Override public void setDataSyncEnabled(final String cmHandleId, final boolean dataSyncEnabled) { - final CompositeState compositeState = inventoryPersistence - .getCmHandleState(cmHandleId); + final CompositeState compositeState = inventoryPersistence.getCmHandleState(cmHandleId); if (compositeState.getDataSyncEnabled().equals(dataSyncEnabled)) { log.info("Data-Sync Enabled flag is already: {} ", dataSyncEnabled); } else if (compositeState.getCmHandleState() != CmHandleState.READY) { @@ -268,8 +285,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService */ @Override public Map<String, String> getCmHandlePublicProperties(final String cmHandleId) { - final YangModelCmHandle yangModelCmHandle = - inventoryPersistence.getYangModelCmHandle(cmHandleId); + final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId); final List<YangModelCmHandle.Property> yangModelPublicProperties = yangModelCmHandle.getPublicProperties(); final Map<String, String> cmHandlePublicProperties = new HashMap<>(); YangDataConverter.asPropertiesMap(yangModelPublicProperties, cmHandlePublicProperties); @@ -293,7 +309,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService * @param dmiPluginRegistration dmi plugin registration information. * @return cm-handle registration response for create cm-handle requests. */ - public List<CmHandleRegistrationResponse> parseAndCreateCmHandlesInDmiRegistrationAndSyncModules( + public List<CmHandleRegistrationResponse> parseAndProcessCreatedCmHandlesInRegistration( final DmiPluginRegistration dmiPluginRegistration) { final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle = new HashMap<>(); dmiPluginRegistration.getCreatedCmHandles() @@ -302,18 +318,19 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService dmiPluginRegistration.getDmiPlugin(), dmiPluginRegistration.getDmiDataPlugin(), dmiPluginRegistration.getDmiModelPlugin(), - cmHandle); + cmHandle, + cmHandle.getModuleSetTag()); cmHandleStatePerCmHandle.put(yangModelCmHandle, CmHandleState.ADVISED); }); return registerNewCmHandles(cmHandleStatePerCmHandle); } - protected List<CmHandleRegistrationResponse> parseAndRemoveCmHandlesInDmiRegistration( + protected List<CmHandleRegistrationResponse> parseAndProcessDeletedCmHandlesInRegistration( final List<String> tobeRemovedCmHandles) { final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses = new ArrayList<>(tobeRemovedCmHandles.size()); final Collection<YangModelCmHandle> yangModelCmHandles = - inventoryPersistence.getYangModelCmHandles(tobeRemovedCmHandles); + inventoryPersistence.getYangModelCmHandles(tobeRemovedCmHandles); updateCmHandleStateBatch(yangModelCmHandles, CmHandleState.DELETING); @@ -343,6 +360,42 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService return cmHandleRegistrationResponses; } + protected List<CmHandleRegistrationResponse> parseAndProcessUpgradedCmHandlesInRegistration( + final DmiPluginRegistration dmiPluginRegistration) { + + final UpgradedCmHandles upgradedCmHandles = dmiPluginRegistration.getUpgradedCmHandles(); + final String moduleSetTag = dmiPluginRegistration.getUpgradedCmHandles().getModuleSetTag(); + final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle = + new HashMap<>(upgradedCmHandles.getCmHandles().size()); + final Collection<String> notReadyCmHandles = new ArrayList<>(upgradedCmHandles.getCmHandles().size()); + final NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle(); + final String formattedModuleSetTag = MessageFormat.format("new moduleSetTag: {0}", moduleSetTag); + + upgradedCmHandles.getCmHandles().forEach(cmHandleId -> { + if (cmHandleQueries.cmHandleHasState(cmHandleId, CmHandleState.READY)) { + ncmpServiceCmHandle.setCmHandleId(cmHandleId); + ncmpServiceCmHandle.setCompositeState(new CompositeStateBuilder() + .withCmHandleState(CmHandleState.READY) + .withLockReason(MODULE_UPGRADE, formattedModuleSetTag).build()); + final YangModelCmHandle yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle( + dmiPluginRegistration.getDmiPlugin(), + dmiPluginRegistration.getDmiDataPlugin(), + dmiPluginRegistration.getDmiModelPlugin(), + ncmpServiceCmHandle, + moduleSetTag); + cmHandleStatePerCmHandle.put(yangModelCmHandle, CmHandleState.LOCKED); + } else { + notReadyCmHandles.add(cmHandleId); + } + }); + + final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses + = upgradeCmHandles(cmHandleStatePerCmHandle); + cmHandleRegistrationResponses.addAll(CmHandleRegistrationResponse.createFailureResponses(notReadyCmHandles, + CM_HANDLES_NOT_READY)); + return cmHandleRegistrationResponses; + } + private CmHandleRegistrationResponse deleteCmHandleAndGetCmHandleRegistrationResponse(final String cmHandleId) { try { deleteCmHandleFromDbAndModuleSyncMap(cmHandleId); @@ -350,13 +403,11 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService } catch (final DataNodeNotFoundException dataNodeNotFoundException) { log.error("Unable to find dataNode for cmHandleId : {} , caused by : {}", cmHandleId, dataNodeNotFoundException.getMessage()); - return CmHandleRegistrationResponse.createFailureResponse(cmHandleId, - RegistrationError.CM_HANDLE_DOES_NOT_EXIST); + return CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLES_NOT_FOUND); } catch (final DataValidationException dataValidationException) { log.error("Unable to de-register cm-handle id: {}, caused by: {}", cmHandleId, dataValidationException.getMessage()); - return CmHandleRegistrationResponse.createFailureResponse(cmHandleId, - RegistrationError.CM_HANDLE_INVALID_ID); + return CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLE_INVALID_ID); } catch (final Exception exception) { log.error("Unable to de-register cm-handle id : {} , caused by : {}", cmHandleId, exception.getMessage()); return CmHandleRegistrationResponse.createFailureResponse(cmHandleId, exception); @@ -372,7 +423,8 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService private void deleteCmHandleFromDbAndModuleSyncMap(final String cmHandleId) { inventoryPersistence.deleteSchemaSetWithCascade(cmHandleId); - inventoryPersistence.deleteDataNode("/dmi-registry/cm-handles[@id='" + cmHandleId + "']"); + inventoryPersistence.deleteDataNode(NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + + "']"); removeDeletedCmHandleFromModuleSyncMap(cmHandleId); } @@ -384,8 +436,8 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService private Collection<String> mapCmHandleIdsToXpaths(final Collection<String> cmHandles) { return cmHandles.stream() - .map(cmHandleId -> "/dmi-registry/cm-handles[@id='" + cmHandleId + "']") - .collect(Collectors.toSet()); + .map(cmHandleId -> NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']") + .collect(Collectors.toSet()); } // CPS-1239 Robustness cleaning of in progress cache @@ -397,18 +449,41 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService private List<CmHandleRegistrationResponse> registerNewCmHandles(final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle) { - final List<String> cmHandleIds = cmHandleStatePerCmHandle.keySet().stream().map(YangModelCmHandle::getId) - .collect(Collectors.toList()); + final List<String> cmHandleIds = getCmHandleIds(cmHandleStatePerCmHandle); try { lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle); return CmHandleRegistrationResponse.createSuccessResponses(cmHandleIds); } catch (final AlreadyDefinedException alreadyDefinedException) { return CmHandleRegistrationResponse.createFailureResponses( alreadyDefinedException.getAlreadyDefinedObjectNames(), - RegistrationError.CM_HANDLE_ALREADY_EXIST); + CM_HANDLE_ALREADY_EXIST); + } catch (final Exception exception) { + return CmHandleRegistrationResponse.createFailureResponses(cmHandleIds, exception); + } + } + + private List<CmHandleRegistrationResponse> upgradeCmHandles(final Map<YangModelCmHandle, CmHandleState> + cmHandleStatePerCmHandle) { + final List<String> cmHandleIds = getCmHandleIds(cmHandleStatePerCmHandle); + log.info("Moving cm handles : {} into locked (for upgrade) state.", cmHandleIds); + try { + lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle); + return CmHandleRegistrationResponse.createSuccessResponses(cmHandleIds); } catch (final Exception exception) { return CmHandleRegistrationResponse.createFailureResponses(cmHandleIds, exception); } } + private static List<String> getCmHandleIds(final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle) { + return cmHandleStatePerCmHandle.keySet().stream().map(YangModelCmHandle::getId).toList(); + } + + private void setTrustLevelPerDmiPlugin(final DmiPluginRegistration dmiPluginRegistration) { + if (DmiPluginRegistration.isNullEmptyOrBlank(dmiPluginRegistration.getDmiDataPlugin())) { + trustLevelPerDmiPlugin.put(dmiPluginRegistration.getDmiPlugin(), TrustLevel.COMPLETE); + } else { + trustLevelPerDmiPlugin.put(dmiPluginRegistration.getDmiDataPlugin(), TrustLevel.COMPLETE); + } + } + } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java index bbb2c0f56f..401b190360 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * Modifications Copyright (C) 2023 TechMahindra Ltd. * ================================================================================ @@ -22,6 +22,8 @@ package org.onap.cps.ncmp.api.impl; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID; import static org.onap.cps.ncmp.api.impl.NetworkCmProxyDataServicePropertyHandler.PropertyType.DMI_PROPERTY; import static org.onap.cps.ncmp.api.impl.NetworkCmProxyDataServicePropertyHandler.PropertyType.PUBLIC_PROPERTY; @@ -36,9 +38,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse; -import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.onap.cps.spi.exceptions.DataNodeNotFoundException; import org.onap.cps.spi.exceptions.DataValidationException; @@ -75,13 +76,12 @@ public class NetworkCmProxyDataServicePropertyHandler { log.error("Unable to find dataNode for cmHandleId : {} , caused by : {}", cmHandleId, e.getMessage()); cmHandleRegistrationResponses.add(CmHandleRegistrationResponse - .createFailureResponse(cmHandleId, RegistrationError.CM_HANDLE_DOES_NOT_EXIST)); + .createFailureResponse(cmHandleId, CM_HANDLES_NOT_FOUND)); } catch (final DataValidationException e) { log.error("Unable to update cm handle : {}, caused by : {}", cmHandleId, e.getMessage()); cmHandleRegistrationResponses.add( - CmHandleRegistrationResponse.createFailureResponse(cmHandleId, - RegistrationError.CM_HANDLE_INVALID_ID)); + CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLE_INVALID_ID)); } catch (final Exception exception) { log.error("Unable to update cmHandle : {} , caused by : {}", cmHandleId, exception.getMessage()); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java index 5540ecd213..d8353f3029 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ package org.onap.cps.ncmp.api.impl; -import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfig.java index 62a380ca5c..8b28717db4 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfig.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfig.java @@ -23,6 +23,7 @@ package org.onap.cps.ncmp.api.impl.config.embeddedcache; import com.hazelcast.config.MapConfig; import com.hazelcast.config.QueueConfig; import com.hazelcast.map.IMap; +import java.util.Set; import java.util.concurrent.BlockingQueue; import lombok.extern.slf4j.Slf4j; import org.onap.cps.cache.HazelcastCacheConfig; @@ -44,6 +45,8 @@ public class SynchronizationCacheConfig extends HazelcastCacheConfig { private static final MapConfig moduleSyncStartedConfig = createMapConfig("moduleSyncStartedConfig"); private static final MapConfig dataSyncSemaphoresConfig = createMapConfig("dataSyncSemaphoresConfig"); + private static final MapConfig moduleSetTagCacheMapConfig = createMapConfig("moduleSetTagCacheMapConfig"); + /** * Module Sync Distributed Queue Instance. * @@ -74,4 +77,15 @@ public class SynchronizationCacheConfig extends HazelcastCacheConfig { public IMap<String, Boolean> dataSyncSemaphores() { return createHazelcastInstance("dataSyncSemaphores", dataSyncSemaphoresConfig).getMap("dataSyncSemaphores"); } + + /** + * IMap instance for cached ModulesSetTags. + * + * @return configured map of ModuleSetTags + */ + @Bean + public IMap<String, Set<String>> moduleSetTagCache() { + return createHazelcastInstance("moduleSetTags", moduleSetTagCacheMapConfig) + .getMap("moduleSetTagCache"); + } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/constants/DmiRegistryConstants.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/constants/DmiRegistryConstants.java deleted file mode 100644 index a133cfb80d..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/constants/DmiRegistryConstants.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.constants; - -import java.time.OffsetDateTime; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -/** - * DmiRegistryConstants class to be strictly used for DMI Related constants only. - */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public final class DmiRegistryConstants { - - public static final String NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME = "NFP-Operational"; - - public static final OffsetDateTime NO_TIMESTAMP = null; -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/EventsPublisher.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/EventsPublisher.java index 58d0d2d48f..355e5cdf79 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/EventsPublisher.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/EventsPublisher.java @@ -64,8 +64,8 @@ public class EventsPublisher<T> { cloudEventKafkaTemplate.send(topicName, eventKey, event); eventFuture.whenComplete((result, e) -> { if (e == null) { - log.debug("Successfully published event to topic : {} , Event : {}", - result.getRecordMetadata().topic(), result.getProducerRecord().value()); + log.debug("Successfully published event to topic : {} , Event : {}", result.getRecordMetadata().topic(), + result.getProducerRecord().value()); } else { log.error("Unable to publish event to topic : {} due to {}", topicName, e.getMessage()); @@ -85,14 +85,7 @@ public class EventsPublisher<T> { public void publishEvent(final String topicName, final String eventKey, final T event) { final CompletableFuture<SendResult<String, T>> eventFuture = legacyKafkaEventTemplate.send(topicName, eventKey, event); - eventFuture.whenComplete((result, e) -> { - if (e == null) { - log.debug("Successfully published event to topic : {} , Event : {}", - result.getRecordMetadata().topic(), result.getProducerRecord().value()); - } else { - log.error("Unable to publish event to topic : {} due to {}", topicName, e.getMessage()); - } - }); + handleLegacyEventCallback(topicName, eventFuture); } /** @@ -107,16 +100,8 @@ public class EventsPublisher<T> { final ProducerRecord<String, T> producerRecord = new ProducerRecord<>(topicName, null, eventKey, event, eventHeaders); - final CompletableFuture<SendResult<String, T>> eventFuture = - legacyKafkaEventTemplate.send(producerRecord); - eventFuture.whenComplete((result, ex) -> { - if (ex != null) { - log.error("Unable to publish event to topic : {} due to {}", topicName, ex.getMessage()); - } else { - log.debug("Successfully published event to topic : {} , Event : {}", - result.getRecordMetadata().topic(), result.getProducerRecord().value()); - } - }); + final CompletableFuture<SendResult<String, T>> eventFuture = legacyKafkaEventTemplate.send(producerRecord); + handleLegacyEventCallback(topicName, eventFuture); } /** @@ -133,6 +118,17 @@ public class EventsPublisher<T> { publishEvent(topicName, eventKey, convertToKafkaHeaders(eventHeaders), event); } + private void handleLegacyEventCallback(final String topicName, + final CompletableFuture<SendResult<String, T>> eventFuture) { + eventFuture.whenComplete((result, e) -> { + if (e != null) { + log.error("Unable to publish event to topic : {} due to {}", topicName, e.getMessage()); + } else { + log.debug("Successfully published event to topic : {} , Event : {}", result.getRecordMetadata().topic(), + result.getProducerRecord().value()); + } + }); + } private Headers convertToKafkaHeaders(final Map<String, Object> eventMessageHeaders) { final Headers eventHeaders = new RecordHeaders(); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpInEventForwarder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpInEventForwarder.java index ea2d17d3a7..5f26db335b 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpInEventForwarder.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpInEventForwarder.java @@ -36,13 +36,13 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.impl.config.embeddedcache.ForwardedSubscriptionEventCacheConfig; import org.onap.cps.ncmp.api.impl.events.EventsPublisher; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionPersistence; import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionStatus; import org.onap.cps.ncmp.api.impl.utils.CmSubscriptionEventCloudMapper; import org.onap.cps.ncmp.api.impl.utils.DmiServiceNameOrganizer; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelSubscriptionEvent; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.models.CmSubscriptionEvent; import org.onap.cps.ncmp.events.cmsubscription1_0_0.client_to_ncmp.CmSubscriptionNcmpInEvent; import org.onap.cps.ncmp.events.cmsubscription1_0_0.ncmp_to_dmi.CmHandle; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisher.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisher.java index 473538c93e..a0fd81c12a 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisher.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisher.java @@ -20,13 +20,20 @@ package org.onap.cps.ncmp.api.impl.events.cmsubscription; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.PARTIALLY_APPLIED_SUBSCRIPTION; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.SUBSCRIPTION_NOT_APPLICABLE; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.SUBSCRIPTION_PENDING; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.SUCCESSFULLY_APPLIED_SUBSCRIPTION; +import static org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionStatus.ACCEPTED; +import static org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionStatus.PENDING; +import static org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionStatus.REJECTED; + import io.cloudevents.CloudEvent; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.NcmpEventResponseCode; +import org.onap.cps.ncmp.api.NcmpResponseStatus; import org.onap.cps.ncmp.api.impl.events.EventsPublisher; import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionPersistence; import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionStatus; @@ -100,48 +107,39 @@ public class CmSubscriptionNcmpOutEventPublisher { cmSubscriptionStatus.setStatus(SubscriptionStatus.fromString(status)); cmSubscriptionStatus.setDetails(details); return cmSubscriptionStatus; - }).collect(Collectors.toList()); + }).toList(); } - private NcmpEventResponseCode decideOnNcmpEventResponseCodeForSubscription( + private NcmpResponseStatus decideOnNcmpEventResponseCodeForSubscription( final Map<String, Map<String, String>> cmHandleIdToStatusAndDetailsAsMap) { - final boolean isAllTargetsPending = isAllTargetCmHandleStatusMatch(cmHandleIdToStatusAndDetailsAsMap, - SubscriptionStatus.PENDING); - - final boolean isAllTargetsRejected = isAllTargetCmHandleStatusMatch(cmHandleIdToStatusAndDetailsAsMap, - SubscriptionStatus.REJECTED); - - final boolean isAllTargetsAccepted = isAllTargetCmHandleStatusMatch(cmHandleIdToStatusAndDetailsAsMap, - SubscriptionStatus.ACCEPTED); - - if (isAllTargetsAccepted) { - return NcmpEventResponseCode.SUCCESSFULLY_APPLIED_SUBSCRIPTION; - } else if (isAllTargetsRejected) { - return NcmpEventResponseCode.SUBSCRIPTION_NOT_APPLICABLE; - } else if (isAllTargetsPending) { - return NcmpEventResponseCode.SUBSCRIPTION_PENDING; - } else { - return NcmpEventResponseCode.PARTIALLY_APPLIED_SUBSCRIPTION; + if (allTargetsHaveStatus(cmHandleIdToStatusAndDetailsAsMap, ACCEPTED)) { + return SUCCESSFULLY_APPLIED_SUBSCRIPTION; + } + if (allTargetsHaveStatus(cmHandleIdToStatusAndDetailsAsMap, REJECTED)) { + return SUBSCRIPTION_NOT_APPLICABLE; + } + if (allTargetsHaveStatus(cmHandleIdToStatusAndDetailsAsMap, PENDING)) { + return SUBSCRIPTION_PENDING; } + return PARTIALLY_APPLIED_SUBSCRIPTION; } - private boolean isAllTargetCmHandleStatusMatch( - final Map<String, Map<String, String>> cmHandleIdToStatusAndDetailsAsMap, - final SubscriptionStatus subscriptionStatus) { + private boolean allTargetsHaveStatus(final Map<String, Map<String, String>> cmHandleIdToStatusAndDetailsAsMap, + final SubscriptionStatus subscriptionStatus) { return cmHandleIdToStatusAndDetailsAsMap.values().stream() .allMatch(entryset -> entryset.containsValue(subscriptionStatus.toString())); } private CmSubscriptionNcmpOutEvent fromCmSubscriptionEvent( final CmSubscriptionEvent cmSubscriptionEvent, - final NcmpEventResponseCode ncmpEventResponseCode) { + final NcmpResponseStatus ncmpResponseStatus) { final CmSubscriptionNcmpOutEvent cmSubscriptionNcmpOutEvent = cmSubscriptionEventToCmSubscriptionNcmpOutEventMapper.toCmSubscriptionNcmpOutEvent( cmSubscriptionEvent); - cmSubscriptionNcmpOutEvent.getData().setStatusCode(Integer.parseInt(ncmpEventResponseCode.getStatusCode())); - cmSubscriptionNcmpOutEvent.getData().setStatusMessage(ncmpEventResponseCode.getStatusMessage()); + cmSubscriptionNcmpOutEvent.getData().setStatusCode(Integer.parseInt(ncmpResponseStatus.getCode())); + cmSubscriptionNcmpOutEvent.getData().setStatusMessage(ncmpResponseStatus.getMessage()); return cmSubscriptionNcmpOutEvent; } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java index 2ae118872b..fdee28e337 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java @@ -21,8 +21,8 @@ package org.onap.cps.ncmp.api.impl.events.lcm; import java.util.Map; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CmHandleState; /** * The implementation of it should handle the persisting of composite state and delegate the request to publish the diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java index ce19712c08..02368b8574 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java @@ -20,10 +20,10 @@ package org.onap.cps.ncmp.api.impl.events.lcm; -import static org.onap.cps.ncmp.api.inventory.CmHandleState.ADVISED; -import static org.onap.cps.ncmp.api.inventory.CmHandleState.DELETED; -import static org.onap.cps.ncmp.api.inventory.CmHandleState.LOCKED; -import static org.onap.cps.ncmp.api.inventory.CmHandleState.READY; +import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.ADVISED; +import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.DELETED; +import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.LOCKED; +import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.READY; import io.micrometer.core.annotation.Timed; import java.util.ArrayList; @@ -36,12 +36,12 @@ import lombok.NoArgsConstructor; import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState; +import org.onap.cps.ncmp.api.impl.inventory.CompositeStateUtils; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CmHandleState; -import org.onap.cps.ncmp.api.inventory.CompositeState; -import org.onap.cps.ncmp.api.inventory.CompositeStateUtils; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.springframework.stereotype.Service; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorHelper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorHelper.java index d3b45d4a63..19d9ba5c0d 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorHelper.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorHelper.java @@ -23,7 +23,7 @@ package org.onap.cps.ncmp.api.impl.events.lcm; import static org.onap.cps.ncmp.api.impl.events.lcm.LcmEventType.CREATE; import static org.onap.cps.ncmp.api.impl.events.lcm.LcmEventType.DELETE; import static org.onap.cps.ncmp.api.impl.events.lcm.LcmEventType.UPDATE; -import static org.onap.cps.ncmp.api.inventory.CmHandleState.DELETED; +import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.DELETED; import com.google.common.collect.MapDifference; import com.google.common.collect.Maps; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleQueries.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java index ff78f00229..a5892afc3e 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleQueries.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.api.inventory; +package org.onap.cps.ncmp.api.impl.inventory; import java.util.Collection; import java.util.List; @@ -53,12 +53,21 @@ public interface CmHandleQueries { List<DataNode> queryCmHandlesByState(CmHandleState cmHandleState); /** + * Method to return data nodes with ancestor representing the cm handles. + * + * @param cpsPath cps path for which the cmHandle is requested + * @return a list of data nodes representing the cm handles. + */ + List<DataNode> queryCmHandleAncestorsByCpsPath(String cpsPath, + FetchDescendantsOption fetchDescendantsOption); + + /** * Method to return data nodes representing the cm handles. * * @param cpsPath cps path for which the cmHandle is requested * @return a list of data nodes representing the cm handles. */ - List<DataNode> queryCmHandleDataNodesByCpsPath(String cpsPath, FetchDescendantsOption fetchDescendantsOption); + List<DataNode> queryNcmpRegistryByCpsPath(String cpsPath, FetchDescendantsOption fetchDescendantsOption); /** * Method to check the state of a cm handle with given id. diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java index f61d6c348a..c4e3fd098d 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java @@ -19,8 +19,11 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.api.inventory; +package org.onap.cps.ncmp.api.impl.inventory; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS; import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS; @@ -31,7 +34,7 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; -import org.onap.cps.ncmp.api.inventory.enums.PropertyType; +import org.onap.cps.ncmp.api.impl.inventory.enums.PropertyType; import org.onap.cps.spi.CpsDataPersistenceService; import org.onap.cps.spi.FetchDescendantsOption; import org.onap.cps.spi.model.DataNode; @@ -41,8 +44,6 @@ import org.springframework.stereotype.Component; @Component public class CmHandleQueriesImpl implements CmHandleQueries { - private static final String NCMP_DATASPACE_NAME = "NCMP-Admin"; - private static final String NCMP_DMI_REGISTRY_ANCHOR = "ncmp-dmi-registry"; private static final String DESCENDANT_PATH = "//"; private final CpsDataPersistenceService cpsDataPersistenceService; @@ -60,15 +61,21 @@ public class CmHandleQueriesImpl implements CmHandleQueries { @Override public List<DataNode> queryCmHandlesByState(final CmHandleState cmHandleState) { - return queryCmHandleDataNodesByCpsPath("//state[@cm-handle-state=\"" + cmHandleState + "\"]", + return queryCmHandleAncestorsByCpsPath("//state[@cm-handle-state=\"" + cmHandleState + "\"]", INCLUDE_ALL_DESCENDANTS); } @Override - public List<DataNode> queryCmHandleDataNodesByCpsPath(final String cpsPath, - final FetchDescendantsOption fetchDescendantsOption) { + public List<DataNode> queryNcmpRegistryByCpsPath(final String cpsPath, + final FetchDescendantsOption fetchDescendantsOption) { return cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - cpsPath + ANCESTOR_CM_HANDLES, fetchDescendantsOption); + cpsPath, fetchDescendantsOption); + } + + @Override + public List<DataNode> queryCmHandleAncestorsByCpsPath(final String cpsPath, + final FetchDescendantsOption fetchDescendantsOption) { + return queryNcmpRegistryByCpsPath(cpsPath + ANCESTOR_CM_HANDLES, fetchDescendantsOption); } @Override @@ -80,7 +87,7 @@ public class CmHandleQueriesImpl implements CmHandleQueries { @Override public List<DataNode> queryCmHandlesByOperationalSyncState(final DataStoreSyncState dataStoreSyncState) { - return queryCmHandleDataNodesByCpsPath("//state/datastores" + "/operational[@sync-state=\"" + return queryCmHandleAncestorsByCpsPath("//state/datastores" + "/operational[@sync-state=\"" + dataStoreSyncState + "\"]", FetchDescendantsOption.OMIT_DESCENDANTS); } @@ -113,7 +120,8 @@ public class CmHandleQueriesImpl implements CmHandleQueries { + publicPropertyQueryPair.getKey() + "\" and @value=\"" + publicPropertyQueryPair.getValue() + "\"]"; - final Collection<DataNode> dataNodes = queryCmHandleDataNodesByCpsPath(cpsPath, OMIT_DESCENDANTS); + final Collection<DataNode> dataNodes = queryCmHandleAncestorsByCpsPath(cpsPath, + OMIT_DESCENDANTS); if (cmHandleIds == null) { cmHandleIds = collectCmHandleIdsFromDataNodes(dataNodes); } else { @@ -128,14 +136,14 @@ public class CmHandleQueriesImpl implements CmHandleQueries { } private List<DataNode> getCmHandlesByDmiPluginIdentifierAndDmiProperty(final String dmiPluginIdentifier, - final String dmiProperty) { + final String dmiProperty) { return cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - "/dmi-registry/cm-handles[@" + dmiProperty + "='" + dmiPluginIdentifier + "']", + NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@" + dmiProperty + "='" + dmiPluginIdentifier + "']", OMIT_DESCENDANTS); } private DataNode getCmHandleState(final String cmHandleId) { - final String xpath = "/dmi-registry/cm-handles[@id='" + cmHandleId + "']/state"; + final String xpath = NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']/state"; return cpsDataPersistenceService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, xpath, OMIT_DESCENDANTS).iterator().next(); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleState.java index 7628c81dda..5485ee7e80 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleState.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleState.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.api.inventory; +package org.onap.cps.ncmp.api.impl.inventory; public enum CmHandleState { ADVISED, READY, LOCKED, DELETING, DELETED diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeState.java index bf448c568f..5b88f560eb 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeState.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeState.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.api.inventory; +package org.onap.cps.ncmp.api.impl.inventory; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateBuilder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateBuilder.java index d6a33302d9..2fbe2b2f78 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateBuilder.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateBuilder.java @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2022 Bell Canada - * Modifications Copyright (C) 2022 Nordix Foundation. + * Modifications Copyright (C) 2022-2023 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,11 +19,11 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.api.inventory; +package org.onap.cps.ncmp.api.impl.inventory; -import org.onap.cps.ncmp.api.inventory.CompositeState.DataStores; -import org.onap.cps.ncmp.api.inventory.CompositeState.LockReason; -import org.onap.cps.ncmp.api.inventory.CompositeState.Operational; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState.DataStores; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState.LockReason; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState.Operational; import org.onap.cps.spi.model.DataNode; public class CompositeStateBuilder { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateUtils.java index cff1000fe9..99cca8c0b3 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateUtils.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateUtils.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.api.inventory; +package org.onap.cps.ncmp.api.impl.inventory; import java.util.function.Consumer; import lombok.AccessLevel; @@ -100,7 +100,9 @@ public class CompositeStateUtils { compositeState.setLastUpdateTimeNow(); final String oldLockReasonDetails = compositeState.getLockReason().getDetails(); final CompositeState.LockReason lockReason = - CompositeState.LockReason.builder().details(oldLockReasonDetails).build(); + CompositeState.LockReason.builder() + .lockReasonCategory(compositeState.getLockReason().getLockReasonCategory()) + .details(oldLockReasonDetails).build(); compositeState.setLockReason(lockReason); }; } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/DataStoreSyncState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/DataStoreSyncState.java index 4dbedf5f1c..b92d152bfa 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/DataStoreSyncState.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/DataStoreSyncState.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.api.inventory; +package org.onap.cps.ncmp.api.impl.inventory; public enum DataStoreSyncState { SYNCHRONIZED, UNSYNCHRONIZED, NONE_REQUESTED diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistence.java index cbd30a8fef..09de9a7bf3 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistence.java @@ -19,17 +19,17 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.api.inventory; +package org.onap.cps.ncmp.api.impl.inventory; import java.util.Collection; import java.util.Map; +import org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.spi.FetchDescendantsOption; import org.onap.cps.spi.model.DataNode; import org.onap.cps.spi.model.ModuleDefinition; import org.onap.cps.spi.model.ModuleReference; -public interface InventoryPersistence { +public interface InventoryPersistence extends NcmpPersistence { /** * Get the Cm Handle Composite State from the data node. @@ -101,61 +101,6 @@ public interface InventoryPersistence { void saveCmHandleBatch(Collection<YangModelCmHandle> yangModelCmHandles); /** - * Method to delete a list or a list element. - * - * @param listElementXpath list element xPath - */ - 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 - * @return data node - */ - Collection<DataNode> getDataNode(String xpath); - - /** - * Get data node via xpath. - * - * @param xpath xpath - * @param fetchDescendantsOption fetch descendants option - * @return data node - */ - Collection<DataNode> getDataNode(String xpath, FetchDescendantsOption fetchDescendantsOption); - - /** - * Get collection of data nodes via xpaths. - * - * @param xpaths collection of xpaths - * @return collection of data nodes - */ - Collection<DataNode> getDataNodes(Collection<String> xpaths); - - /** - * Get collection of data nodes via xpaths. - * - * @param xpaths collection of xpaths - * @param fetchDescendantsOption fetch descendants option - * @return collection of data nodes - */ - Collection<DataNode> getDataNodes(Collection<String> xpaths, FetchDescendantsOption fetchDescendantsOption); - - /** * Get data node of given cm handle. * * @param cmHandleId cmHandle ID @@ -178,26 +123,4 @@ public interface InventoryPersistence { * @return Collection of CM handle Ids */ Collection<String> getCmHandleIdsWithGivenModules(Collection<String> moduleNamesForQuery); - - /** - * Replaces list content by removing all existing elements and inserting the given new elements as data nodes. - * - * @param parentNodeXpath parent node xpath - * @param dataNodes datanodes representing the updated data - */ - void replaceListContent(String parentNodeXpath, Collection<DataNode> dataNodes); - - /** - * Deletes data node. - * - * @param dataNodeXpath data node xpath - */ - void deleteDataNode(String dataNodeXpath); - - /** - * Deletes multiple data nodes. - * - * @param dataNodeXpaths data node xpaths - */ - void deleteDataNodes(Collection<String> dataNodeXpaths); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImpl.java index 7908e629cb..159d8f345a 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImpl.java @@ -20,21 +20,14 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.api.inventory; +package org.onap.cps.ncmp.api.impl.inventory; -import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; -import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NO_TIMESTAMP; -import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED; -import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS; - -import io.micrometer.core.annotation.Timed; import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.CpsAdminService; import org.onap.cps.api.CpsDataService; @@ -43,7 +36,6 @@ import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; import org.onap.cps.spi.FetchDescendantsOption; import org.onap.cps.spi.exceptions.DataValidationException; -import org.onap.cps.spi.exceptions.SchemaSetNotFoundException; import org.onap.cps.spi.model.DataNode; import org.onap.cps.spi.model.ModuleDefinition; import org.onap.cps.spi.model.ModuleReference; @@ -52,31 +44,37 @@ import org.onap.cps.utils.JsonObjectMapper; import org.springframework.stereotype.Component; @Slf4j -@RequiredArgsConstructor @Component -public class InventoryPersistenceImpl implements InventoryPersistence { - - private static final String NCMP_DATASPACE_NAME = "NCMP-Admin"; - - private static final String NCMP_DMI_REGISTRY_ANCHOR = "ncmp-dmi-registry"; - - private static final String NCMP_DMI_REGISTRY_PARENT = "/dmi-registry"; - - private final JsonObjectMapper jsonObjectMapper; - - private final CpsDataService cpsDataService; +public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements InventoryPersistence { private final CpsModuleService cpsModuleService; - private final CpsAdminService cpsAdminService; - private final CpsValidator cpsValidator; + /** + * 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 cpsAdminService cps admin service instance + */ + public InventoryPersistenceImpl(final JsonObjectMapper jsonObjectMapper, final CpsDataService cpsDataService, + final CpsModuleService cpsModuleService, final CpsValidator cpsValidator, + final CpsAdminService cpsAdminService) { + super(jsonObjectMapper, cpsDataService, cpsModuleService, cpsValidator); + this.cpsModuleService = cpsModuleService; + this.cpsAdminService = cpsAdminService; + this.cpsValidator = cpsValidator; + } + + @Override public CompositeState getCmHandleState(final String cmHandleId) { final DataNode stateAsDataNode = cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - createCmHandleXPath(cmHandleId) + "/state", - FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS).iterator().next(); + createCmHandleXPath(cmHandleId) + "/state", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) + .iterator().next(); cpsValidator.validateNameCharacters(cmHandleId); return new CompositeStateBuilder().fromDataNode(stateAsDataNode).build(); } @@ -85,8 +83,7 @@ public class InventoryPersistenceImpl implements InventoryPersistence { public void saveCmHandleState(final String cmHandleId, final CompositeState compositeState) { final String cmHandleJsonData = createStateJsonData(jsonObjectMapper.asJsonString(compositeState)); cpsDataService.updateDataNodeAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - createCmHandleXPath(cmHandleId), - cmHandleJsonData, OffsetDateTime.now()); + createCmHandleXPath(cmHandleId), cmHandleJsonData, OffsetDateTime.now()); } @Override @@ -150,60 +147,6 @@ public class InventoryPersistenceImpl implements InventoryPersistence { } @Override - public void deleteListOrListElement(final String listElementXpath) { - cpsDataService.deleteListOrListElement(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - listElementXpath, NO_TIMESTAMP); - } - - @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) { - return getDataNode(xpath, INCLUDE_ALL_DESCENDANTS); - } - - @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, final FetchDescendantsOption fetchDescendantsOption) { - return cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - xpath, fetchDescendantsOption); - } - - @Override - public Collection<DataNode> getDataNodes(final Collection<String> xpaths) { - return getDataNodes(xpaths, INCLUDE_ALL_DESCENDANTS); - } - - @Override - public Collection<DataNode> getDataNodes(final Collection<String> xpaths, - final FetchDescendantsOption fetchDescendantsOption) { - return cpsDataService.getDataNodesForMultipleXpaths(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - xpaths, fetchDescendantsOption); - } - - @Override public Collection<DataNode> getCmHandleDataNode(final String cmHandleId) { return this.getDataNode(createCmHandleXPath(cmHandleId)); } @@ -220,24 +163,8 @@ public class InventoryPersistenceImpl implements InventoryPersistence { return cpsAdminService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, moduleNamesForQuery); } - @Override - public void replaceListContent(final String parentNodeXpath, final Collection<DataNode> dataNodes) { - cpsDataService.replaceListContent(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - parentNodeXpath, dataNodes, NO_TIMESTAMP); - } - - @Override - public void deleteDataNode(final String dataNodeXpath) { - cpsDataService.deleteDataNode(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, dataNodeXpath, NO_TIMESTAMP); - } - - @Override - public void deleteDataNodes(final Collection<String> dataNodeXpaths) { - cpsDataService.deleteDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, dataNodeXpaths, NO_TIMESTAMP); - } - private static String createCmHandleXPath(final String cmHandleId) { - return "/dmi-registry/cm-handles[@id='" + cmHandleId + "']"; + return NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']"; } private static String createStateJsonData(final String state) { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/LockReasonCategory.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/LockReasonCategory.java index 16ae881935..e2b2c6b4ae 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/LockReasonCategory.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/LockReasonCategory.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,8 +18,11 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.api.inventory; +package org.onap.cps.ncmp.api.impl.inventory; public enum LockReasonCategory { - LOCKED_MODULE_SYNC_FAILED + MODULE_SYNC_FAILED, + MODULE_UPGRADE, + MODULE_UPGRADE_FAILED, + LOCKED_MISBEHAVING } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/ModelledDmiServiceLeaves.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/ModelledDmiServiceLeaves.java index 0546c388bf..b8a1ba02db 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/ModelledDmiServiceLeaves.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/ModelledDmiServiceLeaves.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.api.inventory; +package org.onap.cps.ncmp.api.impl.inventory; public enum ModelledDmiServiceLeaves { DMI_SERVICE_NAME("dmi-service-name"), diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/NcmpPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/NcmpPersistenceImpl.java new file mode 100644 index 0000000000..6a2d6d810b --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/NcmpPersistenceImpl.java @@ -0,0 +1,120 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.api.impl.inventory; + +import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED; +import static org.onap.cps.spi.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.CpsDataService; +import org.onap.cps.api.CpsModuleService; +import org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence; +import org.onap.cps.spi.FetchDescendantsOption; +import org.onap.cps.spi.exceptions.SchemaSetNotFoundException; +import org.onap.cps.spi.model.DataNode; +import org.onap.cps.spi.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 CpsDataService cpsDataService; + private final CpsModuleService cpsModuleService; + private final CpsValidator cpsValidator; + + @Override + public void deleteListOrListElement(final String listElementXpath) { + cpsDataService.deleteListOrListElement(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, listElementXpath, + NO_TIMESTAMP); + } + + @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) { + return getDataNode(xpath, INCLUDE_ALL_DESCENDANTS); + } + + @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, final FetchDescendantsOption fetchDescendantsOption) { + return cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, xpath, + fetchDescendantsOption); + } + + @Override + public Collection<DataNode> getDataNodes(final Collection<String> xpaths) { + return getDataNodes(xpaths, INCLUDE_ALL_DESCENDANTS); + } + + @Override + public Collection<DataNode> getDataNodes(final Collection<String> xpaths, + final FetchDescendantsOption fetchDescendantsOption) { + return cpsDataService.getDataNodesForMultipleXpaths(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, xpaths, + fetchDescendantsOption); + } + + @Override + public void replaceListContent(final String parentNodeXpath, final Collection<DataNode> dataNodes) { + cpsDataService.replaceListContent(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, parentNodeXpath, dataNodes, + NO_TIMESTAMP); + } + + @Override + public void deleteDataNode(final String dataNodeXpath) { + cpsDataService.deleteDataNode(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, dataNodeXpath, NO_TIMESTAMP); + } + + @Override + public void deleteDataNodes(final Collection<String> dataNodeXpaths) { + cpsDataService.deleteDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, dataNodeXpaths, NO_TIMESTAMP); + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/enums/PropertyType.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/enums/PropertyType.java index c3c46c35e1..08bfe98e5c 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/enums/PropertyType.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/enums/PropertyType.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.api.inventory.enums; +package org.onap.cps.ncmp.api.impl.inventory.enums; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/DataSyncWatchdog.java index 9fa75a0d07..49804adc13 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdog.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/DataSyncWatchdog.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,9 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.api.inventory.sync; +package org.onap.cps.ncmp.api.impl.inventory.sync; + +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; import com.hazelcast.map.IMap; import java.time.OffsetDateTime; @@ -28,9 +30,9 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.CpsDataService; import org.onap.cps.ncmp.api.impl.config.embeddedcache.SynchronizationCacheConfig; -import org.onap.cps.ncmp.api.inventory.CompositeState; -import org.onap.cps.ncmp.api.inventory.DataStoreSyncState; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState; +import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @@ -66,7 +68,7 @@ public class DataSyncWatchdog { if (resourceData == null) { log.debug("Error retrieving resource data for Cm-Handle: {}", cmHandleId); } else { - cpsDataService.saveData("NFP-Operational", cmHandleId, + cpsDataService.saveData(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, resourceData, OffsetDateTime.now()); setSyncStateToSynchronized().accept(compositeState); inventoryPersistence.saveCmHandleState(cmHandleId, compositeState); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java new file mode 100644 index 0000000000..8e17ab9166 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java @@ -0,0 +1,167 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-2023 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.api.impl.inventory.sync; + +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; + +import java.time.OffsetDateTime; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.onap.cps.api.CpsAdminService; +import org.onap.cps.api.CpsDataService; +import org.onap.cps.api.CpsModuleService; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState; +import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory; +import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations; +import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; +import org.onap.cps.spi.CascadeDeleteAllowed; +import org.onap.cps.spi.FetchDescendantsOption; +import org.onap.cps.spi.exceptions.SchemaSetNotFoundException; +import org.onap.cps.spi.model.DataNode; +import org.onap.cps.spi.model.ModuleReference; +import org.onap.cps.utils.JsonObjectMapper; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ModuleSyncService { + + private final DmiModelOperations dmiModelOperations; + private final CpsModuleService cpsModuleService; + private final CpsAdminService cpsAdminService; + private final CmHandleQueries cmHandleQueries; + private final CpsDataService cpsDataService; + private final JsonObjectMapper jsonObjectMapper; + + /** + * This method registers a cm handle and initiates modules sync. + * + * @param upgradedCmHandle the yang model of cm handle. + */ + public void syncAndCreateOrUpgradeSchemaSetAndAnchor(final YangModelCmHandle upgradedCmHandle) { + + final String moduleSetTag = extractModuleSetTag(upgradedCmHandle.getCompositeState()); + final Optional<DataNode> existingCmHandleWithSameModuleSetTag + = getFirstReadyDataNodeWithModuleSetTag(moduleSetTag); + + if (existingCmHandleWithSameModuleSetTag.isPresent()) { + upgradeUsingModuleSetTag(upgradedCmHandle, moduleSetTag); + } else { + syncAndCreateSchemaSetAndAnchor(upgradedCmHandle); + } + setCmHandleModuleSetTag(upgradedCmHandle, moduleSetTag); + } + + private void syncAndCreateSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle) { + final Collection<ModuleReference> allModuleReferencesFromCmHandle = + dmiModelOperations.getModuleReferences(yangModelCmHandle); + + final Collection<ModuleReference> identifiedNewModuleReferencesFromCmHandle = cpsModuleService + .identifyNewModuleReferences(allModuleReferencesFromCmHandle); + + final Map<String, String> newModuleNameToContentMap; + if (identifiedNewModuleReferencesFromCmHandle.isEmpty()) { + newModuleNameToContentMap = Collections.emptyMap(); + } else { + newModuleNameToContentMap = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, + identifiedNewModuleReferencesFromCmHandle); + } + createSchemaSetAndAnchor(yangModelCmHandle, newModuleNameToContentMap, allModuleReferencesFromCmHandle); + } + + private void createSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle, + final Map<String, String> newModuleNameToContentMap, + final Collection<ModuleReference> allModuleReferencesFromCmHandle) { + final String schemaSetAndAnchorName = yangModelCmHandle.getId(); + cpsModuleService.createOrUpgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, + schemaSetAndAnchorName, newModuleNameToContentMap, allModuleReferencesFromCmHandle); + cpsAdminService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetAndAnchorName, + schemaSetAndAnchorName); + } + + /** + * 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 Optional<DataNode> getFirstReadyDataNodeWithModuleSetTag(final String moduleSetTag) { + final List<DataNode> dataNodes = StringUtils.isNotBlank(moduleSetTag) ? cmHandleQueries + .queryNcmpRegistryByCpsPath("//cm-handles[@module-set-tag='" + moduleSetTag + "']", + FetchDescendantsOption.OMIT_DESCENDANTS) : Collections.emptyList(); + return dataNodes.stream().filter(dataNode -> { + final String cmHandleId = YangDataConverter.extractCmHandleIdFromXpath(dataNode.getXpath()); + return cmHandleQueries.cmHandleHasState(cmHandleId, CmHandleState.READY); + }).findFirst(); + } + + private void setCmHandleModuleSetTag(final YangModelCmHandle upgradedCmHandle, final String moduleSetTag) { + final Map<String, Map<String, String>> dmiRegistryProperties = new HashMap<>(1); + final Map<String, String> cmHandleProperties = new HashMap<>(2); + cmHandleProperties.put("id", upgradedCmHandle.getId()); + cmHandleProperties.put("module-set-tag", moduleSetTag); + dmiRegistryProperties.put("cm-handles", cmHandleProperties); + cpsDataService.updateNodeLeaves(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT, + jsonObjectMapper.asJsonString(dmiRegistryProperties), OffsetDateTime.now()); + } + + private void upgradeUsingModuleSetTag(final YangModelCmHandle upgradedCmHandle, final String moduleSetTag) { + log.info("Found cm handle having module set tag: {}", moduleSetTag); + final Collection<ModuleReference> moduleReferencesFromExistingCmHandle = + cpsModuleService.getYangResourcesModuleReferences(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR); + final String upgradedSchemaSetAndAnchorName = upgradedCmHandle.getId(); + final Map<String, String> noNewModules = Collections.emptyMap(); + cpsModuleService.createOrUpgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, + upgradedSchemaSetAndAnchorName, noNewModules, moduleReferencesFromExistingCmHandle); + } + + private static String extractModuleSetTag(final CompositeState compositeState) { + return compositeState.getLockReason() != null && compositeState.getLockReason().getLockReasonCategory() + == LockReasonCategory.MODULE_UPGRADE + ? Arrays.stream(compositeState.getLockReason().getDetails().split(":")).toList().get(1).trim() + : StringUtils.EMPTY; + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncTasks.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java index 914b626e33..c19dbeb900 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncTasks.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.api.inventory.sync; +package org.onap.cps.ncmp.api.impl.inventory.sync; import com.hazelcast.map.IMap; import java.util.Collection; @@ -30,12 +30,12 @@ import java.util.concurrent.atomic.AtomicInteger; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; +import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory; import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CmHandleState; -import org.onap.cps.ncmp.api.inventory.CompositeState; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; -import org.onap.cps.ncmp.api.inventory.LockReasonCategory; import org.onap.cps.spi.model.DataNode; import org.springframework.stereotype.Component; @@ -60,7 +60,8 @@ public class ModuleSyncTasks { public CompletableFuture<Void> performModuleSync(final Collection<DataNode> cmHandlesAsDataNodes, final AtomicInteger batchCounter) { try { - final Map<YangModelCmHandle, CmHandleState> cmHandelStatePerCmHandle = new HashMap<>(); + final Map<YangModelCmHandle, CmHandleState> cmHandelStatePerCmHandle + = new HashMap<>(cmHandlesAsDataNodes.size()); for (final DataNode cmHandleAsDataNode : cmHandlesAsDataNodes) { final String cmHandleId = String.valueOf(cmHandleAsDataNode.getLeaves().get("id")); final YangModelCmHandle yangModelCmHandle = @@ -68,16 +69,18 @@ public class ModuleSyncTasks { final CompositeState compositeState = inventoryPersistence.getCmHandleState(cmHandleId); try { moduleSyncService.deleteSchemaSetIfExists(cmHandleId); - moduleSyncService.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle); + moduleSyncService.syncAndCreateOrUpgradeSchemaSetAndAnchor(yangModelCmHandle); + yangModelCmHandle.getCompositeState().setLockReason(null); cmHandelStatePerCmHandle.put(yangModelCmHandle, CmHandleState.READY); } catch (final Exception e) { - log.warn("Processing of {} module sync failed due to reason {}.", cmHandleId, e.getMessage()); + log.warn("Processing of {} module sync failed due to reason {}.", + cmHandleId, e.getMessage()); syncUtils.updateLockReasonDetailsAndAttempts(compositeState, - LockReasonCategory.LOCKED_MODULE_SYNC_FAILED, e.getMessage()); + LockReasonCategory.MODULE_SYNC_FAILED, e.getMessage()); setCmHandleStateLocked(yangModelCmHandle, compositeState.getLockReason()); cmHandelStatePerCmHandle.put(yangModelCmHandle, CmHandleState.LOCKED); } - log.info("{} is now in {} state", cmHandleId, compositeState.getCmHandleState().name()); + log.info("{} is now in {} state", cmHandleId, cmHandelStatePerCmHandle.get(yangModelCmHandle).name()); } lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandelStatePerCmHandle); } finally { @@ -96,7 +99,7 @@ public class ModuleSyncTasks { final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle = new HashMap<>(failedCmHandles.size()); for (final YangModelCmHandle failedCmHandle : failedCmHandles) { final CompositeState compositeState = failedCmHandle.getCompositeState(); - final boolean isReadyForRetry = syncUtils.isReadyForRetry(compositeState); + final boolean isReadyForRetry = syncUtils.needsModuleSyncRetryOrUpgrade(compositeState); log.info("Retry for cmHandleId : {} is {}", failedCmHandle.getId(), isReadyForRetry); if (isReadyForRetry) { final String resetCmHandleId = failedCmHandle.getId(); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdog.java index 6ff426d66f..75781eb1b3 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdog.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdog.java @@ -19,12 +19,13 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.api.inventory.sync; +package org.onap.cps.ncmp.api.impl.inventory.sync; import com.hazelcast.map.IMap; import java.util.Collection; import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; @@ -32,8 +33,8 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.impl.config.embeddedcache.SynchronizationCacheConfig; +import org.onap.cps.ncmp.api.impl.inventory.sync.executor.AsyncTaskExecutor; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.sync.executor.AsyncTaskExecutor; import org.onap.cps.spi.model.DataNode; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @@ -48,6 +49,7 @@ public class ModuleSyncWatchdog { private final IMap<String, Object> moduleSyncStartedOnCmHandles; private final ModuleSyncTasks moduleSyncTasks; private final AsyncTaskExecutor asyncTaskExecutor; + private final IMap<String, Set<String>> moduleSetTagCache; private static final int MODULE_SYNC_BATCH_SIZE = 100; private static final long PREVENT_CPU_BURN_WAIT_TIME_MILLIS = 10; private static final String VALUE_FOR_HAZELCAST_IN_PROGRESS_MAP = "Started"; @@ -88,7 +90,7 @@ public class ModuleSyncWatchdog { @Scheduled(fixedDelayString = "${ncmp.timers.locked-modules-sync.sleep-time-ms:300000}") public void resetPreviouslyFailedCmHandles() { log.info("Processing module sync retry-watchdog waking up."); - final List<YangModelCmHandle> failedCmHandles = syncUtils.getModuleSyncFailedCmHandles(); + final List<YangModelCmHandle> failedCmHandles = syncUtils.getCmHandlesThatFailedModelSyncOrUpgrade(); log.info("Retrying {} cmHandles", failedCmHandles.size()); moduleSyncTasks.resetFailedCmHandles(failedCmHandles); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/SyncUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/SyncUtils.java index 53d8c797b8..ab85c2127e 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/SyncUtils.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/SyncUtils.java @@ -19,7 +19,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.api.inventory.sync; +package org.onap.cps.ncmp.api.impl.inventory.sync; import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL; @@ -35,17 +35,16 @@ import java.util.Map; import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState; +import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState; +import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory; import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations; import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CmHandleQueries; -import org.onap.cps.ncmp.api.inventory.CmHandleState; -import org.onap.cps.ncmp.api.inventory.CompositeState; -import org.onap.cps.ncmp.api.inventory.DataStoreSyncState; -import org.onap.cps.ncmp.api.inventory.LockReasonCategory; import org.onap.cps.spi.FetchDescendantsOption; import org.onap.cps.spi.model.DataNode; import org.onap.cps.utils.JsonObjectMapper; @@ -56,12 +55,10 @@ import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor public class SyncUtils { - private final CmHandleQueries cmHandleQueries; + private final CmHandleQueries cmHandleQueries; private final DmiDataOperations dmiDataOperations; - private final JsonObjectMapper jsonObjectMapper; - private static final Pattern retryAttemptPattern = Pattern.compile("^Attempt #(\\d+) failed:"); /** @@ -102,13 +99,14 @@ public class SyncUtils { } /** - * Query data nodes for cm handles with an "LOCKED" cm handle state with reason LOCKED_MODULE_SYNC_FAILED". + * Query data nodes for cm handles with an "LOCKED" cm handle state with reason. * * @return a random LOCKED yang model cm handle, return null if not found */ - public List<YangModelCmHandle> getModuleSyncFailedCmHandles() { - final List<DataNode> lockedCmHandlesAsDataNodeList = cmHandleQueries.queryCmHandleDataNodesByCpsPath( - "//lock-reason[@reason=\"LOCKED_MODULE_SYNC_FAILED\"]", + public List<YangModelCmHandle> getCmHandlesThatFailedModelSyncOrUpgrade() { + final List<DataNode> lockedCmHandlesAsDataNodeList + = cmHandleQueries.queryCmHandleAncestorsByCpsPath( + "//lock-reason[@reason=\"MODULE_SYNC_FAILED\" or @reason=\"MODULE_UPGRADE\"]", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); return convertCmHandlesDataNodesToYangModelCmHandles(lockedCmHandlesAsDataNodeList); } @@ -136,28 +134,44 @@ public class SyncUtils { /** - * Check if the retry mechanism should attempt to unlock the cm handle based on the last update time. + * Check if a module sync retry is needed. * * @param compositeState the composite state currently in the locked state * @return if the retry mechanism should be attempted */ - public boolean isReadyForRetry(final CompositeState compositeState) { - int timeInMinutesUntilNextAttempt = 1; - final OffsetDateTime time = - OffsetDateTime.parse(compositeState.getLastUpdateTime(), - DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")); - final Matcher matcher = retryAttemptPattern.matcher(compositeState.getLockReason().getDetails()); - if (matcher.find()) { - timeInMinutesUntilNextAttempt = (int) Math.pow(2, Integer.parseInt(matcher.group(1))); - } else { - log.debug("First Attempt: no current attempts found."); - } - final int timeSinceLastAttempt = (int) Duration.between(time, OffsetDateTime.now()).toMinutes(); - if (timeInMinutesUntilNextAttempt >= timeSinceLastAttempt) { - log.info("Time until next attempt is {} minutes: ", - timeInMinutesUntilNextAttempt - timeSinceLastAttempt); + public boolean needsModuleSyncRetryOrUpgrade(final CompositeState compositeState) { + final OffsetDateTime time = OffsetDateTime.parse(compositeState.getLastUpdateTime(), + DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")); + final CompositeState.LockReason lockReason = compositeState.getLockReason(); + + final boolean failedDuringModuleSync = LockReasonCategory.MODULE_SYNC_FAILED + == lockReason.getLockReasonCategory(); + final boolean moduleUpgrade = LockReasonCategory.MODULE_UPGRADE + == lockReason.getLockReasonCategory(); + + if (failedDuringModuleSync) { + final int timeInMinutesUntilNextAttempt; + final Matcher matcher = retryAttemptPattern.matcher(lockReason.getDetails()); + if (matcher.find()) { + timeInMinutesUntilNextAttempt = (int) Math.pow(2, Integer.parseInt(matcher.group(1))); + } else { + timeInMinutesUntilNextAttempt = 1; + log.info("First Attempt: no current attempts found."); + } + final int timeSinceLastAttempt = (int) Duration.between(time, OffsetDateTime.now()).toMinutes(); + if (timeInMinutesUntilNextAttempt >= timeSinceLastAttempt) { + log.info("Time until next attempt is {} minutes: ", + timeInMinutesUntilNextAttempt - timeSinceLastAttempt); + return false; + } + log.info("Retry due now"); + return true; + } else if (moduleUpgrade) { + log.info("Locked for module upgrade."); + return true; } - return timeSinceLastAttempt > timeInMinutesUntilNextAttempt; + log.info("Locked for other reason"); + return false; } /** @@ -189,6 +203,6 @@ public class SyncUtils { final List<DataNode> cmHandlesAsDataNodeList) { return cmHandlesAsDataNodeList.stream() .map(cmHandle -> YangDataConverter.convertCmHandleToYangModel(cmHandle, - cmHandle.getLeaves().get("id").toString())).collect(Collectors.toList()); + cmHandle.getLeaves().get("id").toString())).toList(); } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/config/WatchdogSchedulingConfigurer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/config/WatchdogSchedulingConfigurer.java index 196a655ca4..1aaee2708f 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/config/WatchdogSchedulingConfigurer.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/config/WatchdogSchedulingConfigurer.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.api.inventory.sync.config; +package org.onap.cps.ncmp.api.impl.inventory.sync.config; import java.util.concurrent.ThreadPoolExecutor; import org.springframework.context.annotation.Bean; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/executor/AsyncTaskExecutor.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/executor/AsyncTaskExecutor.java index 3d08185e14..2d5e7a1abc 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/executor/AsyncTaskExecutor.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/executor/AsyncTaskExecutor.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.api.inventory.sync.executor; +package org.onap.cps.ncmp.api.impl.inventory.sync.executor; import static java.util.concurrent.TimeUnit.MILLISECONDS; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/ncmppersistence/NcmpPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/ncmppersistence/NcmpPersistence.java new file mode 100644 index 0000000000..d72b5d58f1 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/ncmppersistence/NcmpPersistence.java @@ -0,0 +1,116 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-2023 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.api.impl.ncmppersistence; + +import java.time.OffsetDateTime; +import java.util.Collection; +import org.onap.cps.spi.FetchDescendantsOption; +import org.onap.cps.spi.model.DataNode; + +/** + * DmiRegistryConstants class to be strictly used for DMI Related constants only. + */ +public interface NcmpPersistence { + + String NCMP_DATASPACE_NAME = "NCMP-Admin"; + String NCMP_DMI_REGISTRY_ANCHOR = "ncmp-dmi-registry"; + String NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME = "NFP-Operational"; + String NCMP_DMI_REGISTRY_PARENT = "/dmi-registry"; + OffsetDateTime NO_TIMESTAMP = null; + + /** + * Method to delete a list or a list element. + * + * @param listElementXpath list element xPath + */ + 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 + * @return data node + */ + Collection<DataNode> getDataNode(String xpath); + + /** + * Get data node via xpath. + * + * @param xpath xpath + * @param fetchDescendantsOption fetch descendants option + * @return data node + */ + Collection<DataNode> getDataNode(String xpath, FetchDescendantsOption fetchDescendantsOption); + + /** + * Get collection of data nodes via xpaths. + * + * @param xpaths collection of xpaths + * @return collection of data nodes + */ + Collection<DataNode> getDataNodes(Collection<String> xpaths); + + /** + * Get collection of data nodes via xpaths. + * + * @param xpaths collection of xpaths + * @param fetchDescendantsOption fetch descendants option + * @return collection of data nodes + */ + Collection<DataNode> getDataNodes(Collection<String> xpaths, + FetchDescendantsOption fetchDescendantsOption); + + /** + * Replaces list content by removing all existing elements and inserting the given new elements as data nodes. + * + * @param parentNodeXpath parent node xpath + * @param dataNodes datanodes representing the updated data + */ + void replaceListContent(String parentNodeXpath, Collection<DataNode> dataNodes); + + /** + * Deletes data node. + * + * @param dataNodeXpath data node xpath + */ + void deleteDataNode(String dataNodeXpath); + + /** + * Deletes multiple data nodes. + * + * @param dataNodeXpaths data node xpaths + */ + void deleteDataNodes(Collection<String> dataNodeXpaths); +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java index ba6f89192d..b8edeccf2e 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java @@ -21,6 +21,8 @@ package org.onap.cps.ncmp.api.impl.operations; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.DMI_SERVICE_NOT_RESPONDING; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNABLE_TO_READ_RESOURCE_DATA; import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING; import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ; @@ -30,16 +32,16 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.NcmpEventResponseCode; +import org.onap.cps.ncmp.api.NcmpResponseStatus; import org.onap.cps.ncmp.api.impl.client.DmiRestClient; import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration; import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException; import org.onap.cps.ncmp.api.impl.executor.TaskExecutor; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder; import org.onap.cps.ncmp.api.impl.utils.data.operation.ResourceDataOperationRequestUtils; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CmHandleState; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.models.DataOperationRequest; import org.onap.cps.spi.exceptions.CpsException; import org.onap.cps.utils.JsonObjectMapper; @@ -230,9 +232,7 @@ public class DmiDataOperations extends DmiOperations { final Map<String, List<DmiDataOperation>> groupsOutPerDmiServiceName) { - groupsOutPerDmiServiceName.entrySet().forEach(groupsOutPerDmiServiceNameEntry -> { - final String dmiServiceName = groupsOutPerDmiServiceNameEntry.getKey(); - final List<DmiDataOperation> dmiDataOperationRequestBodies = groupsOutPerDmiServiceNameEntry.getValue(); + groupsOutPerDmiServiceName.forEach((dmiServiceName, dmiDataOperationRequestBodies) -> { final String dmiDataOperationResourceUrl = getDmiServiceDataOperationRequestUrl(dmiServiceName, topicParamInQuery, requestId); sendDataOperationRequestToDmiService(dmiDataOperationResourceUrl, dmiDataOperationRequestBodies); @@ -261,18 +261,18 @@ public class DmiDataOperations extends DmiOperations { final String topicName = dataOperationResourceUrlParameters.get("topic").get(0); final String requestId = dataOperationResourceUrlParameters.get("requestId").get(0); - final MultiValueMap<DmiDataOperation, Map<NcmpEventResponseCode, List<String>>> + final MultiValueMap<DmiDataOperation, Map<NcmpResponseStatus, List<String>>> cmHandleIdsPerResponseCodesPerOperation = new LinkedMultiValueMap<>(); dmiDataOperationRequestBodies.forEach(dmiDataOperationRequestBody -> { final List<String> cmHandleIds = dmiDataOperationRequestBody.getCmHandles().stream() - .map(CmHandle::getId).collect(Collectors.toList()); + .map(CmHandle::getId).toList(); if (throwable.getCause() instanceof HttpClientRequestException) { cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperationRequestBody, - Map.of(NcmpEventResponseCode.UNABLE_TO_READ_RESOURCE_DATA, cmHandleIds)); + Map.of(UNABLE_TO_READ_RESOURCE_DATA, cmHandleIds)); } else { cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperationRequestBody, - Map.of(NcmpEventResponseCode.DMI_SERVICE_NOT_RESPONDING, cmHandleIds)); + Map.of(DMI_SERVICE_NOT_RESPONDING, cmHandleIds)); } }); ResourceDataOperationRequestUtils.publishErrorMessageToClientTopic(topicName, requestId, diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java index 1bbd725646..32b5cb7304 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java @@ -32,9 +32,9 @@ import java.util.List; import java.util.Map; import org.onap.cps.ncmp.api.impl.client.DmiRestClient; import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.models.YangResource; import org.onap.cps.spi.model.ModuleReference; import org.onap.cps.utils.JsonObjectMapper; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java index 7e9079ec94..c8d73eac63 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java @@ -24,8 +24,8 @@ package org.onap.cps.ncmp.api.impl.operations; import lombok.RequiredArgsConstructor; import org.onap.cps.ncmp.api.impl.client.DmiRestClient; import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; import org.onap.cps.utils.JsonObjectMapper; import org.springframework.stereotype.Service; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistence.java index 27d4266566..8092e39510 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistence.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistence.java @@ -21,10 +21,11 @@ package org.onap.cps.ncmp.api.impl.subscriptions; import java.util.Collection; +import org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelSubscriptionEvent; import org.onap.cps.spi.model.DataNode; -public interface SubscriptionPersistence { +public interface SubscriptionPersistence extends NcmpPersistence { /** * Save subscription Event. diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistenceImpl.java index 83a375b1b8..dd0c20d590 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistenceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistenceImpl.java @@ -20,42 +20,43 @@ package org.onap.cps.ncmp.api.impl.subscriptions; -import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NO_TIMESTAMP; - -import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.CpsDataService; +import org.onap.cps.api.CpsModuleService; +import org.onap.cps.ncmp.api.impl.inventory.NcmpPersistenceImpl; import org.onap.cps.ncmp.api.impl.utils.DataNodeHelper; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelSubscriptionEvent; import org.onap.cps.spi.FetchDescendantsOption; import org.onap.cps.spi.model.DataNode; +import org.onap.cps.spi.utils.CpsValidator; import org.onap.cps.utils.JsonObjectMapper; import org.springframework.stereotype.Component; @Slf4j -@RequiredArgsConstructor @Component -public class SubscriptionPersistenceImpl implements SubscriptionPersistence { +public class SubscriptionPersistenceImpl extends NcmpPersistenceImpl implements SubscriptionPersistence { - private static final String SUBSCRIPTION_DATASPACE_NAME = "NCMP-Admin"; private static final String SUBSCRIPTION_ANCHOR_NAME = "AVC-Subscriptions"; private static final String SUBSCRIPTION_REGISTRY_PARENT = "/subscription-registry"; - private final JsonObjectMapper jsonObjectMapper; - private final CpsDataService cpsDataService; + + public SubscriptionPersistenceImpl(final JsonObjectMapper jsonObjectMapper, final CpsDataService cpsDataService, + final CpsModuleService cpsModuleService, final CpsValidator cpsValidator) { + super(jsonObjectMapper, cpsDataService, cpsModuleService, cpsValidator); + } + @Override public void saveSubscriptionEvent(final YangModelSubscriptionEvent yangModelSubscriptionEvent) { final String clientId = yangModelSubscriptionEvent.getClientId(); final String subscriptionName = yangModelSubscriptionEvent.getSubscriptionName(); - final Collection<DataNode> dataNodes = cpsDataService.getDataNodes(SUBSCRIPTION_DATASPACE_NAME, + final Collection<DataNode> dataNodes = cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, SUBSCRIPTION_REGISTRY_PARENT, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); if (isSubscriptionRegistryEmptyOrNonExist(dataNodes, clientId, subscriptionName)) { @@ -74,8 +75,7 @@ public class SubscriptionPersistenceImpl implements SubscriptionPersistence { final Map<String, Map<String, String>> cmHandleIdToStatusAndDetailsAsMapOriginal = DataNodeHelper.cmHandleIdToStatusAndDetailsAsMapFromDataNode(dataNodes); - final Map<String, Map<String, String>> newTargetCmHandles = - mapDifference(cmHandleIdToStatusAndDetailsAsMapNew, + final Map<String, Map<String, String>> newTargetCmHandles = mapDifference(cmHandleIdToStatusAndDetailsAsMapNew, cmHandleIdToStatusAndDetailsAsMapOriginal); traverseCmHandleList(newTargetCmHandles, clientId, subscriptionName, true); @@ -88,7 +88,7 @@ public class SubscriptionPersistenceImpl implements SubscriptionPersistence { final YangModelSubscriptionEvent yangModelSubscriptionEvent) { return yangModelSubscriptionEvent.getPredicates().getTargetCmHandles() .stream().collect( - HashMap<String, Map<String, String>>::new, + HashMap::new, (result, cmHandle) -> { final String cmHandleId = cmHandle.getCmHandleId(); final SubscriptionStatus status = cmHandle.getStatus(); @@ -130,34 +130,31 @@ public class SubscriptionPersistenceImpl implements SubscriptionPersistence { final boolean isAddListElementOperation) { if (isAddListElementOperation) { log.info("targetCmHandleAsJson to be added into DB {}", targetCmHandleAsJson); - cpsDataService.saveListElements(SUBSCRIPTION_DATASPACE_NAME, - SUBSCRIPTION_ANCHOR_NAME, createCmHandleXpathPredicates(clientId, subscriptionName), - targetCmHandleAsJson, NO_TIMESTAMP); + cpsDataService.saveListElements(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, + createCmHandleXpathPredicates(clientId, subscriptionName), targetCmHandleAsJson, NO_TIMESTAMP); } else { log.info("targetCmHandleAsJson to be updated into DB {}", targetCmHandleAsJson); - cpsDataService.updateNodeLeaves(SUBSCRIPTION_DATASPACE_NAME, - SUBSCRIPTION_ANCHOR_NAME, createCmHandleXpathPredicates(clientId, subscriptionName), - targetCmHandleAsJson, NO_TIMESTAMP); + cpsDataService.updateNodeLeaves(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, + createCmHandleXpathPredicates(clientId, subscriptionName), targetCmHandleAsJson, NO_TIMESTAMP); } } private void saveSubscriptionEventYangModel(final String subscriptionEventJsonData) { log.info("SubscriptionEventJsonData to be saved into DB {}", subscriptionEventJsonData); - cpsDataService.saveListElements(SUBSCRIPTION_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, + cpsDataService.saveListElements(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, SUBSCRIPTION_REGISTRY_PARENT, subscriptionEventJsonData, NO_TIMESTAMP); } @Override public Collection<DataNode> getDataNodesForSubscriptionEvent() { - return cpsDataService.getDataNodes(SUBSCRIPTION_DATASPACE_NAME, - SUBSCRIPTION_ANCHOR_NAME, SUBSCRIPTION_REGISTRY_PARENT, - FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); + return cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, + SUBSCRIPTION_REGISTRY_PARENT, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); } @Override public Collection<DataNode> getCmHandlesForSubscriptionEvent(final String clientId, final String subscriptionName) { - return cpsDataService.getDataNodesForMultipleXpaths(SUBSCRIPTION_DATASPACE_NAME, - SUBSCRIPTION_ANCHOR_NAME, Arrays.asList(createCmHandleXpath(clientId, subscriptionName)), + return cpsDataService.getDataNodesForMultipleXpaths(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, + List.of(createCmHandleXpath(clientId, subscriptionName)), FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); } @@ -168,8 +165,8 @@ public class SubscriptionPersistenceImpl implements SubscriptionPersistence { final Map<String, String> statusAndDetailsMap = entry.getValue(); final String status = statusAndDetailsMap.get("status"); final String details = statusAndDetailsMap.get("details"); - return new YangModelSubscriptionEvent.TargetCmHandle(cmHandleId, - SubscriptionStatus.fromString(status), details); + return new YangModelSubscriptionEvent.TargetCmHandle(cmHandleId, SubscriptionStatus.fromString(status), + details); }).collect(Collectors.toList()); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDog.java index dac32aa736..d3b95eacbf 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDog.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDog.java @@ -46,7 +46,7 @@ public class DMiPluginWatchDog { */ @Scheduled(fixedDelayString = "${ncmp.timers.trust-evel.dmi-availability-watchdog-ms:30000}") public void watchDmiPluginAliveness() { - trustLevelPerDmiPlugin.keySet().forEach((dmiPluginName) -> { + trustLevelPerDmiPlugin.keySet().forEach(dmiPluginName -> { final DmiPluginStatus dmiPluginStatus = dmiRestClient.getDmiPluginStatus(dmiPluginName); log.debug("Trust level for dmi-plugin: {} is {}", dmiPluginName, dmiPluginStatus.toString()); if (DmiPluginStatus.UP.equals(dmiPluginStatus)) { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java index 7466308981..b6a04d3677 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java @@ -30,9 +30,9 @@ import java.util.regex.Pattern; import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState; +import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CompositeState; -import org.onap.cps.ncmp.api.inventory.CompositeStateBuilder; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.onap.cps.spi.model.DataNode; @@ -86,7 +86,8 @@ public class YangDataConverter { (String) cmHandleDataNode.getLeaves().get("dmi-service-name"), (String) cmHandleDataNode.getLeaves().get("dmi-data-service-name"), (String) cmHandleDataNode.getLeaves().get("dmi-model-service-name"), - ncmpServiceCmHandle + ncmpServiceCmHandle, + (String) cmHandleDataNode.getLeaves().get("module-set-tag") ); } @@ -105,7 +106,12 @@ public class YangDataConverter { return yangModelCmHandles; } - private static String extractCmHandleIdFromXpath(final String xpath) { + /** + * This method extract cm handle id from xpath of data node. + * @param xpath for data node of the cm handle + * @return cm handle Id + */ + public static String extractCmHandleIdFromXpath(final String xpath) { final Matcher matcher = cmHandleIdInXpathPattern.matcher(xpath); matcher.find(); return matcher.group(1); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/DataOperationEventCreator.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/DataOperationEventCreator.java index 65cda94787..61da706c59 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/DataOperationEventCreator.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/DataOperationEventCreator.java @@ -28,7 +28,7 @@ import java.util.Map; import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.NcmpEventResponseCode; +import org.onap.cps.ncmp.api.NcmpResponseStatus; import org.onap.cps.ncmp.api.impl.events.NcmpCloudEventBuilder; import org.onap.cps.ncmp.api.impl.operations.DmiDataOperation; import org.onap.cps.ncmp.events.async1_0_0.Data; @@ -51,7 +51,7 @@ public class DataOperationEventCreator { public static CloudEvent createDataOperationEvent(final String clientTopic, final String requestId, final MultiValueMap<DmiDataOperation, - Map<NcmpEventResponseCode, List<String>>> + Map<NcmpResponseStatus, List<String>>> cmHandleIdsPerResponseCodesPerOperation) { final DataOperationEvent dataOperationEvent = new DataOperationEvent(); final Data data = createPayloadFromDataOperationResponses(cmHandleIdsPerResponseCodesPerOperation); @@ -62,7 +62,7 @@ public class DataOperationEventCreator { } private static Data createPayloadFromDataOperationResponses(final MultiValueMap<DmiDataOperation, - Map<NcmpEventResponseCode, List<String>>> cmHandleIdsPerResponseCodesPerOperation) { + Map<NcmpResponseStatus, List<String>>> cmHandleIdsPerResponseCodesPerOperation) { final Data data = new Data(); final List<org.onap.cps.ncmp.events.async1_0_0.Response> responses = new ArrayList<>(); cmHandleIdsPerResponseCodesPerOperation.forEach((dmiDataOperation, cmHandleIdsPerResponseCodes) -> @@ -75,13 +75,13 @@ public class DataOperationEventCreator { private static List<Response> createResponseFromDataOperationResponses( final DmiDataOperation dmiDataOperation, - final Map<NcmpEventResponseCode, List<String>> cmHandleIdsPerResponseCodeEntries) { + final Map<NcmpResponseStatus, List<String>> cmHandleIdsPerResponseCodeEntries) { final List<org.onap.cps.ncmp.events.async1_0_0.Response> responses = new ArrayList<>(); cmHandleIdsPerResponseCodeEntries.forEach((ncmpEventResponseCode, cmHandleIds) -> { final Response response = new Response(); response.setOperationId(dmiDataOperation.getOperationId()); - response.setStatusCode(ncmpEventResponseCode.getStatusCode()); - response.setStatusMessage(ncmpEventResponseCode.getStatusMessage()); + response.setStatusCode(ncmpEventResponseCode.getCode()); + response.setStatusMessage(ncmpEventResponseCode.getMessage()); response.setIds(cmHandleIds); response.setResourceIdentifier(dmiDataOperation.getResourceIdentifier()); response.setOptions(dmiDataOperation.getOptions()); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java index c455337ac3..e78f0901fe 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java @@ -20,6 +20,9 @@ package org.onap.cps.ncmp.api.impl.utils.data.operation; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_READY; + import io.cloudevents.CloudEvent; import java.util.ArrayList; import java.util.Collection; @@ -32,14 +35,14 @@ import java.util.stream.Collectors; import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.NcmpEventResponseCode; +import org.onap.cps.ncmp.api.NcmpResponseStatus; import org.onap.cps.ncmp.api.impl.events.EventsPublisher; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; import org.onap.cps.ncmp.api.impl.operations.CmHandle; import org.onap.cps.ncmp.api.impl.operations.DmiDataOperation; import org.onap.cps.ncmp.api.impl.utils.DmiServiceNameOrganizer; import org.onap.cps.ncmp.api.impl.utils.context.CpsApplicationContext; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CmHandleState; import org.onap.cps.ncmp.api.models.DataOperationDefinition; import org.onap.cps.ncmp.api.models.DataOperationRequest; import org.springframework.scheduling.annotation.Async; @@ -68,7 +71,7 @@ public class ResourceDataOperationRequestUtils { final Collection<YangModelCmHandle> yangModelCmHandles) { final Map<String, List<DmiDataOperation>> dmiDataOperationsOutPerDmiServiceName = new HashMap<>(); - final MultiValueMap<DmiDataOperation, Map<NcmpEventResponseCode, + final MultiValueMap<DmiDataOperation, Map<NcmpResponseStatus, List<String>>> cmHandleIdsPerResponseCodesPerOperation = new LinkedMultiValueMap<>(); final Set<String> nonReadyCmHandleIdsLookup = filterAndGetNonReadyCmHandleIds(yangModelCmHandles); @@ -102,10 +105,10 @@ public class ResourceDataOperationRequestUtils { } populateCmHandleIdsPerOperationIdPerResponseCode(cmHandleIdsPerResponseCodesPerOperation, DmiDataOperation.buildDmiDataOperationRequestBodyWithoutCmHandles(dataOperationDefinitionIn), - NcmpEventResponseCode.CM_HANDLES_NOT_FOUND, nonExistingCmHandleIds); + CM_HANDLES_NOT_FOUND, nonExistingCmHandleIds); populateCmHandleIdsPerOperationIdPerResponseCode(cmHandleIdsPerResponseCodesPerOperation, DmiDataOperation.buildDmiDataOperationRequestBodyWithoutCmHandles(dataOperationDefinitionIn), - NcmpEventResponseCode.CM_HANDLES_NOT_READY, nonReadyCmHandleIds); + CM_HANDLES_NOT_READY, nonReadyCmHandleIds); } if (!cmHandleIdsPerResponseCodesPerOperation.isEmpty()) { publishErrorMessageToClientTopic(topicParamInQuery, requestId, cmHandleIdsPerResponseCodesPerOperation); @@ -124,7 +127,7 @@ public class ResourceDataOperationRequestUtils { public static void publishErrorMessageToClientTopic(final String clientTopic, final String requestId, final MultiValueMap<DmiDataOperation, - Map<NcmpEventResponseCode, List<String>>> + Map<NcmpResponseStatus, List<String>>> cmHandleIdsPerResponseCodesPerOperation) { final CloudEvent dataOperationCloudEvent = DataOperationEventCreator.createDataOperationEvent(clientTopic, requestId, cmHandleIdsPerResponseCodesPerOperation); @@ -175,13 +178,13 @@ public class ResourceDataOperationRequestUtils { } private static void populateCmHandleIdsPerOperationIdPerResponseCode(final MultiValueMap<DmiDataOperation, - Map<NcmpEventResponseCode, List<String>>> cmHandleIdsPerResponseCodesPerOperation, + Map<NcmpResponseStatus, List<String>>> cmHandleIdsPerResponseCodesPerOperation, final DmiDataOperation dmiDataOperation, - final NcmpEventResponseCode - ncmpEventResponseCode, + final NcmpResponseStatus + ncmpResponseStatus, final List<String> cmHandleIds) { if (!cmHandleIds.isEmpty()) { - cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperation, Map.of(ncmpEventResponseCode, cmHandleIds)); + cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperation, Map.of(ncmpResponseStatus, cmHandleIds)); } } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java index a6f953aa86..d148f371b5 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java @@ -34,8 +34,8 @@ import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState; import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService; -import org.onap.cps.ncmp.api.inventory.CompositeState; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; /** @@ -64,6 +64,9 @@ public class YangModelCmHandle { @JsonProperty("dmi-model-service-name") private String dmiModelServiceName; + @JsonProperty("module-set-tag") + private String moduleSetTag; + @JsonProperty("additional-properties") private List<Property> dmiProperties; @@ -102,12 +105,14 @@ public class YangModelCmHandle { public static YangModelCmHandle toYangModelCmHandle(final String dmiServiceName, final String dmiDataServiceName, final String dmiModelServiceName, - final NcmpServiceCmHandle ncmpServiceCmHandle) { + final NcmpServiceCmHandle ncmpServiceCmHandle, + final String moduleSetTag) { final YangModelCmHandle yangModelCmHandle = new YangModelCmHandle(); yangModelCmHandle.setId(ncmpServiceCmHandle.getCmHandleId()); yangModelCmHandle.setDmiServiceName(dmiServiceName); yangModelCmHandle.setDmiDataServiceName(dmiDataServiceName); yangModelCmHandle.setDmiModelServiceName(dmiModelServiceName); + yangModelCmHandle.setModuleSetTag(moduleSetTag); yangModelCmHandle.setDmiProperties(asYangModelCmHandleProperties(ncmpServiceCmHandle.getDmiProperties())); yangModelCmHandle.setPublicProperties(asYangModelCmHandleProperties( ncmpServiceCmHandle.getPublicProperties())); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncService.java deleted file mode 100644 index 7efce1ad52..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncService.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.inventory.sync; - -import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.api.CpsAdminService; -import org.onap.cps.api.CpsModuleService; -import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.spi.CascadeDeleteAllowed; -import org.onap.cps.spi.exceptions.SchemaSetNotFoundException; -import org.onap.cps.spi.model.ModuleReference; -import org.springframework.stereotype.Service; - -@Slf4j -@Service -@RequiredArgsConstructor -public class ModuleSyncService { - - private final DmiModelOperations dmiModelOperations; - private final CpsModuleService cpsModuleService; - - private final CpsAdminService cpsAdminService; - - /** - * This method registers a cm handle and initiates modules sync. - * - * @param yangModelCmHandle the yang model of cm handle. - */ - public void syncAndCreateSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle) { - - final Collection<ModuleReference> allModuleReferencesFromCmHandle = - dmiModelOperations.getModuleReferences(yangModelCmHandle); - - final Collection<ModuleReference> identifiedNewModuleReferencesFromCmHandle = cpsModuleService - .identifyNewModuleReferences(allModuleReferencesFromCmHandle); - - final Map<String, String> newModuleNameToContentMap; - if (identifiedNewModuleReferencesFromCmHandle.isEmpty()) { - newModuleNameToContentMap = Collections.emptyMap(); - } else { - newModuleNameToContentMap = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, - identifiedNewModuleReferencesFromCmHandle); - } - createSchemaSetAndAnchor(yangModelCmHandle, newModuleNameToContentMap, allModuleReferencesFromCmHandle); - } - - private void createSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle, - final Map<String, String> newModuleNameToContentMap, - final Collection<ModuleReference> allModuleReferencesFromCmHandle) { - final String schemaSetAndAnchorName = yangModelCmHandle.getId(); - cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetAndAnchorName, - newModuleNameToContentMap, allModuleReferencesFromCmHandle); - cpsAdminService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetAndAnchorName, - schemaSetAndAnchorName); - } - - /** - * 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); - } - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java index d5b27b61f6..e007491ce0 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2022 Bell Canada - * Modifications Copyright (C) 2022 Nordix Foundation + * Modifications Copyright (C) 2022-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,16 +21,16 @@ package org.onap.cps.ncmp.api.models; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR; + import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; import lombok.Builder; import lombok.Data; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.NcmpResponseStatus; +import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; @Data @Builder @@ -39,11 +39,9 @@ public class CmHandleRegistrationResponse { private final String cmHandle; private final Status status; - private RegistrationError registrationError; + private NcmpResponseStatus ncmpResponseStatus; private String errorText; - private static final Pattern cmHandleIdInXpathPattern = Pattern.compile("\\[@id='(.*?)']"); - /** * Creates a failure response based on exception. * @@ -56,7 +54,7 @@ public class CmHandleRegistrationResponse { return CmHandleRegistrationResponse.builder() .cmHandle(cmHandleId) .status(Status.FAILURE) - .registrationError(RegistrationError.UNKNOWN_ERROR) + .ncmpResponseStatus(UNKNOWN_ERROR) .errorText(exception.getMessage()).build(); } @@ -64,15 +62,15 @@ public class CmHandleRegistrationResponse { * Creates a failure response based on registration error. * * @param cmHandleId cmHandleId - * @param registrationError registrationError + * @param ncmpResponseStatus registration error code and status * @return CmHandleRegistrationResponse */ public static CmHandleRegistrationResponse createFailureResponse(final String cmHandleId, - final RegistrationError registrationError) { + final NcmpResponseStatus ncmpResponseStatus) { return CmHandleRegistrationResponse.builder().cmHandle(cmHandleId) .status(Status.FAILURE) - .registrationError(registrationError) - .errorText(registrationError.errorText) + .ncmpResponseStatus(ncmpResponseStatus) + .errorText(ncmpResponseStatus.getMessage()) .build(); } @@ -80,18 +78,18 @@ public class CmHandleRegistrationResponse { * Creates a failure response based on registration error. * * @param failedXpaths list of failed Xpaths - * @param registrationError enum describing the type of registration error + * @param ncmpResponseStatus enum describing the type of registration error * @return CmHandleRegistrationResponse */ public static List<CmHandleRegistrationResponse> createFailureResponses(final Collection<String> failedXpaths, - final RegistrationError registrationError) { + final NcmpResponseStatus ncmpResponseStatus) { final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses = new ArrayList<>(failedXpaths.size()); for (final String xpath : failedXpaths) { - final Matcher matcher = cmHandleIdInXpathPattern.matcher(xpath); - if (matcher.find()) { + try { + final String cmHandleId = YangDataConverter.extractCmHandleIdFromXpath(xpath); cmHandleRegistrationResponses.add( - CmHandleRegistrationResponse.createFailureResponse(matcher.group(1), registrationError)); - } else { + CmHandleRegistrationResponse.createFailureResponse(cmHandleId, ncmpResponseStatus)); + } catch (IllegalArgumentException | IllegalStateException e) { log.warn("Unexpected xpath {}", xpath); } } @@ -109,7 +107,7 @@ public class CmHandleRegistrationResponse { final Exception exception) { return cmHandleIds.stream() .map(cmHandleId -> CmHandleRegistrationResponse.createFailureResponse(cmHandleId, exception)) - .collect(Collectors.toList()); + .toList(); } public static CmHandleRegistrationResponse createSuccessResponse(final String cmHandle) { @@ -118,23 +116,10 @@ public class CmHandleRegistrationResponse { } public static List<CmHandleRegistrationResponse> createSuccessResponses(final List<String> cmHandleIds) { - return cmHandleIds.stream().map(CmHandleRegistrationResponse::createSuccessResponse) - .collect(Collectors.toList()); + return cmHandleIds.stream().map(CmHandleRegistrationResponse::createSuccessResponse).toList(); } public enum Status { SUCCESS, FAILURE; } - - @RequiredArgsConstructor - public enum RegistrationError { - UNKNOWN_ERROR("00", "Unknown error"), - CM_HANDLE_ALREADY_EXIST("01", "cm-handle already exists"), - CM_HANDLE_DOES_NOT_EXIST("02", "cm-handle does not exist"), - CM_HANDLE_INVALID_ID("03", "cm-handle has an invalid character(s) in id"); - - public final String errorCode; - public final String errorText; - - } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java index d1360c3256..4615af61c1 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2022 Nordix Foundation + * Copyright (C) 2021-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,6 +50,8 @@ public class DmiPluginRegistration { private List<String> removedCmHandles = Collections.emptyList(); + private UpgradedCmHandles upgradedCmHandles; + /** * Validates plugin service names. * @throws NcmpException if validation fails. @@ -80,7 +82,7 @@ public class DmiPluginRegistration { } } - private static boolean isNullEmptyOrBlank(final String serviceName) { + public static boolean isNullEmptyOrBlank(final String serviceName) { return Strings.isNullOrEmpty(serviceName) || serviceName.isBlank(); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistrationResponse.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistrationResponse.java index 8a3d26414a..ee034176e3 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistrationResponse.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistrationResponse.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2022 Bell Canada + * Modifications Copyright (C) 2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,4 +32,5 @@ public class DmiPluginRegistrationResponse { private List<CmHandleRegistrationResponse> createdCmHandles = Collections.emptyList(); private List<CmHandleRegistrationResponse> updatedCmHandles = Collections.emptyList(); private List<CmHandleRegistrationResponse> removedCmHandles = Collections.emptyList(); + private List<CmHandleRegistrationResponse> upgradedCmHandles = Collections.emptyList(); }
\ No newline at end of file diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java index ae40d330ba..0b50346f81 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2022 Nordix Foundation + * Copyright (C) 2021-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,7 +28,7 @@ import java.util.Map; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.onap.cps.ncmp.api.inventory.CompositeState; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState; import org.springframework.validation.annotation.Validated; /** @@ -52,6 +52,9 @@ public class NcmpServiceCmHandle { @JsonSetter(nulls = Nulls.AS_EMPTY) private CompositeState compositeState; + @JsonSetter(nulls = Nulls.AS_EMPTY) + private String moduleSetTag; + /** * NcmpServiceCmHandle copy constructor. * @@ -63,5 +66,6 @@ public class NcmpServiceCmHandle { this.publicProperties = new LinkedHashMap<>(ncmpServiceCmHandle.getPublicProperties()); this.compositeState = ncmpServiceCmHandle.getCompositeState() != null ? new CompositeState( ncmpServiceCmHandle.getCompositeState()) : null; + this.moduleSetTag = ncmpServiceCmHandle.getModuleSetTag(); } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/UpgradedCmHandles.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/UpgradedCmHandles.java new file mode 100644 index 0000000000..61cd99ac8f --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/UpgradedCmHandles.java @@ -0,0 +1,36 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.api.models; + +import com.fasterxml.jackson.annotation.JsonInclude; +import java.util.Collections; +import java.util.List; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class UpgradedCmHandles { + private List<String> cmHandles = Collections.emptyList(); + private String moduleSetTag; +} + diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java index 5316d666d5..b805cdcd84 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java @@ -20,6 +20,9 @@ package org.onap.cps.ncmp.init; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR; + import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.CpsAdminService; import org.onap.cps.api.CpsDataService; @@ -32,8 +35,6 @@ public class InventoryModelLoader extends AbstractModelLoader { private static final String NEW_MODEL_FILE_NAME = "dmi-registry@2023-08-23.yang"; private static final String NEW_SCHEMA_SET_NAME = "dmi-registry-2023-08-23"; - private static final String DATASPACE_NAME = "NCMP-Admin"; - private static final String ANCHOR_NAME = "ncmp-dmi-registry"; public InventoryModelLoader(final CpsAdminService cpsAdminService, final CpsModuleService cpsModuleService, @@ -43,20 +44,20 @@ public class InventoryModelLoader extends AbstractModelLoader { @Override public void onboardOrUpgradeModel() { - waitUntilDataspaceIsAvailable(DATASPACE_NAME); + waitUntilDataspaceIsAvailable(NCMP_DATASPACE_NAME); updateInventoryModel(); log.info("Inventory Model updated successfully"); } private void updateInventoryModel() { - createSchemaSet(DATASPACE_NAME, NEW_SCHEMA_SET_NAME, NEW_MODEL_FILE_NAME); - updateAnchorSchemaSet(DATASPACE_NAME, ANCHOR_NAME, NEW_SCHEMA_SET_NAME); + createSchemaSet(NCMP_DATASPACE_NAME, NEW_SCHEMA_SET_NAME, NEW_MODEL_FILE_NAME); + updateAnchorSchemaSet(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NEW_SCHEMA_SET_NAME); deleteOldButNotThePreviousSchemaSets(); } private void deleteOldButNotThePreviousSchemaSets() { //No schema sets passed in yet, but wil be required for future updates - deleteUnusedSchemaSets(DATASPACE_NAME); + deleteUnusedSchemaSets(NCMP_DATASPACE_NAME); } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/SubscriptionModelLoader.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/SubscriptionModelLoader.java index 891244c7ca..4d1a91ca99 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/SubscriptionModelLoader.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/SubscriptionModelLoader.java @@ -20,6 +20,8 @@ package org.onap.cps.ncmp.init; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME; + import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.CpsAdminService; import org.onap.cps.api.CpsDataService; @@ -32,7 +34,6 @@ import org.springframework.stereotype.Service; public class SubscriptionModelLoader extends AbstractModelLoader { private static final String MODEL_FILENAME = "subscription.yang"; - private static final String DATASPACE_NAME = "NCMP-Admin"; private static final String ANCHOR_NAME = "AVC-Subscriptions"; private static final String SCHEMASET_NAME = "subscriptions"; private static final String REGISTRY_DATANODE_NAME = "subscription-registry"; @@ -49,7 +50,7 @@ public class SubscriptionModelLoader extends AbstractModelLoader { @Override public void onboardOrUpgradeModel() { if (subscriptionModelLoaderEnabled) { - waitUntilDataspaceIsAvailable(DATASPACE_NAME); + waitUntilDataspaceIsAvailable(NCMP_DATASPACE_NAME); onboardSubscriptionModel(); log.info("Subscription Model onboarded successfully"); } else { @@ -58,9 +59,9 @@ public class SubscriptionModelLoader extends AbstractModelLoader { } private void onboardSubscriptionModel() { - createSchemaSet(DATASPACE_NAME, SCHEMASET_NAME, MODEL_FILENAME); - createAnchor(DATASPACE_NAME, SCHEMASET_NAME, ANCHOR_NAME); - createTopLevelDataNode(DATASPACE_NAME, ANCHOR_NAME, REGISTRY_DATANODE_NAME); + createSchemaSet(NCMP_DATASPACE_NAME, SCHEMASET_NAME, MODEL_FILENAME); + createAnchor(NCMP_DATASPACE_NAME, SCHEMASET_NAME, ANCHOR_NAME); + createTopLevelDataNode(NCMP_DATASPACE_NAME, ANCHOR_NAME, REGISTRY_DATANODE_NAME); } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceSpec.groovy index 93af7f4bf4..ce6d856589 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceSpec.groovy @@ -20,11 +20,13 @@ package org.onap.cps.ncmp.api.impl +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT + import org.onap.cps.cpspath.parser.PathParsingException import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle -import org.onap.cps.ncmp.api.inventory.CmHandleQueries -import org.onap.cps.ncmp.api.inventory.CmHandleQueriesImpl -import org.onap.cps.ncmp.api.inventory.InventoryPersistence +import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries +import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueriesImpl +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle import org.onap.cps.spi.FetchDescendantsOption @@ -40,7 +42,7 @@ class NetworkCmProxyCmHandleQueryServiceSpec extends Specification { def partiallyMockedCmHandleQueries = Spy(CmHandleQueriesImpl) def mockInventoryPersistence = Mock(InventoryPersistence) - def dmiRegistry = new DataNode(xpath: '/dmi-registry', childDataNodes: createDataNodeList(['PNFDemo1', 'PNFDemo2', 'PNFDemo3', 'PNFDemo4'])) + def dmiRegistry = new DataNode(xpath: NCMP_DMI_REGISTRY_PARENT, childDataNodes: createDataNodeList(['PNFDemo1', 'PNFDemo2', 'PNFDemo3', 'PNFDemo4'])) def objectUnderTest = new NetworkCmProxyCmHandleQueryServiceImpl(cmHandleQueries, mockInventoryPersistence) def objectUnderTestWithPartiallyMockedQueries = new NetworkCmProxyCmHandleQueryServiceImpl(partiallyMockedCmHandleQueries, mockInventoryPersistence) @@ -51,7 +53,7 @@ class NetworkCmProxyCmHandleQueryServiceSpec extends Specification { def conditionProperties = createConditionProperties('cmHandleWithCpsPath', [['cpsPath' : '/some/cps/path']]) cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties]) and: 'the query get the cm handle datanodes excluding all descendants returns a datanode' - cmHandleQueries.queryCmHandleDataNodesByCpsPath('/some/cps/path', FetchDescendantsOption.OMIT_DESCENDANTS) >> [new DataNode(leaves: ['id':'some-cmhandle-id'])] + cmHandleQueries.queryCmHandleAncestorsByCpsPath('/some/cps/path', FetchDescendantsOption.OMIT_DESCENDANTS) >> [new DataNode(leaves: ['id':'some-cmhandle-id'])] when: 'the query is executed for cm handle ids' def result = objectUnderTest.queryCmHandleIds(cmHandleQueryParameters) then: 'the correct expected cm handles ids are returned' @@ -64,7 +66,7 @@ class NetworkCmProxyCmHandleQueryServiceSpec extends Specification { def conditionProperties = createConditionProperties('cmHandleWithCpsPath', [['cpsPath' : '/some/cps/path']]) cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties]) and: 'cmHandleQueries throws a path parsing exception' - cmHandleQueries.queryCmHandleDataNodesByCpsPath('/some/cps/path', FetchDescendantsOption.OMIT_DESCENDANTS) >> { throw thrownException } + cmHandleQueries.queryCmHandleAncestorsByCpsPath('/some/cps/path', FetchDescendantsOption.OMIT_DESCENDANTS) >> { throw thrownException } when: 'the query is executed for cm handle ids' objectUnderTest.queryCmHandleIds(cmHandleQueryParameters) then: 'a data validation exception is thrown' @@ -126,7 +128,7 @@ class NetworkCmProxyCmHandleQueryServiceSpec extends Specification { given: 'We use an empty query' def cmHandleQueryParameters = new CmHandleQueryServiceParameters() and: 'the inventory persistence returns the dmi registry datanode with just ids' - mockInventoryPersistence.getDataNode("/dmi-registry", FetchDescendantsOption.DIRECT_CHILDREN_ONLY) >> [dmiRegistry] + mockInventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT, FetchDescendantsOption.DIRECT_CHILDREN_ONLY) >> [dmiRegistry] when: 'the query is executed for both cm handle ids' def result = objectUnderTest.queryCmHandleIds(cmHandleQueryParameters) then: 'the correct expected cm handles are returned' @@ -137,7 +139,7 @@ class NetworkCmProxyCmHandleQueryServiceSpec extends Specification { given: 'We use an empty query' def cmHandleQueryParameters = new CmHandleQueryServiceParameters() and: 'the inventory persistence returns the dmi registry datanode with just ids' - mockInventoryPersistence.getDataNode("/dmi-registry") >> [dmiRegistry] + mockInventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT) >> [dmiRegistry] when: 'the query is executed for both cm handle details' def result = objectUnderTest.queryCmHandles(cmHandleQueryParameters) then: 'the correct cm handles are returned' diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy index 8942c42f13..9e4737fff0 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy @@ -21,6 +21,12 @@ package org.onap.cps.ncmp.api.impl +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_ALREADY_EXIST +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID +import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR +import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.Status + import com.fasterxml.jackson.databind.ObjectMapper import com.hazelcast.map.IMap import org.onap.cps.api.CpsDataService @@ -29,10 +35,11 @@ import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler import org.onap.cps.ncmp.api.impl.exception.DmiRequestException import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations +import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle -import org.onap.cps.ncmp.api.inventory.CmHandleQueries -import org.onap.cps.ncmp.api.inventory.CmHandleState -import org.onap.cps.ncmp.api.inventory.InventoryPersistence +import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse import org.onap.cps.ncmp.api.models.DmiPluginRegistration import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle @@ -44,12 +51,6 @@ import org.onap.cps.utils.JsonObjectMapper import spock.lang.Shared import spock.lang.Specification -import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.CM_HANDLE_DOES_NOT_EXIST -import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.CM_HANDLE_ALREADY_EXIST -import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.CM_HANDLE_INVALID_ID -import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.UNKNOWN_ERROR -import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.Status - class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { @Shared @@ -65,6 +66,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { def mockLcmEventsCmHandleStateHandler = Mock(LcmEventsCmHandleStateHandler) def mockCpsDataService = Mock(CpsDataService) def mockModuleSyncStartedOnCmHandles = Mock(IMap<String, Object>) + def mockTrustLevelPerDmiPlugin = Mock(IMap<String, TrustLevel>) def objectUnderTest = getObjectUnderTest() def 'DMI Registration: Create, Update & Delete operations are processed in the right order'() { @@ -78,11 +80,11 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { when: 'registration is processed' objectUnderTest.updateDmiRegistrationAndSyncModule(dmiRegistration) then: 'cm-handles are removed first' - 1 * objectUnderTest.parseAndRemoveCmHandlesInDmiRegistration(*_) + 1 * objectUnderTest.parseAndProcessDeletedCmHandlesInRegistration(*_) and: 'de-registered cm handle entry is removed from in progress map' 1 * mockModuleSyncStartedOnCmHandles.remove('cmhandle-2') then: 'cm-handles are created' - 1 * objectUnderTest.parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(*_) + 1 * objectUnderTest.parseAndProcessCreatedCmHandlesInRegistration(*_) then: 'cm-handles are updated' 1 * mockNetworkCmProxyDataServicePropertyHandler.updateCmHandleProperties(*_) } @@ -98,10 +100,10 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { mockNetworkCmProxyDataServicePropertyHandler.updateCmHandleProperties(*_) >> updateResponses and: 'create cm-handles can be processed successfully' def createdResponses = [CmHandleRegistrationResponse.createSuccessResponse('cmhandle-1')] - objectUnderTest.parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(*_) >> createdResponses + objectUnderTest.parseAndProcessCreatedCmHandlesInRegistration(*_) >> createdResponses and: 'delete cm-handles can be processed successfully' def removeResponses = [CmHandleRegistrationResponse.createSuccessResponse('cmhandle-3')] - objectUnderTest.parseAndRemoveCmHandlesInDmiRegistration(*_) >> removeResponses + objectUnderTest.parseAndProcessDeletedCmHandlesInRegistration(*_) >> removeResponses when: 'registration is processed' def response = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiRegistration) then: 'response has values from all operations' @@ -118,12 +120,14 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { when: 'update registration and sync module is called with correct DMI plugin information' objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration) then: 'create cm handles registration and sync modules is called with the correct plugin information' - 1 * objectUnderTest.parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(dmiPluginRegistration) + 1 * objectUnderTest.parseAndProcessCreatedCmHandlesInRegistration(dmiPluginRegistration) + and: 'dmi is added to the trustLevel map' + 1 * mockTrustLevelPerDmiPlugin.put(dmiPluginRegisteredName, TrustLevel.COMPLETE) where: - scenario | dmiPlugin | dmiModelPlugin | dmiDataPlugin - 'combined DMI plugin' | 'service1' | '' | '' - 'data & model DMI plugins' | '' | 'service1' | 'service2' - 'data & model using same service' | '' | 'service1' | 'service1' + scenario | dmiPlugin | dmiModelPlugin | dmiDataPlugin | dmiPluginRegisteredName + 'combined DMI plugin' | 'service1' | '' | '' | 'service1' + 'data & model DMI plugins' | '' | 'service1' | 'service2' | 'service2' + 'data & model using same service' | '' | 'service1' | 'service1' | 'service1' } def 'Create CM-handle Validation: Invalid DMI plugin service name with #scenario'() { @@ -137,7 +141,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { def exceptionThrown = thrown(DmiRequestException.class) assert exceptionThrown.getMessage().contains(expectedMessageDetails) and: 'registration is not called' - 0 * objectUnderTest.parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(dmiPluginRegistration) + 0 * objectUnderTest.parseAndProcessCreatedCmHandlesInRegistration(dmiPluginRegistration) where: scenario | dmiPlugin | dmiModelPlugin | dmiDataPlugin || expectedMessageDetails 'empty DMI plugins' | '' | '' | '' || 'No DMI plugin service names' @@ -199,7 +203,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { response.createdCmHandles.each { assert it.cmHandle == 'cmhandle2' assert it.status == Status.FAILURE - assert it.registrationError == CM_HANDLE_ALREADY_EXIST + assert it.ncmpResponseStatus == CM_HANDLE_ALREADY_EXIST assert it.errorText == 'cm-handle already exists' } } @@ -217,7 +221,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { with(response.createdCmHandles[0]) { assert it.status == Status.FAILURE assert it.cmHandle == 'cmhandle' - assert it.registrationError == expectedError + assert it.ncmpResponseStatus == expectedError assert it.errorText == expectedErrorText } where: @@ -232,7 +236,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { and: 'cm-handle updates can be processed successfully' def updateOperationResponse = [CmHandleRegistrationResponse.createSuccessResponse('cm-handle-1'), CmHandleRegistrationResponse.createFailureResponse('cm-handle-2', new Exception("Failed")), - CmHandleRegistrationResponse.createFailureResponse('cm-handle-3', CM_HANDLE_DOES_NOT_EXIST), + CmHandleRegistrationResponse.createFailureResponse('cm-handle-3', CM_HANDLES_NOT_FOUND), CmHandleRegistrationResponse.createFailureResponse('cm handle 4', CM_HANDLE_INVALID_ID)] mockNetworkCmProxyDataServicePropertyHandler.updateCmHandleProperties(_) >> updateOperationResponse when: 'registration is updated' @@ -306,7 +310,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { and: '2nd cm-handle deletion fails' with(response.removedCmHandles[1]) { assert it.status == Status.FAILURE - assert it.registrationError == UNKNOWN_ERROR + assert it.ncmpResponseStatus == UNKNOWN_ERROR assert it.errorText == 'Failed' assert it.cmHandle == 'cmhandle2' } @@ -340,7 +344,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { assert it.status == Status.FAILURE assert it.cmHandle == 'cmhandle' assert it.errorText == 'Failed' - assert it.registrationError == UNKNOWN_ERROR + assert it.ncmpResponseStatus == UNKNOWN_ERROR } } @@ -360,23 +364,23 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { with(response.removedCmHandles[0]) { assert it.status == Status.FAILURE assert it.cmHandle == 'cmhandle' - assert it.registrationError == expectedError + assert it.ncmpResponseStatus == expectedError assert it.errorText == expectedErrorText } and: 'the cm handle state is not updated to "DELETED"' 0 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_, CmHandleState.DELETED) where: - scenario | cmHandleId | deleteListElementException || expectedError | expectedErrorText - 'cm-handle does not exist' | 'cmhandle' | new DataNodeNotFoundException('', '', '') || CM_HANDLE_DOES_NOT_EXIST | 'cm-handle does not exist' - 'cm-handle has invalid name' | 'cm handle with space' | new DataValidationException('', '') || CM_HANDLE_INVALID_ID | 'cm-handle has an invalid character(s) in id' - 'an unexpected exception' | 'cmhandle' | new RuntimeException('Failed') || UNKNOWN_ERROR | 'Failed' + scenario | cmHandleId | deleteListElementException || expectedError | expectedErrorText + 'cm-handle does not exist' | 'cmhandle' | new DataNodeNotFoundException('', '', '') || CM_HANDLES_NOT_FOUND | 'cm handle id(s) not found' + 'cm-handle has invalid name' | 'cm handle with space' | new DataValidationException('', '') || CM_HANDLE_INVALID_ID | 'cm-handle has an invalid character(s) in id' + 'an unexpected exception' | 'cmhandle' | new RuntimeException('Failed') || UNKNOWN_ERROR | 'Failed' } def getObjectUnderTest() { return Spy(new NetworkCmProxyDataServiceImpl(spiedJsonObjectMapper, mockDmiDataOperations, mockNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, mockCmhandleQueries, stubbedNetworkCmProxyCmHandlerQueryService, mockLcmEventsCmHandleStateHandler, mockCpsDataService, - mockModuleSyncStartedOnCmHandles)) + mockModuleSyncStartedOnCmHandles, mockTrustLevelPerDmiPlugin)) } def addPersistedYangModelCmHandles(ids) { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy index 75af0439bd..0d9aa6124a 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy @@ -23,16 +23,26 @@ package org.onap.cps.ncmp.api.impl +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR +import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.OPERATIONAL +import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL +import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING +import static org.onap.cps.ncmp.api.impl.operations.OperationType.CREATE +import static org.onap.cps.ncmp.api.impl.operations.OperationType.UPDATE + import com.hazelcast.map.IMap import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler +import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle -import org.onap.cps.ncmp.api.inventory.CmHandleQueries -import org.onap.cps.ncmp.api.inventory.CmHandleState -import org.onap.cps.ncmp.api.inventory.CompositeState -import org.onap.cps.ncmp.api.inventory.InventoryPersistence -import org.onap.cps.ncmp.api.inventory.LockReasonCategory -import org.onap.cps.ncmp.api.inventory.DataStoreSyncState +import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState +import org.onap.cps.ncmp.api.impl.inventory.CompositeState +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence +import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory +import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState import org.onap.cps.ncmp.api.models.DataOperationDefinition import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters @@ -54,12 +64,6 @@ import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import spock.lang.Specification -import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.OPERATIONAL -import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL -import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING -import static org.onap.cps.ncmp.api.impl.operations.OperationType.CREATE -import static org.onap.cps.ncmp.api.impl.operations.OperationType.UPDATE - class NetworkCmProxyDataServiceImplSpec extends Specification { def mockCpsDataService = Mock(CpsDataService) @@ -72,6 +76,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { def mockCpsCmHandlerQueryService = Mock(NetworkCmProxyCmHandleQueryService) def mockLcmEventsCmHandleStateHandler = Mock(LcmEventsCmHandleStateHandler) def stubModuleSyncStartedOnCmHandles = Stub(IMap<String, Object>) + def stubTrustLevelPerDmiPlugin = Stub(IMap<String, TrustLevel>) def NO_TOPIC = null def NO_REQUEST_ID = null @@ -89,7 +94,8 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { mockCpsCmHandlerQueryService, mockLcmEventsCmHandleStateHandler, mockCpsDataService, - stubModuleSyncStartedOnCmHandles) + stubModuleSyncStartedOnCmHandles, + stubTrustLevelPerDmiPlugin) def cmHandleXPath = "/dmi-registry/cm-handles[@id='testCmHandle']" @@ -163,7 +169,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { given: 'the system returns a yang modelled cm handle' def dmiServiceName = 'some service name' def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED, - lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.LOCKED_MODULE_SYNC_FAILED).details("lock details").build(), + lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.MODULE_SYNC_FAILED).details("lock details").build(), lastUpdateTime: 'some-timestamp', dataSyncEnabled: false, dataStores: dataStores()) @@ -220,7 +226,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { def 'Get cm handle composite state'() { given: 'a yang modelled cm handle' def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED, - lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.LOCKED_MODULE_SYNC_FAILED).details("lock details").build(), + lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.MODULE_SYNC_FAILED).details("lock details").build(), lastUpdateTime: 'some-timestamp', dataSyncEnabled: false, dataStores: dataStores()) @@ -237,8 +243,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { def 'Update resource data for pass-through running from dmi using POST #scenario DMI properties.'() { given: 'cpsDataService returns valid datanode' - mockCpsDataService.getDataNodes('NCMP-Admin', 'ncmp-dmi-registry', - cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode + mockCpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode when: 'get resource data is called' objectUnderTest.writeResourceDataPassThroughRunningForCmHandle('testCmHandle', 'testResourceId', UPDATE, @@ -256,7 +261,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { dmiPluginRegistration.createdCmHandles = [ncmpServiceCmHandle] mockDmiPluginRegistration.getCreatedCmHandles() >> [ncmpServiceCmHandle] when: 'parse and create cm handle in dmi registration then sync module' - objectUnderTest.parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(mockDmiPluginRegistration) + objectUnderTest.parseAndProcessCreatedCmHandlesInRegistration(mockDmiPluginRegistration) then: 'system persists the cm handle state' 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_) >> { args -> { @@ -325,7 +330,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { and: 'the data store sync state is set to #expectedDataStoreSyncState' compositeState.dataStores.operationalDataStore.dataStoreSyncState == expectedDataStoreSyncState and: 'the cps data service to delete data nodes is invoked the expected number of times' - deleteDataNodeExpectedNumberOfInvocation * mockCpsDataService.deleteDataNode('NFP-Operational', 'some-cm-handle-id', '/netconf-state', _) + deleteDataNodeExpectedNumberOfInvocation * mockCpsDataService.deleteDataNode(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'some-cm-handle-id', '/netconf-state', _) and: 'the inventory persistence service to update node leaves is called with the correct values' saveCmHandleStateExpectedNumberOfInvocations * mockInventoryPersistence.saveCmHandleState('some-cm-handle-id', compositeState) where: 'the following data sync enabled flag is used' @@ -368,8 +373,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { } def mockDataNode() { - mockCpsDataService.getDataNodes('NCMP-Admin', 'ncmp-dmi-registry', - cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode + mockCpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode } def getDataOperationRequest(datastore) { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy index 0df61f4e0b..6439f0b58a 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * Modifications Copyright (C) 2023 TechMahindra Ltd. * ================================================================================ @@ -22,14 +22,15 @@ package org.onap.cps.ncmp.api.impl -import org.onap.cps.ncmp.api.inventory.InventoryPersistence -import org.onap.cps.spi.exceptions.DataValidationException - -import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.CM_HANDLE_DOES_NOT_EXIST -import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.CM_HANDLE_INVALID_ID -import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.UNKNOWN_ERROR +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID +import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.Status +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence +import org.onap.cps.spi.exceptions.DataValidationException import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle import org.onap.cps.spi.exceptions.DataNodeNotFoundException import org.onap.cps.spi.model.DataNode @@ -130,14 +131,14 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification { with(response.get(0)) { assert it.status == Status.FAILURE assert it.cmHandle == cmHandleId - assert it.registrationError == expectedError + assert it.ncmpResponseStatus == expectedError assert it.errorText == expectedErrorText } where: - scenario | cmHandleId | exception || expectedError | expectedErrorText - 'Cm Handle does not exist' | 'cmHandleId' | new DataNodeNotFoundException('NCMP-Admin', 'ncmp-dmi-registry') || CM_HANDLE_DOES_NOT_EXIST | 'cm-handle does not exist' - 'Unknown' | 'cmHandleId' | new RuntimeException('Failed') || UNKNOWN_ERROR | 'Failed' - 'Invalid cm handle id' | 'cmHandleId with spaces' | new DataValidationException('Name Validation Error.', cmHandleId + 'contains an invalid character') || CM_HANDLE_INVALID_ID | 'cm-handle has an invalid character(s) in id' + scenario | cmHandleId | exception || expectedError | expectedErrorText + 'Cm Handle does not exist' | 'cmHandleId' | new DataNodeNotFoundException(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR) || CM_HANDLES_NOT_FOUND | 'cm handle id(s) not found' + 'Unknown' | 'cmHandleId' | new RuntimeException('Failed') || UNKNOWN_ERROR | 'Failed' + 'Invalid cm handle id' | 'cmHandleId with spaces' | new DataValidationException('Name Validation Error.', cmHandleId + 'contains an invalid character') || CM_HANDLE_INVALID_ID | 'cm-handle has an invalid character(s) in id' } def 'Multiple update operations in a single request'() { @@ -147,7 +148,7 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification { new NcmpServiceCmHandle(cmHandleId: cmHandleId, publicProperties: ['publicProp1': "value"], dmiProperties: [:])] and: 'data node can be found for 1st and 3rd cm-handle but not for 2nd cm-handle' mockInventoryPersistence.getCmHandleDataNode(*_) >> cmHandleDataNodeAsCollection >> { - throw new DataNodeNotFoundException('NCMP-Admin', 'ncmp-dmi-registry') } >> cmHandleDataNodeAsCollection + throw new DataNodeNotFoundException(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR) } >> cmHandleDataNodeAsCollection when: 'update data node leaves is called using correct parameters' def cmHandleResponseList = objectUnderTest.updateCmHandleProperties(cmHandleUpdateRequest) then: 'response has 3 values' @@ -165,8 +166,8 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification { with(cmHandleResponseList.get(1)) { assert it.status == Status.FAILURE assert it.cmHandle == cmHandleId - assert it.registrationError == CM_HANDLE_DOES_NOT_EXIST - assert it.errorText == "cm-handle does not exist" + assert it.ncmpResponseStatus == CM_HANDLES_NOT_FOUND + assert it.errorText == 'cm handle id(s) not found' } then: 'the replace list method is called twice' 2 * mockInventoryPersistence.replaceListContent(cmHandleXpath,_) diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImplSpec.groovy index 1e86a0b80a..5f4f248c65 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImplSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,9 @@ package org.onap.cps.ncmp.api.impl +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR + import org.onap.cps.api.CpsQueryService import org.onap.cps.spi.FetchDescendantsOption import org.onap.cps.spi.model.DataNode @@ -35,10 +38,10 @@ class NetworkCmProxyQueryServiceImplSpec extends Specification { given: 'a list of datanodes' def dataNodes = [new DataNode(xpath: '/cps/path'), new DataNode(xpath: '/cps/path/child')] and: 'the list of datanodes is returned for query data node' - 1 * mockCpsQueryService.queryDataNodes('NFP-Operational', 'ncmp-dmi-registry', + 1 * mockCpsQueryService.queryDataNodes(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '//cps/path', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNodes when: 'query resource data operational for cm-handle is called' - def response = objectUnderTest.queryResourceDataOperational('ncmp-dmi-registry', + def response = objectUnderTest.queryResourceDataOperational(NCMP_DMI_REGISTRY_ANCHOR, '//cps/path', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) then: 'the expected datanodes are returned from the DMI' response == dataNodes diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfigSpec.groovy index c0fc18abfc..2fa9606923 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfigSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfigSpec.groovy @@ -44,6 +44,9 @@ class SynchronizationCacheConfigSpec extends Specification { @Autowired private IMap<String, Boolean> dataSyncSemaphores + @Autowired + private IMap<String, Set<String>> moduleSetTagCache + def 'Embedded (hazelcast) Caches for Module and Data Sync.'() { expect: 'system is able to create an instance of the Module Sync Work Queue' assert null != moduleSyncWorkQueue @@ -51,10 +54,12 @@ 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: 'there are at least 3 instances' - assert Hazelcast.allHazelcastInstances.size() > 2 + and: 'system is able to create an instance of a map to hold module set tags' + assert null != moduleSetTagCache + and: 'there are at least 4 instances' + assert Hazelcast.allHazelcastInstances.size() > 3 and: 'they have the correct names (in any order)' - assert Hazelcast.allHazelcastInstances.name.containsAll('moduleSyncWorkQueue', 'moduleSyncStartedOnCmHandles', 'dataSyncSemaphores' ) + assert Hazelcast.allHazelcastInstances.name.containsAll('moduleSyncWorkQueue', 'moduleSyncStartedOnCmHandles', 'dataSyncSemaphores', 'moduleSetTags') } def 'Verify configs for Distributed objects'(){ @@ -67,6 +72,9 @@ class SynchronizationCacheConfigSpec extends Specification { and: 'the Data Sync Semaphores Map config' def dataSyncSemaphoresConfig = Hazelcast.getHazelcastInstanceByName('dataSyncSemaphores').config def dataSyncSemaphoresMapConfig = dataSyncSemaphoresConfig.mapConfigs.get('dataSyncSemaphoresConfig') + and: 'the Module Set Tag Map config' + def moduleSetTagCacheConfig = Hazelcast.getHazelcastInstanceByName('moduleSetTags').config + def moduleSetTagMapConfig = moduleSetTagCacheConfig.mapConfigs.get('moduleSetTagCacheMapConfig') expect: 'system created instance with correct config of Module Sync Work Queue' assert moduleSyncDefaultWorkQueueConfig.backupCount == 3 assert moduleSyncDefaultWorkQueueConfig.asyncBackupCount == 3 @@ -76,11 +84,15 @@ class SynchronizationCacheConfigSpec extends Specification { and: 'Data Sync Semaphore Map has the correct settings' assert dataSyncSemaphoresMapConfig.backupCount == 3 assert dataSyncSemaphoresMapConfig.asyncBackupCount == 3 + and: 'Module Set Tag Map has the correct settings' + assert moduleSetTagMapConfig.backupCount == 3 + assert moduleSetTagMapConfig.asyncBackupCount == 3 and: 'all instances are part of same cluster' def testClusterName = 'cps-and-ncmp-test-caches' assert moduleSyncWorkQueueConfig.clusterName == testClusterName assert moduleSyncStartedOnCmHandlesConfig.clusterName == testClusterName assert dataSyncSemaphoresConfig.clusterName == testClusterName + assert moduleSetTagCacheConfig.clusterName == testClusterName } def 'Verify deployment network configs for Distributed objects'() { @@ -90,6 +102,8 @@ class SynchronizationCacheConfigSpec extends Specification { def moduleSyncStartedOnCmHandlesNetworkConfig = Hazelcast.getHazelcastInstanceByName('moduleSyncStartedOnCmHandles').config.networkConfig and: 'the Data Sync Semaphores Map config' def dataSyncSemaphoresNetworkConfig = Hazelcast.getHazelcastInstanceByName('dataSyncSemaphores').config.networkConfig + and: 'the Module Set Tag Map config' + def moduleSetTagNetworkConfig = Hazelcast.getHazelcastInstanceByName('moduleSetTags').config.networkConfig expect: 'system created instance with correct config of Module Sync Work Queue' assert queueNetworkConfig.join.autoDetectionConfig.enabled assert !queueNetworkConfig.join.kubernetesConfig.enabled @@ -99,7 +113,9 @@ class SynchronizationCacheConfigSpec extends Specification { and: 'Data Sync Semaphore Map has the correct settings' assert dataSyncSemaphoresNetworkConfig.join.autoDetectionConfig.enabled assert !dataSyncSemaphoresNetworkConfig.join.kubernetesConfig.enabled - + and: 'Module Set Tag Map has the correct settings' + assert moduleSetTagNetworkConfig.join.autoDetectionConfig.enabled + assert !moduleSetTagNetworkConfig.join.kubernetesConfig.enabled } def 'Verify network config'() { @@ -135,6 +151,15 @@ class SynchronizationCacheConfigSpec extends Specification { waitMax2SecondsForKeyExpiration(dataSyncSemaphores, 'testKeyDataSync') } + def 'Time to Live Verify for Module Set Tag'() { + when: 'the key is inserted with a TTL of 1 second' + moduleSetTagCache.put('testKeyModuleSetTag', ['module-set-tag'] as Set, 1, TimeUnit.SECONDS) + then: 'the entry is present in the map' + assert moduleSetTagCache.get('testKeyModuleSetTag') != null + and: 'the entry expires in less then 2 seconds' + waitMax2SecondsForKeyExpiration(moduleSetTagCache, 'testKeyModuleSetTag') + } + def waitMax2SecondsForKeyExpiration(map, key) { def count = 0 while ( map.get(key)!=null && ++count <= 20 ) { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionDmiOutEventConsumerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionDmiOutEventConsumerSpec.groovy index 175ead8062..95dee77bf3 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionDmiOutEventConsumerSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionDmiOutEventConsumerSpec.groovy @@ -20,6 +20,8 @@ package org.onap.cps.ncmp.api.impl.events.cmsubscription +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME + import com.fasterxml.jackson.databind.ObjectMapper import com.hazelcast.map.IMap import io.cloudevents.CloudEvent @@ -131,7 +133,7 @@ class CmSubscriptionDmiOutEventConsumerSpec extends MessagingBaseSpec { def getDataNode() { def leaves = [status:'ACCEPTED', cmHandleId:'cmhandle1'] as Map - return new DataNodeBuilder().withDataspace('NCMP-Admin') + return new DataNodeBuilder().withDataspace(NCMP_DATASPACE_NAME) .withAnchor('AVC-Subscriptions').withXpath('/subscription-registry/subscription') .withLeaves(leaves).build() } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpInEventForwarderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpInEventForwarderSpec.groovy index fd1a83ee08..1edfa58f9a 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpInEventForwarderSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpInEventForwarderSpec.groovy @@ -20,6 +20,8 @@ package org.onap.cps.ncmp.api.impl.events.cmsubscription +import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent + import com.fasterxml.jackson.databind.ObjectMapper import com.hazelcast.map.IMap import io.cloudevents.CloudEvent @@ -30,12 +32,9 @@ import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionStatus import org.onap.cps.ncmp.api.impl.utils.CmSubscriptionEventCloudMapper import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle import org.onap.cps.ncmp.api.impl.yangmodels.YangModelSubscriptionEvent.TargetCmHandle -import org.onap.cps.ncmp.api.inventory.InventoryPersistence +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence import org.onap.cps.ncmp.api.kafka.MessagingBaseSpec -import org.onap.cps.ncmp.api.models.CmSubscriptionEvent import org.onap.cps.ncmp.events.cmsubscription1_0_0.client_to_ncmp.CmSubscriptionNcmpInEvent -import org.onap.cps.ncmp.events.cmsubscription1_0_0.dmi_to_ncmp.CmSubscriptionDmiOutEvent -import org.onap.cps.ncmp.events.cmsubscription1_0_0.dmi_to_ncmp.Data import org.onap.cps.ncmp.events.cmsubscription1_0_0.ncmp_to_dmi.CmHandle import org.onap.cps.ncmp.events.cmsubscription1_0_0.ncmp_to_dmi.CmSubscriptionDmiInEvent import org.onap.cps.ncmp.utils.TestUtils @@ -46,8 +45,6 @@ import org.springframework.boot.test.context.SpringBootTest import spock.util.concurrent.BlockingVariable import java.util.concurrent.TimeUnit -import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent - @SpringBootTest(classes = [ObjectMapper, JsonObjectMapper, CmSubscriptionNcmpInEventForwarder]) class CmSubscriptionNcmpInEventForwarderSpec extends MessagingBaseSpec { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisherSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisherSpec.groovy index cc14195191..a0567cb4cb 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisherSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisherSpec.groovy @@ -20,11 +20,15 @@ package org.onap.cps.ncmp.api.impl.events.cmsubscription +import static org.onap.cps.ncmp.api.NcmpResponseStatus.SUCCESSFULLY_APPLIED_SUBSCRIPTION +import static org.onap.cps.ncmp.api.NcmpResponseStatus.SUBSCRIPTION_PENDING +import static org.onap.cps.ncmp.api.NcmpResponseStatus.SUBSCRIPTION_NOT_APPLICABLE +import static org.onap.cps.ncmp.api.NcmpResponseStatus.PARTIALLY_APPLIED_SUBSCRIPTION + import com.fasterxml.jackson.databind.ObjectMapper import io.cloudevents.CloudEvent import io.cloudevents.core.builder.CloudEventBuilder import org.mapstruct.factory.Mappers -import org.onap.cps.ncmp.api.NcmpEventResponseCode import org.onap.cps.ncmp.api.impl.events.EventsPublisher import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionPersistence import org.onap.cps.ncmp.api.impl.utils.DataNodeBaseSpec @@ -98,9 +102,9 @@ class CmSubscriptionNcmpOutEventPublisherSpec extends DataNodeBaseSpec { then: 'the result will be equal to ncmp out event' expectedResult == ncmpOutEvent where: 'the following values are used' - scenario | ncmpEventResponseCode || statusMessage || statusCode - 'is full outcome' | NcmpEventResponseCode.SUCCESSFULLY_APPLIED_SUBSCRIPTION || 'successfully applied subscription' || 1 - 'is partial outcome' | NcmpEventResponseCode.PARTIALLY_APPLIED_SUBSCRIPTION || 'partially applied subscription' || 104 + scenario | ncmpEventResponseCode || statusMessage || statusCode + 'is full outcome' | SUCCESSFULLY_APPLIED_SUBSCRIPTION || 'successfully applied subscription' || 1 + 'is partial outcome' | PARTIALLY_APPLIED_SUBSCRIPTION || 'partially applied subscription' || 104 } def 'Check cm handle id to status map to see if it is a full outcome response'() { @@ -109,16 +113,16 @@ class CmSubscriptionNcmpOutEventPublisherSpec extends DataNodeBaseSpec { then: 'the result will be as expected' response == expectedOutcomeResponseDecision where: 'the following values are used' - scenario | cmHandleIdToStatusAndDetailsAsMap || expectedOutcomeResponseDecision - 'The map contains PENDING status' | [CMHandle1: [details:'Subscription forwarded to dmi plugin',status:'PENDING'] as Map] as Map || NcmpEventResponseCode.SUBSCRIPTION_PENDING - 'The map contains ACCEPTED status' | [CMHandle1: [details:'',status:'ACCEPTED'] as Map] as Map || NcmpEventResponseCode.SUCCESSFULLY_APPLIED_SUBSCRIPTION - 'The map contains REJECTED status' | [CMHandle1: [details:'Cm handle does not exist',status:'REJECTED'] as Map] as Map || NcmpEventResponseCode.SUBSCRIPTION_NOT_APPLICABLE - 'The map contains PENDING and PENDING statuses' | [CMHandle1: [details:'Some details',status:'PENDING'] as Map, CMHandle2: [details:'Some details',status:'PENDING'] as Map as Map] as Map || NcmpEventResponseCode.SUBSCRIPTION_PENDING - 'The map contains ACCEPTED and ACCEPTED statuses' | [CMHandle1: [details:'',status:'ACCEPTED'] as Map, CMHandle2: [details:'',status:'ACCEPTED'] as Map as Map] as Map || NcmpEventResponseCode.SUCCESSFULLY_APPLIED_SUBSCRIPTION - 'The map contains REJECTED and REJECTED statuses' | [CMHandle1: [details:'Reject details',status:'REJECTED'] as Map, CMHandle2: [details:'Reject details',status:'REJECTED'] as Map as Map] as Map || NcmpEventResponseCode.SUBSCRIPTION_NOT_APPLICABLE - 'The map contains PENDING and ACCEPTED statuses' | [CMHandle1: [details:'Some details',status:'PENDING'] as Map, CMHandle2: [details:'',status:'ACCEPTED'] as Map as Map] as Map || NcmpEventResponseCode.PARTIALLY_APPLIED_SUBSCRIPTION - 'The map contains REJECTED and ACCEPTED statuses' | [CMHandle1: [details:'Cm handle does not exist',status:'REJECTED'] as Map, CMHandle2: [details:'',status:'ACCEPTED'] as Map as Map] as Map || NcmpEventResponseCode.PARTIALLY_APPLIED_SUBSCRIPTION - 'The map contains PENDING and REJECTED statuses' | [CMHandle1: [details:'Subscription forwarded to dmi plugin',status:'PENDING'] as Map, CMHandle2: [details:'Cm handle does not exist',status:'REJECTED'] as Map as Map] as Map || NcmpEventResponseCode.PARTIALLY_APPLIED_SUBSCRIPTION + scenario | cmHandleIdToStatusAndDetailsAsMap || expectedOutcomeResponseDecision + 'The map contains PENDING status' | [CMHandle1: [details: 'Subscription forwarded to dmi plugin', status: 'PENDING'] as Map] as Map || SUBSCRIPTION_PENDING + 'The map contains ACCEPTED status' | [CMHandle1: [details: '', status: 'ACCEPTED'] as Map] as Map || SUCCESSFULLY_APPLIED_SUBSCRIPTION + 'The map contains REJECTED status' | [CMHandle1: [details: 'Cm handle does not exist', status: 'REJECTED'] as Map] as Map || SUBSCRIPTION_NOT_APPLICABLE + 'The map contains PENDING and PENDING statuses' | [CMHandle1: [details: 'Some details', status: 'PENDING'] as Map, CMHandle2: [details: 'Some details', status: 'PENDING'] as Map as Map] as Map || SUBSCRIPTION_PENDING + 'The map contains ACCEPTED and ACCEPTED statuses' | [CMHandle1: [details: '', status: 'ACCEPTED'] as Map, CMHandle2: [details: '', status: 'ACCEPTED'] as Map as Map] as Map || SUCCESSFULLY_APPLIED_SUBSCRIPTION + 'The map contains REJECTED and REJECTED statuses' | [CMHandle1: [details: 'Reject details', status: 'REJECTED'] as Map, CMHandle2: [details: 'Reject details', status: 'REJECTED'] as Map as Map] as Map || SUBSCRIPTION_NOT_APPLICABLE + 'The map contains PENDING and ACCEPTED statuses' | [CMHandle1: [details: 'Some details', status: 'PENDING'] as Map, CMHandle2: [details: '', status: 'ACCEPTED'] as Map as Map] as Map || PARTIALLY_APPLIED_SUBSCRIPTION + 'The map contains REJECTED and ACCEPTED statuses' | [CMHandle1: [details: 'Cm handle does not exist', status: 'REJECTED'] as Map, CMHandle2: [details: '', status: 'ACCEPTED'] as Map as Map] as Map || PARTIALLY_APPLIED_SUBSCRIPTION + 'The map contains PENDING and REJECTED statuses' | [CMHandle1: [details: 'Subscription forwarded to dmi plugin', status: 'PENDING'] as Map, CMHandle2: [details: 'Cm handle does not exist', status: 'REJECTED'] as Map as Map] as Map || PARTIALLY_APPLIED_SUBSCRIPTION } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy index 261b6e069d..0ec73a26a4 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy @@ -20,19 +20,19 @@ package org.onap.cps.ncmp.api.impl.events.lcm +import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.ADVISED +import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.DELETED +import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.DELETING +import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.LOCKED +import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.READY +import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.MODULE_SYNC_FAILED + import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle -import org.onap.cps.ncmp.api.inventory.CompositeState -import org.onap.cps.ncmp.api.inventory.DataStoreSyncState -import org.onap.cps.ncmp.api.inventory.InventoryPersistence +import org.onap.cps.ncmp.api.impl.inventory.CompositeState +import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence import spock.lang.Specification -import static org.onap.cps.ncmp.api.inventory.CmHandleState.ADVISED -import static org.onap.cps.ncmp.api.inventory.CmHandleState.DELETED -import static org.onap.cps.ncmp.api.inventory.CmHandleState.DELETING -import static org.onap.cps.ncmp.api.inventory.CmHandleState.LOCKED -import static org.onap.cps.ncmp.api.inventory.CmHandleState.READY -import static org.onap.cps.ncmp.api.inventory.LockReasonCategory.LOCKED_MODULE_SYNC_FAILED - class LcmEventsCmHandleStateHandlerImplSpec extends Specification { def mockInventoryPersistence = Mock(InventoryPersistence) @@ -80,7 +80,7 @@ class LcmEventsCmHandleStateHandlerImplSpec extends Specification { def 'Update and Publish Events on State Change from LOCKED to ADVISED'() { given: 'Cm Handle represented as YangModelCmHandle in LOCKED state' compositeState = new CompositeState(cmHandleState: LOCKED, - lockReason: CompositeState.LockReason.builder().lockReasonCategory(LOCKED_MODULE_SYNC_FAILED).details('some lock details').build()) + lockReason: CompositeState.LockReason.builder().lockReasonCategory(MODULE_SYNC_FAILED).details('some lock details').build()) yangModelCmHandle = new YangModelCmHandle(id: cmHandleId, dmiProperties: [], publicProperties: [], compositeState: compositeState) when: 'update state is invoked' objectUnderTest.updateCmHandleState(yangModelCmHandle, ADVISED) diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorSpec.groovy index 6d7d6250f1..09179539a6 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorSpec.groovy @@ -20,17 +20,17 @@ package org.onap.cps.ncmp.api.impl.events.lcm +import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.ADVISED +import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.DELETING +import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.READY + import org.mapstruct.factory.Mappers -import org.onap.cps.ncmp.api.inventory.CmHandleState -import org.onap.cps.ncmp.api.inventory.CompositeState +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState +import org.onap.cps.ncmp.api.impl.inventory.CompositeState import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle import org.onap.cps.ncmp.events.lcm.v1.Values import spock.lang.Specification -import static org.onap.cps.ncmp.api.inventory.CmHandleState.ADVISED -import static org.onap.cps.ncmp.api.inventory.CmHandleState.DELETING -import static org.onap.cps.ncmp.api.inventory.CmHandleState.READY - class LcmEventsCreatorSpec extends Specification { LcmEventHeaderMapper lcmEventsHeaderMapper = Mappers.getMapper(LcmEventHeaderMapper) diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy index 76ef23fe55..39c4fe6ee5 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy @@ -21,8 +21,16 @@ package org.onap.cps.ncmp.api.impl.operations +import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL +import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING +import static org.onap.cps.ncmp.api.impl.operations.OperationType.CREATE +import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ +import static org.onap.cps.ncmp.api.impl.operations.OperationType.UPDATE +import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent +import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNABLE_TO_READ_RESOURCE_DATA +import static org.onap.cps.ncmp.api.NcmpResponseStatus.DMI_SERVICE_NOT_RESPONDING + import com.fasterxml.jackson.databind.ObjectMapper -import org.onap.cps.ncmp.api.NcmpEventResponseCode import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration import org.onap.cps.ncmp.api.impl.events.EventsPublisher import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException @@ -41,13 +49,6 @@ import org.springframework.http.HttpStatus import spock.lang.Shared import java.util.concurrent.TimeoutException -import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL -import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING -import static org.onap.cps.ncmp.api.impl.operations.OperationType.CREATE -import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ -import static org.onap.cps.ncmp.api.impl.operations.OperationType.UPDATE -import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent - @SpringBootTest @ContextConfiguration(classes = [EventsPublisher, CpsApplicationContext, NcmpConfiguration.DmiProperties, DmiDataOperations]) class DmiDataOperationsSpec extends DmiOperationsBaseSpec { @@ -128,12 +129,12 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec { def eventDataValue = extractDataValue(actualDataOperationCloudEvent) assert eventDataValue.operationId == dmiDataOperation.operationId assert eventDataValue.ids == dmiDataOperation.cmHandles.id - assert eventDataValue.statusCode == responseCode.statusCode - assert eventDataValue.statusMessage == responseCode.statusMessage + assert eventDataValue.statusCode == responseCode.code + assert eventDataValue.statusMessage == responseCode.message where: 'the following exceptions are occurred' scenario | exception || responseCode - 'http client request exception' | new HttpClientRequestException('error-message', 'error-details', HttpStatus.SERVICE_UNAVAILABLE.value()) || NcmpEventResponseCode.UNABLE_TO_READ_RESOURCE_DATA - 'timeout exception' | new TimeoutException() || NcmpEventResponseCode.DMI_SERVICE_NOT_RESPONDING + 'http client request exception' | new HttpClientRequestException('error-message', 'error-details', HttpStatus.SERVICE_UNAVAILABLE.value()) || UNABLE_TO_READ_RESOURCE_DATA + 'timeout exception' | new TimeoutException() || DMI_SERVICE_NOT_RESPONDING } def 'call get all resource data.'() { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy index 1b2c50ae76..cc64255293 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2022 Nordix Foundation + * Copyright (C) 2021-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,9 +25,9 @@ import org.onap.cps.ncmp.api.impl.client.DmiRestClient import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder -import org.onap.cps.ncmp.api.inventory.CmHandleState -import org.onap.cps.ncmp.api.inventory.CompositeState -import org.onap.cps.ncmp.api.inventory.InventoryPersistence +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState +import org.onap.cps.ncmp.api.impl.inventory.CompositeState +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence import org.onap.cps.spi.utils.CpsValidator import org.spockframework.spring.SpringBean import spock.lang.Shared diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistenceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistenceSpec.groovy index 7116a17862..541a4f7ba1 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistenceSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistenceSpec.groovy @@ -20,25 +20,31 @@ package org.onap.cps.ncmp.api.impl.subscriptions +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NO_TIMESTAMP + import com.fasterxml.jackson.databind.ObjectMapper import org.onap.cps.api.CpsDataService import org.onap.cps.ncmp.api.impl.yangmodels.YangModelSubscriptionEvent import org.onap.cps.spi.model.DataNodeBuilder import org.onap.cps.utils.JsonObjectMapper +import org.onap.cps.api.CpsModuleService +import org.onap.cps.spi.utils.CpsValidator import spock.lang.Specification -import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NO_TIMESTAMP - class SubscriptionPersistenceSpec extends Specification { - private static final String SUBSCRIPTION_DATASPACE_NAME = "NCMP-Admin"; private static final String SUBSCRIPTION_ANCHOR_NAME = "AVC-Subscriptions"; private static final String SUBSCRIPTION_REGISTRY_PARENT = "/subscription-registry"; private static final String SUBSCRIPTION_REGISTRY_PREDICATES_XPATH = "/subscription-registry/subscription[@clientID='some-client-id' and @subscriptionName='some-subscription-name']/predicates"; - def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper()) + def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper())) def mockCpsDataService = Mock(CpsDataService) - def objectUnderTest = new SubscriptionPersistenceImpl(jsonObjectMapper, mockCpsDataService) + def mockCpsModuleService = Mock(CpsModuleService) + def mockCpsValidator = Mock(CpsValidator) + + def objectUnderTest = new SubscriptionPersistenceImpl(spiedJsonObjectMapper, mockCpsDataService, + mockCpsModuleService, mockCpsValidator) def predicates = new YangModelSubscriptionEvent.Predicates(datastore: 'some-datastore', targetCmHandles: [new YangModelSubscriptionEvent.TargetCmHandle('cmhandle1'), @@ -48,14 +54,14 @@ class SubscriptionPersistenceSpec extends Specification { def 'save a subscription event as yang model into db for the #scenarios' () { given: 'a blank data node that exist in db' - def blankDataNode = new DataNodeBuilder().withDataspace('NCMP-Admin') + def blankDataNode = new DataNodeBuilder().withDataspace(NCMP_DATASPACE_NAME) .withAnchor('AVC-Subscriptions').withXpath('/subscription-registry').build() and: 'cps data service return an empty data node' mockCpsDataService.getDataNodes(*_) >> [blankDataNode] when: 'the yangModelSubscriptionEvent is saved into db' objectUnderTest.saveSubscriptionEvent(yangModelSubscriptionEvent) then: 'the cpsDataService save operation is called with the correct data' - 1 * mockCpsDataService.saveListElements(SUBSCRIPTION_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, + 1 * mockCpsDataService.saveListElements(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, SUBSCRIPTION_REGISTRY_PARENT, '{"subscription":[{' + '"topic":"some-topic",' + @@ -68,10 +74,10 @@ class SubscriptionPersistenceSpec extends Specification { def 'add or replace cm handle list element into db' () { given: 'a data node with child node exist in db' def leaves1 = [status:'REJECTED', cmHandleId:'cmhandle1', details:'Cm handle does not exist'] as Map - def childDataNode = new DataNodeBuilder().withDataspace('NCMP-Admin') + def childDataNode = new DataNodeBuilder().withDataspace(NCMP_DATASPACE_NAME) .withAnchor('AVC-Subscriptions').withXpath('/subscription-registry/subscription') .withLeaves(leaves1).build() - def engagedDataNode = new DataNodeBuilder().withDataspace('NCMP-Admin') + def engagedDataNode = new DataNodeBuilder().withDataspace(NCMP_DATASPACE_NAME) .withAnchor('AVC-Subscriptions').withXpath('/subscription-registry') .withChildDataNodes([childDataNode]).build() and: 'cps data service return data node including a child data node' @@ -81,11 +87,11 @@ class SubscriptionPersistenceSpec extends Specification { when: 'the yang model subscription event is saved into db' objectUnderTest.saveSubscriptionEvent(yangModelSubscriptionEvent) then: 'the cpsDataService save non-existing cm handle with the correct data' - 1 * mockCpsDataService.saveListElements(SUBSCRIPTION_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, + 1 * mockCpsDataService.saveListElements(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, SUBSCRIPTION_REGISTRY_PREDICATES_XPATH, '{"targetCmHandles":[{"cmHandleId":"cmhandle2","status":"PENDING","details":"Subscription forwarded to dmi plugin"}]}', NO_TIMESTAMP) and: 'the cpsDataService update existing cm handle with the correct data' - 1 * mockCpsDataService.updateNodeLeaves(SUBSCRIPTION_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, + 1 * mockCpsDataService.updateNodeLeaves(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, SUBSCRIPTION_REGISTRY_PREDICATES_XPATH, '{"targetCmHandles":[{"cmHandleId":"cmhandle1","status":"PENDING","details":"Subscription forwarded to dmi plugin"}]}', NO_TIMESTAMP) } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DataNodeBaseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DataNodeBaseSpec.groovy index e28a10261e..9f84fb0739 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DataNodeBaseSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DataNodeBaseSpec.groovy @@ -20,6 +20,8 @@ package org.onap.cps.ncmp.api.impl.utils +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME + import org.onap.cps.spi.model.DataNodeBuilder import spock.lang.Specification @@ -38,13 +40,13 @@ class DataNodeBaseSpec extends Specification { def dataNode4 = createDataNodeWithLeavesAndChildDataNodes(leaves4, [dataNode1, dataNode2, dataNode3]) static def createDataNodeWithLeaves(leaves) { - return new DataNodeBuilder().withDataspace('NCMP-Admin') + return new DataNodeBuilder().withDataspace(NCMP_DATASPACE_NAME) .withAnchor('AVC-Subscriptions').withXpath('/subscription-registry/subscription') .withLeaves(leaves).build() } static def createDataNodeWithLeavesAndChildDataNodes(leaves, dataNodes) { - return new DataNodeBuilder().withDataspace('NCMP-Admin') + return new DataNodeBuilder().withDataspace(NCMP_DATASPACE_NAME) .withAnchor('AVC-Subscriptions').withXpath('/subscription-registry/subscription') .withLeaves(leaves).withChildDataNodes(dataNodes) .build() diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DataNodeHelperSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DataNodeHelperSpec.groovy index 28db7babf9..05e5f58983 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DataNodeHelperSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DataNodeHelperSpec.groovy @@ -20,13 +20,15 @@ package org.onap.cps.ncmp.api.impl.utils +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME + import org.onap.cps.spi.model.DataNodeBuilder class DataNodeHelperSpec extends DataNodeBaseSpec { def 'Get data node leaves as expected from a nested data node.'() { given: 'a nested data node' - def dataNode = new DataNodeBuilder().withDataspace('NCMP-Admin') + def dataNode = new DataNodeBuilder().withDataspace(NCMP_DATASPACE_NAME) .withAnchor('AVC-Subscriptions').withXpath('/subscription-registry/subscription') .withLeaves([clientID:'SCO-9989752', isTagged:false, subscriptionName:'cm-subscription-001']) .withChildDataNodes([dataNode4]).build() @@ -44,7 +46,7 @@ class DataNodeHelperSpec extends DataNodeBaseSpec { def 'Get cm handle id to status as expected from a nested data node.'() { given: 'a nested data node' - def dataNode = new DataNodeBuilder().withDataspace('NCMP-Admin') + def dataNode = new DataNodeBuilder().withDataspace(NCMP_DATASPACE_NAME) .withAnchor('AVC-Subscriptions').withXpath('/subscription-registry/subscription') .withLeaves([clientID:'SCO-9989752', isTagged:false, subscriptionName:'cm-subscription-001']) .withChildDataNodes([dataNode4]).build() @@ -65,7 +67,7 @@ class DataNodeHelperSpec extends DataNodeBaseSpec { def 'Get cm handle id to status map as expected from a nested data node.'() { given: 'a nested data node' - def dataNode = new DataNodeBuilder().withDataspace('NCMP-Admin') + def dataNode = new DataNodeBuilder().withDataspace(NCMP_DATASPACE_NAME) .withAnchor('AVC-Subscriptions').withXpath('/subscription-registry/subscription') .withLeaves([clientID:'SCO-9989752', isTagged:false, subscriptionName:'cm-subscription-001']) .withChildDataNodes([dataNode4]).build() diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilderSpec.groovy index 6c4575515f..2b17e5d413 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilderSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilderSpec.groovy @@ -32,7 +32,7 @@ import spock.lang.Specification class DmiServiceUrlBuilderSpec extends Specification { static YangModelCmHandle yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle('dmiServiceName', - 'dmiDataServiceName', 'dmiModuleServiceName', new NcmpServiceCmHandle(cmHandleId: 'some-cm-handle-id')) + 'dmiDataServiceName', 'dmiModuleServiceName', new NcmpServiceCmHandle(cmHandleId: 'some-cm-handle-id'),'') NcmpConfiguration.DmiProperties dmiProperties = new NcmpConfiguration.DmiProperties() diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtilsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtilsSpec.groovy index 38b2056d00..f57988b352 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtilsSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtilsSpec.groovy @@ -28,8 +28,8 @@ import org.apache.kafka.clients.consumer.KafkaConsumer import org.onap.cps.ncmp.api.impl.events.EventsPublisher import org.onap.cps.ncmp.api.impl.utils.context.CpsApplicationContext import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle -import org.onap.cps.ncmp.api.inventory.CmHandleState -import org.onap.cps.ncmp.api.inventory.CompositeStateBuilder +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState +import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder import org.onap.cps.ncmp.api.kafka.MessagingBaseSpec import org.onap.cps.ncmp.api.models.DataOperationRequest import org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandleSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandleSpec.groovy index 5fe2660249..ca0015e995 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandleSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandleSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2022 Nordix Foundation + * Copyright (C) 2021-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,11 +20,11 @@ package org.onap.cps.ncmp.api.impl.yangmodels -import org.onap.cps.ncmp.api.inventory.CmHandleState -import org.onap.cps.ncmp.api.inventory.CompositeState -import org.onap.cps.ncmp.api.inventory.CompositeStateBuilder -import org.onap.cps.ncmp.api.inventory.LockReasonCategory -import org.onap.cps.ncmp.api.inventory.DataStoreSyncState +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState +import org.onap.cps.ncmp.api.impl.inventory.CompositeState +import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder +import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory +import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle import spock.lang.Specification @@ -43,11 +43,11 @@ class YangModelCmHandleSpec extends Specification { def compositeState = new CompositeStateBuilder() .withCmHandleState(CmHandleState.LOCKED) .withLastUpdatedTime('some-update-time') - .withLockReason(LockReasonCategory.LOCKED_MODULE_SYNC_FAILED, 'locked details') + .withLockReason(LockReasonCategory.MODULE_SYNC_FAILED, 'locked details') .withOperationalDataStores(DataStoreSyncState.SYNCHRONIZED, 'some-sync-time').build() ncmpServiceCmHandle.setCompositeState(compositeState) when: 'it is converted to a yang model cm handle' - def objectUnderTest = YangModelCmHandle.toYangModelCmHandle('', '', '', ncmpServiceCmHandle) + def objectUnderTest = YangModelCmHandle.toYangModelCmHandle('', '', '', ncmpServiceCmHandle,'') then: 'the result has the right size' assert objectUnderTest.dmiProperties.size() == 1 and: 'the DMI property in the result has the correct name and value' @@ -63,7 +63,8 @@ class YangModelCmHandleSpec extends Specification { def 'Resolve DMI service name: #scenario and #requiredService service require.'() { given: 'a yang model cm handle' - def objectUnderTest = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, dmiDataServiceName, dmiModelServiceName, new NcmpServiceCmHandle(cmHandleId: 'cm-handle-id-1')) + def objectUnderTest = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, dmiDataServiceName, + dmiModelServiceName, new NcmpServiceCmHandle(cmHandleId: 'cm-handle-id-1'),'') expect: assert objectUnderTest.resolveDmiServiceName(requiredService) == expectedService where: diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImplSpec.groovy index fd01a05ee7..e7c337cc20 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImplSpec.groovy @@ -21,14 +21,20 @@ package org.onap.cps.ncmp.api.inventory +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT +import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS +import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS + +import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueriesImpl +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState +import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState import org.onap.cps.spi.CpsDataPersistenceService import org.onap.cps.spi.model.DataNode import spock.lang.Shared import spock.lang.Specification -import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS -import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS - class CmHandleQueriesImplSpec extends Specification { def cpsDataPersistenceService = Mock(CpsDataPersistenceService) @@ -88,7 +94,7 @@ class CmHandleQueriesImplSpec extends Specification { given: 'a cm handle state to query' def cmHandleState = CmHandleState.ADVISED and: 'the persistence service returns a list of data nodes' - cpsDataPersistenceService.queryDataNodes('NCMP-Admin', 'ncmp-dmi-registry', + cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '//state[@cm-handle-state="ADVISED"]/ancestor::cm-handles', INCLUDE_ALL_DESCENDANTS) >> sampleDataNodes when: 'cm handles are fetched by state' def result = objectUnderTest.queryCmHandlesByState(cmHandleState) @@ -100,8 +106,9 @@ class CmHandleQueriesImplSpec extends Specification { given: 'a cm handle state to compare' def cmHandleState = state and: 'the persistence service returns a list of data nodes' - cpsDataPersistenceService.getDataNodes('NCMP-Admin', 'ncmp-dmi-registry', - '/dmi-registry/cm-handles[@id=\'some-cm-handle\']/state', OMIT_DESCENDANTS) >> [new DataNode(leaves: ['cm-handle-state': 'READY'])] + cpsDataPersistenceService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, + NCMP_DMI_REGISTRY_PARENT + '/cm-handles[@id=\'some-cm-handle\']/state', + OMIT_DESCENDANTS) >> [new DataNode(leaves: ['cm-handle-state': 'READY'])] when: 'cm handles are compared by state' def result = objectUnderTest.cmHandleHasState('some-cm-handle', cmHandleState) then: 'the returned result matches the expected result from the persistence service' @@ -116,8 +123,9 @@ class CmHandleQueriesImplSpec extends Specification { given: 'a cm handle state to query' def cmHandleState = CmHandleState.READY and: 'cps data service returns a list of data nodes' - cpsDataPersistenceService.getDataNodes('NCMP-Admin', 'ncmp-dmi-registry', - '/dmi-registry/cm-handles[@id=\'some-cm-handle\']/state', OMIT_DESCENDANTS) >> [new DataNode(leaves: ['cm-handle-state': 'READY'])] + cpsDataPersistenceService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, + NCMP_DMI_REGISTRY_PARENT + '/cm-handles[@id=\'some-cm-handle\']/state', + OMIT_DESCENDANTS) >> [new DataNode(leaves: ['cm-handle-state': 'READY'])] when: 'cm handles are fetched by state and id' def result = objectUnderTest.getCmHandleState('some-cm-handle') then: 'the returned result is a list of data nodes returned by cps data service' @@ -128,7 +136,7 @@ class CmHandleQueriesImplSpec extends Specification { given: 'a cm handle state to query' def cmHandleState = CmHandleState.READY and: 'cps data service returns a list of data nodes' - cpsDataPersistenceService.queryDataNodes('NCMP-Admin', 'ncmp-dmi-registry', + cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '//state/datastores/operational[@sync-state="'+'UNSYNCHRONIZED'+'"]/ancestor::cm-handles', OMIT_DESCENDANTS) >> sampleDataNodes when: 'cm handles are fetched by the UNSYNCHRONIZED operational sync state' def result = objectUnderTest.queryCmHandlesByOperationalSyncState(DataStoreSyncState.UNSYNCHRONIZED) @@ -141,11 +149,11 @@ class CmHandleQueriesImplSpec extends Specification { def cmHandleDataNode = new DataNode(xpath: 'xpath', leaves: ['cm-handle-state': 'LOCKED']) def cpsPath = '//cps-path' and: 'cps data service returns a valid data node' - cpsDataPersistenceService.queryDataNodes('NCMP-Admin', 'ncmp-dmi-registry', + cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, cpsPath + '/ancestor::cm-handles', INCLUDE_ALL_DESCENDANTS) >> Arrays.asList(cmHandleDataNode) when: 'get cm handles by cps path is invoked' - def result = objectUnderTest.queryCmHandleDataNodesByCpsPath(cpsPath, INCLUDE_ALL_DESCENDANTS) + def result = objectUnderTest.queryCmHandleAncestorsByCpsPath(cpsPath, INCLUDE_ALL_DESCENDANTS) then: 'the returned result is a list of data nodes returned by cps data service' assert result.contains(cmHandleDataNode) } @@ -168,9 +176,9 @@ class CmHandleQueriesImplSpec extends Specification { cpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\"Contact2\" and @value=\"\"]/ancestor::cm-handles', _) >> [] cpsDataPersistenceService.queryDataNodes(_, _, '//state[@cm-handle-state=\"READY\"]/ancestor::cm-handles', _) >> [pnfDemo, pnfDemo3] cpsDataPersistenceService.queryDataNodes(_, _, '//state[@cm-handle-state=\"LOCKED\"]/ancestor::cm-handles', _) >> [pnfDemo2, pnfDemo4] - cpsDataPersistenceService.queryDataNodes('NCMP-Admin','ncmp-dmi-registry','/dmi-registry/cm-handles[@dmi-service-name=\'my-dmi-plugin-identifier\']',OMIT_DESCENDANTS) >> [pnfDemo, pnfDemo2] - cpsDataPersistenceService.queryDataNodes('NCMP-Admin','ncmp-dmi-registry','/dmi-registry/cm-handles[@dmi-data-service-name=\'my-dmi-plugin-identifier\']',OMIT_DESCENDANTS) >> [pnfDemo,pnfDemo4] - cpsDataPersistenceService.queryDataNodes('NCMP-Admin','ncmp-dmi-registry','/dmi-registry/cm-handles[@dmi-model-service-name=\'my-dmi-plugin-identifier\']',OMIT_DESCENDANTS) >> [pnfDemo2,pnfDemo4] + cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@dmi-service-name=\'my-dmi-plugin-identifier\']', OMIT_DESCENDANTS) >> [pnfDemo, pnfDemo2] + cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@dmi-data-service-name=\'my-dmi-plugin-identifier\']', OMIT_DESCENDANTS) >> [pnfDemo, pnfDemo4] + cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@dmi-model-service-name=\'my-dmi-plugin-identifier\']', OMIT_DESCENDANTS) >> [pnfDemo2, pnfDemo4] } def static createDataNode(dataNodeId) { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateBuilderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateBuilderSpec.groovy index fa437987b5..c2cdd9bc2e 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateBuilderSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateBuilderSpec.groovy @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2022 Bell Canada - * Modifications Copyright (C) 2022 Nordix Foundation. + * Modifications Copyright (C) 2022-2023 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,9 +21,13 @@ package org.onap.cps.ncmp.api.inventory +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState +import org.onap.cps.ncmp.api.impl.inventory.CompositeState +import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder +import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState +import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory import org.onap.cps.spi.model.DataNode import org.onap.cps.spi.model.DataNodeBuilder -import org.onap.cps.ncmp.api.inventory.CompositeStateBuilder import spock.lang.Specification import java.time.OffsetDateTime @@ -38,7 +42,7 @@ class CompositeStateBuilderSpec extends Specification { def static cmHandleId = 'myHandle1' def static cmHandleXpath = "/dmi-registry/cm-handles[@id='${cmHandleId}/state']" def static stateDataNodes = [new DataNodeBuilder().withXpath("/dmi-registry/cm-handles[@id='${cmHandleId}']/state/lock-reason") - .withLeaves(['reason': 'LOCKED_MODULE_SYNC_FAILED', 'details': 'lock details']).build(), + .withLeaves(['reason': 'MODULE_SYNC_FAILED', 'details': 'lock details']).build(), new DataNodeBuilder().withXpath("/dmi-registry/cm-handles[@id='${cmHandleId}']/state/datastores") .withChildDataNodes(Arrays.asList(new DataNodeBuilder() .withXpath("/dmi-registry/cm-handles[@id='${cmHandleId}']/state/datastores/operational") @@ -48,7 +52,7 @@ class CompositeStateBuilderSpec extends Specification { def "Composite State Specification"() { when: 'using composite state builder ' def compositeState = new CompositeStateBuilder().withCmHandleState(CmHandleState.ADVISED) - .withLockReason(LockReasonCategory.LOCKED_MODULE_SYNC_FAILED,"").withOperationalDataStores(DataStoreSyncState.UNSYNCHRONIZED, + .withLockReason(LockReasonCategory.MODULE_SYNC_FAILED,"").withOperationalDataStores(DataStoreSyncState.UNSYNCHRONIZED, formattedDateAndTime.toString()).withLastUpdatedTime(formattedDateAndTime).build() then: 'it matches expected cm handle state and data store sync state' assert compositeState.cmHandleState == CmHandleState.ADVISED @@ -69,7 +73,7 @@ class CompositeStateBuilderSpec extends Specification { def finalCompositeStateBuilder = new CompositeStateBuilder() .withCmHandleState(CmHandleState.ADVISED) .withLastUpdatedTime(formattedDateAndTime.toString()) - .withLockReason(LockReasonCategory.LOCKED_MODULE_SYNC_FAILED, 'locked details') + .withLockReason(LockReasonCategory.MODULE_SYNC_FAILED, 'locked details') .withOperationalDataStores(DataStoreSyncState.SYNCHRONIZED, formattedDateAndTime) when: 'build is called' def result = finalCompositeStateBuilder.build() @@ -78,7 +82,7 @@ class CompositeStateBuilderSpec extends Specification { and: 'built result should have correct values' assert !result.getDataSyncEnabled() assert result.getLastUpdateTime() == formattedDateAndTime - assert result.getLockReason().getLockReasonCategory() == LockReasonCategory.LOCKED_MODULE_SYNC_FAILED + assert result.getLockReason().getLockReasonCategory() == LockReasonCategory.MODULE_SYNC_FAILED assert result.getLockReason().getDetails() == 'locked details' assert result.getCmHandleState() == CmHandleState.ADVISED assert result.getDataStores().getOperationalDataStore().getDataStoreSyncState() == DataStoreSyncState.SYNCHRONIZED diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateSpec.groovy index 7bdf335e3d..985bdc5cd4 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,13 +21,17 @@ package org.onap.cps.ncmp.api.inventory import com.fasterxml.jackson.databind.ObjectMapper +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState +import org.onap.cps.ncmp.api.impl.inventory.CompositeState +import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState +import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory import spock.lang.Specification import java.time.OffsetDateTime import java.time.ZoneOffset import java.time.format.DateTimeFormatter -import static org.onap.cps.ncmp.api.inventory.CompositeState.DataStores -import static org.onap.cps.ncmp.api.inventory.CompositeState.Operational +import static org.onap.cps.ncmp.api.impl.inventory.CompositeState.DataStores +import static org.onap.cps.ncmp.api.impl.inventory.CompositeState.Operational import static org.onap.cps.ncmp.utils.TestUtils.getResourceFileContent import static org.springframework.util.StringUtils.trimAllWhitespace @@ -40,7 +44,7 @@ class CompositeStateSpec extends Specification { def "Composite State Specification"() { given: "a Composite State" def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED, - lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.LOCKED_MODULE_SYNC_FAILED).details("lock details").build(), + lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.MODULE_SYNC_FAILED).details("lock details").build(), lastUpdateTime: formattedDateAndTime.toString(), dataSyncEnabled: false, dataStores: dataStores()) diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImplSpec.groovy index efe6f00bca..724f05b1b8 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImplSpec.groovy @@ -22,14 +22,23 @@ package org.onap.cps.ncmp.api.inventory +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NO_TIMESTAMP +import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS + import com.fasterxml.jackson.databind.ObjectMapper import org.onap.cps.api.CpsAdminService import org.onap.cps.api.CpsDataService import org.onap.cps.api.CpsModuleService +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState +import org.onap.cps.ncmp.api.impl.inventory.CompositeState +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistenceImpl import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle import org.onap.cps.spi.CascadeDeleteAllowed import org.onap.cps.spi.FetchDescendantsOption -import org.onap.cps.spi.exceptions.DataValidationException import org.onap.cps.spi.model.DataNode import org.onap.cps.spi.model.ModuleDefinition import org.onap.cps.spi.model.ModuleReference @@ -41,9 +50,6 @@ import java.time.OffsetDateTime import java.time.ZoneOffset import java.time.format.DateTimeFormatter -import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NO_TIMESTAMP -import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS - class InventoryPersistenceImplSpec extends Specification { def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper())) @@ -57,7 +63,7 @@ class InventoryPersistenceImplSpec extends Specification { def mockCpsValidator = Mock(CpsValidator) def objectUnderTest = new InventoryPersistenceImpl(spiedJsonObjectMapper, mockCpsDataService, mockCpsModuleService, - mockCpsAdminService, mockCpsValidator) + mockCpsValidator, mockCpsAdminService) def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ") .format(OffsetDateTime.of(2022, 12, 31, 20, 30, 40, 1, ZoneOffset.UTC)) @@ -85,7 +91,7 @@ class InventoryPersistenceImplSpec extends Specification { def "Retrieve CmHandle using datanode with #scenario."() { given: 'the cps data service returns a data node from the DMI registry' def dataNode = new DataNode(childDataNodes:childDataNodes, leaves: leaves) - mockCpsDataService.getDataNodes('NCMP-Admin', 'ncmp-dmi-registry', xpath, INCLUDE_ALL_DESCENDANTS) >> [dataNode] + mockCpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, xpath, INCLUDE_ALL_DESCENDANTS) >> [dataNode] when: 'retrieving the yang modelled cm handle' def result = objectUnderTest.getYangModelCmHandle(cmHandleId) then: 'the result has the correct id and service names' @@ -112,7 +118,7 @@ class InventoryPersistenceImplSpec extends Specification { def "Handling missing service names as null."() { given: 'the cps data service returns a data node from the DMI registry with empty child and leaf attributes' def dataNode = new DataNode(childDataNodes:[], leaves: [:]) - mockCpsDataService.getDataNodes('NCMP-Admin', 'ncmp-dmi-registry', xpath, INCLUDE_ALL_DESCENDANTS) >> [dataNode] + mockCpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, xpath, INCLUDE_ALL_DESCENDANTS) >> [dataNode] when: 'retrieving the yang modelled cm handle' def result = objectUnderTest.getYangModelCmHandle(cmHandleId) then: 'the service names are returned as null' @@ -126,7 +132,7 @@ class InventoryPersistenceImplSpec extends Specification { def "Retrieve multiple YangModelCmHandles"() { given: 'the cps data service returns 2 data nodes from the DMI registry' def dataNodes = [new DataNode(xpath: xpath), new DataNode(xpath: xpath2)] - mockCpsDataService.getDataNodesForMultipleXpaths('NCMP-Admin', 'ncmp-dmi-registry', [xpath, xpath2] , INCLUDE_ALL_DESCENDANTS) >> dataNodes + mockCpsDataService.getDataNodesForMultipleXpaths(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, [xpath, xpath2] , INCLUDE_ALL_DESCENDANTS) >> dataNodes when: 'retrieving the yang modelled cm handle' def results = objectUnderTest.getYangModelCmHandles([cmHandleId, cmHandleId2]) then: 'verify both have returned and cmhandleIds are correct' @@ -139,7 +145,7 @@ class InventoryPersistenceImplSpec extends Specification { def cmHandleId = 'Some-Cm-Handle' def dataNode = new DataNode(leaves: ['cm-handle-state': 'ADVISED']) and: 'cps data service returns a valid data node' - mockCpsDataService.getDataNodes('NCMP-Admin', 'ncmp-dmi-registry', + mockCpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@id=\'Some-Cm-Handle\']/state', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> [dataNode] when: 'get cm handle state is invoked' def result = objectUnderTest.getCmHandleState(cmHandleId) @@ -156,7 +162,7 @@ class InventoryPersistenceImplSpec extends Specification { when: 'update cm handle state is invoked with the #scenario state' objectUnderTest.saveCmHandleState(cmHandleId, compositeState) then: 'update node leaves is invoked with the correct params' - 1 * mockCpsDataService.updateDataNodeAndDescendants('NCMP-Admin', 'ncmp-dmi-registry', '/dmi-registry/cm-handles[@id=\'Some-Cm-Handle\']', expectedJsonData, _ as OffsetDateTime) + 1 * mockCpsDataService.updateDataNodeAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@id=\'Some-Cm-Handle\']', expectedJsonData, _ as OffsetDateTime) where: 'the following states are used' scenario | cmHandleState || expectedJsonData 'READY' | CmHandleState.READY || '{"state":{"cm-handle-state":"READY","last-update-time":"2022-12-31T20:30:40.000+0000"}}' @@ -172,7 +178,7 @@ class InventoryPersistenceImplSpec extends Specification { def cmHandleStateMap = ['Some-Cm-Handle1' : compositeState1, 'Some-Cm-Handle2' : compositeState2] objectUnderTest.saveCmHandleStateBatch(cmHandleStateMap) then: 'update node leaves is invoked with the correct params' - 1 * mockCpsDataService.updateDataNodesAndDescendants('NCMP-Admin', 'ncmp-dmi-registry', cmHandlesJsonDataMap, _ as OffsetDateTime) + 1 * mockCpsDataService.updateDataNodesAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, cmHandlesJsonDataMap, _ as OffsetDateTime) where: 'the following states are used' scenario | cmHandleState || cmHandlesJsonDataMap 'READY' | CmHandleState.READY || ['/dmi-registry/cm-handles[@id=\'Some-Cm-Handle1\']':'{"state":{"cm-handle-state":"READY","last-update-time":"2022-12-31T20:30:40.000+0000"}}', '/dmi-registry/cm-handles[@id=\'Some-Cm-Handle2\']':'{"state":{"cm-handle-state":"READY","last-update-time":"2022-12-31T20:30:40.000+0000"}}'] @@ -183,7 +189,7 @@ class InventoryPersistenceImplSpec extends Specification { def 'Get module definitions'() { given: 'cps module service returns a collection of module definitions' def moduleDefinitions = [new ModuleDefinition('moduleName','revision','content')] - mockCpsModuleService.getModuleDefinitionsByAnchorName('NFP-Operational','some-cmHandle-Id') >> moduleDefinitions + mockCpsModuleService.getModuleDefinitionsByAnchorName(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,'some-cmHandle-Id') >> moduleDefinitions when: 'get module definitions by cmHandle is invoked' def result = objectUnderTest.getModuleDefinitionsByCmHandleId('some-cmHandle-Id') then: 'the returned result are the same module definitions as returned from the module service' @@ -193,7 +199,7 @@ class InventoryPersistenceImplSpec extends Specification { def 'Get module references'() { given: 'cps module service returns a collection of module references' def moduleReferences = [new ModuleReference('moduleName','revision','namespace')] - mockCpsModuleService.getYangResourcesModuleReferences('NFP-Operational','some-cmHandle-Id') >> moduleReferences + mockCpsModuleService.getYangResourcesModuleReferences(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,'some-cmHandle-Id') >> moduleReferences when: 'get yang resources module references by cmHandle is invoked' def result = objectUnderTest.getYangResourcesModuleReferences('some-cmHandle-Id') then: 'the returned result is a collection of module definitions' @@ -208,7 +214,8 @@ class InventoryPersistenceImplSpec extends Specification { when: 'the method to save cmhandle is called' objectUnderTest.saveCmHandle(yangModelCmHandle) then: 'the data service method to save list elements is called once' - 1 * mockCpsDataService.saveListElements('NCMP-Admin','ncmp-dmi-registry','/dmi-registry',_,null) >> { + 1 * mockCpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT, + _,null) >> { args -> { assert args[3].startsWith('{"cm-handles":[{"id":"cmhandle","additional-properties":[],"public-properties":[]}]}') } @@ -222,7 +229,8 @@ class InventoryPersistenceImplSpec extends Specification { when: 'the cm handles are saved' objectUnderTest.saveCmHandleBatch([yangModelCmHandle1, yangModelCmHandle2]) then: 'CPS Data Service persists both cm handles as a batch' - 1 * mockCpsDataService.saveListElementsBatch('NCMP-Admin','ncmp-dmi-registry','/dmi-registry',_,null) >> { + 1 * mockCpsDataService.saveListElementsBatch(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, + NCMP_DMI_REGISTRY_PARENT, _,null) >> { args -> { def jsonDataList = (args[3] as List) (jsonDataList[0] as String).contains('cmhandle1') @@ -235,14 +243,14 @@ class InventoryPersistenceImplSpec extends Specification { when: 'the method to delete list or list elements is called' objectUnderTest.deleteListOrListElement('sample xPath') then: 'the data service method to save list elements is called once' - 1 * mockCpsDataService.deleteListOrListElement('NCMP-Admin','ncmp-dmi-registry','sample xPath',null) + 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', 'validSchemaSetName', CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED) + 1 * mockCpsModuleService.deleteSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'validSchemaSetName', CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED) and: 'the schema set name is validated' 1 * mockCpsValidator.validateNameCharacters('validSchemaSetName') } @@ -251,7 +259,7 @@ class InventoryPersistenceImplSpec extends Specification { 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', ['validSchemaSetName1', 'validSchemaSetName2']) + 1 * mockCpsModuleService.deleteSchemaSetsWithCascade(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, ['validSchemaSetName1', 'validSchemaSetName2']) and: 'the schema set names are validated' 1 * mockCpsValidator.validateNameCharacters(['validSchemaSetName1', 'validSchemaSetName2']) } @@ -260,7 +268,7 @@ class InventoryPersistenceImplSpec extends Specification { when: 'the method to get data nodes is called' objectUnderTest.getDataNode('sample xPath') then: 'the data persistence service method to get data node is invoked once' - 1 * mockCpsDataService.getDataNodes('NCMP-Admin','ncmp-dmi-registry','sample xPath', INCLUDE_ALL_DESCENDANTS) + 1 * mockCpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,'sample xPath', INCLUDE_ALL_DESCENDANTS) } def 'Get cmHandle data node'() { @@ -269,38 +277,35 @@ class InventoryPersistenceImplSpec extends Specification { when: 'the method to get data nodes is called' objectUnderTest.getCmHandleDataNode('sample cmHandleId') then: 'the data persistence service method to get cmHandle data node is invoked once with expected xPath' - 1 * mockCpsDataService.getDataNodes('NCMP-Admin','ncmp-dmi-registry',expectedXPath, INCLUDE_ALL_DESCENDANTS) + 1 * mockCpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, expectedXPath, INCLUDE_ALL_DESCENDANTS) } def 'Get CM handles that has given module names'() { when: 'the method to get cm handles is called' objectUnderTest.getCmHandleIdsWithGivenModules(['sample-module-name']) then: 'the admin persistence service method to query anchors is invoked once with the same parameter' - 1 * mockCpsAdminService.queryAnchorNames('NFP-Operational',['sample-module-name']) + 1 * mockCpsAdminService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, ['sample-module-name']) } def 'Replace list content'() { when: 'replace list content method is called with xpath and data nodes collection' objectUnderTest.replaceListContent('sample xpath', [new DataNode()]) then: 'the cps data service method to replace list content is invoked once with same parameters' - 1 * mockCpsDataService.replaceListContent('NCMP-Admin', 'ncmp-dmi-registry', - 'sample xpath', [new DataNode()], NO_TIMESTAMP); + 1 * mockCpsDataService.replaceListContent(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,'sample xpath', [new DataNode()], NO_TIMESTAMP); } def 'Delete data node via xPath'() { when: 'Delete data node method is called with xpath as parameter' objectUnderTest.deleteDataNode('sample dataNode xpath') then: 'the cps data service method to delete data node is invoked once with the same xPath' - 1 * mockCpsDataService.deleteDataNode('NCMP-Admin', 'ncmp-dmi-registry', - 'sample dataNode xpath', NO_TIMESTAMP); + 1 * mockCpsDataService.deleteDataNode(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, 'sample dataNode xpath', NO_TIMESTAMP); } def 'Delete multiple data nodes via xPath'() { when: 'Delete data nodes method is called with multiple xpaths as parameters' objectUnderTest.deleteDataNodes(['xpath1', 'xpath2']) then: 'the cps data service method to delete data nodes is invoked once with the same xPaths' - 1 * mockCpsDataService.deleteDataNodes('NCMP-Admin', 'ncmp-dmi-registry', - ['xpath1', 'xpath2'], NO_TIMESTAMP); + 1 * mockCpsDataService.deleteDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, ['xpath1', 'xpath2'], NO_TIMESTAMP); } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdogSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdogSpec.groovy index 0d09bef3f7..ed313a0ad8 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdogSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdogSpec.groovy @@ -20,13 +20,17 @@ package org.onap.cps.ncmp.api.inventory.sync +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME + import com.hazelcast.map.IMap import org.onap.cps.api.CpsDataService +import org.onap.cps.ncmp.api.impl.inventory.sync.DataSyncWatchdog +import org.onap.cps.ncmp.api.impl.inventory.sync.SyncUtils import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle -import org.onap.cps.ncmp.api.inventory.CmHandleState -import org.onap.cps.ncmp.api.inventory.CompositeState -import org.onap.cps.ncmp.api.inventory.InventoryPersistence -import org.onap.cps.ncmp.api.inventory.DataStoreSyncState +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState +import org.onap.cps.ncmp.api.impl.inventory.CompositeState +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence +import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState import spock.lang.Specification class DataSyncWatchdogSpec extends Specification { @@ -61,7 +65,7 @@ class DataSyncWatchdogSpec extends Specification { and: 'the sync util returns first resource data' 1 * mockSyncUtils.getResourceData('cm-handle-1') >> resourceData and: 'the cm-handle data is saved' - 1 * mockCpsDataService.saveData('NFP-Operational', 'cm-handle-1', jsonString, _) + 1 * mockCpsDataService.saveData(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'cm-handle-1', jsonString, _) and: 'the first cm handle operational sync state is updated' 1 * mockInventoryPersistence.saveCmHandleState('cm-handle-1', compositeState) then: 'the inventory persistence cm handle returns a composite state for the second cm handle' @@ -69,7 +73,7 @@ class DataSyncWatchdogSpec extends Specification { and: 'the sync util returns first resource data' 1 * mockSyncUtils.getResourceData('cm-handle-2') >> resourceData and: 'the cm-handle data is saved' - 1 * mockCpsDataService.saveData('NFP-Operational', 'cm-handle-2', jsonString, _) + 1 * mockCpsDataService.saveData(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'cm-handle-2', jsonString, _) and: 'the second cm handle operational sync state is updated from "UNSYNCHRONIZED" to "SYNCHRONIZED"' 1 * mockInventoryPersistence.saveCmHandleState('cm-handle-2', compositeState) } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncServiceSpec.groovy index 3c4c6f554f..b547da7a16 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncServiceSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncServiceSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,14 +20,24 @@ package org.onap.cps.ncmp.api.inventory.sync +import org.onap.cps.spi.FetchDescendantsOption + +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME +import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.MODULE_UPGRADE + import org.onap.cps.api.CpsAdminService +import org.onap.cps.api.CpsDataService import org.onap.cps.api.CpsModuleService +import org.onap.cps.ncmp.api.impl.inventory.sync.ModuleSyncService import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle +import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries +import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle import org.onap.cps.spi.CascadeDeleteAllowed import org.onap.cps.spi.exceptions.SchemaSetNotFoundException import org.onap.cps.spi.model.ModuleReference +import org.onap.cps.utils.JsonObjectMapper import spock.lang.Specification class ModuleSyncServiceSpec extends Specification { @@ -35,17 +45,23 @@ class ModuleSyncServiceSpec extends Specification { def mockCpsModuleService = Mock(CpsModuleService) def mockDmiModelOperations = Mock(DmiModelOperations) def mockCpsAdminService = Mock(CpsAdminService) + def mockCmHandleQueries = Mock(CmHandleQueries) + def mockCpsDataService = Mock(CpsDataService) + def mockJsonObjectMapper = Mock(JsonObjectMapper) - def objectUnderTest = new ModuleSyncService(mockDmiModelOperations, mockCpsModuleService, mockCpsAdminService) + def objectUnderTest = new ModuleSyncService(mockDmiModelOperations, mockCpsModuleService, mockCpsAdminService, + mockCmHandleQueries, mockCpsDataService, mockJsonObjectMapper) - def expectedDataspaceName = 'NFP-Operational' + def expectedDataspaceName = NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME def 'Sync model for a (new) cm handle with #scenario'() { - given: 'a cm handle' + given: 'a cm handle having lock reason : MODULE_UPGRADE' def ncmpServiceCmHandle = new NcmpServiceCmHandle() + ncmpServiceCmHandle.setCompositeState(new CompositeStateBuilder() + .withLockReason(MODULE_UPGRADE, 'new moduleSetTag: someModuleSetTag').build()) def dmiServiceName = 'some service name' ncmpServiceCmHandle.cmHandleId = 'cmHandleId-1' - def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, '', '', ncmpServiceCmHandle) + def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, '', '', ncmpServiceCmHandle,'someModuleSetTag') and: 'DMI operations returns some module references' def moduleReferences = [ new ModuleReference('module1','1'), new ModuleReference('module2','2') ] mockDmiModelOperations.getModuleReferences(yangModelCmHandle) >> moduleReferences @@ -53,13 +69,16 @@ class ModuleSyncServiceSpec extends Specification { mockCpsModuleService.getYangResourceModuleReferences(expectedDataspaceName) >> toModuleReference(existingModuleResourcesInCps) and: 'DMI-Plugin returns resource(s) for "new" module(s)' mockDmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, [new ModuleReference('module1', '1')]) >> newModuleNameContentToMap + and: 'empty data node list is returned by cps path a query' + mockCmHandleQueries.queryNcmpRegistryByCpsPath("//cm-handles[@module-set-tag='someModuleSetTag']", + FetchDescendantsOption.OMIT_DESCENDANTS) >> Collections.emptyList() when: 'module sync is triggered' mockCpsModuleService.identifyNewModuleReferences(moduleReferences) >> toModuleReference(identifiedNewModuleReferences) - objectUnderTest.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle) + objectUnderTest.syncAndCreateOrUpgradeSchemaSetAndAnchor(yangModelCmHandle) then: 'create schema set from module is invoked with correct parameters' - 1 * mockCpsModuleService.createSchemaSetFromModules('NFP-Operational', 'cmHandleId-1', newModuleNameContentToMap, moduleReferences) + 1 * mockCpsModuleService.createOrUpgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'cmHandleId-1', newModuleNameContentToMap, moduleReferences) and: 'anchor is created with the correct parameters' - 1 * mockCpsAdminService.createAnchor('NFP-Operational', 'cmHandleId-1', 'cmHandleId-1') + 1 * mockCpsAdminService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'cmHandleId-1', 'cmHandleId-1') where: 'the following parameters are used' scenario | existingModuleResourcesInCps | identifiedNewModuleReferences | newModuleNameContentToMap 'one new module' | [['module2' : '2'], ['module3' : '3']] | [['module1' : '1']] | [module1: 'some yang source'] diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncTasksSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncTasksSpec.groovy index 382d5da4e3..a11f14838c 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncTasksSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncTasksSpec.groovy @@ -25,12 +25,15 @@ import com.hazelcast.config.Config import com.hazelcast.instance.impl.HazelcastInstanceFactory import com.hazelcast.map.IMap import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler +import org.onap.cps.ncmp.api.impl.inventory.sync.ModuleSyncService +import org.onap.cps.ncmp.api.impl.inventory.sync.ModuleSyncTasks +import org.onap.cps.ncmp.api.impl.inventory.sync.SyncUtils import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle -import org.onap.cps.ncmp.api.inventory.CmHandleState -import org.onap.cps.ncmp.api.inventory.CompositeState -import org.onap.cps.ncmp.api.inventory.CompositeStateBuilder -import org.onap.cps.ncmp.api.inventory.InventoryPersistence -import org.onap.cps.ncmp.api.inventory.LockReasonCategory +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState +import org.onap.cps.ncmp.api.impl.inventory.CompositeState +import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence +import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory import org.onap.cps.spi.model.DataNode import spock.lang.Specification import java.util.concurrent.atomic.AtomicInteger @@ -66,8 +69,8 @@ class ModuleSyncTasksSpec extends Specification { 1 * mockModuleSyncService.deleteSchemaSetIfExists('cm-handle-1') 1 * mockModuleSyncService.deleteSchemaSetIfExists('cm-handle-2') and: 'module sync service is invoked for each cm handle' - 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(_) >> { args -> assertYamgModelCmHandleArgument(args, 'cm-handle-1') } - 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(_) >> { args -> assertYamgModelCmHandleArgument(args, 'cm-handle-2') } + 1 * mockModuleSyncService.syncAndCreateOrUpgradeSchemaSetAndAnchor(_) >> { args -> assertYamgModelCmHandleArgument(args, 'cm-handle-1') } + 1 * mockModuleSyncService.syncAndCreateOrUpgradeSchemaSetAndAnchor(_) >> { args -> assertYamgModelCmHandleArgument(args, 'cm-handle-2') } and: 'the state handler is called for the both cm handles' 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_) >> { args -> assertBatch(args, ['cm-handle-1', 'cm-handle-2'], CmHandleState.READY) @@ -83,11 +86,11 @@ class ModuleSyncTasksSpec extends Specification { def cmHandleState = new CompositeState(cmHandleState: CmHandleState.ADVISED) 1 * mockInventoryPersistence.getCmHandleState('cm-handle') >> cmHandleState and: 'module sync service attempts to sync the cm handle and throws an exception' - 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(*_) >> { throw new Exception('some exception') } + 1 * mockModuleSyncService.syncAndCreateOrUpgradeSchemaSetAndAnchor(*_) >> { throw new Exception('some exception') } when: 'module sync is executed' objectUnderTest.performModuleSync([cmHandle], batchCount) then: 'update lock reason, details and attempts is invoked' - 1 * mockSyncUtils.updateLockReasonDetailsAndAttempts(cmHandleState, LockReasonCategory.LOCKED_MODULE_SYNC_FAILED, 'some exception') + 1 * mockSyncUtils.updateLockReasonDetailsAndAttempts(cmHandleState, LockReasonCategory.MODULE_SYNC_FAILED, 'some exception') and: 'the state handler is called to update the state to LOCKED' 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_) >> { args -> assertBatch(args, ['cm-handle'], CmHandleState.LOCKED) @@ -99,7 +102,7 @@ class ModuleSyncTasksSpec extends Specification { def 'Reset failed CM Handles #scenario.'() { given: 'cm handles in an locked state' def lockedState = new CompositeStateBuilder().withCmHandleState(CmHandleState.LOCKED) - .withLockReason(LockReasonCategory.LOCKED_MODULE_SYNC_FAILED, '').withLastUpdatedTimeNow().build() + .withLockReason(LockReasonCategory.MODULE_SYNC_FAILED, '').withLastUpdatedTimeNow().build() def yangModelCmHandle1 = new YangModelCmHandle(id: 'cm-handle-1', compositeState: lockedState) def yangModelCmHandle2 = new YangModelCmHandle(id: 'cm-handle-2', compositeState: lockedState) def expectedCmHandleStatePerCmHandle = [(yangModelCmHandle1): CmHandleState.ADVISED] @@ -109,7 +112,7 @@ class ModuleSyncTasksSpec extends Specification { moduleSyncStartedOnCmHandles.put('cm-handle-1', 'started') moduleSyncStartedOnCmHandles.put('cm-handle-2', 'started') and: 'sync utils retry locked cm handle returns #isReadyForRetry' - mockSyncUtils.isReadyForRetry(lockedState) >>> isReadyForRetry + mockSyncUtils.needsModuleSyncRetryOrUpgrade(lockedState) >>> isReadyForRetry when: 'resetting failed cm handles' objectUnderTest.resetFailedCmHandles([yangModelCmHandle1, yangModelCmHandle2]) then: 'updated to state "ADVISED" from "READY" is called as often as there are cm handles ready for retry' @@ -132,7 +135,7 @@ class ModuleSyncTasksSpec extends Specification { when: 'module sync poll is executed' objectUnderTest.performModuleSync([cmHandle1], batchCount) then: 'module sync service is invoked for cm handle' - 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(_) >> { args -> assertYamgModelCmHandleArgument(args, 'cm-handle-1') } + 1 * mockModuleSyncService.syncAndCreateOrUpgradeSchemaSetAndAnchor(_) >> { args -> assertYamgModelCmHandleArgument(args, 'cm-handle-1') } and: 'the entry for other cm handle is still in the progress map' assert moduleSyncStartedOnCmHandles.get('other-cm-handle') != null } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdogSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdogSpec.groovy index bb730fc34d..390e88b3d4 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdogSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdogSpec.groovy @@ -22,8 +22,11 @@ package org.onap.cps.ncmp.api.inventory.sync import com.hazelcast.map.IMap +import org.onap.cps.ncmp.api.impl.inventory.sync.ModuleSyncTasks +import org.onap.cps.ncmp.api.impl.inventory.sync.ModuleSyncWatchdog +import org.onap.cps.ncmp.api.impl.inventory.sync.SyncUtils import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle -import org.onap.cps.ncmp.api.inventory.sync.executor.AsyncTaskExecutor +import org.onap.cps.ncmp.api.impl.inventory.sync.executor.AsyncTaskExecutor import java.util.concurrent.ArrayBlockingQueue import org.onap.cps.spi.model.DataNode import spock.lang.Specification @@ -42,7 +45,9 @@ class ModuleSyncWatchdogSpec extends Specification { def spiedAsyncTaskExecutor = Spy(AsyncTaskExecutor) - def objectUnderTest = new ModuleSyncWatchdog(mockSyncUtils, moduleSyncWorkQueue , mockModuleSyncStartedOnCmHandles, mockModuleSyncTasks, spiedAsyncTaskExecutor) + def moduleSetTagCache = Mock(IMap<String, Set<String>>) + + def objectUnderTest = new ModuleSyncWatchdog(mockSyncUtils, moduleSyncWorkQueue , mockModuleSyncStartedOnCmHandles, mockModuleSyncTasks, spiedAsyncTaskExecutor, moduleSetTagCache) void setup() { spiedAsyncTaskExecutor.setupThreadPool() @@ -106,7 +111,7 @@ class ModuleSyncWatchdogSpec extends Specification { def 'Reset failed cm handles.'() { given: 'sync utilities returns failed cm handles' def failedCmHandles = [new YangModelCmHandle()] - mockSyncUtils.getModuleSyncFailedCmHandles() >> failedCmHandles + mockSyncUtils.getCmHandlesThatFailedModelSyncOrUpgrade() >> failedCmHandles when: 'reset failed cm handles is started' objectUnderTest.resetPreviouslyFailedCmHandles() then: 'it is delegated to the module sync task (service)' diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy index c6ce1a5dfe..00d14cd2a0 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy @@ -22,22 +22,29 @@ package org.onap.cps.ncmp.api.inventory.sync import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL - +import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.MODULE_SYNC_FAILED +import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.MODULE_UPGRADE +import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.MODULE_UPGRADE_FAILED + +import ch.qos.logback.classic.Level +import ch.qos.logback.classic.Logger +import ch.qos.logback.core.read.ListAppender +import org.onap.cps.ncmp.api.impl.inventory.sync.SyncUtils +import org.slf4j.LoggerFactory +import org.springframework.context.annotation.AnnotationConfigApplicationContext import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.ObjectMapper import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations -import org.onap.cps.ncmp.api.inventory.CmHandleQueries -import org.onap.cps.ncmp.api.inventory.CmHandleState -import org.onap.cps.ncmp.api.inventory.CompositeState -import org.onap.cps.ncmp.api.inventory.CompositeStateBuilder -import org.onap.cps.ncmp.api.inventory.DataStoreSyncState -import org.onap.cps.ncmp.api.inventory.LockReasonCategory +import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState +import org.onap.cps.ncmp.api.impl.inventory.CompositeState +import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder +import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState import org.onap.cps.spi.FetchDescendantsOption import org.onap.cps.spi.model.DataNode import org.onap.cps.utils.JsonObjectMapper import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity -import spock.lang.Shared import spock.lang.Specification import java.time.OffsetDateTime import java.time.format.DateTimeFormatter @@ -53,12 +60,31 @@ class SyncUtilsSpec extends Specification{ def objectUnderTest = new SyncUtils(mockCmHandleQueries, mockDmiDataOperations, jsonObjectMapper) - @Shared - def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(OffsetDateTime.now()) + def static neverUpdatedBefore = '1900-01-01T00:00:00.000+0100' + + def static now = OffsetDateTime.now() + + def static nowAsString = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(now) + + def static dataNode = new DataNode(leaves: ['id': 'cm-handle-123']) + + def applicationContext = new AnnotationConfigApplicationContext() - @Shared - def dataNode = new DataNode(leaves: ['id': 'cm-handle-123']) + def logger = (Logger) LoggerFactory.getLogger(SyncUtils) + def loggingListAppender + void setup() { + logger.setLevel(Level.DEBUG) + loggingListAppender = new ListAppender() + logger.addAppender(loggingListAppender) + loggingListAppender.start() + applicationContext.refresh() + } + + void cleanup() { + ((Logger) LoggerFactory.getLogger(SyncUtils.class)).detachAndStopAllAppenders() + applicationContext.close() + } def 'Get an advised Cm-Handle where ADVISED cm handle #scenario'() { given: 'the inventory persistence service returns a collection of data nodes' @@ -77,9 +103,9 @@ class SyncUtilsSpec extends Specification{ given: 'A locked state' def compositeState = new CompositeState(lockReason: lockReason) when: 'update cm handle details and attempts is called' - objectUnderTest.updateLockReasonDetailsAndAttempts(compositeState, LockReasonCategory.LOCKED_MODULE_SYNC_FAILED, 'new error message') + objectUnderTest.updateLockReasonDetailsAndAttempts(compositeState, MODULE_SYNC_FAILED, 'new error message') then: 'the composite state lock reason and details are updated' - assert compositeState.lockReason.lockReasonCategory == LockReasonCategory.LOCKED_MODULE_SYNC_FAILED + assert compositeState.lockReason.lockReasonCategory == MODULE_SYNC_FAILED assert compositeState.lockReason.details == expectedDetails where: scenario | lockReason || expectedDetails @@ -87,13 +113,13 @@ class SyncUtilsSpec extends Specification{ 'exists' | CompositeState.LockReason.builder().details("Attempt #2 failed: some error message").build() || 'Attempt #3 failed: new error message' } - def 'Get all locked Cm-Handle where Lock Reason is LOCKED_MODULE_SYNC_FAILED cm handle #scenario'() { + def 'Get all locked Cm-Handle where Lock Reason is MODULE_SYNC_FAILED cm handle #scenario'() { given: 'the cps (persistence service) returns a collection of data nodes' - mockCmHandleQueries.queryCmHandleDataNodesByCpsPath( - '//lock-reason[@reason="LOCKED_MODULE_SYNC_FAILED"]', + mockCmHandleQueries.queryCmHandleAncestorsByCpsPath( + '//lock-reason[@reason="MODULE_SYNC_FAILED" or @reason="MODULE_UPGRADE"]', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> [dataNode] when: 'get locked Misbehaving cm handle is called' - def result = objectUnderTest.getModuleSyncFailedCmHandles() + def result = objectUnderTest.getCmHandlesThatFailedModelSyncOrUpgrade() then: 'the returned cm handle collection is the correct size' result.size() == 1 and: 'the correct cm handle is returned' @@ -101,19 +127,43 @@ class SyncUtilsSpec extends Specification{ } def 'Retry Locked Cm-Handle where the last update time is #scenario'() { - when: 'retry locked cm handle is invoked' - def result = objectUnderTest.isReadyForRetry(new CompositeStateBuilder() - .withLockReason(LockReasonCategory.LOCKED_MODULE_SYNC_FAILED, details) - .withLastUpdatedTime(lastUpdateTime).build()) - then: 'result returns #expectedResult' - result == expectedResult - where: - scenario | lastUpdateTime | details || expectedResult - 'the first attempt' | '1900-01-01T00:00:00.000+0100' | 'First Attempt' || true - 'greater than one minute' | '1900-01-01T00:00:00.000+0100' | 'Attempt #1 failed:' || true - 'less than eight minutes' | formattedDateAndTime | 'Attempt #3 failed:' || false + given: 'Last update was #lastUpdateMinutesAgo minutes ago (-1 means never)' + def lastUpdatedTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(now.minusMinutes(lastUpdateMinutesAgo)) + if (lastUpdateMinutesAgo < 0 ) { + lastUpdatedTime = neverUpdatedBefore + } + when: 'checking to see if cm handle is ready for retry' + def result = objectUnderTest.needsModuleSyncRetryOrUpgrade(new CompositeStateBuilder() + .withLockReason(MODULE_SYNC_FAILED, lockDetails) + .withLastUpdatedTime(lastUpdatedTime).build()) + then: 'retry is only attempted when expected' + assert result == retryExpected + and: 'logs contain related information' + def logs = loggingListAppender.list.toString() + assert logs.contains(logReason) + where: 'the following parameters are used' + scenario | lastUpdateMinutesAgo | lockDetails | logReason || retryExpected + 'never attempted before' | -1 | 'fist attempt:' | 'First Attempt:' || true + '1st attempt, last attempt > 2 minute ago' | 3 | 'Attempt #1 failed:' | 'Retry due now' || true + '2nd attempt, last attempt < 4 minutes ago' | 1 | 'Attempt #2 failed:' | 'Time until next attempt is 3 minutes:' || false + '2nd attempt, last attempt > 4 minutes ago' | 5 | 'Attempt #2 failed:' | 'Retry due now' || true } + def 'Retry Locked Cm-Handle with other lock reasons (category) #lockReasonCategory'() { + when: 'checking to see if cm handle is ready for retry' + def result = objectUnderTest.needsModuleSyncRetryOrUpgrade(new CompositeStateBuilder() + .withLockReason(lockReasonCategory, 'some details') + .withLastUpdatedTime(nowAsString).build()) + then: 'verify retry attempts' + assert result == retryAttempt + and: 'logs contain related information' + def logs = loggingListAppender.list.toString() + assert logs.contains(logReason) + where: 'the following lock reasons occurred' + scenario | lockReasonCategory || logReason | retryAttempt + 'module upgrade' | MODULE_UPGRADE || 'Locked for module upgrade.' | true + 'module sync failed' | MODULE_SYNC_FAILED || 'First Attempt:' | false + } def 'Get a Cm-Handle where #scenario'() { given: 'the inventory persistence service returns a collection of data nodes' diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/config/WatchdogSchedulingConfigurerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/config/WatchdogSchedulingConfigurerSpec.groovy index d4010aa781..7361948bc6 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/config/WatchdogSchedulingConfigurerSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/config/WatchdogSchedulingConfigurerSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ package org.onap.cps.ncmp.api.inventory.sync.config import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.BeforeEach +import org.onap.cps.ncmp.api.impl.inventory.sync.config.WatchdogSchedulingConfigurer import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.context.ConfigurableApplicationContext diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/executor/AsyncTaskExecutorSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/executor/AsyncTaskExecutorSpec.groovy index ba1820e645..b3ed94520a 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/executor/AsyncTaskExecutorSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/executor/AsyncTaskExecutorSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ package org.onap.cps.ncmp.api.inventory.sync.executor +import org.onap.cps.ncmp.api.impl.inventory.sync.executor.AsyncTaskExecutor import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import spock.lang.Specification diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponseSpec.groovy index dba29343e9..d76f912234 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponseSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponseSpec.groovy @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2022 Bell Canada + * Modifications Copyright (C) 2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,10 +21,11 @@ package org.onap.cps.ncmp.api.models -import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_ALREADY_EXIST +import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR + import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.Status import spock.lang.Specification - import java.util.stream.Collectors class CmHandleRegistrationResponseSpec extends Specification { @@ -37,7 +39,7 @@ class CmHandleRegistrationResponseSpec extends Specification { assert it.status == Status.SUCCESS } and: 'error details are null' - cmHandleRegistrationResponse.registrationError == null + cmHandleRegistrationResponse.ncmpResponseStatus == null cmHandleRegistrationResponse.errorText == null } @@ -47,33 +49,29 @@ class CmHandleRegistrationResponseSpec extends Specification { CmHandleRegistrationResponse.createFailureResponse('cmHandle', new Exception('unexpected error')) then: 'the response is created with expected value' with(cmHandleRegistrationResponse) { - assert it.registrationError == RegistrationError.UNKNOWN_ERROR + assert it.ncmpResponseStatus == UNKNOWN_ERROR assert it.cmHandle == 'cmHandle' assert errorText == 'unexpected error' } } - def 'Failed cm-handle Registration Response: for #scenario'() { - when: 'cm-handle failure response is created for #scenario' - def cmHandleRegistrationResponse = - CmHandleRegistrationResponse.createFailureResponse(cmHandleId, registrationError) + def 'Failed cm-handle Registration Response'() { + when: 'cm-handle failure response is created' + def cmHandleRegistrationResponse = + CmHandleRegistrationResponse.createFailureResponse('cmHandle', CM_HANDLE_ALREADY_EXIST) then: 'the response is created with expected value' - with(cmHandleRegistrationResponse) { - assert it.registrationError == registrationError - assert it.cmHandle == cmHandleId - assert it.status == Status.FAILURE - assert errorText == registrationError.errorText - } - where: - scenario | cmHandleId | registrationError - 'cm-handle already exists' | 'cmHandle' | RegistrationError.CM_HANDLE_ALREADY_EXIST - 'cm-handle id is invalid' | 'cm handle' | RegistrationError.CM_HANDLE_INVALID_ID + with(cmHandleRegistrationResponse) { + assert it.ncmpResponseStatus == CM_HANDLE_ALREADY_EXIST + assert it.cmHandle == 'cmHandle' + assert it.status == Status.FAILURE + assert errorText == CM_HANDLE_ALREADY_EXIST.message + } } def 'Failed cm-handle Registration with multiple responses.'() { when: 'cm-handle failure response is created for 2 xpaths' def cmHandleRegistrationResponses = - CmHandleRegistrationResponse.createFailureResponses(["somePathWithId[@id='123']","somePathWithId[@id='456']"], RegistrationError.CM_HANDLE_ALREADY_EXIST) + CmHandleRegistrationResponse.createFailureResponses(["somePathWithId[@id='123']","somePathWithId[@id='456']"], CM_HANDLE_ALREADY_EXIST) then: 'the response has the correct cm handle ids' assert cmHandleRegistrationResponses.size() == 2 assert cmHandleRegistrationResponses.stream().map(it -> it.cmHandle).collect(Collectors.toList()) @@ -83,12 +81,9 @@ class CmHandleRegistrationResponseSpec extends Specification { def 'Failed cm-handle Registration with multiple responses with an unexpected xpath.'() { when: 'cm-handle failure response is created for one valid and one unexpected xpath' def cmHandleRegistrationResponses = - CmHandleRegistrationResponse.createFailureResponses(["somePathWithId[@id='123']","valid/xpath/without-id[@key='123']"], RegistrationError.CM_HANDLE_ALREADY_EXIST) + CmHandleRegistrationResponse.createFailureResponses(["somePathWithId[@id='123']","valid/xpath/without-id[@key='123']"], CM_HANDLE_ALREADY_EXIST) then: 'the response has only one entry' assert cmHandleRegistrationResponses.size() == 1 } - - - } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/NcmpServiceCmHandleSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/NcmpServiceCmHandleSpec.groovy index 3569887e5a..e42b914d2a 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/NcmpServiceCmHandleSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/NcmpServiceCmHandleSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,8 +20,8 @@ package org.onap.cps.ncmp.api.models -import org.onap.cps.ncmp.api.inventory.CmHandleState -import org.onap.cps.ncmp.api.inventory.CompositeState +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState +import org.onap.cps.ncmp.api.impl.inventory.CompositeState import spock.lang.Specification class NcmpServiceCmHandleSpec extends Specification { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy index 9195bc74ca..16ab0b8846 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy @@ -20,6 +20,9 @@ package org.onap.cps.ncmp.init +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR + import ch.qos.logback.classic.Level import ch.qos.logback.classic.Logger import ch.qos.logback.core.read.ListAppender @@ -61,15 +64,15 @@ class InventoryModelLoaderSpec extends Specification { def 'Onboard subscription model via application ready event.'() { given: 'dataspace is ready for use' - mockCpsAdminService.getDataspace('NCMP-Admin') >> new Dataspace('') + mockCpsAdminService.getDataspace(NCMP_DATASPACE_NAME) >> new Dataspace('') when: 'the application is ready' objectUnderTest.onApplicationEvent(Mock(ApplicationReadyEvent)) then: 'the module service is used to create the new schema set from the correct resource' - 1 * mockCpsModuleService.createSchemaSet('NCMP-Admin', 'dmi-registry-2023-08-23', expectedYangResourceToContentMap) + 1 * mockCpsModuleService.createSchemaSet(NCMP_DATASPACE_NAME, 'dmi-registry-2023-08-23', expectedYangResourceToContentMap) and: 'the admin service is used to update the anchor' - 1 * mockCpsAdminService.updateAnchorSchemaSet('NCMP-Admin', 'ncmp-dmi-registry', 'dmi-registry-2023-08-23') + 1 * mockCpsAdminService.updateAnchorSchemaSet(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, 'dmi-registry-2023-08-23') and: 'No schema sets are being removed by the module service (yet)' - 0 * mockCpsModuleService.deleteSchemaSet('NCMP-Admin', _, _) + 0 * mockCpsModuleService.deleteSchemaSet(NCMP_DATASPACE_NAME, _, _) } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/SubscriptionModelLoaderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/SubscriptionModelLoaderSpec.groovy index d99874ad6c..3486316a0a 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/SubscriptionModelLoaderSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/SubscriptionModelLoaderSpec.groovy @@ -20,6 +20,8 @@ package org.onap.cps.ncmp.init +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME + import ch.qos.logback.classic.Level import ch.qos.logback.classic.Logger import ch.qos.logback.core.read.ListAppender @@ -63,15 +65,15 @@ class SubscriptionModelLoaderSpec extends Specification { given:'model loader is enabled' objectUnderTest.subscriptionModelLoaderEnabled = true and: 'dataspace is ready for use' - mockCpsAdminService.getDataspace('NCMP-Admin') >> new Dataspace('') + mockCpsAdminService.getDataspace(NCMP_DATASPACE_NAME) >> new Dataspace('') when: 'the application is ready' objectUnderTest.onApplicationEvent(Mock(ApplicationReadyEvent)) then: 'the module service to create schema set is called once' - 1 * mockCpsModuleService.createSchemaSet('NCMP-Admin', 'subscriptions', expectedYangResourceToContentMap) + 1 * mockCpsModuleService.createSchemaSet(NCMP_DATASPACE_NAME, 'subscriptions', expectedYangResourceToContentMap) and: 'the admin service to create an anchor set is called once' - 1 * mockCpsAdminService.createAnchor('NCMP-Admin', 'subscriptions', 'AVC-Subscriptions') + 1 * mockCpsAdminService.createAnchor(NCMP_DATASPACE_NAME, 'subscriptions', 'AVC-Subscriptions') and: 'the data service to create a top level datanode is called once' - 1 * mockCpsDataService.saveData('NCMP-Admin', 'AVC-Subscriptions', '{"subscription-registry":{}}', _) + 1 * mockCpsDataService.saveData(NCMP_DATASPACE_NAME, 'AVC-Subscriptions', '{"subscription-registry":{}}', _) } def 'Subscription model loader disabled.' () { diff --git a/cps-ncmp-service/src/test/resources/expectedStateModel.json b/cps-ncmp-service/src/test/resources/expectedStateModel.json index 07275e0823..79ce22801b 100644 --- a/cps-ncmp-service/src/test/resources/expectedStateModel.json +++ b/cps-ncmp-service/src/test/resources/expectedStateModel.json @@ -1,7 +1,7 @@ { "cm-handle-state" : "ADVISED", "lock-reason" : { - "reason" : "LOCKED_MODULE_SYNC_FAILED", + "reason" : "MODULE_SYNC_FAILED", "details" : "lock details" }, "last-update-time" : "2022-12-31T20:30:40.000+0000", |