[BUG] Effective trust factors in DMI trust level 46/139646/1
authordanielhanrahan <daniel.hanrahan@est.tech>
Wed, 4 Dec 2024 14:37:26 +0000 (14:37 +0000)
committerdanielhanrahan <daniel.hanrahan@est.tech>
Wed, 4 Dec 2024 14:54:15 +0000 (14:54 +0000)
Effective trust of a CM handle should be the trust level of the
handle or the DMI, whichever is lower. Currently, effective trust
level of a CM handle is not reported correctly when the DMI is down,
as DMI trust level is not considered.

- Add DMI service names to NcmpServiceCmHandle
- Introduce new DmiServiceNameResolver class
- Correctly calculate effective trust level

Issue-ID: CPS-2375
Signed-off-by: danielhanrahan <daniel.hanrahan@est.tech>
Change-Id: Iaded0fadad58d960eb76c69f79a308df8329e534

cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/NcmpServiceCmHandle.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceNameResolver.java [new file with mode: 0644]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandle.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/YangDataConverter.java
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/YangDataConverterSpec.groovy

index 3ebceed..25c9f76 100644 (file)
@@ -41,6 +41,15 @@ public class NcmpServiceCmHandle {
 
     private String cmHandleId;
 
+    @JsonSetter(nulls = Nulls.AS_EMPTY)
+    private String dmiServiceName;
+
+    @JsonSetter(nulls = Nulls.AS_EMPTY)
+    private String dmiDataServiceName;
+
+    @JsonSetter(nulls = Nulls.AS_EMPTY)
+    private String dmiModelServiceName;
+
     @JsonSetter(nulls = Nulls.AS_EMPTY)
     private Map<String, String> dmiProperties = Collections.emptyMap();
 
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceNameResolver.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceNameResolver.java
new file mode 100644 (file)
index 0000000..e9378da
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2024 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.impl.dmi;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration;
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.models.RequiredDmiService;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class DmiServiceNameResolver {
+
+    /**
+     * Resolve a dmi service name.
+     *
+     * @param requiredService   indicates what type of service is required
+     * @param yangModelCmHandle cm handle
+     * @return dmi service name
+     */
+    public static String resolveDmiServiceName(final RequiredDmiService requiredService,
+                                               final YangModelCmHandle yangModelCmHandle) {
+        return resolveDmiServiceName(requiredService,
+                yangModelCmHandle.getDmiServiceName(),
+                yangModelCmHandle.getDmiDataServiceName(),
+                yangModelCmHandle.getDmiModelServiceName());
+    }
+
+    /**
+     * Resolve a dmi service name.
+     *
+     * @param requiredService     indicates what type of service is required
+     * @param ncmpServiceCmHandle cm handle
+     * @return dmi service name
+     */
+    public static String resolveDmiServiceName(final RequiredDmiService requiredService,
+                                               final NcmpServiceCmHandle ncmpServiceCmHandle) {
+        return resolveDmiServiceName(requiredService,
+                ncmpServiceCmHandle.getDmiServiceName(),
+                ncmpServiceCmHandle.getDmiDataServiceName(),
+                ncmpServiceCmHandle.getDmiModelServiceName());
+    }
+
+    /**
+     * Resolve a dmi service name.
+     *
+     * @param requiredService       indicates what type of service is required
+     * @param dmiPluginRegistration dmi plugin registration
+     * @return dmi service name
+     */
+    public static String resolveDmiServiceName(final RequiredDmiService requiredService,
+                                               final DmiPluginRegistration dmiPluginRegistration) {
+        return resolveDmiServiceName(requiredService,
+                dmiPluginRegistration.getDmiPlugin(),
+                dmiPluginRegistration.getDmiDataPlugin(),
+                dmiPluginRegistration.getDmiModelPlugin());
+    }
+
+    private static String resolveDmiServiceName(final RequiredDmiService requiredService,
+                                                final String dmiServiceName,
+                                                final String dmiDataServiceName,
+                                                final String dmiModelServiceName) {
+        if (StringUtils.isBlank(dmiServiceName)) {
+            if (RequiredDmiService.DATA.equals(requiredService)) {
+                return dmiDataServiceName;
+            }
+            return dmiModelServiceName;
+        }
+        return dmiServiceName;
+    }
+
+}
index 76ee286..a262367 100644 (file)
@@ -35,6 +35,7 @@ import lombok.Setter;
 import org.apache.commons.lang3.StringUtils;
 import org.onap.cps.ncmp.api.inventory.models.CompositeState;
 import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.impl.dmi.DmiServiceNameResolver;
 import org.onap.cps.ncmp.impl.models.RequiredDmiService;
 
 /**
@@ -129,8 +130,7 @@ public class YangModelCmHandle {
         yangModelCmHandle.setAlternateId(StringUtils.trimToEmpty(alternateId));
         yangModelCmHandle.setDataProducerIdentifier(StringUtils.trimToEmpty(dataProducerIdentifier));
         yangModelCmHandle.setDmiProperties(asYangModelCmHandleProperties(ncmpServiceCmHandle.getDmiProperties()));
-        yangModelCmHandle.setPublicProperties(asYangModelCmHandleProperties(
-                ncmpServiceCmHandle.getPublicProperties()));
+        yangModelCmHandle.setPublicProperties(asYangModelCmHandleProperties(ncmpServiceCmHandle.getPublicProperties()));
         yangModelCmHandle.setCompositeState(ncmpServiceCmHandle.getCompositeState());
         return yangModelCmHandle;
     }
@@ -138,17 +138,11 @@ public class YangModelCmHandle {
     /**
      * Resolve a dmi service name.
      *
-     * @param requiredService indicates what typo of service is required
+     * @param requiredService indicates what type of service is required
      * @return dmi service name
      */
     public String resolveDmiServiceName(final RequiredDmiService requiredService) {
-        if (StringUtils.isBlank(dmiServiceName)) {
-            if (RequiredDmiService.DATA.equals(requiredService)) {
-                return dmiDataServiceName;
-            }
-            return dmiModelServiceName;
-        }
-        return dmiServiceName;
+        return DmiServiceNameResolver.resolveDmiServiceName(requiredService, this);
     }
 
     private static List<Property> asYangModelCmHandleProperties(final Map<String, String> propertiesAsMap) {
index a10e8ba..b61e538 100644 (file)
@@ -23,6 +23,7 @@ package org.onap.cps.ncmp.impl.inventory.trustlevel;
 import com.hazelcast.map.IMap;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
@@ -31,6 +32,7 @@ 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.dmi.DmiServiceNameResolver;
 import org.onap.cps.ncmp.impl.inventory.InventoryPersistence;
 import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
 import org.onap.cps.ncmp.impl.models.RequiredDmiService;
@@ -60,12 +62,8 @@ public class TrustLevelManager {
      * @param dmiPluginRegistration a dmi plugin being registered
      */
     public void registerDmiPlugin(final DmiPluginRegistration dmiPluginRegistration) {
-        final String dmiServiceName;
-        if (DmiPluginRegistration.isNullEmptyOrBlank(dmiPluginRegistration.getDmiDataPlugin())) {
-            dmiServiceName = dmiPluginRegistration.getDmiPlugin();
-        } else {
-            dmiServiceName = dmiPluginRegistration.getDmiDataPlugin();
-        }
+        final String dmiServiceName = DmiServiceNameResolver.resolveDmiServiceName(RequiredDmiService.DATA,
+                dmiPluginRegistration);
         trustLevelPerDmiPlugin.put(dmiServiceName, TrustLevel.COMPLETE);
     }
 
@@ -146,9 +144,13 @@ public class TrustLevelManager {
     public void applyEffectiveTrustLevels(final Collection<NcmpServiceCmHandle> ncmpServiceCmHandles) {
         final Set<String> cmHandleIds = getCmHandleIds(ncmpServiceCmHandles);
         final Map<String, TrustLevel> trustLevelPerCmHandleIdInBatch = trustLevelPerCmHandleId.getAll(cmHandleIds);
+        final Map<String, TrustLevel> trustLevelPerDmiPluginInBatch = new HashMap<>(trustLevelPerDmiPlugin);
         for (final NcmpServiceCmHandle ncmpServiceCmHandle : ncmpServiceCmHandles) {
             final String cmHandleId = ncmpServiceCmHandle.getCmHandleId();
-            final TrustLevel dmiTrustLevel = TrustLevel.COMPLETE; // TODO: CPS-2375
+            final String dmiDataServiceName = DmiServiceNameResolver.resolveDmiServiceName(RequiredDmiService.DATA,
+                    ncmpServiceCmHandle);
+            final TrustLevel dmiTrustLevel = trustLevelPerDmiPluginInBatch.getOrDefault(dmiDataServiceName,
+                    TrustLevel.NONE);
             final TrustLevel cmHandleTrustLevel = trustLevelPerCmHandleIdInBatch.getOrDefault(cmHandleId,
                     TrustLevel.NONE);
             final TrustLevel effectiveTrustLevel = dmiTrustLevel.getEffectiveTrustLevel(cmHandleTrustLevel);
@@ -187,7 +189,7 @@ public class TrustLevelManager {
 
     private String getDmiServiceName(final String cmHandleId) {
         final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId);
-        return yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA);
+        return DmiServiceNameResolver.resolveDmiServiceName(RequiredDmiService.DATA, yangModelCmHandle);
     }
 
     private void sendAvcNotificationIfRequired(final String notificationCandidateCmHandleId,
index ac0c44e..1842107 100644 (file)
@@ -47,12 +47,14 @@ public class YangDataConverter {
      * @param yangModelCmHandle the yang model of the cm handle
      * @return ncmp service cm handle
      */
-    public static NcmpServiceCmHandle toNcmpServiceCmHandle(
-        final YangModelCmHandle yangModelCmHandle) {
+    public static NcmpServiceCmHandle toNcmpServiceCmHandle(final YangModelCmHandle yangModelCmHandle) {
         final NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle();
         final List<YangModelCmHandle.Property> dmiProperties = yangModelCmHandle.getDmiProperties();
         final List<YangModelCmHandle.Property> publicProperties = yangModelCmHandle.getPublicProperties();
         ncmpServiceCmHandle.setCmHandleId(yangModelCmHandle.getId());
+        ncmpServiceCmHandle.setDmiServiceName(yangModelCmHandle.getDmiServiceName());
+        ncmpServiceCmHandle.setDmiDataServiceName(yangModelCmHandle.getDmiDataServiceName());
+        ncmpServiceCmHandle.setDmiModelServiceName(yangModelCmHandle.getDmiModelServiceName());
         ncmpServiceCmHandle.setCompositeState(yangModelCmHandle.getCompositeState());
         ncmpServiceCmHandle.setModuleSetTag(yangModelCmHandle.getModuleSetTag());
         ncmpServiceCmHandle.setAlternateId(yangModelCmHandle.getAlternateId());
index bf79fe3..1088ca8 100644 (file)
@@ -177,25 +177,23 @@ class TrustLevelManagerSpec extends Specification {
             def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'ch-1')
         when: 'effective trust level selected'
             objectUnderTest.applyEffectiveTrustLevel(ncmpServiceCmHandle)
-        then: 'effective trust level is trusted'
-            // FIXME CPS-2375: the expected behaviour is to return the lower TrustLevel (NONE)
-            assert ncmpServiceCmHandle.currentTrustLevel == TrustLevel.COMPLETE
+        then: 'effective trust level is none'
+            assert ncmpServiceCmHandle.currentTrustLevel == TrustLevel.NONE
     }
 
     def 'Apply effective trust levels from CmHandle batch'() {
-        given: 'a non trusted dmi'
-            trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.NONE)
+        given: 'a trusted dmi'
+            trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.COMPLETE)
         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')
+            def ncmpServiceCmHandle1 = new NcmpServiceCmHandle(cmHandleId: 'ch-1', dmiServiceName: 'my-dmi')
+            def ncmpServiceCmHandle2 = new NcmpServiceCmHandle(cmHandleId: 'ch-2', dmiDataServiceName: 'my-dmi')
         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
     }
index bb45e8a..1b8a33f 100644 (file)
@@ -31,11 +31,15 @@ class YangDataConverterSpec extends Specification{
                     leaves: ['name': 'dmiProp1', 'value': 'dmiValue1'])
             def dataNodePublicProperties = new DataNode(xpath:'/public-properties[@name="pubProp1"]',
                     leaves: ['name': 'pubProp1', 'value': 'pubValue1'])
-            def dataNodeCmHandle = new DataNode(leaves:['id':'sample-id'], childDataNodes:[dataNodeAdditionalProperties, dataNodePublicProperties])
+            def dataNodeCmHandle = new DataNode(leaves:['id':'sample-id', 'alternate-id': 'alt-id', 'module-set-tag': 'my-tag', 'dmi-service-name': 'my-dmi', 'data-producer-identifier': 'my-dpi'], childDataNodes:[dataNodeAdditionalProperties, dataNodePublicProperties])
         when: 'the dataNode is converted'
             def yangModelCmHandle = YangDataConverter.toYangModelCmHandle(dataNodeCmHandle)
-        then: 'the converted object has the correct id'
+        then: 'the converted object has the fields'
             assert yangModelCmHandle.id == 'sample-id'
+            assert yangModelCmHandle.alternateId == 'alt-id'
+            assert yangModelCmHandle.dmiServiceName == 'my-dmi'
+            assert yangModelCmHandle.moduleSetTag == 'my-tag'
+            assert yangModelCmHandle.dataProducerIdentifier == 'my-dpi'
         and: 'the additional (dmi, private) properties are included'
             assert yangModelCmHandle.dmiProperties[0].name == 'dmiProp1'
             assert yangModelCmHandle.dmiProperties[0].value == 'dmiValue1'