Allow get operation on the non-passthrough datastore 33/141633/3
authormpriyank <priyank.maheshwari@est.tech>
Thu, 31 Jul 2025 11:50:48 +0000 (12:50 +0100)
committerPriyank Maheshwari <priyank.maheshwari@est.tech>
Fri, 1 Aug 2025 15:12:55 +0000 (15:12 +0000)
- Now that the data can be cached when the data sync is enabled , this
  patch allows to query that data using ncmp-passthrough-operational
  datastore
- Added testware to support the above feature
- Updated outstanding copyright from the last patch

Issue-ID: CPS-2912
Change-Id: I6b62c4b3e83b3cc1616e0dc353a4736f0815b50b
Signed-off-by: mpriyank <priyank.maheshwari@est.tech>
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpCachedResourceRequestHandler.java
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/NcmpCachedResourceRequestHandlerSpec.groovy
cps-service/src/main/java/org/onap/cps/utils/YangParser.java
cps-service/src/test/groovy/org/onap/cps/utils/YangParserSpec.groovy

index 1b5dd2f..5b2fede 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2022-2025 Nordix Foundation
+ *  Copyright (C) 2022-2025 OpenInfra Foundation Europe. All rights reserved.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 
 package org.onap.cps.ncmp.impl.data;
 
+import static org.onap.cps.ncmp.api.data.models.DatastoreType.OPERATIONAL;
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME;
+
 import java.util.Collection;
+import java.util.Map;
 import lombok.RequiredArgsConstructor;
-import org.onap.cps.api.CpsDataService;
+import org.onap.cps.api.CpsFacade;
 import org.onap.cps.api.model.DataNode;
 import org.onap.cps.api.parameters.FetchDescendantsOption;
 import org.onap.cps.ncmp.api.data.models.CmResourceAddress;
