aboutsummaryrefslogtreecommitdiffstats
path: root/cps-service
diff options
context:
space:
mode:
authorRenu Kumari <renu.kumari@bell.ca>2022-01-09 08:38:31 -0500
committerRenu Kumari <renu.kumari@bell.ca>2022-01-11 08:19:58 -0500
commit4bee6edd2dcf1b2ada3a808ae19b003c684025cd (patch)
treefe30aa0f4cfcdfae0c98d1acc200374233c1d12b /cps-service
parent15fffd19b49827184096ae1444b8ca2ed86a5201 (diff)
Send operation information in existing notification events
Issue-ID: CPS-791 Signed-off-by: Renu Kumari <renu.kumari@bell.ca> Change-Id: Ic68dd476942291cf03afed99e95a245dafde5be9
Diffstat (limited to 'cps-service')
-rwxr-xr-xcps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java31
-rw-r--r--cps-service/src/main/java/org/onap/cps/notification/CpsDataUpdatedEventFactory.java14
-rw-r--r--cps-service/src/main/java/org/onap/cps/notification/NotificationService.java20
-rw-r--r--cps-service/src/main/java/org/onap/cps/notification/Operation.java27
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy23
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/notification/CpsDataUpdateEventFactorySpec.groovy10
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy61
7 files changed, 133 insertions, 53 deletions
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
index 1445ccadf..a23bc95f3 100755
--- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
+++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
@@ -1,7 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2021 Nordix Foundation
- * Modifications Copyright (C) 2020-2021 Bell Canada.
+ * Modifications Copyright (C) 2020-2022 Bell Canada.
* Modifications Copyright (C) 2021 Pantheon.tech
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -27,8 +27,8 @@ import java.util.Collection;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.api.CpsAdminService;
import org.onap.cps.api.CpsDataService;
-import org.onap.cps.api.CpsModuleService;
import org.onap.cps.notification.NotificationService;
+import org.onap.cps.notification.Operation;
import org.onap.cps.spi.CpsDataPersistenceService;
import org.onap.cps.spi.FetchDescendantsOption;
import org.onap.cps.spi.exceptions.DataValidationException;
@@ -53,9 +53,6 @@ public class CpsDataServiceImpl implements CpsDataService {
private CpsAdminService cpsAdminService;
@Autowired
- private CpsModuleService cpsModuleService;
-
- @Autowired
private YangTextSchemaSourceSetCache yangTextSchemaSourceSetCache;
@Autowired
@@ -66,7 +63,7 @@ public class CpsDataServiceImpl implements CpsDataService {
final OffsetDateTime observedTimestamp) {
final var dataNode = buildDataNode(dataspaceName, anchorName, ROOT_NODE_XPATH, jsonData);
cpsDataPersistenceService.storeDataNode(dataspaceName, anchorName, dataNode);
- processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp);
+ processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, ROOT_NODE_XPATH, Operation.CREATE);
}
@Override
@@ -74,7 +71,7 @@ public class CpsDataServiceImpl implements CpsDataService {
final String jsonData, final OffsetDateTime observedTimestamp) {
final var dataNode = buildDataNode(dataspaceName, anchorName, parentNodeXpath, jsonData);
cpsDataPersistenceService.addChildDataNode(dataspaceName, anchorName, parentNodeXpath, dataNode);
- processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp);
+ processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.CREATE);
}
@Override
@@ -84,7 +81,7 @@ public class CpsDataServiceImpl implements CpsDataService {
buildDataNodes(dataspaceName, anchorName, parentNodeXpath, jsonData);
cpsDataPersistenceService.addListElements(dataspaceName, anchorName, parentNodeXpath,
listElementDataNodeCollection);
- processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp);
+ processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.UPDATE);
}
@Override
@@ -99,7 +96,7 @@ public class CpsDataServiceImpl implements CpsDataService {
final var dataNode = buildDataNode(dataspaceName, anchorName, parentNodeXpath, jsonData);
cpsDataPersistenceService
.updateDataLeaves(dataspaceName, anchorName, dataNode.getXpath(), dataNode.getLeaves());
- processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp);
+ processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.UPDATE);
}
@Override
@@ -113,7 +110,7 @@ public class CpsDataServiceImpl implements CpsDataService {
for (final DataNode dataNodeUpdate : dataNodeUpdates) {
processDataNodeUpdate(dataspaceName, anchorName, dataNodeUpdate);
}
- processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp);
+ processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.UPDATE);
}
@Override
@@ -121,7 +118,7 @@ public class CpsDataServiceImpl implements CpsDataService {
final String jsonData, final OffsetDateTime observedTimestamp) {
final var dataNode = buildDataNode(dataspaceName, anchorName, parentNodeXpath, jsonData);
cpsDataPersistenceService.replaceDataNodeTree(dataspaceName, anchorName, dataNode);
- processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp);
+ processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.UPDATE);
}
@Override
@@ -130,21 +127,21 @@ public class CpsDataServiceImpl implements CpsDataService {
final Collection<DataNode> newListElements =
buildDataNodes(dataspaceName, anchorName, parentNodeXpath, jsonData);
cpsDataPersistenceService.replaceListContent(dataspaceName, anchorName, parentNodeXpath, newListElements);
- processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp);
+ processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.UPDATE);
}
@Override
public void deleteDataNode(final String dataspaceName, final String anchorName, final String dataNodeXpath,
final OffsetDateTime observedTimestamp) {
cpsDataPersistenceService.deleteDataNode(dataspaceName, anchorName, dataNodeXpath);
- processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp);
+ processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, dataNodeXpath, Operation.DELETE);
}
@Override
public void deleteListOrListElement(final String dataspaceName, final String anchorName, final String listNodeXpath,
final OffsetDateTime observedTimestamp) {
cpsDataPersistenceService.deleteListDataNode(dataspaceName, anchorName, listNodeXpath);
- processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp);
+ processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, listNodeXpath, Operation.DELETE);
}
private DataNode buildDataNode(final String dataspaceName, final String anchorName,
@@ -186,9 +183,10 @@ public class CpsDataServiceImpl implements CpsDataService {
}
private void processDataUpdatedEventAsync(final String dataspaceName, final String anchorName,
- final OffsetDateTime observedTimestamp) {
+ final OffsetDateTime observedTimestamp, final String xpath,
+ final Operation operation) {
try {
- notificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp);
+ notificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, xpath, operation);
} catch (final Exception exception) {
log.error("Failed to send message to notification service", exception);
}
@@ -210,4 +208,5 @@ public class CpsDataServiceImpl implements CpsDataService {
processDataNodeUpdate(dataspaceName, anchorName, childDataNodeUpdate);
}
}
+
}
diff --git a/cps-service/src/main/java/org/onap/cps/notification/CpsDataUpdatedEventFactory.java b/cps-service/src/main/java/org/onap/cps/notification/CpsDataUpdatedEventFactory.java
index 2985ed53b..6054ce5d7 100644
--- a/cps-service/src/main/java/org/onap/cps/notification/CpsDataUpdatedEventFactory.java
+++ b/cps-service/src/main/java/org/onap/cps/notification/CpsDataUpdatedEventFactory.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (c) 2021 Bell Canada.
+ * Copyright (c) 2021-2022 Bell Canada.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -71,20 +71,21 @@ public class CpsDataUpdatedEventFactory {
* @param dataspaceName dataspaceName
* @param anchorName anchorName
* @param observedTimestamp observedTimestamp
+ * @param operation operation
* @return CpsDataUpdatedEvent
*/
public CpsDataUpdatedEvent createCpsDataUpdatedEvent(final String dataspaceName, final String anchorName,
- final OffsetDateTime observedTimestamp) {
+ final OffsetDateTime observedTimestamp, final Operation operation) {
final var dataNode = cpsDataService
.getDataNode(dataspaceName, anchorName, "/", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS);
final var anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
- return toCpsDataUpdatedEvent(anchor, dataNode, observedTimestamp);
+ return toCpsDataUpdatedEvent(anchor, dataNode, observedTimestamp, operation);
}
private CpsDataUpdatedEvent toCpsDataUpdatedEvent(final Anchor anchor, final DataNode dataNode,
- final OffsetDateTime observedTimestamp) {
+ final OffsetDateTime observedTimestamp, final Operation operation) {
final var cpsDataUpdatedEvent = new CpsDataUpdatedEvent();
- cpsDataUpdatedEvent.withContent(createContent(anchor, dataNode, observedTimestamp));
+ cpsDataUpdatedEvent.withContent(createContent(anchor, dataNode, observedTimestamp, operation));
cpsDataUpdatedEvent.withId(UUID.randomUUID().toString());
cpsDataUpdatedEvent.withSchema(EVENT_SCHEMA);
cpsDataUpdatedEvent.withSource(EVENT_SOURCE);
@@ -99,12 +100,13 @@ public class CpsDataUpdatedEventFactory {
}
private Content createContent(final Anchor anchor, final DataNode dataNode,
- final OffsetDateTime observedTimestamp) {
+ final OffsetDateTime observedTimestamp, final Operation operation) {
final var content = new Content();
content.withAnchorName(anchor.getName());
content.withDataspaceName(anchor.getDataspaceName());
content.withSchemaSetName(anchor.getSchemaSetName());
content.withData(createData(dataNode));
+ content.withOperation(Content.Operation.fromValue(operation.name()));
content.withObservedTimestamp(
DATE_TIME_FORMATTER.format(observedTimestamp == null ? OffsetDateTime.now() : observedTimestamp));
return content;
diff --git a/cps-service/src/main/java/org/onap/cps/notification/NotificationService.java b/cps-service/src/main/java/org/onap/cps/notification/NotificationService.java
index 029efbe79..97a14797b 100644
--- a/cps-service/src/main/java/org/onap/cps/notification/NotificationService.java
+++ b/cps-service/src/main/java/org/onap/cps/notification/NotificationService.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (c) 2021 Bell Canada.
+ * Copyright (c) 2021-2022 Bell Canada.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,6 +36,8 @@ import org.springframework.stereotype.Service;
@Slf4j
public class NotificationService {
+ private static final String ROOT_NODE_XPATH = "/";
+
private NotificationProperties notificationProperties;
private NotificationPublisher notificationPublisher;
private CpsDataUpdatedEventFactory cpsDataUpdatedEventFactory;
@@ -78,19 +80,23 @@ public class NotificationService {
/**
* Process Data Updated Event and publishes the notification.
*
- * @param dataspaceName dataspace name
- * @param anchorName anchor name
+ * @param dataspaceName dataspace name
+ * @param anchorName anchor name
* @param observedTimestamp observedTimestamp
+ * @param xpath xpath of changed data node
+ * @param operation operation
* @return future
*/
@Async("notificationExecutor")
public Future<Void> processDataUpdatedEvent(final String dataspaceName, final String anchorName,
- final OffsetDateTime observedTimestamp) {
+ final OffsetDateTime observedTimestamp,
+ final String xpath, final Operation operation) {
log.debug("process data updated event for dataspace '{}' & anchor '{}'", dataspaceName, anchorName);
try {
if (shouldSendNotification(dataspaceName)) {
final var cpsDataUpdatedEvent =
- cpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp);
+ cpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(dataspaceName, anchorName,
+ observedTimestamp, getRootNodeOperation(xpath, operation));
log.debug("data updated event to be published {}", cpsDataUpdatedEvent);
notificationPublisher.sendNotification(cpsDataUpdatedEvent);
}
@@ -114,4 +120,8 @@ public class NotificationService {
.anyMatch(pattern -> pattern.matcher(dataspaceName).find());
}
+ private Operation getRootNodeOperation(final String xpath, final Operation operation) {
+ return ROOT_NODE_XPATH.equals(xpath) ? operation : Operation.UPDATE;
+ }
+
}
diff --git a/cps-service/src/main/java/org/onap/cps/notification/Operation.java b/cps-service/src/main/java/org/onap/cps/notification/Operation.java
new file mode 100644
index 000000000..83e1ccf79
--- /dev/null
+++ b/cps-service/src/main/java/org/onap/cps/notification/Operation.java
@@ -0,0 +1,27 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (c) 2022 Bell Canada.
+ * ================================================================================
+ * 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.notification;
+
+public enum Operation {
+ CREATE,
+ UPDATE,
+ DELETE
+}
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
index ba9c156d7..6c899c793 100644
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* Copyright (C) 2021 Nordix Foundation
* Modifications Copyright (C) 2021 Pantheon.tech
- * Modifications Copyright (C) 2021 Bell Canada.
+ * Modifications Copyright (C) 2021-2022 Bell Canada.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@ import org.onap.cps.TestUtils
import org.onap.cps.api.CpsAdminService
import org.onap.cps.api.CpsModuleService
import org.onap.cps.notification.NotificationService
+import org.onap.cps.notification.Operation
import org.onap.cps.spi.CpsDataPersistenceService
import org.onap.cps.spi.FetchDescendantsOption
import org.onap.cps.spi.exceptions.DataValidationException
@@ -40,7 +41,6 @@ import java.time.OffsetDateTime
class CpsDataServiceImplSpec extends Specification {
def mockCpsDataPersistenceService = Mock(CpsDataPersistenceService)
def mockCpsAdminService = Mock(CpsAdminService)
- def mockCpsModuleService = Mock(CpsModuleService)
def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)
def mockNotificationService = Mock(NotificationService)
@@ -49,7 +49,6 @@ class CpsDataServiceImplSpec extends Specification {
def setup() {
objectUnderTest.cpsDataPersistenceService = mockCpsDataPersistenceService
objectUnderTest.cpsAdminService = mockCpsAdminService
- objectUnderTest.cpsModuleService = mockCpsModuleService
objectUnderTest.yangTextSchemaSourceSetCache = mockYangTextSchemaSourceSetCache
objectUnderTest.notificationService = mockNotificationService
}
@@ -69,7 +68,7 @@ class CpsDataServiceImplSpec extends Specification {
1 * mockCpsDataPersistenceService.storeDataNode(dataspaceName, anchorName,
{ dataNode -> dataNode.xpath == '/test-tree' })
and: 'data updated event is sent to notification service'
- 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp)
+ 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, '/', Operation.CREATE)
}
def 'Saving child data fragment under existing node.'() {
@@ -82,7 +81,7 @@ class CpsDataServiceImplSpec extends Specification {
1 * mockCpsDataPersistenceService.addChildDataNode(dataspaceName, anchorName, '/test-tree',
{ dataNode -> dataNode.xpath == '/test-tree/branch[@name=\'New\']' })
and: 'data updated event is sent to notification service'
- 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp)
+ 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, '/test-tree', Operation.CREATE)
}
def 'Saving list element data fragment under existing node.'() {
@@ -102,7 +101,7 @@ class CpsDataServiceImplSpec extends Specification {
}
)
and: 'data updated event is sent to notification service'
- 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp)
+ 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, '/test-tree', Operation.UPDATE)
}
def 'Saving empty list element data fragment.'() {
@@ -134,7 +133,7 @@ class CpsDataServiceImplSpec extends Specification {
then: 'the persistence service method is invoked with correct parameters'
1 * mockCpsDataPersistenceService.updateDataLeaves(dataspaceName, anchorName, expectedNodeXpath, leaves)
and: 'data updated event is sent to notification service'
- 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp)
+ 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.UPDATE)
where: 'following parameters were used'
scenario | parentNodeXpath | jsonData || expectedNodeXpath | leaves
'top level node' | '/' | '{"test-tree": {"branch": []}}' || '/test-tree' | Collections.emptyMap()
@@ -167,7 +166,7 @@ class CpsDataServiceImplSpec extends Specification {
1 * mockCpsDataPersistenceService.updateDataLeaves(dataspaceName, anchorName,
"/dmi-registry/cm-handles[@id='cmHandle001']", ['id': 'cmHandle001'])
and: 'the data updated event is sent to the notification service'
- 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp)
+ 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, '/dmi-registry', Operation.UPDATE)
}
def 'Replace data node: #scenario.'() {
@@ -179,7 +178,7 @@ class CpsDataServiceImplSpec extends Specification {
1 * mockCpsDataPersistenceService.replaceDataNodeTree(dataspaceName, anchorName,
{ dataNode -> dataNode.xpath == expectedNodeXpath })
and: 'data updated event is sent to notification service'
- 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp)
+ 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.UPDATE)
where: 'following parameters were used'
scenario | parentNodeXpath | jsonData || expectedNodeXpath
'top level node' | '/' | '{"test-tree": {"branch": []}}' || '/test-tree'
@@ -203,7 +202,7 @@ class CpsDataServiceImplSpec extends Specification {
}
)
and: 'data updated event is sent to notification service'
- 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp)
+ 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, '/test-tree', Operation.UPDATE)
}
def 'Replace whole list content with empty list element.'() {
@@ -224,7 +223,7 @@ class CpsDataServiceImplSpec extends Specification {
then: 'the persistence service method is invoked with correct parameters'
1 * mockCpsDataPersistenceService.deleteListDataNode(dataspaceName, anchorName, '/test-tree/branch')
and: 'data updated event is sent to notification service'
- 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp)
+ 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, '/test-tree/branch', Operation.DELETE)
}
def 'Delete data node under anchor and dataspace.'() {
@@ -235,7 +234,7 @@ class CpsDataServiceImplSpec extends Specification {
then: 'the persistence service method is invoked with the correct parameters'
1 * mockCpsDataPersistenceService.deleteDataNode(dataspaceName, anchorName, '/data-node')
and: 'data updated event is sent to notification service'
- 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp)
+ 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, '/data-node', Operation.DELETE)
}
def setupSchemaSetMocks(String... yangResources) {
diff --git a/cps-service/src/test/groovy/org/onap/cps/notification/CpsDataUpdateEventFactorySpec.groovy b/cps-service/src/test/groovy/org/onap/cps/notification/CpsDataUpdateEventFactorySpec.groovy
index aa0c7c0b3..67ed3d90f 100644
--- a/cps-service/src/test/groovy/org/onap/cps/notification/CpsDataUpdateEventFactorySpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/notification/CpsDataUpdateEventFactorySpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (c) 2021 Bell Canada.
+ * Copyright (c) 2021-2022 Bell Canada.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@ import java.time.format.DateTimeFormatter
import org.onap.cps.utils.DateTimeUtility
import org.onap.cps.api.CpsAdminService
import org.onap.cps.api.CpsDataService
+import org.onap.cps.event.model.Content
import org.onap.cps.event.model.Data
import org.onap.cps.spi.FetchDescendantsOption
import org.onap.cps.spi.model.Anchor
@@ -45,7 +46,6 @@ class CpsDataUpdateEventFactorySpec extends Specification {
def dateTimeFormat = 'yyyy-MM-dd\'T\'HH:mm:ss.SSSZ'
def 'Create a CPS data updated event successfully: #scenario'() {
-
given: 'cps admin service is able to return anchor details'
mockCpsAdminService.getAnchor(myDataspaceName, myAnchorName) >>
new Anchor(myAnchorName, myDataspaceName, mySchemasetName)
@@ -54,13 +54,10 @@ class CpsDataUpdateEventFactorySpec extends Specification {
def dataNode = new DataNodeBuilder().withXpath(xpath).withLeaves(['leafName': 'leafValue']).build()
mockCpsDataService.getDataNode(
myDataspaceName, myAnchorName, xpath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
-
when: 'CPS data updated event is created'
def cpsDataUpdatedEvent = objectUnderTest.createCpsDataUpdatedEvent(myDataspaceName,
- myAnchorName, DateTimeUtility.toOffsetDateTime(inputObservedTimestamp))
-
+ myAnchorName, DateTimeUtility.toOffsetDateTime(inputObservedTimestamp), Operation.CREATE)
then: 'CPS data updated event is created with correct envelope'
-
with(cpsDataUpdatedEvent) {
type == 'org.onap.cps.data-updated-event'
source == new URI('urn:cps:org.onap.cps')
@@ -79,6 +76,7 @@ class CpsDataUpdateEventFactorySpec extends Specification {
assert anchorName == myAnchorName
assert dataspaceName == myDataspaceName
assert schemaSetName == mySchemasetName
+ assert operation == Content.Operation.CREATE
assert data == new Data().withAdditionalProperty('leafName', 'leafValue')
}
where:
diff --git a/cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy
index ca704edb4..306e187a0 100644
--- a/cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (c) 2021 Bell Canada.
+ * Copyright (c) 2021-2022 Bell Canada.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -61,7 +61,7 @@ class NotificationServiceSpec extends Specification {
given: 'notification is disabled'
spyNotificationProperties.isEnabled() >> false
when: 'dataUpdatedEvent is received'
- objectUnderTest.processDataUpdatedEvent(myDataspacePublishedName, myAnchorName, myObservedTimestamp)
+ objectUnderTest.processDataUpdatedEvent(myDataspacePublishedName, myAnchorName, myObservedTimestamp, '/', Operation.CREATE)
then: 'the notification is not sent'
0 * mockNotificationPublisher.sendNotification(_)
}
@@ -71,10 +71,12 @@ class NotificationServiceSpec extends Specification {
spyNotificationProperties.isEnabled() >> true
and: 'event factory can create event successfully'
def cpsDataUpdatedEvent = new CpsDataUpdatedEvent()
- mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(dataspaceName, myAnchorName, myObservedTimestamp) >>
- cpsDataUpdatedEvent
+ mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(dataspaceName, myAnchorName, myObservedTimestamp,
+ Operation.CREATE) >>
+ cpsDataUpdatedEvent
when: 'dataUpdatedEvent is received'
- def future = objectUnderTest.processDataUpdatedEvent(dataspaceName, myAnchorName, myObservedTimestamp)
+ def future = objectUnderTest.processDataUpdatedEvent(dataspaceName, myAnchorName, myObservedTimestamp,
+ '/', Operation.CREATE)
and: 'wait for async processing to complete'
future.get(10, TimeUnit.SECONDS)
then: 'async process completed successfully'
@@ -87,14 +89,57 @@ class NotificationServiceSpec extends Specification {
'dataspace name matches filter' | myDataspacePublishedName || 1
}
+ def 'Send UPDATE operation when non-root data nodes are changed.'() {
+ given: 'notification is enabled'
+ spyNotificationProperties.isEnabled() >> true
+ and: 'event factory creates event if operation is UPDATE'
+ def cpsDataUpdatedEvent = new CpsDataUpdatedEvent()
+ mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(myDataspacePublishedName, myAnchorName, myObservedTimestamp,
+ Operation.UPDATE) >> cpsDataUpdatedEvent
+ when: 'dataUpdatedEvent is received for non-root xpath'
+ def future = objectUnderTest.processDataUpdatedEvent(myDataspacePublishedName, myAnchorName, myObservedTimestamp, '/non-root-node',
+ operation)
+ and: 'wait for async processing to complete'
+ future.get(10, TimeUnit.SECONDS)
+ then: 'async process completed successfully'
+ future.isDone()
+ and: 'notification is sent'
+ 1 * mockNotificationPublisher.sendNotification(cpsDataUpdatedEvent)
+ where:
+ operation << [Operation.CREATE, Operation.UPDATE, Operation.DELETE]
+ }
+
+ def 'Send same operation when root nodes are changed.'() {
+ given: 'notification is enabled'
+ spyNotificationProperties.isEnabled() >> true
+ and: 'event factory creates event if operation is #operation'
+ def cpsDataUpdatedEvent = new CpsDataUpdatedEvent()
+ mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(myDataspacePublishedName, myAnchorName, myObservedTimestamp,
+ operation) >> cpsDataUpdatedEvent
+ when: 'dataUpdatedEvent is received for root xpath'
+ def future = objectUnderTest.processDataUpdatedEvent(myDataspacePublishedName, myAnchorName, myObservedTimestamp, '/',
+ operation)
+ and: 'wait for async processing to complete'
+ future.get(10, TimeUnit.SECONDS)
+ then: 'async process completed successfully'
+ future.isDone()
+ and: 'notification is sent'
+ 1 * mockNotificationPublisher.sendNotification(cpsDataUpdatedEvent)
+ where:
+ operation << [Operation.CREATE, Operation.UPDATE, Operation.DELETE]
+ }
+
+
def 'Error handling in notification service.'() {
given: 'notification is enabled'
spyNotificationProperties.isEnabled() >> true
and: 'event factory can not create event successfully'
- mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(myDataspacePublishedName, myAnchorName, myObservedTimestamp) >>
- { throw new Exception("Could not create event") }
+ mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(myDataspacePublishedName, myAnchorName,
+ myObservedTimestamp, Operation.CREATE) >>
+ { throw new Exception("Could not create event") }
when: 'event is sent for processing'
- def future = objectUnderTest.processDataUpdatedEvent(myDataspacePublishedName, myAnchorName, myObservedTimestamp)
+ def future = objectUnderTest.processDataUpdatedEvent(myDataspacePublishedName, myAnchorName,
+ myObservedTimestamp, '/', Operation.CREATE)
and: 'wait for async processing to complete'
future.get(10, TimeUnit.SECONDS)
then: 'async process completed successfully'