CPS-2182 - #4 Add module Set tag to NCMPs DMI Batch Data interface 62/137862/13 master
authordavid.mcweeney <david.mcweeney@est.tech>
Wed, 8 May 2024 14:11:12 +0000 (15:11 +0100)
committerdavid.mcweeney <david.mcweeney@est.tech>
Mon, 20 May 2024 15:33:59 +0000 (16:33 +0100)
Change-Id: I46b261e0a0ef2d37a307291931ba67762fb7767d
Signed-off-by: david.mcweeney <david.mcweeney@est.tech>
Issue-ID: CPS-2182

cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperation.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperationCmHandle.java [moved from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/CmHandle.java with 68% similarity]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtilsSpec.groovy
dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/controller/DmiRestStubController.java
dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/model/data/operational/DataOperationRequest.java
dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/model/data/operational/DmiOperationCmHandle.java [moved from dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/model/data/operational/CmHandle.java with 94% similarity]

index 2e66ac0..7baac34 100644 (file)
@@ -40,7 +40,7 @@ public class DmiDataOperation {
     private String options;
     private String resourceIdentifier;
 
     private String options;
     private String resourceIdentifier;
 
-    private final List<CmHandle> cmHandles = new ArrayList<>();
+    private final List<DmiOperationCmHandle> cmHandles = new ArrayList<>();
 
     /**
      * Create and initialise a (outgoing) DMI data operation.
 
     /**
      * Create and initialise a (outgoing) DMI data operation.
index c66ca01..c9e193d 100644 (file)
@@ -292,7 +292,7 @@ public class DmiDataOperations extends DmiOperations {
 
         dmiDataOperationRequestBodies.forEach(dmiDataOperationRequestBody -> {
             final List<String> cmHandleIds = dmiDataOperationRequestBody.getCmHandles().stream()
 
         dmiDataOperationRequestBodies.forEach(dmiDataOperationRequestBody -> {
             final List<String> cmHandleIds = dmiDataOperationRequestBody.getCmHandles().stream()
-                    .map(CmHandle::getId).toList();
+                    .map(DmiOperationCmHandle::getId).toList();
             cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperationRequestBody,
                     Map.of(dmiClientRequestException.getNcmpResponseStatus(), cmHandleIds));
         });
             cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperationRequestBody,
                     Map.of(dmiClientRequestException.getNcmpResponseStatus(), cmHandleIds));
         });
@@ -29,14 +29,21 @@ import lombok.Getter;
 @JsonInclude(JsonInclude.Include.NON_NULL)
 @Getter
 @Builder
 @JsonInclude(JsonInclude.Include.NON_NULL)
 @Getter
 @Builder
-public class CmHandle {
+public class DmiOperationCmHandle {
     private String id;
 
     @JsonProperty("cmHandleProperties")
     private Map<String, String> dmiProperties;
     private String id;
 
     @JsonProperty("cmHandleProperties")
     private Map<String, String> dmiProperties;
+    private String moduleSetTag;
 
 
-    public static CmHandle buildCmHandleWithProperties(final String cmHandleId,
-                                                       final Map<String, String> dmiProperties) {
-        return CmHandle.builder().id(cmHandleId).dmiProperties(dmiProperties).build();
+    /**
+     * Builds Dmi Operation Cm Handle object with all its associated properties.
+     */
+    public static DmiOperationCmHandle buildDmiOperationCmHandle(final String cmHandleId,
+                                                                 final Map<String, String> dmiProperties,
+                                                                 final String moduleSetTag) {
+        return DmiOperationCmHandle.builder().id(cmHandleId)
+                .dmiProperties(dmiProperties).moduleSetTag(moduleSetTag)
+                .build();
     }
 }
     }
 }
index 4b016b3..dc4108c 100644 (file)
@@ -39,8 +39,8 @@ import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.events.EventsPublisher;
 import org.onap.cps.ncmp.api.NcmpResponseStatus;
 import org.onap.cps.ncmp.api.impl.inventory.CmHandleState;
 import org.onap.cps.events.EventsPublisher;
 import org.onap.cps.ncmp.api.NcmpResponseStatus;
 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.operations.DmiDataOperation;
+import org.onap.cps.ncmp.api.impl.operations.DmiOperationCmHandle;
 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.impl.utils.DmiServiceNameOrganizer;
 import org.onap.cps.ncmp.api.impl.utils.context.CpsApplicationContext;
 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
