From: Joseph Keenan Date: Tue, 21 Jun 2022 09:30:08 +0000 (+0000) Subject: Merge "Publish LCM Events" X-Git-Tag: 3.1.0~97 X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=affb95e48d7bf80a2062eb8228b816846a99f977;hp=bb751bac8610645758d8f315087e79904b94c370;p=cps.git Merge "Publish LCM Events" --- diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java index f8cab4f1c..2c7d92ef4 100755 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java @@ -31,6 +31,7 @@ import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NO_TIMES import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum; import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED; import static org.onap.cps.utils.CmHandleQueryRestParametersValidator.validateCmHandleQueryParameters; +import static org.onap.ncmp.cmhandle.lcm.event.Event.Operation.DELETE; import java.util.ArrayList; import java.util.Collection; @@ -46,6 +47,7 @@ import org.onap.cps.api.CpsDataService; import org.onap.cps.api.CpsModuleService; import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService; import org.onap.cps.ncmp.api.NetworkCmProxyDataService; +import org.onap.cps.ncmp.api.impl.event.NcmpEventsService; import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations; import org.onap.cps.ncmp.api.impl.operations.DmiOperations; import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; @@ -93,6 +95,8 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService private final NetworkCmProxyCmHandlerQueryService networkCmProxyCmHandlerQueryService; + private final NcmpEventsService ncmpEventsService; + @Override public DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule( final DmiPluginRegistration dmiPluginRegistration) { @@ -261,6 +265,8 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService cpsDataService.deleteListOrListElement(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, "/dmi-registry/cm-handles[@id='" + cmHandle + "']", NO_TIMESTAMP); cmHandleRegistrationResponses.add(CmHandleRegistrationResponse.createSuccessResponse(cmHandle)); + log.debug("Publishing LCM Delete Event for cmHandleId : {}", cmHandle); + ncmpEventsService.publishNcmpEvent(cmHandle, DELETE); } catch (final DataNodeNotFoundException dataNodeNotFoundException) { log.error("Unable to find dataNode for cmHandleId : {} , caused by : {}", cmHandle, dataNodeNotFoundException.getMessage()); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java index aae2f209a..1eef4c25f 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java @@ -27,6 +27,7 @@ import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NCMP_DAT import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NCMP_DMI_REGISTRY_ANCHOR; import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NCMP_DMI_REGISTRY_PARENT; import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NO_TIMESTAMP; +import static org.onap.ncmp.cmhandle.lcm.event.Event.Operation.UPDATE; import com.google.common.collect.ImmutableMap; import java.util.ArrayList; @@ -40,6 +41,7 @@ import java.util.regex.Pattern; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.CpsDataService; +import org.onap.cps.ncmp.api.impl.event.NcmpEventsService; import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse; import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; @@ -62,6 +64,8 @@ public class NetworkCmProxyDataServicePropertyHandler { private final CpsDataService cpsDataService; + private final NcmpEventsService ncmpEventsService; + /** * Iterates over incoming ncmpServiceCmHandles and update the dataNodes based on the updated attributes. * The attributes which are not passed will remain as is. @@ -105,6 +109,7 @@ public class NetworkCmProxyDataServicePropertyHandler { private void processUpdates(final DataNode existingCmHandleDataNode, final NcmpServiceCmHandle incomingCmHandle) { if (!incomingCmHandle.getPublicProperties().isEmpty()) { updateProperties(existingCmHandleDataNode, PUBLIC_PROPERTY, incomingCmHandle.getPublicProperties()); + publishLcmEventOnPublicPropertiesUpdate(incomingCmHandle.getCmHandleId()); } if (!incomingCmHandle.getDmiProperties().isEmpty()) { updateProperties(existingCmHandleDataNode, DMI_PROPERTY, incomingCmHandle.getDmiProperties()); @@ -180,6 +185,11 @@ public class NetworkCmProxyDataServicePropertyHandler { return new DataNodeBuilder().withXpath(xpath).withLeaves(ImmutableMap.copyOf(updatedLeaves)).build(); } + private void publishLcmEventOnPublicPropertiesUpdate(final String cmHandleId) { + log.debug("Publishing LCM Update event for cmHandleId : {}", cmHandleId); + ncmpEventsService.publishNcmpEvent(cmHandleId, UPDATE); + } + enum PropertyType { DMI_PROPERTY("additional-properties"), PUBLIC_PROPERTY("public-properties"); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsCreator.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsCreator.java index 609306f08..3fca1bae8 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsCreator.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsCreator.java @@ -20,7 +20,6 @@ package org.onap.cps.ncmp.api.impl.event; -import static org.onap.ncmp.cmhandle.lcm.event.Event.CmhandleState.READY; import static org.onap.ncmp.cmhandle.lcm.event.Event.Operation.DELETE; import java.time.ZonedDateTime; @@ -70,7 +69,8 @@ public class NcmpEventsCreator { event.setCmHandleId(eventCorrelationId); if (!DELETE.equals(operation)) { - event.setCmhandleState(READY); + event.setCmhandleState(Event.CmhandleState.fromValue( + ncmpServiceCmHandle.getCompositeState().getCmHandleState().toString())); event.setCmhandleProperties(List.of(ncmpServiceCmHandle.getPublicProperties())); } return event; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsService.java index 045a67a10..3cd4068a9 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsService.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsService.java @@ -56,8 +56,11 @@ public class NcmpEventsService { */ public void publishNcmpEvent(final String cmHandleId, final Operation operation) { - final NcmpServiceCmHandle ncmpServiceCmHandle = YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle( - inventoryPersistence.getYangModelCmHandle(cmHandleId)); + NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle(); + if (Operation.DELETE != operation) { + ncmpServiceCmHandle = YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle( + inventoryPersistence.getYangModelCmHandle(cmHandleId)); + } final NcmpEvent ncmpEvent = ncmpEventsCreator.populateNcmpEvent(cmHandleId, operation, ncmpServiceCmHandle); ncmpEventsPublisher.publishEvent(topicName, cmHandleId, ncmpEvent); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdog.java index dbc7dd4f2..d6aaa32be 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdog.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdog.java @@ -21,9 +21,12 @@ package org.onap.cps.ncmp.api.inventory.sync; +import static org.onap.ncmp.cmhandle.lcm.event.Event.Operation.CREATE; + import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.impl.event.NcmpEventsService; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; import org.onap.cps.ncmp.api.inventory.CmHandleState; import org.onap.cps.ncmp.api.inventory.CompositeState; @@ -44,8 +47,11 @@ public class ModuleSyncWatchdog { private final ModuleSyncService moduleSyncService; + private final NcmpEventsService ncmpEventsService; + /** * Execute Cm Handle poll which changes the cm handle state from 'ADVISED' to 'READY'. + * Also publish the LCM Create Event when cm handle state is moved to 'READY'. */ @Scheduled(fixedDelayString = "${timers.advised-modules-sync.sleep-time-ms:30000}") public void executeAdvisedCmHandlePoll() { @@ -66,6 +72,10 @@ public class ModuleSyncWatchdog { inventoryPersistence.saveCmHandleState(cmHandleId, compositeState); log.info("{} is now in {} state", cmHandleId, advisedCmHandle.getCompositeState().getCmHandleState()); + if (compositeState.getCmHandleState() == CmHandleState.READY) { + log.debug("Publishing LCM Create Event for cmHandleId : {}", cmHandleId); + ncmpEventsService.publishNcmpEvent(cmHandleId, CREATE); + } advisedCmHandle = syncUtils.getAnAdvisedCmHandle(); } log.debug("No Cm-Handles currently found in an ADVISED state"); diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy index e9d02dfc7..8a45e6697 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy @@ -23,6 +23,7 @@ package org.onap.cps.ncmp.api.impl import com.fasterxml.jackson.databind.ObjectMapper import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService +import org.onap.cps.ncmp.api.impl.event.NcmpEventsService import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle import org.onap.cps.api.CpsAdminService import org.onap.cps.api.CpsDataService @@ -66,6 +67,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { def mockInventoryPersistence = Mock(InventoryPersistence) def mockModuleSyncService = Mock(ModuleSyncService) def stubbedNetworkCmProxyCmHandlerQueryService = Stub(NetworkCmProxyCmHandlerQueryService) + def mockNcmpEventsService = Mock(NcmpEventsService) def noTimestamp = null def objectUnderTest = getObjectUnderTest() @@ -350,6 +352,6 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { def getObjectUnderTest() { return Spy(new NetworkCmProxyDataServiceImpl(mockCpsDataService, spiedJsonObjectMapper, mockDmiDataOperations, mockCpsModuleService, mockCpsAdminService, mockNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, - mockModuleSyncService, stubbedNetworkCmProxyCmHandlerQueryService)) + mockModuleSyncService, stubbedNetworkCmProxyCmHandlerQueryService, mockNcmpEventsService)) } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy index d58fe6a7c..783fabb1d 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy @@ -23,6 +23,7 @@ package org.onap.cps.ncmp.api.impl import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService +import org.onap.cps.ncmp.api.impl.event.NcmpEventsService import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle import org.onap.cps.ncmp.api.inventory.CmHandleState import org.onap.cps.ncmp.api.inventory.CompositeState @@ -66,6 +67,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { def mockModuleSyncService = Mock(ModuleSyncService) def mockDmiPluginRegistration = Mock(DmiPluginRegistration) def mockCpsCmHandlerQueryService = Mock(NetworkCmProxyCmHandlerQueryService) + def mockNcmpEventsService = Mock(NcmpEventsService) def NO_TOPIC = null def NO_REQUEST_ID = null @@ -76,7 +78,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { def objectUnderTest = new NetworkCmProxyDataServiceImpl(mockCpsDataService, spiedJsonObjectMapper, mockDmiDataOperations, mockCpsModuleService, mockCpsAdminService, nullNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, - mockModuleSyncService, mockCpsCmHandlerQueryService) + mockModuleSyncService, mockCpsCmHandlerQueryService, mockNcmpEventsService) def cmHandleXPath = "/dmi-registry/cm-handles[@id='testCmHandle']" diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy index 5eba5eecd..0cf04a9ff 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy @@ -21,12 +21,14 @@ package org.onap.cps.ncmp.api.impl +import org.onap.cps.ncmp.api.impl.event.NcmpEventsService import org.onap.cps.spi.exceptions.DataValidationException import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.CM_HANDLE_DOES_NOT_EXIST import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.CM_HANDLE_INVALID_ID import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.UNKNOWN_ERROR import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.Status +import static org.onap.ncmp.cmhandle.lcm.event.Event.Operation.UPDATE import org.onap.cps.api.CpsDataService import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle @@ -39,8 +41,9 @@ import spock.lang.Specification class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification { def mockCpsDataService = Mock(CpsDataService) + def mockNcmpEventsService = Mock(NcmpEventsService) - def objectUnderTest = new NetworkCmProxyDataServicePropertyHandler(mockCpsDataService) + def objectUnderTest = new NetworkCmProxyDataServicePropertyHandler(mockCpsDataService, mockNcmpEventsService) def dataspaceName = 'NCMP-Admin' def anchorName = 'ncmp-dmi-registry' def static cmHandleId = 'myHandle1' @@ -67,6 +70,8 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification { assert args[3].leaves.containsAll(convertToProperties(expectedPropertiesAfterUpdate)) } } + and: 'ncmp event is published' + 1 * mockNcmpEventsService.publishNcmpEvent(cmHandleId, UPDATE) where: 'following public properties updates are made' scenario | updatedPublicProperties || expectedPropertiesAfterUpdate 'property added' | ['newPubProp1': 'pub-val'] || [['publicProp3': 'publicValue3'], ['publicProp4': 'publicValue4'], ['newPubProp1': 'pub-val']] @@ -89,6 +94,8 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification { assert args[3].leaves.containsAll(convertToProperties(expectedPropertiesAfterUpdate)) } } + and: 'ncmp event is not published on dmi properties update' + 0 * mockNcmpEventsService.publishNcmpEvent(_, _) where: 'following DMI properties updates are made' scenario | updatedDmiProperties || expectedPropertiesAfterUpdate | expectedCallsToReplaceMethod 'property added' | ['newAdditionalProp1': 'add-value'] || [['additionalProp1': 'additionalValue1'], ['additionalProp2': 'additionalValue2'], ['newAdditionalProp1': 'add-value']] | 1 @@ -114,6 +121,8 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification { assert arg[2].contains("@name='publicProp") } } + and: 'ncmp event is published with updated public properties' + 1 * mockNcmpEventsService.publishNcmpEvent(cmHandleId, UPDATE) where: 'following public properties updates are made' scenario | originalPropertyDataNodes || expectedCallsToDeleteDataNode '2 original properties, both removed' | propertyDataNodes || 2 @@ -136,6 +145,8 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification { assert it.registrationError == expectedError assert it.errorText == expectedErrorText } + and: 'ncmp event is not published' + 0 * mockNcmpEventsService.publishNcmpEvent(_, _) where: scenario | cmHandleId | exception || expectedError | expectedErrorText 'Cm Handle does not exist' | 'cmHandleId' | new DataNodeNotFoundException('NCMP-Admin', 'ncmp-dmi-registry') || CM_HANDLE_DOES_NOT_EXIST | 'cm-handle does not exist' @@ -171,7 +182,9 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification { assert it.errorText == "cm-handle does not exist" } then: 'the replace list method is called twice' - 2 * mockCpsDataService.replaceListContent(*_) + 2 * mockCpsDataService.replaceListContent(dataspaceName, anchorName, cmHandleXpath, _, noTimeStamp) + and: 'the ncmp event is published' + 2 * mockNcmpEventsService.publishNcmpEvent(cmHandleId, UPDATE) } def convertToProperties(expectedPropertiesAfterUpdateAsMap) { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncSpec.groovy index 544f739c0..802035c72 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncSpec.groovy @@ -21,6 +21,9 @@ package org.onap.cps.ncmp.api.inventory.sync +import static org.onap.ncmp.cmhandle.lcm.event.Event.Operation.CREATE + +import org.onap.cps.ncmp.api.impl.event.NcmpEventsService import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle import org.onap.cps.ncmp.api.inventory.CmHandleState import org.onap.cps.ncmp.api.inventory.CompositeState @@ -37,9 +40,11 @@ class ModuleSyncSpec extends Specification { def mockModuleSyncService = Mock(ModuleSyncService) + def mockNcmpEventsService = Mock(NcmpEventsService) + def cmHandleState = CmHandleState.ADVISED - def objectUnderTest = new ModuleSyncWatchdog(mockInventoryPersistence, mockSyncUtils, mockModuleSyncService) + def objectUnderTest = new ModuleSyncWatchdog(mockInventoryPersistence, mockSyncUtils, mockModuleSyncService, mockNcmpEventsService) def 'Schedule a Cm-Handle Sync for ADVISED Cm-Handles'() { given: 'cm handles in an advised state' @@ -67,6 +72,9 @@ class ModuleSyncSpec extends Specification { assert compositeState2.getCmHandleState() == CmHandleState.READY and: 'the second cm handle state is updated' 1 * mockInventoryPersistence.saveCmHandleState('some-cm-handle-2', compositeState2) + and: 'the ncmp event will be published for both cmHandles' + 1 * mockNcmpEventsService.publishNcmpEvent('some-cm-handle', CREATE) + 1 * mockNcmpEventsService.publishNcmpEvent('some-cm-handle-2', CREATE) } def 'Schedule a Cm-Handle Sync for ADVISED Cm-Handle with failure'() { @@ -87,6 +95,8 @@ class ModuleSyncSpec extends Specification { 1 * mockSyncUtils.updateLockReasonDetailsAndAttempts(compositeState, LockReasonCategory.LOCKED_MISBEHAVING ,'some exception') and: 'the cm handle state is updated' 1 * mockInventoryPersistence.saveCmHandleState('some-cm-handle', compositeState) + and: 'the ncmp event is not published' + 0 * mockNcmpEventsService.publishNcmpEvent(_, _) }