@@ -33,7 +37,7 @@ import reactor.core.publisher.Mono;
 @RequiredArgsConstructor
 public class NcmpCachedResourceRequestHandler extends NcmpDatastoreRequestHandler {
 
-    private final CpsDataService cpsDataService;
+    private final CpsFacade cpsFacade;
     private final NetworkCmProxyQueryService networkCmProxyQueryService;
 
     /**
@@ -60,14 +64,22 @@ public class NcmpCachedResourceRequestHandler extends NcmpDatastoreRequestHandle
                                                       final String requestId,
                                                       final boolean includeDescendants,
                                                       final String authorization) {
-        final FetchDescendantsOption fetchDescendantsOption
-            = FetchDescendantsOption.getFetchDescendantsOption(includeDescendants);
+        final FetchDescendantsOption fetchDescendantsOption =
+                FetchDescendantsOption.getFetchDescendantsOption(includeDescendants);
+
+        final Map<String, Object> dataNodes = cpsFacade.getDataNodesByAnchorV3(resolveDatastoreName(cmResourceAddress),
+                cmResourceAddress.resolveCmHandleReferenceToId(), cmResourceAddress.getResourceIdentifier(),
+                fetchDescendantsOption);
+        return Mono.justOrEmpty(dataNodes);
+    }
 
-        final DataNode dataNode = cpsDataService.getDataNodes(cmResourceAddress.getDatastoreName(),
-            cmResourceAddress.resolveCmHandleReferenceToId(),
-            cmResourceAddress.getResourceIdentifier(),
-            fetchDescendantsOption).iterator().next();
-        return Mono.justOrEmpty(dataNode);
+    private String resolveDatastoreName(final CmResourceAddress cmResourceAddress) {
+        final String datastoreName = cmResourceAddress.getDatastoreName();
+        if (datastoreName.equals(OPERATIONAL.getDatastoreName())) {
+            return NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME;
+        }
+        throw new IllegalArgumentException(
+                "Unsupported datastore name provided to fetch the cached data: " + datastoreName);
     }
 
 }
index 9876e66..b8d6e5d 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2024 Nordix Foundation
+ *  Copyright (C) 2024-2025 OpenInfra Foundation Europe. All rights reserved.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 
 package org.onap.cps.ncmp.impl.data
 
-import org.onap.cps.api.CpsDataService
+import org.onap.cps.api.CpsFacade
+import org.onap.cps.api.parameters.FetchDescendantsOption
 import org.onap.cps.ncmp.api.data.models.CmResourceAddress
 import org.onap.cps.ncmp.config.CpsApplicationContext
 import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher
-import org.onap.cps.api.model.DataNode
 import org.spockframework.spring.SpringBean
 import org.springframework.boot.test.context.SpringBootTest
 import org.springframework.context.ApplicationContext
@@ -39,8 +39,8 @@ import static org.onap.cps.api.parameters.FetchDescendantsOption.OMIT_DESCENDANT
 @ContextConfiguration(classes = [CpsApplicationContext])
 class NcmpCachedResourceRequestHandlerSpec extends Specification {
 
-    def cpsDataService = Mock(CpsDataService)
-    def networkCmProxyQueryService= Mock(NetworkCmProxyQueryService)
+    def mockCpsFacade = Mock(CpsFacade)
+    def mockNetworkCmProxyQueryService = Mock(NetworkCmProxyQueryService)
 
     @SpringBean
     AlternateIdMatcher alternateIdMatcher = Mock()
@@ -48,31 +48,44 @@ class NcmpCachedResourceRequestHandlerSpec extends Specification {
     @SpringBean
     ApplicationContext applicationContext = Mock()
 
-    def objectUnderTest = new NcmpCachedResourceRequestHandler(cpsDataService, networkCmProxyQueryService)
+    def objectUnderTest = new NcmpCachedResourceRequestHandler(mockCpsFacade, mockNetworkCmProxyQueryService)
 
     def 'Execute a request with include descendants = #includeDescendants.'() {
         when: 'executing a request'
             objectUnderTest.executeRequest('ch-1', 'resource', includeDescendants)
         then: 'it is delegated to the ncmp query service with the correct option'
-            1 * networkCmProxyQueryService.queryResourceDataOperational('ch-1','resource', expectedFetchDescendantsOption)
+            1 * mockNetworkCmProxyQueryService.queryResourceDataOperational('ch-1', 'resource', expectedFetchDescendantsOption)
         where: 'the following options are used'
             includeDescendants || expectedFetchDescendantsOption
             true               || INCLUDE_ALL_DESCENDANTS
             false              || OMIT_DESCENDANTS
     }
 
-    def 'Get resource data.'() {
-        given: 'the data service returns 2 nodes for the given resource address'
-            def cmResourceAddress = new CmResourceAddress('datastore','ch-1','resource')
-            def dataNode1 = new DataNode(xpath:'p1')
-            def dataNode2 = new DataNode(xpath:'p2')
-            cpsDataService.getDataNodes('datastore','ch-1','resource',OMIT_DESCENDANTS) >> [dataNode1, dataNode2]
-        when: 'getting the resource data'
-            alternateIdMatcher.getCmHandleId('ch-1') >> 'ch-1'
-            def result = objectUnderTest.getResourceDataForCmHandle(cmResourceAddress, 'options', 'topic', 'request id', false, 'authorization')
-        then: 'the result is a "Mono" holding just the first data node'
+    def 'Get resource data using NCMP operational datastore'() {
+        given: 'a CmResourceAddress with OPERATIONAL datastore'
+            def cmResourceAddress = new CmResourceAddress('ncmp-datastore:operational', 'ch-ref', 'resource')
+        and: 'a mocked resolved cm handle id and data node map'
+            def expectedData = [node1: 'value1']
+            1 * alternateIdMatcher.getCmHandleId('ch-ref') >> 'ch-id'
+            1 * mockCpsFacade.getDataNodesByAnchorV3('NFP-Operational', 'ch-id', 'resource', FetchDescendantsOption.getFetchDescendantsOption(includeDescendants)) >> expectedData
+        when: 'the method is invoked'
+            def result = objectUnderTest.getResourceDataForCmHandle(cmResourceAddress, 'options', null,null, includeDescendants, 'auth')
+        then: 'a Mono with expected data is returned'
             assert result instanceof Mono
-            assert result.block() == dataNode1
+            assert result.block() == expectedData
+        where: 'the following descendants options are used'
+            includeDescendants << [true, false]
+    }
+
+    def 'Get resource data with unsupported datastore throws exception'() {
+        given: 'a CmResourceAddress with unsupported datastore name'
+            def cmResourceAddress = new CmResourceAddress('unsupported-datastore', 'some-cm-handle-ref', 'some-resource-id')
+        when: 'the method is invoked'
+            objectUnderTest.getResourceDataForCmHandle(cmResourceAddress, 'options', null, null, false, 'auth'
+            ).block()
+        then: 'an IllegalArgumentException is thrown'
+            def exception = thrown(IllegalArgumentException)
+            assert exception.message == 'Unsupported datastore name provided to fetch the cached data: unsupported-datastore'
     }
 
 }
index a0846a7..d998f09 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ============LICENSE_START=======================================================
- * Copyright (C) 2024-2025 Nordix Foundation.
+ * Copyright (C) 2024-2025 OpenInfra Foundation Europe. All rights reserved.
  * Modifications Copyright (C) 2024 TechMahindra Ltd.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
index a1a0b8c..93ee182 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2024 Nordix Foundation
+ *  Copyright (C) 2024-2025 OpenInfra Foundation Europe. All rights reserved.
  *  Modifications Copyright (C) 2024 TechMahindra Ltd.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");