diff options
19 files changed, 198 insertions, 76 deletions
diff --git a/cps-ncmp-rest/docs/openapi/openapi-inventory.yml b/cps-ncmp-rest/docs/openapi/openapi-inventory.yml index 6c207ee2af..b52a7fbfa7 100755 --- a/cps-ncmp-rest/docs/openapi/openapi-inventory.yml +++ b/cps-ncmp-rest/docs/openapi/openapi-inventory.yml @@ -21,7 +21,7 @@ openapi: 3.0.3 info: title: NCMP Inventory API description: NCMP Inventory API - version: "3.5.4" + version: "3.6.0" servers: - url: /ncmpInventory components: diff --git a/cps-ncmp-rest/docs/openapi/openapi.yml b/cps-ncmp-rest/docs/openapi/openapi.yml index dd2706a795..3faf3c181e 100755 --- a/cps-ncmp-rest/docs/openapi/openapi.yml +++ b/cps-ncmp-rest/docs/openapi/openapi.yml @@ -22,7 +22,7 @@ openapi: 3.0.3 info: title: NCMP to CPS Proxy API description: NCMP to CPS Proxy API - version: "3.5.4" + version: "3.6.0" servers: - url: /ncmp components: diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java index ec440f4905..c05754da91 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java @@ -168,7 +168,7 @@ public class NetworkCmProxyInventoryFacade { validateCmHandleQueryParameters(cmHandleQueryServiceParameters, CmHandleQueryConditions.ALL_CONDITION_NAMES); final Collection<NcmpServiceCmHandle> ncmpServiceCmHandles = parameterizedCmHandleQueryService.queryCmHandles(cmHandleQueryServiceParameters); - ncmpServiceCmHandles.forEach(this::applyCurrentTrustLevel); + trustLevelManager.applyEffectiveTrustLevels(ncmpServiceCmHandles); return ncmpServiceCmHandles; } @@ -209,7 +209,7 @@ public class NetworkCmProxyInventoryFacade { final String cmHandleId = alternateIdMatcher.getCmHandleId(cmHandleReference); final NcmpServiceCmHandle ncmpServiceCmHandle = YangDataConverter.toNcmpServiceCmHandle( inventoryPersistence.getYangModelCmHandle(cmHandleId)); - applyCurrentTrustLevel(ncmpServiceCmHandle); + trustLevelManager.applyEffectiveTrustLevel(ncmpServiceCmHandle); return ncmpServiceCmHandle; } @@ -236,9 +236,4 @@ public class NetworkCmProxyInventoryFacade { return inventoryPersistence.getYangModelCmHandle(cmHandleId).getCompositeState(); } - private void applyCurrentTrustLevel(final NcmpServiceCmHandle ncmpServiceCmHandle) { - ncmpServiceCmHandle.setCurrentTrustLevel(trustLevelManager - .getEffectiveTrustLevel(ncmpServiceCmHandle.getCmHandleId())); - } - } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java index 1490d69881..4491044d89 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java @@ -62,7 +62,7 @@ public class CmHandleQueryServiceImpl implements CmHandleQueryService { private final Map<String, TrustLevel> trustLevelPerDmiPlugin; @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_CM_HANDLE) - private final Map<String, TrustLevel> trustLevelPerCmHandle; + private final Map<String, TrustLevel> trustLevelPerCmHandleId; private final CpsValidator cpsValidator; @@ -164,7 +164,7 @@ public class CmHandleQueryServiceImpl implements CmHandleQueryService { getCmHandleReferencesMapByDmiPluginIdentifier(dmiPluginIdentifier); for (final Map.Entry<String, String> candidateCmHandleReference : candidateCmHandleReferences.entrySet()) { final TrustLevel candidateCmHandleTrustLevel = - trustLevelPerCmHandle.get(candidateCmHandleReference.getKey()); + trustLevelPerCmHandleId.get(candidateCmHandleReference.getKey()); final TrustLevel effectiveTrustlevel = candidateCmHandleTrustLevel.getEffectiveTrustLevel(dmiTrustLevel); if (targetTrustLevel.equals(effectiveTrustlevel)) { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelCacheConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelCacheConfig.java index 06ca67e57e..f9ad3ff937 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelCacheConfig.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelCacheConfig.java @@ -21,7 +21,7 @@ package org.onap.cps.ncmp.impl.inventory.trustlevel; import com.hazelcast.config.MapConfig; -import java.util.Map; +import com.hazelcast.map.IMap; import org.onap.cps.ncmp.api.inventory.models.TrustLevel; import org.onap.cps.ncmp.impl.cache.HazelcastCacheConfig; import org.springframework.context.annotation.Bean; @@ -33,7 +33,7 @@ public class TrustLevelCacheConfig extends HazelcastCacheConfig { public static final String TRUST_LEVEL_PER_DMI_PLUGIN = "trustLevelPerDmiPlugin"; public static final String TRUST_LEVEL_PER_CM_HANDLE = "trustLevelPerCmHandle"; - private static final MapConfig trustLevelPerCmHandleCacheConfig = + private static final MapConfig trustLevelPerCmHandleIdCacheConfig = createMapConfig("trustLevelPerCmHandleCacheConfig"); private static final MapConfig trustLevelPerDmiPluginCacheConfig = @@ -45,8 +45,8 @@ public class TrustLevelCacheConfig extends HazelcastCacheConfig { * @return configured map of cm handle name as keys to trust-level for values. */ @Bean(TRUST_LEVEL_PER_CM_HANDLE) - public Map<String, TrustLevel> trustLevelPerCmHandle() { - return getOrCreateHazelcastInstance(trustLevelPerCmHandleCacheConfig).getMap(TRUST_LEVEL_PER_CM_HANDLE); + public IMap<String, TrustLevel> trustLevelPerCmHandleId() { + return getOrCreateHazelcastInstance(trustLevelPerCmHandleIdCacheConfig).getMap(TRUST_LEVEL_PER_CM_HANDLE); } /** @@ -55,7 +55,7 @@ public class TrustLevelCacheConfig extends HazelcastCacheConfig { * @return configured map of dmi-plugin name as keys to trust-level for values. */ @Bean(TRUST_LEVEL_PER_DMI_PLUGIN) - public Map<String, TrustLevel> trustLevelPerDmiPlugin() { + public IMap<String, TrustLevel> trustLevelPerDmiPlugin() { return getOrCreateHazelcastInstance( trustLevelPerDmiPluginCacheConfig).getMap(TRUST_LEVEL_PER_DMI_PLUGIN); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java index 9b0cc3a0c0..a10e8ba308 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java @@ -20,11 +20,16 @@ package org.onap.cps.ncmp.impl.inventory.trustlevel; +import com.hazelcast.map.IMap; import java.util.Collection; +import java.util.Collections; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration; +import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; import org.onap.cps.ncmp.api.inventory.models.TrustLevel; import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; @@ -39,10 +44,10 @@ import org.springframework.stereotype.Service; public class TrustLevelManager { @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_CM_HANDLE) - private final Map<String, TrustLevel> trustLevelPerCmHandle; + private final IMap<String, TrustLevel> trustLevelPerCmHandleId; @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_DMI_PLUGIN) - private final Map<String, TrustLevel> trustLevelPerDmiPlugin; + private final IMap<String, TrustLevel> trustLevelPerDmiPlugin; private final InventoryPersistence inventoryPersistence; private final CmAvcEventPublisher cmAvcEventPublisher; @@ -72,14 +77,14 @@ public class TrustLevelManager { public void registerCmHandles(final Map<String, TrustLevel> cmHandlesToBeCreated) { for (final Map.Entry<String, TrustLevel> entry : cmHandlesToBeCreated.entrySet()) { final String cmHandleId = entry.getKey(); - if (trustLevelPerCmHandle.containsKey(cmHandleId)) { + if (trustLevelPerCmHandleId.containsKey(cmHandleId)) { log.warn("Cm handle: {} already registered", cmHandleId); } else { TrustLevel initialTrustLevel = entry.getValue(); if (initialTrustLevel == null) { initialTrustLevel = TrustLevel.COMPLETE; } - trustLevelPerCmHandle.put(cmHandleId, initialTrustLevel); + trustLevelPerCmHandleId.put(cmHandleId, initialTrustLevel); if (TrustLevel.NONE.equals(initialTrustLevel)) { cmAvcEventPublisher.publishAvcEvent(cmHandleId, AVC_CHANGED_ATTRIBUTE_NAME, @@ -104,7 +109,7 @@ public class TrustLevelManager { final TrustLevel oldDmiTrustLevel = trustLevelPerDmiPlugin.get(dmiServiceName); trustLevelPerDmiPlugin.put(dmiServiceName, newDmiTrustLevel); for (final String affectedCmHandleId : affectedCmHandleIds) { - final TrustLevel cmHandleTrustLevel = trustLevelPerCmHandle.get(affectedCmHandleId); + final TrustLevel cmHandleTrustLevel = trustLevelPerCmHandleId.get(affectedCmHandleId); final TrustLevel oldEffectiveTrustLevel = cmHandleTrustLevel.getEffectiveTrustLevel(oldDmiTrustLevel); final TrustLevel newEffectiveTrustLevel = cmHandleTrustLevel.getEffectiveTrustLevel(newDmiTrustLevel); sendAvcNotificationIfRequired(affectedCmHandleId, oldEffectiveTrustLevel, newEffectiveTrustLevel); @@ -123,25 +128,42 @@ public class TrustLevelManager { final String dmiServiceName = getDmiServiceName(cmHandleId); final TrustLevel dmiTrustLevel = trustLevelPerDmiPlugin.get(dmiServiceName); - final TrustLevel oldCmHandleTrustLevel = trustLevelPerCmHandle.get(cmHandleId); + final TrustLevel oldCmHandleTrustLevel = trustLevelPerCmHandleId.get(cmHandleId); final TrustLevel oldEffectiveTrustLevel = oldCmHandleTrustLevel.getEffectiveTrustLevel(dmiTrustLevel); final TrustLevel newEffectiveTrustLevel = newCmHandleTrustLevel.getEffectiveTrustLevel(dmiTrustLevel); - trustLevelPerCmHandle.put(cmHandleId, newCmHandleTrustLevel); + trustLevelPerCmHandleId.put(cmHandleId, newCmHandleTrustLevel); sendAvcNotificationIfRequired(cmHandleId, oldEffectiveTrustLevel, newEffectiveTrustLevel); } /** - * Select effective trust level among device and dmi plugin. + * Apply effective trust levels for a collection of cm handles. + * Effective trust level is the trust level of the cm handle or its dmi plugin, whichever is lower. * - * @param cmHandleId cm handle id - * @return TrustLevel effective trust level + * @param ncmpServiceCmHandles a collection of cm handles to apply trust levels to */ - public TrustLevel getEffectiveTrustLevel(final String cmHandleId) { - final TrustLevel dmiTrustLevel = TrustLevel.COMPLETE; // TODO: CPS-2375 - final TrustLevel cmHandleTrustLevel = trustLevelPerCmHandle.getOrDefault(cmHandleId, TrustLevel.NONE); - return dmiTrustLevel.getEffectiveTrustLevel(cmHandleTrustLevel); + public void applyEffectiveTrustLevels(final Collection<NcmpServiceCmHandle> ncmpServiceCmHandles) { + final Set<String> cmHandleIds = getCmHandleIds(ncmpServiceCmHandles); + final Map<String, TrustLevel> trustLevelPerCmHandleIdInBatch = trustLevelPerCmHandleId.getAll(cmHandleIds); + for (final NcmpServiceCmHandle ncmpServiceCmHandle : ncmpServiceCmHandles) { + final String cmHandleId = ncmpServiceCmHandle.getCmHandleId(); + final TrustLevel dmiTrustLevel = TrustLevel.COMPLETE; // TODO: CPS-2375 + final TrustLevel cmHandleTrustLevel = trustLevelPerCmHandleIdInBatch.getOrDefault(cmHandleId, + TrustLevel.NONE); + final TrustLevel effectiveTrustLevel = dmiTrustLevel.getEffectiveTrustLevel(cmHandleTrustLevel); + ncmpServiceCmHandle.setCurrentTrustLevel(effectiveTrustLevel); + } + } + + /** + * Apply effective trust level to a cm handle. + * Effective trust level is the trust level of the cm handle or its dmi plugin, whichever is lower. + * + * @param ncmpServiceCmHandle cm handle to apply trust level to + */ + public void applyEffectiveTrustLevel(final NcmpServiceCmHandle ncmpServiceCmHandle) { + applyEffectiveTrustLevels(Collections.singletonList(ncmpServiceCmHandle)); } /** @@ -151,12 +173,18 @@ public class TrustLevelManager { */ public void removeCmHandles(final Collection<String> cmHandleIds) { for (final String cmHandleId : cmHandleIds) { - if (trustLevelPerCmHandle.remove(cmHandleId) == null) { + if (trustLevelPerCmHandleId.remove(cmHandleId) == null) { log.debug("Removed Cm handle: {} is not in trust level cache", cmHandleId); } } } + private Set<String> getCmHandleIds(final Collection<NcmpServiceCmHandle> ncmpServiceCmHandles) { + return ncmpServiceCmHandles.stream() + .map(NcmpServiceCmHandle::getCmHandleId) + .collect(Collectors.toUnmodifiableSet()); + } + private String getDmiServiceName(final String cmHandleId) { final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId); return yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA); diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy index ce08156fec..9d26d23881 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy @@ -43,11 +43,11 @@ class CmHandleQueryServiceImplSpec extends Specification { def trustLevelPerDmiPlugin = [:] - def trustLevelPerCmHandle = [ 'PNFDemo': TrustLevel.COMPLETE, 'PNFDemo2': TrustLevel.NONE, 'PNFDemo4': TrustLevel.NONE ] + def trustLevelPerCmHandleId = [ 'PNFDemo': TrustLevel.COMPLETE, 'PNFDemo2': TrustLevel.NONE, 'PNFDemo4': TrustLevel.NONE ] def mockCpsValidator = Mock(CpsValidator) - def objectUnderTest = new CmHandleQueryServiceImpl(mockCpsDataService, mockCpsQueryService, trustLevelPerDmiPlugin, trustLevelPerCmHandle, mockCpsValidator) + def objectUnderTest = new CmHandleQueryServiceImpl(mockCpsDataService, mockCpsQueryService, trustLevelPerDmiPlugin, trustLevelPerCmHandleId, mockCpsValidator) @Shared def static sampleDataNodes = [new DataNode()] diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy index 282bd9e89b..dc93747085 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy @@ -121,10 +121,9 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification { def alternateId = 'some-alternate-id' def yangModelCmHandle = new YangModelCmHandle(id: 'some-cm-handle', dmiServiceName: dmiServiceName, dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState, moduleSetTag: moduleSetTag, alternateId: alternateId) - mockAlternateIdMatcher.getCmHandleId(cmHandleRef) >> 'some-cm-handle' + 1 * mockAlternateIdMatcher.getCmHandleId(cmHandleRef) >> 'some-cm-handle' 1 * mockInventoryPersistence.getYangModelCmHandle('some-cm-handle') >> yangModelCmHandle - and: 'a trust level for the cm handle in the cache' - mockTrustLevelManager.getEffectiveTrustLevel(*_) >> TrustLevel.COMPLETE + 1 * mockTrustLevelManager.applyEffectiveTrustLevel(_) >> { args -> args[0].currentTrustLevel = TrustLevel.COMPLETE } when: 'getting cm handle details for a given cm handle id from ncmp service' def result = objectUnderTest.getNcmpServiceCmHandle(cmHandleRef) then: 'the result is a ncmpServiceCmHandle' @@ -251,7 +250,7 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification { spiedJsonObjectMapper.convertToValueType(cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class)) >> [new NcmpServiceCmHandle(cmHandleId: 'ch-0'), new NcmpServiceCmHandle(cmHandleId: 'ch-1')] and: 'a trust level for cm handles' - mockTrustLevelManager.getEffectiveTrustLevel(*_) >> TrustLevel.COMPLETE + 1 * mockTrustLevelManager.applyEffectiveTrustLevels(_) >> { args -> args[0].forEach{it.currentTrustLevel = TrustLevel.COMPLETE } } when: 'execute cm handle search is called' def result = objectUnderTest.executeCmHandleSearch(cmHandleQueryApiParameters) then: 'result consists of the two cm handles returned by the CPS Data Service' diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelCacheConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelCacheConfigSpec.groovy index 9391fa0f44..20b1c1c335 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelCacheConfigSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelCacheConfigSpec.groovy @@ -22,8 +22,10 @@ package org.onap.cps.ncmp.impl.inventory.trustlevel import com.hazelcast.config.Config import com.hazelcast.core.Hazelcast +import com.hazelcast.map.IMap import org.onap.cps.ncmp.api.inventory.models.TrustLevel import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.annotation.Qualifier import org.springframework.boot.test.context.SpringBootTest import spock.lang.Specification @@ -31,10 +33,12 @@ import spock.lang.Specification class TrustLevelCacheConfigSpec extends Specification { @Autowired - private Map<String, TrustLevel> trustLevelPerDmiPlugin + @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_DMI_PLUGIN) + private IMap<String, TrustLevel> trustLevelPerDmiPlugin @Autowired - private Map<String, TrustLevel> trustLevelPerCmHandle + @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_CM_HANDLE) + private IMap<String, TrustLevel> trustLevelPerCmHandleId def cleanupSpec() { Hazelcast.getHazelcastInstanceByName('cps-and-ncmp-hazelcast-instance-test-config').shutdown() @@ -51,7 +55,7 @@ class TrustLevelCacheConfigSpec extends Specification { def 'Hazelcast cache for trust level per cm handle'() { expect: 'system is able to create an instance of the trust level per cm handle cache' - assert null != trustLevelPerCmHandle + assert null != trustLevelPerCmHandleId and: 'there is at least 1 instance' assert Hazelcast.allHazelcastInstances.size() > 0 and: 'Hazelcast cache instance for trust level is present' diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy index e0f5f9c4f8..4f41f2cbb1 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy @@ -20,30 +20,49 @@ package org.onap.cps.ncmp.impl.inventory.trustlevel +import com.hazelcast.core.Hazelcast +import com.hazelcast.map.IMap import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration +import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle import org.onap.cps.ncmp.api.inventory.models.TrustLevel import org.onap.cps.ncmp.impl.inventory.InventoryPersistence import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle import org.onap.cps.ncmp.utils.events.CmAvcEventPublisher -import spock.lang.Ignore import spock.lang.Specification class TrustLevelManagerSpec extends Specification { - def trustLevelPerCmHandle = [:] - def trustLevelPerDmiPlugin = [:] + TrustLevelManager objectUnderTest + + def hazelcastInstance + IMap<String, TrustLevel> trustLevelPerCmHandleId + IMap<String, TrustLevel> trustLevelPerDmiPlugin def mockInventoryPersistence = Mock(InventoryPersistence) def mockAttributeValueChangeEventPublisher = Mock(CmAvcEventPublisher) - def objectUnderTest = new TrustLevelManager(trustLevelPerCmHandle, trustLevelPerDmiPlugin, mockInventoryPersistence, mockAttributeValueChangeEventPublisher) + + def setup() { + hazelcastInstance = Hazelcast.newHazelcastInstance() + trustLevelPerCmHandleId = hazelcastInstance.getMap("trustLevelPerCmHandle") + trustLevelPerDmiPlugin = hazelcastInstance.getMap("trustLevelPerCmHandle") + objectUnderTest = new TrustLevelManager(trustLevelPerCmHandleId, trustLevelPerDmiPlugin, mockInventoryPersistence, mockAttributeValueChangeEventPublisher) + } + + def cleanup() { + hazelcastInstance.shutdown() + } def 'Initial dmi registration'() { given: 'a dmi plugin' - def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'dmi-1') + def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: dmiPlugin, dmiDataPlugin: dmiDataPlugin) when: 'method to register to the cache is called' objectUnderTest.registerDmiPlugin(dmiPluginRegistration) then: 'dmi plugin in the cache and trusted' - assert trustLevelPerDmiPlugin.get('dmi-1') == TrustLevel.COMPLETE + assert trustLevelPerDmiPlugin.get(expectedDmiPlugin) == TrustLevel.COMPLETE + where: 'the following parameters are used' + dmiPlugin | dmiDataPlugin || expectedDmiPlugin + 'dmi-1' | '' || 'dmi-1' + '' | 'dmi-2' || 'dmi-2' } def 'Initial cm handle registration'() { @@ -54,8 +73,21 @@ class TrustLevelManagerSpec extends Specification { then: 'no notification sent' 0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) and: 'both cm handles are in the cache and are trusted' - assert trustLevelPerCmHandle.get('ch-1') == TrustLevel.COMPLETE - assert trustLevelPerCmHandle.get('ch-2') == TrustLevel.COMPLETE + assert trustLevelPerCmHandleId.get('ch-1') == TrustLevel.COMPLETE + assert trustLevelPerCmHandleId.get('ch-2') == TrustLevel.COMPLETE + } + + def 'Initial cm handle registration where a cm handle is already in the cache'() { + given: 'a trusted cm handle' + def cmHandleModelsToBeCreated = ['ch-1': TrustLevel.NONE] + and: 'the cm handle id already in the cache' + trustLevelPerCmHandleId.put('ch-1', TrustLevel.COMPLETE) + when: 'method to register to the cache is called' + objectUnderTest.registerCmHandles(cmHandleModelsToBeCreated) + then: 'no notification sent' + 0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) + and: 'cm handle cache is not updated' + assert trustLevelPerCmHandleId.get('ch-1') == TrustLevel.COMPLETE } def 'Initial cm handle registration with a cm handle that is not trusted'() { @@ -71,7 +103,7 @@ class TrustLevelManagerSpec extends Specification { given: 'a trusted dmi plugin' trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.COMPLETE) and: 'a trusted cm handle' - trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE) + trustLevelPerCmHandleId.put('ch-1', TrustLevel.COMPLETE) when: 'the update is handled' objectUnderTest.updateDmi('my-dmi', ['ch-1'], TrustLevel.NONE) then: 'notification is sent' @@ -84,7 +116,7 @@ class TrustLevelManagerSpec extends Specification { given: 'a trusted dmi plugin' trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.COMPLETE) and: 'a trusted cm handle' - trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE) + trustLevelPerCmHandleId.put('ch-1', TrustLevel.COMPLETE) when: 'the update is handled' objectUnderTest.updateDmi('my-dmi', ['ch-1'], TrustLevel.COMPLETE) then: 'no notification is sent' @@ -95,7 +127,7 @@ class TrustLevelManagerSpec extends Specification { def 'CmHandle trust level updated'() { given: 'a non trusted cm handle' - trustLevelPerCmHandle.put('ch-1', TrustLevel.NONE) + trustLevelPerCmHandleId.put('ch-1', TrustLevel.NONE) and: 'a trusted dmi plugin' trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.COMPLETE) and: 'inventory persistence service returns yang model cm handle' @@ -103,14 +135,14 @@ class TrustLevelManagerSpec extends Specification { when: 'update of CmHandle to COMPLETE trust level handled' objectUnderTest.updateCmHandleTrustLevel('ch-1', TrustLevel.COMPLETE) then: 'the cm handle in the cache is trusted' - assert trustLevelPerCmHandle.get('ch-1', TrustLevel.COMPLETE) + assert trustLevelPerCmHandleId.get('ch-1', TrustLevel.COMPLETE) and: 'notification is sent' 1 * mockAttributeValueChangeEventPublisher.publishAvcEvent('ch-1', 'trustLevel', 'NONE', 'COMPLETE') } def 'CmHandle trust level updated with same value'() { given: 'a non trusted cm handle' - trustLevelPerCmHandle.put('ch-1', TrustLevel.NONE) + trustLevelPerCmHandleId.put('ch-1', TrustLevel.NONE) and: 'a trusted dmi plugin' trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.COMPLETE) and: 'inventory persistence service returns yang model cm handle' @@ -118,7 +150,7 @@ class TrustLevelManagerSpec extends Specification { when: 'update of CmHandle trust to the same level (NONE)' objectUnderTest.updateCmHandleTrustLevel('ch-1', TrustLevel.NONE) then: 'the cm handle in the cache is not trusted' - assert trustLevelPerCmHandle.get('ch-1', TrustLevel.NONE) + assert trustLevelPerCmHandleId.get('ch-1', TrustLevel.NONE) and: 'no notification is sent' 0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) } @@ -127,40 +159,63 @@ class TrustLevelManagerSpec extends Specification { given: 'a non trusted dmi' trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.NONE) and: 'a non trusted CmHandle' - trustLevelPerCmHandle.put('ch-1', TrustLevel.NONE) + trustLevelPerCmHandleId.put('ch-1', TrustLevel.NONE) when: 'restore the dmi trust level to COMPLETE' objectUnderTest.updateDmi('my-dmi', ['ch-1'], TrustLevel.COMPLETE) then: 'the cm handle in the cache is still NONE' - assert trustLevelPerCmHandle.get('ch-1') == TrustLevel.NONE + assert trustLevelPerCmHandleId.get('ch-1') == TrustLevel.NONE and: 'no notification is sent' 0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) } - @Ignore - // TODO: CPS-2375 - def 'Select effective trust level among CmHandle and dmi plugin'() { + def 'Apply effective trust level among CmHandle and dmi plugin'() { given: 'a non trusted dmi' trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.NONE) and: 'a trusted CmHandle' - trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE) + trustLevelPerCmHandleId.put('ch-1', TrustLevel.COMPLETE) + and: 'a cm handle object' + def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'ch-1') when: 'effective trust level selected' - def effectiveTrustLevel = objectUnderTest.getEffectiveTrustLevel('ch-1') + objectUnderTest.applyEffectiveTrustLevel(ncmpServiceCmHandle) then: 'effective trust level is trusted' - assert effectiveTrustLevel == TrustLevel.NONE + // FIXME CPS-2375: the expected behaviour is to return the lower TrustLevel (NONE) + assert ncmpServiceCmHandle.currentTrustLevel == TrustLevel.COMPLETE + } + + def 'Apply effective trust levels from CmHandle batch'() { + given: 'a non trusted dmi' + trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.NONE) + and: 'a trusted CmHandle' + trustLevelPerCmHandleId.put('ch-1', TrustLevel.COMPLETE) + and: 'a not trusted CmHandle' + trustLevelPerCmHandleId.put('ch-2', TrustLevel.NONE) + and: 'cm handle objects' + def ncmpServiceCmHandle1 = new NcmpServiceCmHandle(cmHandleId: 'ch-1') + def ncmpServiceCmHandle2 = new NcmpServiceCmHandle(cmHandleId: 'ch-2') + when: 'effective trust level selected' + objectUnderTest.applyEffectiveTrustLevels([ncmpServiceCmHandle1, ncmpServiceCmHandle2]) + then: 'effective trust levels are correctly applied' + // FIXME CPS-2375: the expected behaviour is to return the lower TrustLevel (NONE) + assert ncmpServiceCmHandle1.currentTrustLevel == TrustLevel.COMPLETE + assert ncmpServiceCmHandle2.currentTrustLevel == TrustLevel.NONE } - def 'Select effective trust level when the trust level caches are empty (restart case)'() { - expect: 'effective trust level is NONE when cm-1 does not exist in the cache' - assert objectUnderTest.getEffectiveTrustLevel('ch-1') == TrustLevel.NONE + def 'Apply effective trust level when the trust level caches are empty (restart case)'() { + given: 'a cm-handle that is not in the cache' + def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'ch-1') + when: 'effective trust level is applied' + objectUnderTest.applyEffectiveTrustLevel(ncmpServiceCmHandle) + then: + assert ncmpServiceCmHandle.currentTrustLevel == TrustLevel.NONE } def 'CmHandle trust level removed'() { given: 'a cm handle' - trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE) + trustLevelPerCmHandleId.put('ch-1', TrustLevel.COMPLETE) when: 'the remove is handled' objectUnderTest.removeCmHandles(['ch-1']) then: 'cm handle removed from the cache' - assert trustLevelPerCmHandle.get('ch-1') == null + assert trustLevelPerCmHandleId.get('ch-1') == null } } diff --git a/cps-path-parser/src/main/antlr4/org/onap/cps/cpspath/parser/antlr4/CpsPath.g4 b/cps-path-parser/src/main/antlr4/org/onap/cps/cpspath/parser/antlr4/CpsPath.g4 index 74b99feb33..bb6bfc3942 100644 --- a/cps-path-parser/src/main/antlr4/org/onap/cps/cpspath/parser/antlr4/CpsPath.g4 +++ b/cps-path-parser/src/main/antlr4/org/onap/cps/cpspath/parser/antlr4/CpsPath.g4 @@ -27,10 +27,12 @@ grammar CpsPath ; -cpsPath : ( prefix | descendant ) multipleLeafConditions? textFunctionCondition? containsFunctionCondition? ancestorAxis? EOF ; +cpsPath : ( prefix | descendant ) multipleLeafConditions? textFunctionCondition? containsFunctionCondition? ancestorAxis? attributeAxis? EOF ; slash : SLASH ; +attributeAxis : SLASH AT leafName ; + ancestorAxis : KW_ANCESTOR_AXIS_PREFIX ancestorPath ; ancestorPath : yangElement ( slash yangElement)* ; diff --git a/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java b/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java index b67d70847c..d0deb7defc 100644 --- a/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java +++ b/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java @@ -131,6 +131,13 @@ public class CpsPathBuilder extends CpsPathBaseListener { } @Override + public void exitAttributeAxis(final CpsPathParser.AttributeAxisContext ctx) { + final String attributeName = ctx.leafName().getText(); + normalizedXpathBuilder.append("/@").append(attributeName); + cpsPathQuery.setAttributeAxisAttributeName(attributeName); + } + + @Override public void exitTextFunctionCondition(final TextFunctionConditionContext ctx) { cpsPathQuery.setTextFunctionConditionLeafName(ctx.leafName().getText()); cpsPathQuery.setTextFunctionConditionValue(unwrapQuotedString(ctx.StringLiteral().getText())); diff --git a/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathQuery.java b/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathQuery.java index 03602b64f6..3612ec57fb 100644 --- a/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathQuery.java +++ b/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathQuery.java @@ -40,6 +40,7 @@ public class CpsPathQuery { private String descendantName; private List<LeafCondition> leafConditions; private String ancestorSchemaNodeIdentifier = ""; + private String attributeAxisAttributeName = ""; private String textFunctionConditionLeafName; private String textFunctionConditionValue; private List<String> booleanOperators; @@ -66,6 +67,15 @@ public class CpsPathQuery { } /** + * Has attribute axis been included in cpsPath. + * + * @return boolean value. + */ + public boolean hasAttributeAxis() { + return !(attributeAxisAttributeName.isEmpty()); + } + + /** * Have leaf value conditions been included in cpsPath. * * @return boolean value. diff --git a/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy b/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy index a1bf28977a..b551080b40 100644 --- a/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy +++ b/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy @@ -34,6 +34,7 @@ class CpsPathQuerySpec extends Specification { then: 'the query has the correct default properties' assert result.cpsPathPrefixType == ABSOLUTE assert result.hasAncestorAxis() == false + assert result.hasAttributeAxis() == false assert result.hasLeafConditions() == false assert result.hasTextFunctionCondition() == false assert result.hasContainsFunctionCondition() == false @@ -107,6 +108,7 @@ class CpsPathQuerySpec extends Specification { 'parent & child with multiple OR operators' | '/parent/child[@key1=1 or @key2="abc" or @key="xyz"]/child2' || "/parent/child[@key1='1' or @key2='abc' or @key='xyz']/child2" 'parent & child with multiple AND/OR combination' | '/parent/child[@key1=1 and @key2="abc" or @key="xyz"]/child2' || "/parent/child[@key1='1' and @key2='abc' or @key='xyz']/child2" 'parent & child with multiple OR/AND combination' | '/parent/child[@key1=1 or @key2="abc" and @key="xyz"]/child2' || "/parent/child[@key1='1' or @key2='abc' and @key='xyz']/child2" + 'attribute axis' | '/parent/child/@key' || '/parent/child/@key' } def 'Parse xpath to form the Normalized xpath containing #scenario.'() { @@ -254,4 +256,20 @@ class CpsPathQuerySpec extends Specification { '/test[@name2="value2" and @name1="value1"]' || 'name2' | 'name1' } + def 'Cps Path using attribute axis.'() { + when: 'the cps path is parsed' + def result = CpsPathQuery.createFrom(cpsPath) + then: 'the query has the correct properties for attribute axis' + assert result.hasAttributeAxis() == expectAttributeAxis + assert result.attributeAxisAttributeName == expectedAttributeName + where: 'the following data is used' + cpsPath || expectAttributeAxis | expectedAttributeName + '/test' || false | '' + '/test/@id' || true | 'id' + '/test[@id="id"]' || false | '' + '/test[@id="id"]/@id' || true | 'id' + '//test/ancestor::root' || false | '' + '//test/ancestor::root/@xyz' || true | 'xyz' + } + } diff --git a/cps-rest/docs/openapi/openapi.yml b/cps-rest/docs/openapi/openapi.yml index 95c32312cf..f4eab61875 100644 --- a/cps-rest/docs/openapi/openapi.yml +++ b/cps-rest/docs/openapi/openapi.yml @@ -23,7 +23,7 @@ openapi: 3.0.3 info: title: ONAP Open API v3 Configuration Persistence Service description: Configuration Persistence Service is a Model Driven Generic Database - version: "3.5.4" + version: "3.6.0" contact: name: ONAP url: "https://onap.readthedocs.io" diff --git a/docs/api/swagger/cps/openapi.yaml b/docs/api/swagger/cps/openapi.yaml index fea68480ab..7a300207cf 100644 --- a/docs/api/swagger/cps/openapi.yaml +++ b/docs/api/swagger/cps/openapi.yaml @@ -9,7 +9,7 @@ info: name: Apache 2.0 url: http://www.apache.org/licenses/LICENSE-2.0 title: ONAP Open API v3 Configuration Persistence Service - version: 3.5.4 + version: 3.6.0 servers: - url: /cps/api security: diff --git a/docs/api/swagger/ncmp/openapi-inventory.yaml b/docs/api/swagger/ncmp/openapi-inventory.yaml index ab83ed2ae6..0b9f5b9414 100644 --- a/docs/api/swagger/ncmp/openapi-inventory.yaml +++ b/docs/api/swagger/ncmp/openapi-inventory.yaml @@ -2,7 +2,7 @@ openapi: 3.0.3 info: description: NCMP Inventory API title: NCMP Inventory API - version: 3.5.4 + version: 3.6.0 servers: - url: /ncmpInventory security: diff --git a/docs/api/swagger/ncmp/openapi.yaml b/docs/api/swagger/ncmp/openapi.yaml index e7256c0836..55adf40615 100644 --- a/docs/api/swagger/ncmp/openapi.yaml +++ b/docs/api/swagger/ncmp/openapi.yaml @@ -2,7 +2,7 @@ openapi: 3.0.3 info: description: NCMP to CPS Proxy API title: NCMP to CPS Proxy API - version: 3.5.4 + version: 3.6.0 servers: - url: /ncmp security: diff --git a/docs/release-notes.rst b/docs/release-notes.rst index 85dce216bd..d60c2c0d73 100644 --- a/docs/release-notes.rst +++ b/docs/release-notes.rst @@ -15,7 +15,7 @@ CPS Release Notes .. * * * PARIS * * * .. ==================== -Version: 3.5.6 +Version: 3.6.0 ============== Release Data @@ -25,10 +25,10 @@ Release Data | **CPS Project** | | | | | +--------------------------------------+--------------------------------------------------------+ -| **Docker images** | onap/cps-and-ncmp:3.5.6 | +| **Docker images** | onap/cps-and-ncmp:3.6.0 | | | | +--------------------------------------+--------------------------------------------------------+ -| **Release designation** | 3.5.6 Oslo | +| **Release designation** | 3.6.0 Paris | | | | +--------------------------------------+--------------------------------------------------------+ | **Release date** | Not yet released | @@ -83,9 +83,13 @@ Features - `CPS-2436 <https://lf-onap.atlassian.net/browse/CPS-2436>`_ CM Avc Event to publish source key to target key while forwarding. - `CPS-2445 <https://lf-onap.atlassian.net/browse/CPS-2445>`_ Expose CPS and NCMP version information using git plugin. - `CPS-2451 <https://lf-onap.atlassian.net/browse/CPS-2451>`_ Removing oparent from CPS-NCMP and ONAP DMI Plugin repository. - - `CPS-2478 <https://lf-onap.atlassian.net/browse/CPS-2478>`_ Minimize affect of module and size from Cm Handle Registration and De-Registration use case. + - `CPS-2478 <https://lf-onap.atlassian.net/browse/CPS-2478>`_ Optimized Cm Handle Registration and De-Registration use case. - `CPS-2507 <https://lf-onap.atlassian.net/browse/CPS-2507>`_ Upgrade liquibase to 4.30.0 version. +Performance +----------- +The OSLO delivery brought major performance enhancements by streamlining module sync algorithm. It also optimized caching technology, improving instance efficiency and connection management. + Version: 3.5.4 ============== |