summaryrefslogtreecommitdiffstats
path: root/cps-ncmp-service/src
diff options
context:
space:
mode:
Diffstat (limited to 'cps-ncmp-service/src')
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfig.java46
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java10
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumer.java71
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceTrustLevel.java37
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevel.java25
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/DataOperationEventCreator.java42
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java36
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumerSpec.groovy102
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtilsSpec.groovy8
-rw-r--r--cps-ncmp-service/src/test/resources/dataOperationRequest.json7
-rw-r--r--cps-ncmp-service/src/test/resources/dataOperationResponseEvent.json1
11 files changed, 335 insertions, 50 deletions
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfig.java
new file mode 100644
index 0000000000..816fc50675
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfig.java
@@ -0,0 +1,46 @@
+/*
+ * ============LICENSE_START========================================================
+ * Copyright (C) 2023 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.api.impl.config.embeddedcache;
+
+import com.hazelcast.collection.ISet;
+import com.hazelcast.config.SetConfig;
+import org.onap.cps.cache.HazelcastCacheConfig;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class TrustLevelCacheConfig extends HazelcastCacheConfig {
+
+ private static final SetConfig untrustworthyCmHandlesSetConfig = createSetConfig("untrustworthyCmHandlesSetConfig");
+
+ /**
+ * Untrustworthy cmhandle set instance.
+ *
+ * @return instance of distributed set of untrustworthy cmhandles.
+ */
+ @Bean
+ public ISet<String> untrustworthyCmHandlesSet() {
+ return createHazelcastInstance("untrustworthyCmHandlesSet", untrustworthyCmHandlesSetConfig).getSet(
+ "untrustworthyCmHandlesSet");
+ }
+
+
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
index 02de9854ef..ba6f89192d 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
@@ -261,22 +261,22 @@ public class DmiDataOperations extends DmiOperations {
final String topicName = dataOperationResourceUrlParameters.get("topic").get(0);
final String requestId = dataOperationResourceUrlParameters.get("requestId").get(0);
- final MultiValueMap<String, Map<NcmpEventResponseCode, List<String>>>
- cmHandleIdsPerResponseCodesPerOperationId = new LinkedMultiValueMap<>();
+ final MultiValueMap<DmiDataOperation, Map<NcmpEventResponseCode, List<String>>>
+ cmHandleIdsPerResponseCodesPerOperation = new LinkedMultiValueMap<>();
dmiDataOperationRequestBodies.forEach(dmiDataOperationRequestBody -> {
final List<String> cmHandleIds = dmiDataOperationRequestBody.getCmHandles().stream()
.map(CmHandle::getId).collect(Collectors.toList());
if (throwable.getCause() instanceof HttpClientRequestException) {
- cmHandleIdsPerResponseCodesPerOperationId.add(dmiDataOperationRequestBody.getOperationId(),
+ cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperationRequestBody,
Map.of(NcmpEventResponseCode.UNABLE_TO_READ_RESOURCE_DATA, cmHandleIds));
} else {
- cmHandleIdsPerResponseCodesPerOperationId.add(dmiDataOperationRequestBody.getOperationId(),
+ cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperationRequestBody,
Map.of(NcmpEventResponseCode.DMI_SERVICE_NOT_RESPONDING, cmHandleIds));
}
});
ResourceDataOperationRequestUtils.publishErrorMessageToClientTopic(topicName, requestId,
- cmHandleIdsPerResponseCodesPerOperationId);
+ cmHandleIdsPerResponseCodesPerOperation);
}
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumer.java
new file mode 100644
index 0000000000..458c1b8518
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumer.java
@@ -0,0 +1,71 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 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.api.impl.trustlevel;
+
+import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent;
+
+import com.hazelcast.collection.ISet;
+import io.cloudevents.CloudEvent;
+import io.cloudevents.kafka.impl.KafkaHeaders;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.springframework.kafka.annotation.KafkaListener;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class DeviceHeartbeatConsumer {
+
+ private final ISet<String> untrustworthyCmHandlesSet;
+
+ /**
+ * Listening the device heartbeats.
+ *
+ * @param deviceHeartbeatConsumerRecord Device Heartbeat record.
+ */
+ @KafkaListener(topics = "${app.dmi.device-heartbeat.topic}",
+ containerFactory = "cloudEventConcurrentKafkaListenerContainerFactory")
+ public void heartbeatListener(final ConsumerRecord<String, CloudEvent> deviceHeartbeatConsumerRecord) {
+
+ final String cmHandleId = KafkaHeaders.getParsedKafkaHeader(deviceHeartbeatConsumerRecord.headers(), "ce_id");
+
+ final DeviceTrustLevel deviceTrustLevel =
+ toTargetEvent(deviceHeartbeatConsumerRecord.value(), DeviceTrustLevel.class);
+
+ if (deviceTrustLevel == null || deviceTrustLevel.getTrustLevel() == null) {
+ log.warn("No or Invalid trust level defined");
+ return;
+ }
+
+ if (deviceTrustLevel.getTrustLevel().equals(TrustLevel.NONE)) {
+ untrustworthyCmHandlesSet.add(cmHandleId);
+ log.debug("Added cmHandleId to untrustworthy set : {}", cmHandleId);
+ } else if (deviceTrustLevel.getTrustLevel().equals(TrustLevel.COMPLETE) && untrustworthyCmHandlesSet.contains(
+ cmHandleId)) {
+ untrustworthyCmHandlesSet.remove(cmHandleId);
+ log.debug("Removed cmHandleId from untrustworthy set : {}", cmHandleId);
+ }
+ }
+
+}
+
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceTrustLevel.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceTrustLevel.java
new file mode 100644
index 0000000000..2ed4e45220
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceTrustLevel.java
@@ -0,0 +1,37 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 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.api.impl.trustlevel;
+
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@AllArgsConstructor
+@Data
+@NoArgsConstructor
+class DeviceTrustLevel implements Serializable {
+
+ private static final long serialVersionUID = -1705715024067165212L;
+
+ private TrustLevel trustLevel;
+
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevel.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevel.java
new file mode 100644
index 0000000000..f4254bb473
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevel.java
@@ -0,0 +1,25 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 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.api.impl.trustlevel;
+
+public enum TrustLevel {
+ NONE, COMPLETE;
+} \ No newline at end of file
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/DataOperationEventCreator.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/DataOperationEventCreator.java
index 2d9a51b844..65cda94787 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/DataOperationEventCreator.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/DataOperationEventCreator.java
@@ -30,6 +30,7 @@ import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.NcmpEventResponseCode;
import org.onap.cps.ncmp.api.impl.events.NcmpCloudEventBuilder;
+import org.onap.cps.ncmp.api.impl.operations.DmiDataOperation;
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.events.async1_0_0.Response;
@@ -44,49 +45,48 @@ public class DataOperationEventCreator {
*
* @param clientTopic topic the client wants to use for responses
* @param requestId unique identifier per request
- * @param cmHandleIdsPerResponseCodesPerOperationId map of cm handles per operation response per response code
+ * @param cmHandleIdsPerResponseCodesPerOperation map of cm handles per operation response per response code
* @return Cloud Event
*/
public static CloudEvent createDataOperationEvent(final String clientTopic,
final String requestId,
- final MultiValueMap<String,
+ final MultiValueMap<DmiDataOperation,
Map<NcmpEventResponseCode, List<String>>>
- cmHandleIdsPerResponseCodesPerOperationId) {
+ cmHandleIdsPerResponseCodesPerOperation) {
final DataOperationEvent dataOperationEvent = new DataOperationEvent();
- final Data data = createPayloadFromDataOperationResponses(cmHandleIdsPerResponseCodesPerOperationId);
+ final Data data = createPayloadFromDataOperationResponses(cmHandleIdsPerResponseCodesPerOperation);
dataOperationEvent.setData(data);
final Map<String, String> extensions = createDataOperationExtensions(requestId, clientTopic);
return NcmpCloudEventBuilder.builder().type(DataOperationEvent.class.getName())
.event(dataOperationEvent).extensions(extensions).setCloudEvent().build();
}
- private static Data createPayloadFromDataOperationResponses(final MultiValueMap<String, Map<NcmpEventResponseCode,
- List<String>>> cmHandleIdsPerOperationIdPerResponseCode) {
+ private static Data createPayloadFromDataOperationResponses(final MultiValueMap<DmiDataOperation,
+ Map<NcmpEventResponseCode, List<String>>> cmHandleIdsPerResponseCodesPerOperation) {
final Data data = new Data();
final List<org.onap.cps.ncmp.events.async1_0_0.Response> responses = new ArrayList<>();
- cmHandleIdsPerOperationIdPerResponseCode.entrySet().forEach(cmHandleIdsPerOperationIdPerResponseCodeEntries ->
- cmHandleIdsPerOperationIdPerResponseCodeEntries.getValue().forEach(cmHandleIdsPerResponseCodeEntries ->
+ cmHandleIdsPerResponseCodesPerOperation.forEach((dmiDataOperation, cmHandleIdsPerResponseCodes) ->
+ cmHandleIdsPerResponseCodes.forEach(cmHandleIdsPerResponseCodeEntries ->
responses.addAll(createResponseFromDataOperationResponses(
- cmHandleIdsPerOperationIdPerResponseCodeEntries.getKey(),
- cmHandleIdsPerResponseCodeEntries)
- )));
+ dmiDataOperation, cmHandleIdsPerResponseCodeEntries))));
data.setResponses(responses);
return data;
}
private static List<Response> createResponseFromDataOperationResponses(
- final String operationId,
+ final DmiDataOperation dmiDataOperation,
final Map<NcmpEventResponseCode, List<String>> cmHandleIdsPerResponseCodeEntries) {
final List<org.onap.cps.ncmp.events.async1_0_0.Response> responses = new ArrayList<>();
- cmHandleIdsPerResponseCodeEntries.entrySet()
- .forEach(cmHandleIdsPerResponseCodeEntry -> {
- final Response response = new Response();
- response.setOperationId(operationId);
- response.setStatusCode(cmHandleIdsPerResponseCodeEntry.getKey().getStatusCode());
- response.setStatusMessage(cmHandleIdsPerResponseCodeEntry.getKey().getStatusMessage());
- response.setIds(cmHandleIdsPerResponseCodeEntry.getValue());
- responses.add(response);
- });
+ cmHandleIdsPerResponseCodeEntries.forEach((ncmpEventResponseCode, cmHandleIds) -> {
+ final Response response = new Response();
+ response.setOperationId(dmiDataOperation.getOperationId());
+ response.setStatusCode(ncmpEventResponseCode.getStatusCode());
+ response.setStatusMessage(ncmpEventResponseCode.getStatusMessage());
+ response.setIds(cmHandleIds);
+ response.setResourceIdentifier(dmiDataOperation.getResourceIdentifier());
+ response.setOptions(dmiDataOperation.getOptions());
+ responses.add(response);
+ });
return responses;
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java
index d8fb904f21..c455337ac3 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java
@@ -68,8 +68,8 @@ public class ResourceDataOperationRequestUtils {
final Collection<YangModelCmHandle> yangModelCmHandles) {
final Map<String, List<DmiDataOperation>> dmiDataOperationsOutPerDmiServiceName = new HashMap<>();
- final MultiValueMap<String, Map<NcmpEventResponseCode, List<String>>> cmHandleIdsPerResponseCodesPerOperationId
- = new LinkedMultiValueMap<>();
+ final MultiValueMap<DmiDataOperation, Map<NcmpEventResponseCode,
+ List<String>>> cmHandleIdsPerResponseCodesPerOperation = new LinkedMultiValueMap<>();
final Set<String> nonReadyCmHandleIdsLookup = filterAndGetNonReadyCmHandleIds(yangModelCmHandles);
final Map<String, Map<String, Map<String, String>>> dmiPropertiesPerCmHandleIdPerServiceName =
@@ -100,15 +100,15 @@ public class ResourceDataOperationRequestUtils {
}
}
}
- populateCmHandleIdsPerOperationIdPerResponseCode(cmHandleIdsPerResponseCodesPerOperationId,
- dataOperationDefinitionIn.getOperationId(), NcmpEventResponseCode.CM_HANDLES_NOT_FOUND,
- nonExistingCmHandleIds);
- populateCmHandleIdsPerOperationIdPerResponseCode(cmHandleIdsPerResponseCodesPerOperationId,
- dataOperationDefinitionIn.getOperationId(), NcmpEventResponseCode.CM_HANDLES_NOT_READY,
- nonReadyCmHandleIds);
+ populateCmHandleIdsPerOperationIdPerResponseCode(cmHandleIdsPerResponseCodesPerOperation,
+ DmiDataOperation.buildDmiDataOperationRequestBodyWithoutCmHandles(dataOperationDefinitionIn),
+ NcmpEventResponseCode.CM_HANDLES_NOT_FOUND, nonExistingCmHandleIds);
+ populateCmHandleIdsPerOperationIdPerResponseCode(cmHandleIdsPerResponseCodesPerOperation,
+ DmiDataOperation.buildDmiDataOperationRequestBodyWithoutCmHandles(dataOperationDefinitionIn),
+ NcmpEventResponseCode.CM_HANDLES_NOT_READY, nonReadyCmHandleIds);
}
- if (!cmHandleIdsPerResponseCodesPerOperationId.isEmpty()) {
- publishErrorMessageToClientTopic(topicParamInQuery, requestId, cmHandleIdsPerResponseCodesPerOperationId);
+ if (!cmHandleIdsPerResponseCodesPerOperation.isEmpty()) {
+ publishErrorMessageToClientTopic(topicParamInQuery, requestId, cmHandleIdsPerResponseCodesPerOperation);
}
return dmiDataOperationsOutPerDmiServiceName;
}
@@ -118,16 +118,16 @@ public class ResourceDataOperationRequestUtils {
*
* @param clientTopic client given topic
* @param requestId unique identifier per request
- * @param cmHandleIdsPerResponseCodesPerOperationId list of cm handle ids per operation id with response code
+ * @param cmHandleIdsPerResponseCodesPerOperation list of cm handle ids per operation with response code
*/
@Async
public static void publishErrorMessageToClientTopic(final String clientTopic,
final String requestId,
- final MultiValueMap<String,
+ final MultiValueMap<DmiDataOperation,
Map<NcmpEventResponseCode, List<String>>>
- cmHandleIdsPerResponseCodesPerOperationId) {
+ cmHandleIdsPerResponseCodesPerOperation) {
final CloudEvent dataOperationCloudEvent = DataOperationEventCreator.createDataOperationEvent(clientTopic,
- requestId, cmHandleIdsPerResponseCodesPerOperationId);
+ requestId, cmHandleIdsPerResponseCodesPerOperation);
final EventsPublisher<CloudEvent> eventsPublisher = CpsApplicationContext.getCpsBean(EventsPublisher.class);
eventsPublisher.publishCloudEvent(clientTopic, requestId, dataOperationCloudEvent);
}
@@ -174,14 +174,14 @@ public class ResourceDataOperationRequestUtils {
!= CmHandleState.READY).map(YangModelCmHandle::getId).collect(Collectors.toSet());
}
- private static void populateCmHandleIdsPerOperationIdPerResponseCode(final MultiValueMap<String,
- Map<NcmpEventResponseCode, List<String>>> cmHandleIdsPerResponseCodesPerOperationId,
- final String operationId,
+ private static void populateCmHandleIdsPerOperationIdPerResponseCode(final MultiValueMap<DmiDataOperation,
+ Map<NcmpEventResponseCode, List<String>>> cmHandleIdsPerResponseCodesPerOperation,
+ final DmiDataOperation dmiDataOperation,
final NcmpEventResponseCode
ncmpEventResponseCode,
final List<String> cmHandleIds) {
if (!cmHandleIds.isEmpty()) {
- cmHandleIdsPerResponseCodesPerOperationId.add(operationId, Map.of(ncmpEventResponseCode, cmHandleIds));
+ cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperation, Map.of(ncmpEventResponseCode, cmHandleIds));
}
}
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumerSpec.groovy
new file mode 100644
index 0000000000..48de23dca2
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumerSpec.groovy
@@ -0,0 +1,102 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 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.api.impl.trustlevel
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.hazelcast.collection.ISet
+import io.cloudevents.CloudEvent
+import io.cloudevents.core.builder.CloudEventBuilder
+import org.apache.kafka.clients.consumer.ConsumerRecord
+import org.onap.cps.utils.JsonObjectMapper
+import org.springframework.boot.test.context.SpringBootTest
+import spock.lang.Specification
+
+@SpringBootTest(classes = [ObjectMapper, JsonObjectMapper])
+class DeviceHeartbeatConsumerSpec extends Specification {
+
+ def mockUntrustworthyCmHandlesSet = Mock(ISet<String>)
+ def objectMapper = new ObjectMapper()
+
+ def objectUnderTest = new DeviceHeartbeatConsumer(mockUntrustworthyCmHandlesSet)
+
+ def 'Operations to be done in an empty untrustworthy set for #scenario'() {
+ given: 'an event with trustlevel as #trustLevel'
+ def incomingEvent = testCloudEvent(trustLevel)
+ and: 'transformed as a kafka record'
+ def consumerRecord = new ConsumerRecord<String, CloudEvent>('test-device-heartbeat', 0, 0, 'cmhandle1', incomingEvent)
+ consumerRecord.headers().add('ce_id', objectMapper.writeValueAsBytes('cmhandle1'))
+ when: 'the event is consumed'
+ objectUnderTest.heartbeatListener(consumerRecord)
+ then: 'untrustworthy cmhandles are stored'
+ untrustworthyCmHandlesSetInvocationForAdd * mockUntrustworthyCmHandlesSet.add(_)
+ and: 'trustworthy cmHandles will be removed from untrustworthy set'
+ untrustworthyCmHandlesSetInvocationForContains * mockUntrustworthyCmHandlesSet.contains(_)
+
+ where: 'below scenarios are applicable'
+ scenario | trustLevel || untrustworthyCmHandlesSetInvocationForAdd | untrustworthyCmHandlesSetInvocationForContains
+ 'None trust' | TrustLevel.NONE || 1 | 0
+ 'Complete trust' | TrustLevel.COMPLETE || 0 | 1
+ }
+
+ def 'Invalid trust'() {
+ when: 'we provide an invalid trust in the event'
+ def consumerRecord = new ConsumerRecord<String, CloudEvent>('test-device-heartbeat', 0, 0, 'cmhandle1', testCloudEvent(null))
+ consumerRecord.headers().add('ce_id', objectMapper.writeValueAsBytes('cmhandle1'))
+ objectUnderTest.heartbeatListener(consumerRecord)
+ then: 'no interaction with the untrustworthy cmhandles set'
+ 0 * mockUntrustworthyCmHandlesSet.add(_)
+ 0 * mockUntrustworthyCmHandlesSet.contains(_)
+ 0 * mockUntrustworthyCmHandlesSet.remove(_)
+ and: 'control flow returns without any exception'
+ noExceptionThrown()
+
+ }
+
+ def 'Remove trustworthy cmhandles from untrustworthy cmhandles set'() {
+ given: 'an event with COMPLETE trustlevel'
+ def incomingEvent = testCloudEvent(TrustLevel.COMPLETE)
+ and: 'transformed as a kafka record'
+ def consumerRecord = new ConsumerRecord<String, CloudEvent>('test-device-heartbeat', 0, 0, 'cmhandle1', incomingEvent)
+ consumerRecord.headers().add('ce_id', objectMapper.writeValueAsBytes('cmhandle1'))
+ and: 'untrustworthy cmhandles set contains cmhandle1'
+ 1 * mockUntrustworthyCmHandlesSet.contains(_) >> true
+ when: 'the event is consumed'
+ objectUnderTest.heartbeatListener(consumerRecord)
+ then: 'cmhandle removed from untrustworthy cmhandles set'
+ 1 * mockUntrustworthyCmHandlesSet.remove(_) >> {
+ args ->
+ {
+ args[0].equals('cmhandle1')
+ }
+ }
+
+ }
+
+ def testCloudEvent(trustLevel) {
+ return CloudEventBuilder.v1().withData(objectMapper.writeValueAsBytes(new DeviceTrustLevel(trustLevel)))
+ .withId("cmhandle1")
+ .withSource(URI.create('DMI'))
+ .withDataSchema(URI.create('test'))
+ .withType('org.onap.cm.events.trustlevel-notification')
+ .build()
+ }
+
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtilsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtilsSpec.groovy
index c866824062..38b2056d00 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtilsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtilsSpec.groovy
@@ -110,9 +110,9 @@ class ResourceDataOperationRequestUtilsSpec extends MessagingBaseSpec {
toTargetEvent(consumerRecordOut.value(), DataOperationEvent.class)
and: 'data operation response event response size is 3'
dataOperationResponseEvent.data.responses.size() == 3
- and: 'verify published response data as json string'
- jsonObjectMapper.asJsonString(dataOperationResponseEvent.data.responses)
- == '[{"operationId":"operational-14","ids":["unknown-cm-handle"],"statusCode":"100","statusMessage":"cm handle id(s) not found"},{"operationId":"operational-14","ids":["non-ready-cm handle"],"statusCode":"101","statusMessage":"cm handle(s) not ready"},{"operationId":"running-12","ids":["non-ready-cm handle"],"statusCode":"101","statusMessage":"cm handle(s) not ready"}]'
+ and: 'verify published data operation response as json string'
+ def dataOperationResponseEventJson = TestUtils.getResourceFileContent('dataOperationResponseEvent.json')
+ jsonObjectMapper.asJsonString(dataOperationResponseEvent.data.responses) == dataOperationResponseEventJson
}
static def getYangModelCmHandles() {
@@ -126,7 +126,7 @@ class ResourceDataOperationRequestUtilsSpec extends MessagingBaseSpec {
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)
+ new YangModelCmHandle(id: 'non-ready-cm-handle', dmiServiceName: 'dmi2', dmiProperties: dmiProperties, compositeState: advisedState)
]
}
}
diff --git a/cps-ncmp-service/src/test/resources/dataOperationRequest.json b/cps-ncmp-service/src/test/resources/dataOperationRequest.json
index d2e0d64892..f69b87631f 100644
--- a/cps-ncmp-service/src/test/resources/dataOperationRequest.json
+++ b/cps-ncmp-service/src/test/resources/dataOperationRequest.json
@@ -10,18 +10,20 @@
"ch3-dmi2",
"unknown-cm-handle",
"ch6-dmi1",
- "non-ready-cm handle"
+ "non-ready-cm-handle"
]
},
{
"operation": "read",
"operationId": "running-12",
"datastore": "ncmp-datastore:passthrough-running",
+ "options": "some option",
+ "resourceIdentifier": "some resource identifier",
"targetIds": [
"ch1-dmi1",
"ch7-dmi2",
"ch2-dmi1",
- "non-ready-cm handle"
+ "non-ready-cm-handle"
]
},
{
@@ -29,6 +31,7 @@
"operationId": "operational-15",
"datastore": "ncmp-datastore:passthrough-operational",
"options": "some option",
+ "resourceIdentifier": "some resource identifier",
"targetIds": [
"ch4-dmi2",
"ch6-dmi1"
diff --git a/cps-ncmp-service/src/test/resources/dataOperationResponseEvent.json b/cps-ncmp-service/src/test/resources/dataOperationResponseEvent.json
new file mode 100644
index 0000000000..611d47d1a3
--- /dev/null
+++ b/cps-ncmp-service/src/test/resources/dataOperationResponseEvent.json
@@ -0,0 +1 @@
+[{"operationId":"operational-14","ids":["unknown-cm-handle"],"resourceIdentifier":"some resource identifier","options":"some option","statusCode":"100","statusMessage":"cm handle id(s) not found"},{"operationId":"operational-14","ids":["non-ready-cm-handle"],"resourceIdentifier":"some resource identifier","options":"some option","statusCode":"101","statusMessage":"cm handle(s) not ready"},{"operationId":"running-12","ids":["non-ready-cm-handle"],"resourceIdentifier":"some resource identifier","options":"some option","statusCode":"101","statusMessage":"cm handle(s) not ready"}] \ No newline at end of file