Merge "Support Alternate-Id for CPS-E05 data batch interface"
diff --git a/cps-ncmp-rest/docs/openapi/components.yaml b/cps-ncmp-rest/docs/openapi/components.yaml
index 99072c4..a8da693 100644
--- a/cps-ncmp-rest/docs/openapi/components.yaml
+++ b/cps-ncmp-rest/docs/openapi/components.yaml
@@ -366,7 +366,7 @@
type: array
items:
type: string
- description: targeted cm handles, maximum of 50 supported. If this limit is exceeded the request wil be refused.
+ description: targeted cm handle references, maximum of 200 supported. If this limit is exceeded the request wil be refused.
example: [ "da310eecdb8d44c2acc0ddaae01174b1","c748c58f8e0b438f9fd1f28370b17d47" ]
examples:
@@ -516,7 +516,7 @@
outputAlternateIdOptionInQuery:
name: outputAlternateId
in: query
- description: Boolean parameter to determine if returned value(s) will be cmHandle Ids or Alternate Ids for a given query
+ description: Boolean parameter to determine if returned value(s) will be cm handle references for a given query
required: false
schema:
type: boolean
diff --git a/cps-ncmp-rest/docs/openapi/ncmp.yml b/cps-ncmp-rest/docs/openapi/ncmp.yml
index a3ddc3f..4624bc1 100755
--- a/cps-ncmp-rest/docs/openapi/ncmp.yml
+++ b/cps-ncmp-rest/docs/openapi/ncmp.yml
@@ -193,7 +193,7 @@
post:
tags:
- network-cm-proxy
- summary: Execute a data operation for group of cm handle ids
+ summary: Execute a data operation for group of cm handle references
description: This request will be handled asynchronously using messaging to the supplied topic. The rest response will be an acknowledge with a requestId to identify the relevant messages. A maximum of 200 cm handles per operation is supported.
operationId: executeDataOperationForCmHandles
parameters:
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/util/DataOperationRequestMapper.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/util/DataOperationRequestMapper.java
index 42622a2..1e73aca 100644
--- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/util/DataOperationRequestMapper.java
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/util/DataOperationRequestMapper.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2023 Nordix Foundation
+ * Copyright (C) 2023-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.
@@ -35,7 +35,7 @@
DataOperationRequest toDataOperationRequest(
org.onap.cps.ncmp.rest.model.DataOperationRequest dataOperationRequest);
- @Mapping(source = "targetIds", target = "cmHandleIds")
+ @Mapping(source = "targetIds", target = "cmHandleReferences")
DataOperationDefinition toDataOperationDefinition(
org.onap.cps.ncmp.rest.model.DataOperationDefinition dataOperationDefinition);
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/DataOperationDefinition.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/DataOperationDefinition.java
index d1ff1a5..79da44a 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/DataOperationDefinition.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/data/models/DataOperationDefinition.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2023 Nordix Foundation
+ * Copyright (C) 2023-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.
@@ -45,5 +45,5 @@
@JsonProperty("targetIds")
@Valid
- private List<String> cmHandleIds = new ArrayList<>();
+ private List<String> cmHandleReferences = new ArrayList<>();
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java
index 301b819..c4bdc1c 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java
@@ -139,10 +139,10 @@
final String requestId,
final String authorization) {
- final Set<String> cmHandlesIds = getDistinctCmHandleIds(dataOperationRequest);
+ final Set<String> cmHandlesReferences = getDistinctCmHandleReferences(dataOperationRequest);
final Collection<YangModelCmHandle> yangModelCmHandles
- = inventoryPersistence.getYangModelCmHandles(cmHandlesIds);
+ = inventoryPersistence.getYangModelCmHandlesFromCmHandleReferences(cmHandlesReferences);
final Map<String, List<DmiDataOperation>> operationsOutPerDmiServiceName
= DmiDataOperationsHelper.processPerDefinitionInDataOperationsRequest(topicParamInQuery,
@@ -246,10 +246,10 @@
}
}
- private static Set<String> getDistinctCmHandleIds(final DataOperationRequest dataOperationRequest) {
+ private static Set<String> getDistinctCmHandleReferences(final DataOperationRequest dataOperationRequest) {
return dataOperationRequest.getDataOperationDefinitions().stream()
.flatMap(dataOperationDefinition ->
- dataOperationDefinition.getCmHandleIds().stream()).collect(Collectors.toSet());
+ dataOperationDefinition.getCmHandleReferences().stream()).collect(Collectors.toSet());
}
private void asyncSendMultipleRequest(final String requestId, final String topicParamInQuery,
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpPassthroughResourceRequestHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpPassthroughResourceRequestHandler.java
index a21210c..8920839 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpPassthroughResourceRequestHandler.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpPassthroughResourceRequestHandler.java
@@ -91,10 +91,10 @@
throw new InvalidDatastoreException(dataOperationDefinition.getDatastore()
+ " datastore is not supported");
}
- if (dataOperationDefinition.getCmHandleIds().size() > MAXIMUM_CM_HANDLES_PER_OPERATION) {
+ if (dataOperationDefinition.getCmHandleReferences().size() > MAXIMUM_CM_HANDLES_PER_OPERATION) {
final String errorMessage = String.format(PAYLOAD_TOO_LARGE_TEMPLATE,
dataOperationDefinition.getOperationId(),
- dataOperationDefinition.getCmHandleIds().size());
+ dataOperationDefinition.getCmHandleReferences().size());
throw new PayloadTooLargeException(errorMessage);
}
});
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java
index 3104be5..f1dc9af 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java
@@ -31,7 +31,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.stream.Collectors;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -71,8 +70,9 @@
final Map<String, List<DmiDataOperation>> dmiDataOperationsOutPerDmiServiceName = new HashMap<>();
final MultiValueMap<DmiDataOperation, Map<NcmpResponseStatus,
- List<String>>> cmHandleIdsPerResponseCodesPerOperation = new LinkedMultiValueMap<>();
- final Set<String> nonReadyCmHandleIdsLookup = filterAndGetNonReadyCmHandleIds(yangModelCmHandles);
+ List<String>>> cmHandleReferencesPerResponseCodesPerOperation = new LinkedMultiValueMap<>();
+ final Map<String, String> nonReadyCmHandleReferencesLookup =
+ filterAndGetNonReadyCmHandleReferences(yangModelCmHandles);
final Map<String, Map<String, Map<String, String>>> dmiPropertiesPerCmHandleIdPerServiceName =
DmiServiceNameOrganizer.getDmiPropertiesPerCmHandleIdPerServiceName(yangModelCmHandles);
@@ -84,17 +84,19 @@
for (final DataOperationDefinition dataOperationDefinitionIn :
dataOperationRequestIn.getDataOperationDefinitions()) {
- final List<String> nonExistingCmHandleIds = new ArrayList<>();
- final List<String> nonReadyCmHandleIds = new ArrayList<>();
- for (final String cmHandleId : dataOperationDefinitionIn.getCmHandleIds()) {
- if (nonReadyCmHandleIdsLookup.contains(cmHandleId)) {
- nonReadyCmHandleIds.add(cmHandleId);
+ final List<String> nonExistingCmHandleReferences = new ArrayList<>();
+ final List<String> nonReadyCmHandleReferences = new ArrayList<>();
+ for (final String cmHandleReference : dataOperationDefinitionIn.getCmHandleReferences()) {
+ if (nonReadyCmHandleReferencesLookup.containsKey(cmHandleReference)
+ || nonReadyCmHandleReferencesLookup.containsValue(cmHandleReference)) {
+ nonReadyCmHandleReferences.add(cmHandleReference);
} else {
+ final String cmHandleId = getCmHandleId(cmHandleReference, yangModelCmHandles);
final String dmiServiceName = dmiServiceNamesPerCmHandleId.get(cmHandleId);
final Map<String, String> cmHandleIdProperties
= dmiPropertiesPerCmHandleIdPerServiceName.get(dmiServiceName).get(cmHandleId);
if (cmHandleIdProperties == null) {
- nonExistingCmHandleIds.add(cmHandleId);
+ nonExistingCmHandleReferences.add(cmHandleReference);
} else {
final DmiDataOperation dmiBatchOperationOut = getOrAddDmiBatchOperation(dmiServiceName,
dataOperationDefinitionIn, dmiDataOperationsOutPerDmiServiceName);
@@ -105,14 +107,14 @@
}
}
}
- populateCmHandleIdsPerOperationIdPerResponseCode(cmHandleIdsPerResponseCodesPerOperation,
+ populateCmHandleIdsPerOperationIdPerResponseCode(cmHandleReferencesPerResponseCodesPerOperation,
DmiDataOperation.buildDmiDataOperationRequestBodyWithoutCmHandles(dataOperationDefinitionIn),
- CM_HANDLES_NOT_FOUND, nonExistingCmHandleIds);
- populateCmHandleIdsPerOperationIdPerResponseCode(cmHandleIdsPerResponseCodesPerOperation,
+ CM_HANDLES_NOT_FOUND, nonExistingCmHandleReferences);
+ populateCmHandleIdsPerOperationIdPerResponseCode(cmHandleReferencesPerResponseCodesPerOperation,
DmiDataOperation.buildDmiDataOperationRequestBodyWithoutCmHandles(dataOperationDefinitionIn),
- CM_HANDLES_NOT_READY, nonReadyCmHandleIds);
+ CM_HANDLES_NOT_READY, nonReadyCmHandleReferences);
}
- publishErrorMessageToClientTopic(topicParamInQuery, requestId, cmHandleIdsPerResponseCodesPerOperation);
+ publishErrorMessageToClientTopic(topicParamInQuery, requestId, cmHandleReferencesPerResponseCodesPerOperation);
return dmiDataOperationsOutPerDmiServiceName;
}
@@ -182,10 +184,26 @@
return dmiBatchOperationsOut.get(dmiBatchOperationsOut.size() - 1);
}
- private static Set<String> filterAndGetNonReadyCmHandleIds(final Collection<YangModelCmHandle> yangModelCmHandles) {
- return yangModelCmHandles.stream()
- .filter(yangModelCmHandle -> yangModelCmHandle.getCompositeState().getCmHandleState()
- != CmHandleState.READY).map(YangModelCmHandle::getId).collect(Collectors.toSet());
+ private static Map<String, String> filterAndGetNonReadyCmHandleReferences(
+ final Collection<YangModelCmHandle> yangModelCmHandles) {
+ final Map<String, String> cmHandleReferenceMap = new HashMap<>(yangModelCmHandles.size());
+ for (final YangModelCmHandle yangModelCmHandle: yangModelCmHandles) {
+ if (yangModelCmHandle.getCompositeState().getCmHandleState() != CmHandleState.READY) {
+ cmHandleReferenceMap.put(yangModelCmHandle.getId(), yangModelCmHandle.getAlternateId());
+ }
+ }
+ return cmHandleReferenceMap;
+ }
+
+ private static String getCmHandleId(final String cmHandleReference,
+ final Collection<YangModelCmHandle> yangModelCmHandles) {
+ for (final YangModelCmHandle yangModelCmHandle: yangModelCmHandles) {
+ if (cmHandleReference.equals(yangModelCmHandle.getId())
+ || cmHandleReference.equals(yangModelCmHandle.getAlternateId())) {
+ return yangModelCmHandle.getId();
+ }
+ }
+ return cmHandleReference;
}
private static void populateCmHandleIdsPerOperationIdPerResponseCode(final MultiValueMap<DmiDataOperation,
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java
index 850edf7..de8e8e8 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java
@@ -72,6 +72,14 @@
Collection<YangModelCmHandle> getYangModelCmHandles(Collection<String> cmHandleIds);
/**
+ * This method retrieves DMI service name, DMI properties and the state for a given list of cm handle references.
+ *
+ * @param cmHandleReferences a list of the ids of the cm handles
+ * @return collection of yang model cm handles
+ */
+ Collection<YangModelCmHandle> getYangModelCmHandlesFromCmHandleReferences(Collection<String> cmHandleReferences);
+
+ /**
* Method to return module definitions by cmHandleId.
*
* @param cmHandleId cm handle ID
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java
index 655d843..d73fae9 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java
@@ -22,6 +22,7 @@
package org.onap.cps.ncmp.impl.inventory;
+import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS;
import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS;
import com.google.common.collect.Lists;
@@ -33,6 +34,7 @@
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.api.CpsAnchorService;
import org.onap.cps.api.CpsDataService;
@@ -133,6 +135,19 @@
}
@Override
+ public Collection<YangModelCmHandle> getYangModelCmHandlesFromCmHandleReferences(
+ final Collection<String> cmHandleReferences) {
+
+ final String cpsPathForCmHandlesByReferences = getCpsPathForCmHandlesByReferences(cmHandleReferences);
+
+ final Collection<DataNode> cmHandlesAsDataNodes =
+ cmHandleQueryService.queryNcmpRegistryByCpsPath(
+ cpsPathForCmHandlesByReferences, INCLUDE_ALL_DESCENDANTS);
+
+ return YangDataConverter.toYangModelCmHandles(cmHandlesAsDataNodes);
+ }
+
+ @Override
public Collection<ModuleDefinition> getModuleDefinitionsByCmHandleId(final String cmHandleId) {
return cpsModuleService.getModuleDefinitionsByAnchorName(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId);
}
@@ -190,7 +205,8 @@
return Collections.emptyList();
}
final String cpsPathForCmHandlesByAlternateIds = getCpsPathForCmHandlesByAlternateIds(alternateIds);
- return cmHandleQueryService.queryNcmpRegistryByCpsPath(cpsPathForCmHandlesByAlternateIds, OMIT_DESCENDANTS);
+ return cmHandleQueryService.queryNcmpRegistryByCpsPath(cpsPathForCmHandlesByAlternateIds,
+ INCLUDE_ALL_DESCENDANTS);
}
@Override
@@ -234,6 +250,12 @@
NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@alternate-id='", "']"));
}
+ private String getCpsPathForCmHandlesByReferences(final Collection<String> cmHandleReferences) {
+ return cmHandleReferences.stream()
+ .flatMap(id -> Stream.of("@id='" + id + "'", "@alternate-id='" + id + "'"))
+ .collect(Collectors.joining(" or ", NCMP_DMI_REGISTRY_PARENT + "/cm-handles[", "]"));
+ }
+
private static String createStateJsonData(final String state) {
return "{\"state\":" + state + "}";
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy
index fd76abb..b046c12 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy
@@ -112,7 +112,7 @@
mockYangModelCmHandleCollectionRetrieval([yangModelCmHandleProperty])
def dataOperationBatchRequestJsonData = TestUtils.getResourceFileContent('dataOperationRequest.json')
def dataOperationRequest = spiedJsonObjectMapper.convertJsonString(dataOperationBatchRequestJsonData, DataOperationRequest.class)
- dataOperationRequest.dataOperationDefinitions[0].cmHandleIds = [cmHandleId]
+ dataOperationRequest.dataOperationDefinitions[0].cmHandleReferences = [cmHandleId]
and: 'a positive response from DMI service when it is called with valid request parameters'
def responseFromDmi = Mono.just(new ResponseEntity<Object>(HttpStatus.ACCEPTED))
def expectedUrlTemplateWithVariables = new UrlTemplateParameters('myServiceName/dmi/v1/data?requestId={requestId}&topic={topic}', ['requestId': 'requestId', 'topic': 'my-topic-name'])
@@ -129,7 +129,7 @@
mockYangModelCmHandleCollectionRetrieval([yangModelCmHandleProperty])
def dataOperationBatchRequestJsonData = TestUtils.getResourceFileContent('dataOperationRequest.json')
def dataOperationRequest = spiedJsonObjectMapper.convertJsonString(dataOperationBatchRequestJsonData, DataOperationRequest.class)
- dataOperationRequest.dataOperationDefinitions[0].cmHandleIds = [cmHandleId]
+ dataOperationRequest.dataOperationDefinitions[0].cmHandleReferences = [cmHandleId]
and: 'the published cloud event will be captured'
def actualDataOperationCloudEvent = null
eventsPublisher.publishCloudEvent('my-topic-name', 'my-request-id', _) >> { args -> actualDataOperationCloudEvent = args[2] }
@@ -143,7 +143,7 @@
assert eventDataValue.statusMessage == UNKNOWN_ERROR.message
and: 'the event contains the correct operation details'
assert eventDataValue.operationId == dataOperationRequest.dataOperationDefinitions[0].operationId
- assert eventDataValue.ids == dataOperationRequest.dataOperationDefinitions[0].cmHandleIds
+ assert eventDataValue.ids == dataOperationRequest.dataOperationDefinitions[0].cmHandleReferences
}
def 'call get all resource data.'() {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/NcmpDatastoreRequestHandlerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/NcmpDatastoreRequestHandlerSpec.groovy
index d5db24c..d5f705f 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/NcmpDatastoreRequestHandlerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/NcmpDatastoreRequestHandlerSpec.groovy
@@ -73,7 +73,7 @@
and: 'notification feature is turned on/off'
objectUnderTest.notificationFeatureEnabled = notificationFeatureEnabled
when: 'data operation request is executed'
- def dataOperationDefinition = new DataOperationDefinition(operation: 'read', datastore: 'ncmp-datastore:passthrough-running', cmHandleIds: ['ch'])
+ def dataOperationDefinition = new DataOperationDefinition(operation: 'read', datastore: 'ncmp-datastore:passthrough-running', cmHandleReferences: ['ch'])
def result = objectUnderTest.executeAsynchronousRequest('someTopic', new DataOperationRequest(dataOperationDefinitions:[dataOperationDefinition]), NO_AUTH_HEADER)
then: 'the task is executed in an async fashion or not'
expectedCalls * dmiDataOperations.requestResourceDataFromDmi('someTopic', _, _, NO_AUTH_HEADER)
@@ -120,7 +120,7 @@
given: 'a data operation definition with too many cm handles'
def tooMany = objectUnderTest.MAXIMUM_CM_HANDLES_PER_OPERATION + 1
def cmHandleIds = new String[tooMany]
- def dataOperationDefinition = new DataOperationDefinition(operationId: 'abc', operation: 'read', datastore: 'ncmp-datastore:passthrough-running', cmHandleIds: cmHandleIds)
+ def dataOperationDefinition = new DataOperationDefinition(operationId: 'abc', operation: 'read', datastore: 'ncmp-datastore:passthrough-running', cmHandleReferences: cmHandleIds)
when: 'data operation request is executed'
objectUnderTest.executeAsynchronousRequest('someTopic', new DataOperationRequest(dataOperationDefinitions:[dataOperationDefinition]), NO_AUTH_HEADER)
then: 'a payload too large exception is thrown'
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelperSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelperSpec.groovy
index 84eafb0..77e2c4f 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelperSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelperSpec.groovy
@@ -74,15 +74,16 @@
assert dmiDataOperationRequestBodyAsJsonNode.get('operationId').asText() == expectedOperationId
assert dmiDataOperationRequestBodyAsJsonNode.get('datastore').asText() == expectedDatastore
and: 'the correct cm handles (just for #serviceName)'
- assert dmiDataOperationRequestBodyAsJsonNode.get('cmHandles').size() == expectedCmHandleIds.size()
- expectedCmHandleIds.each {
+ assert dmiDataOperationRequestBodyAsJsonNode.get('cmHandles').size() == expectedCmHandleReferences.size()
+ expectedCmHandleReferences.each {
dmiDataOperationRequestBodyAsJsonNode.get('cmHandles').toString().contains(it)
}
where: 'the following dmi service and operations are checked'
- serviceName | operationIndex || expectedOperationId | expectedDatastore | expectedCmHandleIds
+ serviceName | operationIndex || expectedOperationId | expectedDatastore | expectedCmHandleReferences
'dmi1' | 0 || 'operational-14' | 'ncmp-datastore:passthrough-operational' | ['ch6-dmi1']
'dmi1' | 1 || 'running-12' | 'ncmp-datastore:passthrough-running' | ['ch1-dmi1', 'ch2-dmi1']
'dmi1' | 2 || 'operational-15' | 'ncmp-datastore:passthrough-operational' | ['ch6-dmi1']
+ 'dmi1' | 3 || 'operational-16' | 'ncmp-datastore:passthrough-operational' | ['alt6-dmi1']
'dmi2' | 0 || 'operational-14' | 'ncmp-datastore:passthrough-operational' | ['ch3-dmi2']
'dmi2' | 1 || 'running-12' | 'ncmp-datastore:passthrough-running' | ['ch7-dmi2']
'dmi2' | 2 || 'operational-15' | 'ncmp-datastore:passthrough-operational' | ['ch4-dmi2']
@@ -137,14 +138,14 @@
def dmiProperties = [new YangModelCmHandle.Property('prop', 'some DMI property')]
def readyState = new CompositeStateBuilder().withCmHandleState(READY).withLastUpdatedTimeNow().build()
def advisedState = new CompositeStateBuilder().withCmHandleState(ADVISED).withLastUpdatedTimeNow().build()
- return [new YangModelCmHandle(id: 'ch1-dmi1', dmiServiceName: 'dmi1', dmiProperties: dmiProperties, compositeState: readyState),
- new YangModelCmHandle(id: 'ch2-dmi1', dmiServiceName: 'dmi1', dmiProperties: dmiProperties, compositeState: readyState),
- new YangModelCmHandle(id: 'ch6-dmi1', dmiServiceName: 'dmi1', dmiProperties: dmiProperties, compositeState: readyState),
- new YangModelCmHandle(id: 'ch8-dmi1', dmiServiceName: 'dmi1', dmiProperties: dmiProperties, compositeState: readyState),
- new YangModelCmHandle(id: 'ch3-dmi2', dmiServiceName: 'dmi2', dmiProperties: dmiProperties, compositeState: readyState),
- new YangModelCmHandle(id: 'ch4-dmi2', dmiServiceName: 'dmi2', dmiProperties: dmiProperties, compositeState: readyState),
- new YangModelCmHandle(id: 'ch7-dmi2', dmiServiceName: 'dmi2', dmiProperties: dmiProperties, compositeState: readyState),
- new YangModelCmHandle(id: 'non-ready-cm-handle', dmiServiceName: 'dmi2', dmiProperties: dmiProperties, compositeState: advisedState)
+ return [new YangModelCmHandle(id: 'ch1-dmi1', 'alternateId': 'alt1-dmi1', dmiServiceName: 'dmi1', dmiProperties: dmiProperties, compositeState: readyState),
+ new YangModelCmHandle(id: 'ch2-dmi1', 'alternateId': 'alt2-dmi1', dmiServiceName: 'dmi1', dmiProperties: dmiProperties, compositeState: readyState),
+ new YangModelCmHandle(id: 'ch6-dmi1', 'alternateId': 'alt6-dmi1', dmiServiceName: 'dmi1', dmiProperties: dmiProperties, compositeState: readyState),
+ new YangModelCmHandle(id: 'ch8-dmi1', 'alternateId': 'alt8-dmi1', dmiServiceName: 'dmi1', dmiProperties: dmiProperties, compositeState: readyState),
+ new YangModelCmHandle(id: 'ch3-dmi2', 'alternateId': 'alt3-dmi2', dmiServiceName: 'dmi2', dmiProperties: dmiProperties, compositeState: readyState),
+ new YangModelCmHandle(id: 'ch4-dmi2', 'alternateId': 'alt4-dmi2', dmiServiceName: 'dmi2', dmiProperties: dmiProperties, compositeState: readyState),
+ new YangModelCmHandle(id: 'ch7-dmi2', 'alternateId': 'alt7-dmi2', dmiServiceName: 'dmi2', dmiProperties: dmiProperties, compositeState: readyState),
+ new YangModelCmHandle(id: 'non-ready-cm-handle', 'alternateId': 'non-ready-alternate', dmiServiceName: 'dmi2', dmiProperties: dmiProperties, compositeState: advisedState)
]
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy
index 65fda87..d00d3ab 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy
@@ -61,7 +61,7 @@
def mockYangModelCmHandleCollectionRetrieval(dmiProperties) {
populateYangModelCmHandle(dmiProperties, '')
- mockInventoryPersistence.getYangModelCmHandles(_) >> [yangModelCmHandle]
+ mockInventoryPersistence.getYangModelCmHandlesFromCmHandleReferences(_) >> [yangModelCmHandle]
}
def populateYangModelCmHandle(dmiProperties, moduleSetTag) {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy
index e2261f4..34d9374 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy
@@ -38,7 +38,6 @@
import org.onap.cps.spi.model.ModuleReference
import org.onap.cps.utils.ContentType
import org.onap.cps.utils.JsonObjectMapper
-import org.testcontainers.shaded.com.fasterxml.jackson.databind.introspect.BasicClassIntrospector
import spock.lang.Shared
import spock.lang.Specification
@@ -75,12 +74,16 @@
.format(OffsetDateTime.of(2022, 12, 31, 20, 30, 40, 1, ZoneOffset.UTC))
def cmHandleId = 'some-cm-handle'
- def leaves = ["id":cmHandleId,"dmi-service-name":"common service name","dmi-data-service-name":"data service name","dmi-model-service-name":"model service name"]
+ def alternateId = 'some-alternate-id'
+ def leaves = ["id":cmHandleId, "alternateId":alternateId,"dmi-service-name":"common service name","dmi-data-service-name":"data service name","dmi-model-service-name":"model service name"]
def xpath = "/dmi-registry/cm-handles[@id='some-cm-handle']"
def cmHandleId2 = 'another-cm-handle'
+ def alternateId2 = 'another-alternate-id'
def xpath2 = "/dmi-registry/cm-handles[@id='another-cm-handle']"
+ def dataNode = new DataNode(xpath: "/dmi-registry/cm-handles[@id='some cm handle']/additional-properties[@name='name1']", leaves: ["name":"name1", "value":"value1"])
+
@Shared
def childDataNodesForCmHandleWithAllProperties = [new DataNode(xpath: "/dmi-registry/cm-handles[@id='some cm handle']/additional-properties[@name='name1']", leaves: ["name":"name1", "value":"value1"]),
new DataNode(xpath: "/dmi-registry/cm-handles[@id='some cm handle']/public-properties[@name='name2']", leaves: ["name":"name2","value":"value2"])]
@@ -135,7 +138,7 @@
1 * mockCpsValidator.validateNameCharacters(cmHandleId)
}
- def "Retrieve multiple YangModelCmHandles"() {
+ def "Retrieve multiple YangModelCmHandles using cm handle ids"() {
given: 'the cps data service returns 2 data nodes from the DMI registry'
def dataNodes = [new DataNode(xpath: xpath, leaves: ['id': cmHandleId]), new DataNode(xpath: xpath2, leaves: ['id': cmHandleId2])]
mockCpsDataService.getDataNodesForMultipleXpaths(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, [xpath, xpath2] , INCLUDE_ALL_DESCENDANTS) >> dataNodes
@@ -146,6 +149,17 @@
assert results.id.containsAll([cmHandleId, cmHandleId2])
}
+ def "Retrieve multiple YangModelCmHandles using cm handle references"() {
+ given: 'the cps data service returns 2 data nodes from the DMI registry'
+ def dataNodes = [new DataNode(xpath: xpath, leaves: ['id': cmHandleId, 'alternate-id':alternateId]), new DataNode(xpath: xpath2, leaves: ['id': cmHandleId2,'alternate-id':alternateId2])]
+ mockCmHandleQueries.queryNcmpRegistryByCpsPath(_, INCLUDE_ALL_DESCENDANTS) >> dataNodes
+ when: 'retrieving the yang modelled cm handle'
+ def results = objectUnderTest.getYangModelCmHandlesFromCmHandleReferences([cmHandleId, cmHandleId2])
+ then: 'verify both have returned and cmhandleIds are correct'
+ assert results.size() == 2
+ assert results.id.containsAll([cmHandleId, cmHandleId2])
+ }
+
def 'Get a Cm Handle Composite State'() {
given: 'a valid cm handle id'
def cmHandleId = 'Some-Cm-Handle'
@@ -317,15 +331,6 @@
assert thrownException.getMessage().contains('DataNode not found')
}
- def 'Get multiple cm handle data nodes by alternate ids'() {
- given: 'expected xPath to get cmHandle data node'
- def expectedXPath = "/dmi-registry/cm-handles[@alternate-id='A' or @alternate-id='B']"
- when: 'getting the cm handle data node'
- objectUnderTest.getCmHandleDataNodesByAlternateIds(['A', 'B'])
- then: 'query service is invoked with expected xpath'
- 1 * mockCmHandleQueries.queryNcmpRegistryByCpsPath(expectedXPath, OMIT_DESCENDANTS)
- }
-
def 'Get multiple cm handle data nodes by alternate ids, passing empty collection'() {
when: 'getting the cm handle data node for no alternate ids'
objectUnderTest.getCmHandleDataNodesByAlternateIds([])
@@ -372,4 +377,13 @@
then: 'the cps data service method to delete data nodes is invoked once with the same xPaths'
1 * mockCpsDataService.deleteDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, ['xpath1', 'xpath2'], NO_TIMESTAMP);
}
+
+ def 'Check if cm handle exists for a given cm handle id'() {
+ given: 'data service returns a datanode with correct cm handle id'
+ mockCpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, xpath, INCLUDE_ALL_DESCENDANTS) >> [dataNode]
+ when: 'method is called to check if cm handle exists from cm handle id'
+ def result = objectUnderTest.isExistingCmHandleId('some-cm-handle')
+ then: 'check if cm handle id in datanode is equal to given cm handle id'
+ assert result == true
+ }
}
diff --git a/cps-ncmp-service/src/test/resources/dataOperationRequest.json b/cps-ncmp-service/src/test/resources/dataOperationRequest.json
index f69b876..3faaf2b 100644
--- a/cps-ncmp-service/src/test/resources/dataOperationRequest.json
+++ b/cps-ncmp-service/src/test/resources/dataOperationRequest.json
@@ -36,6 +36,17 @@
"ch4-dmi2",
"ch6-dmi1"
]
+ },
+ {
+ "operation": "read",
+ "operationId": "operational-16",
+ "datastore": "ncmp-datastore:passthrough-operational",
+ "options": "some option",
+ "resourceIdentifier": "some resource identifier",
+ "targetIds": [
+ "ch4-dmi2",
+ "alt6-dmi1"
+ ]
}
]
}
diff --git a/docs/api/swagger/ncmp/openapi-inventory.yaml b/docs/api/swagger/ncmp/openapi-inventory.yaml
index 8552ad5..c72f47a 100644
--- a/docs/api/swagger/ncmp/openapi-inventory.yaml
+++ b/docs/api/swagger/ncmp/openapi-inventory.yaml
@@ -136,8 +136,8 @@
\ plugin)."
operationId: searchCmHandleIds
parameters:
- - description: Boolean parameter to determine if returned value(s) will be cmHandle
- Ids or Alternate Ids for a given query
+ - description: Boolean parameter to determine if returned value(s) will be cm
+ handle references for a given query
in: query
name: outputAlternateId
required: false
diff --git a/docs/api/swagger/ncmp/openapi.yaml b/docs/api/swagger/ncmp/openapi.yaml
index aa732c8..024aed6 100644
--- a/docs/api/swagger/ncmp/openapi.yaml
+++ b/docs/api/swagger/ncmp/openapi.yaml
@@ -698,7 +698,7 @@
schema:
$ref: '#/components/schemas/DmiErrorMessage'
description: Bad Gateway
- summary: Execute a data operation for group of cm handle ids
+ summary: Execute a data operation for group of cm handle references
tags:
- network-cm-proxy
/v1/ch/{cm-handle}/data/ds/{datastore-name}/query:
@@ -1141,8 +1141,8 @@
this query.
operationId: searchCmHandleIds
parameters:
- - description: Boolean parameter to determine if returned value(s) will be cmHandle
- Ids or Alternate Ids for a given query
+ - description: Boolean parameter to determine if returned value(s) will be cm
+ handle references for a given query
in: query
name: outputAlternateId
required: false
@@ -1618,8 +1618,8 @@
example: 2024-01-22
type: string
outputAlternateIdOptionInQuery:
- description: Boolean parameter to determine if returned value(s) will be cmHandle
- Ids or Alternate Ids for a given query
+ description: Boolean parameter to determine if returned value(s) will be cm
+ handle references for a given query
in: query
name: outputAlternateId
required: false
@@ -1789,8 +1789,8 @@
type: string
targetIds:
items:
- description: "targeted cm handles, maximum of 50 supported. If this limit\
- \ is exceeded the request wil be refused."
+ description: "targeted cm handle references, maximum of 200 supported.\
+ \ If this limit is exceeded the request wil be refused."
example: "[\"da310eecdb8d44c2acc0ddaae01174b1\",\"c748c58f8e0b438f9fd1f28370b17d47\"\
]"
type: string
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/BearerTokenPassthroughSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/BearerTokenPassthroughSpec.groovy
index 99e8032..a81058f 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/BearerTokenPassthroughSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/BearerTokenPassthroughSpec.groovy
@@ -37,11 +37,14 @@
def setup() {
dmiDispatcher1.moduleNamesPerCmHandleId['ch-1'] = ['M1', 'M2']
- registerCmHandle(DMI1_URL, 'ch-1', NO_MODULE_SET_TAG)
+ dmiDispatcher1.moduleNamesPerCmHandleId['ch-2'] = ['M1', 'M3']
+ registerCmHandle(DMI1_URL, 'ch-1', NO_MODULE_SET_TAG, 'alt-1')
+ registerCmHandle(DMI1_URL, 'ch-2', NO_MODULE_SET_TAG, 'alt-2')
}
def cleanup() {
deregisterCmHandle(DMI1_URL, 'ch-1')
+ deregisterCmHandle(DMI1_URL, 'ch-2')
}
def 'Bearer token is passed from NCMP to DMI in pass-through data operations.'() {
@@ -83,7 +86,7 @@
"operationId": "operational-1",
"datastore": "ncmp-datastore:passthrough-running",
"resourceIdentifier": "my-resource-id",
- "targetIds": ["ch-1"]
+ "targetIds": ["ch-1","alt-2"]
}]}"""
mvc.perform(request(POST, '/ncmp/v1/data')
.queryParam('topic', 'my-topic')