@@ -81,6 +81,8 @@ public class ResourceDataOperationRequestUtils {
         final Map<String, String> dmiServiceNamesPerCmHandleId =
                 getDmiServiceNamesPerCmHandleId(dmiPropertiesPerCmHandleIdPerServiceName);
 
         final Map<String, String> dmiServiceNamesPerCmHandleId =
                 getDmiServiceNamesPerCmHandleId(dmiPropertiesPerCmHandleIdPerServiceName);
 
+        final Map<String, String> moduleSetTagPerCmHandle = getModuleSetTagPerCmHandleId(yangModelCmHandles);
+
         for (final DataOperationDefinition dataOperationDefinitionIn :
                 dataOperationRequestIn.getDataOperationDefinitions()) {
             final List<String> nonExistingCmHandleIds = new ArrayList<>();
         for (final DataOperationDefinition dataOperationDefinitionIn :
                 dataOperationRequestIn.getDataOperationDefinitions()) {
             final List<String> nonExistingCmHandleIds = new ArrayList<>();
@@ -97,9 +99,10 @@ public class ResourceDataOperationRequestUtils {
                     } else {
                         final DmiDataOperation dmiBatchOperationOut = getOrAddDmiBatchOperation(dmiServiceName,
                                 dataOperationDefinitionIn, dmiDataOperationsOutPerDmiServiceName);
                     } else {
                         final DmiDataOperation dmiBatchOperationOut = getOrAddDmiBatchOperation(dmiServiceName,
                                 dataOperationDefinitionIn, dmiDataOperationsOutPerDmiServiceName);
-                        final CmHandle cmHandle = CmHandle.buildCmHandleWithProperties(cmHandleId,
-                                cmHandleIdProperties);
-                        dmiBatchOperationOut.getCmHandles().add(cmHandle);
+                        final DmiOperationCmHandle dmiOperationCmHandle = DmiOperationCmHandle
+                                .buildDmiOperationCmHandle(cmHandleId, cmHandleIdProperties,
+                                        moduleSetTagPerCmHandle.get(cmHandleId));
+                        dmiBatchOperationOut.getCmHandles().add(dmiOperationCmHandle);
                     }
                 }
             }
                     }
                 }
             }
@@ -114,6 +117,14 @@ public class ResourceDataOperationRequestUtils {
         return dmiDataOperationsOutPerDmiServiceName;
     }
 
         return dmiDataOperationsOutPerDmiServiceName;
     }
 
+    private static Map<String, String> getModuleSetTagPerCmHandleId(
+                                                       final Collection<YangModelCmHandle> yangModelCmHandles) {
+        final Map<String, String> moduleSetTagPerCmHandle = new HashMap<>(yangModelCmHandles.size());
+        yangModelCmHandles.forEach(yangModelCmHandle ->
+                moduleSetTagPerCmHandle.put(yangModelCmHandle.getId(), yangModelCmHandle.getModuleSetTag()));
+        return moduleSetTagPerCmHandle;
+    }
+
     /**
      * Handles the async task completion for an entire data, publishing errors to client topic on task failure.
      *
     /**
      * Handles the async task completion for an entire data, publishing errors to client topic on task failure.
      *
index 312cd8a..8fcdc3f 100644 (file)
@@ -102,7 +102,7 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
         and: 'a positive response from DMI service when it is called with valid request parameters'
             def responseFromDmi = new ResponseEntity<Object>(HttpStatus.ACCEPTED)
             def expectedDmiBatchResourceDataUrl = "ncmp/v1/data/topic=my-topic-name"
         and: 'a positive response from DMI service when it is called with valid request parameters'
             def responseFromDmi = new ResponseEntity<Object>(HttpStatus.ACCEPTED)
             def expectedDmiBatchResourceDataUrl = "ncmp/v1/data/topic=my-topic-name"
-            def expectedBatchRequestAsJson = '{"operations":[{"operation":"read","operationId":"operational-14","datastore":"ncmp-datastore:passthrough-operational","options":"some option","resourceIdentifier":"some resource identifier","cmHandles":[{"id":"some-cm-handle","cmHandleProperties":{"prop1":"val1"}}]}]}'
+            def expectedBatchRequestAsJson = '{"operations":[{"operation":"read","operationId":"operational-14","datastore":"ncmp-datastore:passthrough-operational","options":"some option","resourceIdentifier":"some resource identifier","cmHandles":[{"id":"some-cm-handle","moduleSetTag":"","cmHandleProperties":{"prop1":"val1"}}]}]}'
             mockDmiRestClient.postOperationWithJsonData(expectedDmiBatchResourceDataUrl, _, READ.operationName, NO_AUTH_HEADER) >> responseFromDmi
             dmiServiceUrlBuilder.getDataOperationRequestUrl(_, _) >> expectedDmiBatchResourceDataUrl
         when: 'get resource data for group of cm handles are invoked'
             mockDmiRestClient.postOperationWithJsonData(expectedDmiBatchResourceDataUrl, _, READ.operationName, NO_AUTH_HEADER) >> responseFromDmi
             dmiServiceUrlBuilder.getDataOperationRequestUrl(_, _) >> expectedDmiBatchResourceDataUrl
         when: 'get resource data for group of cm handles are invoked'
@@ -114,7 +114,7 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
     def 'Execute (async) data operation from DMI service with dmi client exception.'() {
         given: 'data operation request body and dmi resource url'
             def dmiDataOperation = DmiDataOperation.builder().operationId('some-operation-id').build()
     def 'Execute (async) data operation from DMI service with dmi client exception.'() {
         given: 'data operation request body and dmi resource url'
             def dmiDataOperation = DmiDataOperation.builder().operationId('some-operation-id').build()
-            dmiDataOperation.getCmHandles().add(CmHandle.builder().id('some-cm-handle-id').build())
+            dmiDataOperation.getCmHandles().add(DmiOperationCmHandle.builder().id('some-cm-handle-id').build())
             def dmiDataOperationResourceDataUrl = "http://dmi-service-name:dmi-port/dmi/v1/data?topic=my-topic-name&requestId=some-request-id"
             def actualDataOperationCloudEvent = null
         when: 'exception occurs after sending request to dmi service'
             def dmiDataOperationResourceDataUrl = "http://dmi-service-name:dmi-port/dmi/v1/data?topic=my-topic-name&requestId=some-request-id"
             def actualDataOperationCloudEvent = null
         when: 'exception occurs after sending request to dmi service'
index 8df27bb..9028b9e 100644 (file)
@@ -90,6 +90,23 @@ class ResourceDataOperationRequestUtilsSpec extends MessagingBaseSpec {
             'dmi2'      | 2              || 'operational-15'    | 'ncmp-datastore:passthrough-operational' | ['ch4-dmi2']
     }
 
             'dmi2'      | 2              || 'operational-15'    | 'ncmp-datastore:passthrough-operational' | ['ch4-dmi2']
     }
 
+    def 'Process one data operation request with #serviceName and Module Set Tag set.'() {
+        given: 'data operation request'
+            def dataOperationRequestJsonData = TestUtils.getResourceFileContent('dataOperationRequest.json')
+            def dataOperationRequest = jsonObjectMapper.convertJsonString(dataOperationRequestJsonData, DataOperationRequest.class)
+        and: '1 known cm handles: ch1-dmi1'
+            def yangModelCmHandles = getYangModelCmHandlesForOneCmHandle()
+        when: 'data operation request is processed'
+            def operationsOutPerDmiServiceName = ResourceDataOperationRequestUtils.processPerDefinitionInDataOperationsRequest(clientTopic,'request-id', dataOperationRequest, yangModelCmHandles)
+        and: 'converted to a json node'
+            def dmiDataOperationRequestBody = operationsOutPerDmiServiceName['dmi1']
+            def cmHandlesInRequestBody = dmiDataOperationRequestBody[0].cmHandles
+        then: 'it contains the correct operation details'
+            assert cmHandlesInRequestBody.size() == 1
+            assert cmHandlesInRequestBody[0].id == 'ch1-dmi1'
+            assert cmHandlesInRequestBody[0].moduleSetTag == 'module-set-tag1'
+    }
+
     def 'Process per data operation request with non-ready, non-existing cm handle and publish event to client specified topic'() {
         given: 'consumer subscribing to client topic'
             def cloudEventKafkaConsumer = new KafkaConsumer<>(eventConsumerConfigProperties('test-1', CloudEventDeserializer))
     def 'Process per data operation request with non-ready, non-existing cm handle and publish event to client specified topic'() {
         given: 'consumer subscribing to client topic'
             def cloudEventKafkaConsumer = new KafkaConsumer<>(eventConsumerConfigProperties('test-1', CloudEventDeserializer))
@@ -156,4 +173,10 @@ class ResourceDataOperationRequestUtilsSpec extends MessagingBaseSpec {
                 new YangModelCmHandle(id: 'non-ready-cm-handle', dmiServiceName: 'dmi2', dmiProperties: dmiProperties, compositeState: advisedState)
         ]
     }
                 new YangModelCmHandle(id: 'non-ready-cm-handle', dmiServiceName: 'dmi2', dmiProperties: dmiProperties, compositeState: advisedState)
         ]
     }
+
+    static def getYangModelCmHandlesForOneCmHandle() {
+        def dmiProperties = [new YangModelCmHandle.Property('prop', 'some DMI property')]
+        def readyState = new CompositeStateBuilder().withCmHandleState(CmHandleState.READY).withLastUpdatedTimeNow().build()
+        return [new YangModelCmHandle(id: 'ch1-dmi1', dmiServiceName: 'dmi1', moduleSetTag: 'module-set-tag1', dmiProperties: dmiProperties, compositeState: readyState)]
+    }
 }
 }
index 08bcee7..a596afd 100644 (file)
@@ -37,9 +37,9 @@ import lombok.extern.slf4j.Slf4j;
 import org.json.simple.parser.JSONParser;
 import org.json.simple.parser.ParseException;
 import org.onap.cps.ncmp.api.impl.utils.EventDateTimeFormatter;
 import org.json.simple.parser.JSONParser;
 import org.json.simple.parser.ParseException;
 import org.onap.cps.ncmp.api.impl.utils.EventDateTimeFormatter;
-import org.onap.cps.ncmp.dmi.rest.stub.model.data.operational.CmHandle;
 import org.onap.cps.ncmp.dmi.rest.stub.model.data.operational.DataOperationRequest;
 import org.onap.cps.ncmp.dmi.rest.stub.model.data.operational.DmiDataOperationRequest;
 import org.onap.cps.ncmp.dmi.rest.stub.model.data.operational.DataOperationRequest;
 import org.onap.cps.ncmp.dmi.rest.stub.model.data.operational.DmiDataOperationRequest;
+import org.onap.cps.ncmp.dmi.rest.stub.model.data.operational.DmiOperationCmHandle;
 import org.onap.cps.ncmp.dmi.rest.stub.utils.ResourceFileReaderUtil;
 import org.onap.cps.ncmp.events.async1_0_0.Data;
 import org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent;
 import org.onap.cps.ncmp.dmi.rest.stub.utils.ResourceFileReaderUtil;
 import org.onap.cps.ncmp.events.async1_0_0.Data;
 import org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent;
@@ -238,8 +238,9 @@ public class DmiRestStubController {
         }
         dmiDataOperationRequest.getOperations().forEach(dmiDataOperation -> {
             final DataOperationEvent dataOperationEvent = getDataOperationEvent(dmiDataOperation);
         }
         dmiDataOperationRequest.getOperations().forEach(dmiDataOperation -> {
             final DataOperationEvent dataOperationEvent = getDataOperationEvent(dmiDataOperation);
-            dmiDataOperation.getCmHandles().forEach(cmHandle -> {
-                dataOperationEvent.getData().getResponses().get(0).setIds(List.of(cmHandle.getId()));
+            dmiDataOperation.getCmHandles().forEach(dmiOperationCmHandle -> {
+                log.info("Module Set Tag received: {}", dmiOperationCmHandle.getModuleSetTag());
+                dataOperationEvent.getData().getResponses().get(0).setIds(List.of(dmiOperationCmHandle.getId()));
                 final CloudEvent cloudEvent = buildAndGetCloudEvent(topic, requestId, dataOperationEvent);
                 cloudEventKafkaTemplate.send(ncmpAsyncM2mTopic, UUID.randomUUID().toString(), cloudEvent);
             });
                 final CloudEvent cloudEvent = buildAndGetCloudEvent(topic, requestId, dataOperationEvent);
                 cloudEventKafkaTemplate.send(ncmpAsyncM2mTopic, UUID.randomUUID().toString(), cloudEvent);
             });
@@ -270,10 +271,11 @@ public class DmiRestStubController {
 
     private DataOperationEvent getDataOperationEvent(final DataOperationRequest dataOperationRequest) {
         final Response response = new Response();
 
     private DataOperationEvent getDataOperationEvent(final DataOperationRequest dataOperationRequest) {
         final Response response = new Response();
+
         response.setOperationId(dataOperationRequest.getOperationId());
         response.setStatusCode(SUCCESS.getCode());
         response.setStatusMessage(SUCCESS.getMessage());
         response.setOperationId(dataOperationRequest.getOperationId());
         response.setStatusCode(SUCCESS.getCode());
         response.setStatusMessage(SUCCESS.getMessage());
-        response.setIds(dataOperationRequest.getCmHandles().stream().map(CmHandle::getId).toList());
+        response.setIds(dataOperationRequest.getCmHandles().stream().map(DmiOperationCmHandle::getId).toList());
         response.setResourceIdentifier(dataOperationRequest.getResourceIdentifier());
         response.setOptions(dataOperationRequest.getOptions());
         final String ietfNetworkTopologySample = ResourceFileReaderUtil
         response.setResourceIdentifier(dataOperationRequest.getResourceIdentifier());
         response.setOptions(dataOperationRequest.getOptions());
         final String ietfNetworkTopologySample = ResourceFileReaderUtil
index 85c649e..4107749 100644 (file)
@@ -35,5 +35,5 @@ public class DataOperationRequest {
     private String datastore;
     private String options;
     private String resourceIdentifier;
     private String datastore;
     private String options;
     private String resourceIdentifier;
-    private List<CmHandle> cmHandles = new ArrayList<>();
+    private List<DmiOperationCmHandle> cmHandles = new ArrayList<>();
 }
 }