From a6fa6c368f04c85bf553fce2cf89d25ec366116e Mon Sep 17 00:00:00 2001 From: mpriyank Date: Mon, 11 Jul 2022 12:15:55 +0100 Subject: Code Refactoring Ncmp* to Lcm* as per new scope - Refactored code to reflect the LcmEvents scope now. - Test cases updated and dependencies reviewed. - You can find few occurences of NcmpEvent for now but that will be cleaned up once we implement CPS-1104 which is for LcmEvent schema - UPCOMING: LcmEvent schema and then the code to publish the events on cmHandleStates - LATER : LcmEvents based on public properties update. Issue-ID: CPS-1137 Change-Id: I9f395ed733b4028e706205894c36a38412e3452e Signed-off-by: mpriyank --- .../api/impl/NetworkCmProxyDataServiceImpl.java | 4 +- .../impl/event/NcmpEventsCmHandleStateHandler.java | 39 ------- .../event/NcmpEventsCmHandleStateHandlerImpl.java | 106 ------------------ .../cps/ncmp/api/impl/event/NcmpEventsCreator.java | 79 ------------- .../ncmp/api/impl/event/NcmpEventsPublisher.java | 67 ----------- .../cps/ncmp/api/impl/event/NcmpEventsService.java | 59 ---------- .../event/lcm/LcmEventsCmHandleStateHandler.java | 39 +++++++ .../lcm/LcmEventsCmHandleStateHandlerImpl.java | 102 +++++++++++++++++ .../ncmp/api/impl/event/lcm/LcmEventsCreator.java | 79 +++++++++++++ .../api/impl/event/lcm/LcmEventsPublisher.java | 67 +++++++++++ .../ncmp/api/impl/event/lcm/LcmEventsService.java | 59 ++++++++++ .../ncmp/api/inventory/InventoryPersistence.java | 10 +- ...rkCmProxyDataServiceImplRegistrationSpec.groovy | 15 ++- .../impl/NetworkCmProxyDataServiceImplSpec.groovy | 10 +- .../NcmpEventsCmHandleStateHandlerImplSpec.groovy | 122 --------------------- .../api/impl/event/NcmpEventsCreatorSpec.groovy | 46 -------- .../api/impl/event/NcmpEventsPublisherSpec.groovy | 84 -------------- .../api/impl/event/NcmpEventsServiceSpec.groovy | 49 --------- .../LcmEventsCmHandleStateHandlerImplSpec.groovy | 120 ++++++++++++++++++++ .../api/impl/event/lcm/LcmEventsCreatorSpec.groovy | 47 ++++++++ .../impl/event/lcm/LcmEventsPublisherSpec.groovy | 85 ++++++++++++++ .../api/impl/event/lcm/LcmEventsServiceSpec.groovy | 48 ++++++++ .../api/inventory/InventoryPersistenceSpec.groovy | 14 ++- 23 files changed, 679 insertions(+), 671 deletions(-) delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsCmHandleStateHandler.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsCmHandleStateHandlerImpl.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsCreator.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsPublisher.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsService.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandler.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandlerImpl.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCreator.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsPublisher.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsService.java delete mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsCmHandleStateHandlerImplSpec.groovy delete mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsCreatorSpec.groovy delete mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsPublisherSpec.groovy delete mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsServiceSpec.groovy create mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy create mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCreatorSpec.groovy create mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsPublisherSpec.groovy create mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsServiceSpec.groovy (limited to 'cps-ncmp-service/src') 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 d827d465c0..16b9a66f4e 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 @@ -290,9 +290,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService private CmHandleRegistrationResponse registerNewCmHandle(final YangModelCmHandle yangModelCmHandle) { try { - final String cmHandleJsonData = String.format("{\"cm-handles\":[%s]}", - jsonObjectMapper.asJsonString(yangModelCmHandle)); - inventoryPersistence.saveListElements(cmHandleJsonData); + inventoryPersistence.saveCmHandle(yangModelCmHandle); return CmHandleRegistrationResponse.createSuccessResponse(yangModelCmHandle.getId()); } catch (final AlreadyDefinedException alreadyDefinedException) { return CmHandleRegistrationResponse.createFailureResponse( diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsCmHandleStateHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsCmHandleStateHandler.java deleted file mode 100644 index 7728b5f92d..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsCmHandleStateHandler.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.event; - -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CmHandleState; - -/** - * The implementation of it should handle the persisting of composite state and delegate the request to publish the - * corresponding ncmp event. - */ -public interface NcmpEventsCmHandleStateHandler { - - /** - * Updates the composite state of cmHandle based on cmHandleState. - * - * @param yangModelCmHandle cm handle represented as yang model - * @param targetCmHandleState target cm handle state - */ - void updateCmHandleState(final YangModelCmHandle yangModelCmHandle, final CmHandleState targetCmHandleState); -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsCmHandleStateHandlerImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsCmHandleStateHandlerImpl.java deleted file mode 100644 index 26a1c5bab9..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsCmHandleStateHandlerImpl.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.event; - -import static org.onap.cps.ncmp.api.inventory.CmHandleState.ADVISED; -import static org.onap.cps.ncmp.api.inventory.CmHandleState.LOCKED; -import static org.onap.cps.ncmp.api.inventory.CmHandleState.READY; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CmHandleState; -import org.onap.cps.ncmp.api.inventory.CompositeStateUtils; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; -import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; -import org.onap.cps.utils.JsonObjectMapper; -import org.onap.ncmp.cmhandle.lcm.event.NcmpEvent; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -@Slf4j -@Service -@RequiredArgsConstructor -public class NcmpEventsCmHandleStateHandlerImpl implements NcmpEventsCmHandleStateHandler { - - private final InventoryPersistence inventoryPersistence; - private final NcmpEventsCreator ncmpEventsCreator; - private final JsonObjectMapper jsonObjectMapper; - private final NcmpEventsService ncmpEventsService; - - @Value("${data-sync.cache.enabled:false}") - private boolean isGlobalDataSyncCacheEnabled; - - - @Override - public void updateCmHandleState(final YangModelCmHandle yangModelCmHandle, - final CmHandleState targetCmHandleState) { - - if (yangModelCmHandle.getCompositeState().getCmHandleState() == targetCmHandleState) { - log.debug("CmHandle with id : {} already in state : {}", yangModelCmHandle.getId(), targetCmHandleState); - } else { - updateToSpecifiedCmHandleState(yangModelCmHandle, targetCmHandleState); - publishNcmpEvent(yangModelCmHandle); - } - - } - - private void updateToSpecifiedCmHandleState(final YangModelCmHandle yangModelCmHandle, - final CmHandleState targetCmHandleState) { - - if (READY == targetCmHandleState) { - CompositeStateUtils.setCompositeStateToReadyWithInitialDataStoreSyncState(isGlobalDataSyncCacheEnabled) - .accept(yangModelCmHandle.getCompositeState()); - inventoryPersistence.saveCmHandleState(yangModelCmHandle.getId(), yangModelCmHandle.getCompositeState()); - } else if (ADVISED == targetCmHandleState) { - if (yangModelCmHandle.getCompositeState().getCmHandleState() == LOCKED) { - retryCmHandle(yangModelCmHandle); - } else { - registerNewCmHandle(yangModelCmHandle); - } - } else { - CompositeStateUtils.setCompositeState(targetCmHandleState).accept(yangModelCmHandle.getCompositeState()); - inventoryPersistence.saveCmHandleState(yangModelCmHandle.getId(), yangModelCmHandle.getCompositeState()); - } - - } - - private void retryCmHandle(final YangModelCmHandle yangModelCmHandle) { - CompositeStateUtils.setCompositeStateForRetry() - .accept(yangModelCmHandle.getCompositeState()); - inventoryPersistence.saveCmHandleState(yangModelCmHandle.getId(), yangModelCmHandle.getCompositeState()); - } - - private void registerNewCmHandle(final YangModelCmHandle yangModelCmHandle) { - CompositeStateUtils.setCompositeState(ADVISED).accept(yangModelCmHandle.getCompositeState()); - inventoryPersistence.saveListElements( - String.format("{\"cm-handles\":[%s]}", jsonObjectMapper.asJsonString(yangModelCmHandle))); - } - - private void publishNcmpEvent(final YangModelCmHandle yangModelCmHandle) { - final NcmpServiceCmHandle ncmpServiceCmHandle = - YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle(yangModelCmHandle); - final String cmHandleId = ncmpServiceCmHandle.getCmHandleId(); - final NcmpEvent ncmpEvent = ncmpEventsCreator.populateNcmpEvent(cmHandleId, ncmpServiceCmHandle); - ncmpEventsService.publishNcmpEvent(cmHandleId, ncmpEvent); - } -} 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 deleted file mode 100644 index df41eba8bd..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsCreator.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.event; - -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.List; -import java.util.UUID; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; -import org.onap.ncmp.cmhandle.lcm.event.Event; -import org.onap.ncmp.cmhandle.lcm.event.NcmpEvent; -import org.springframework.stereotype.Component; - - -/** - * NcmpEventsCreator to create NcmpEvent based on relevant operation. - */ -@Slf4j -@Component -public class NcmpEventsCreator { - - - /** - * Populate NcmpEvent. - * - * @param cmHandleId Cm Handle Identifier - * @param ncmpServiceCmHandle Ncmp CmHandle Data - * @return Populated NcmpEvent - */ - public NcmpEvent populateNcmpEvent(final String cmHandleId, final NcmpServiceCmHandle ncmpServiceCmHandle) { - return createNcmpEvent(cmHandleId, ncmpServiceCmHandle); - } - - private NcmpEvent createNcmpEvent(final String cmHandleId, final NcmpServiceCmHandle ncmpServiceCmHandle) { - final NcmpEvent ncmpEvent = ncmpEventHeader(cmHandleId); - ncmpEvent.setEvent(ncmpEventPayload(cmHandleId, ncmpServiceCmHandle)); - return ncmpEvent; - } - - private Event ncmpEventPayload(final String eventCorrelationId, final NcmpServiceCmHandle ncmpServiceCmHandle) { - final Event event = new Event(); - event.setCmHandleId(eventCorrelationId); - event.setCmhandleState( - Event.CmhandleState.fromValue(ncmpServiceCmHandle.getCompositeState().getCmHandleState().toString())); - event.setCmhandleProperties(List.of(ncmpServiceCmHandle.getPublicProperties())); - return event; - } - - private NcmpEvent ncmpEventHeader(final String eventCorrelationId) { - final NcmpEvent ncmpEvent = new NcmpEvent(); - ncmpEvent.setEventId(UUID.randomUUID().toString()); - ncmpEvent.setEventCorrelationId(eventCorrelationId); - ncmpEvent.setEventTime(ZonedDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"))); - ncmpEvent.setEventSource("org.onap.ncmp"); - ncmpEvent.setEventType("org.onap.ncmp.cmhandle-lcm-event"); - ncmpEvent.setEventSchema("org.onap.ncmp:cmhandle-lcm-event:v1"); - return ncmpEvent; - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsPublisher.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsPublisher.java deleted file mode 100644 index 52ac4685e2..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsPublisher.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.event; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.ncmp.cmhandle.lcm.event.NcmpEvent; -import org.springframework.kafka.core.KafkaTemplate; -import org.springframework.kafka.support.SendResult; -import org.springframework.stereotype.Service; -import org.springframework.util.concurrent.ListenableFuture; -import org.springframework.util.concurrent.ListenableFutureCallback; - -/** - * NcmpEventsPublisher to publish the NcmpEvents on event of CREATE, UPDATE and DELETE. - */ - -@Slf4j -@Service -@RequiredArgsConstructor -public class NcmpEventsPublisher { - - private final KafkaTemplate ncmpEventKafkaTemplate; - - /** - * NCMP Event publisher. - * - * @param topicName valid topic name - * @param eventKey message key - * @param ncmpEvent message payload - */ - public void publishEvent(final String topicName, final String eventKey, final NcmpEvent ncmpEvent) { - final ListenableFuture> ncmpEventFuture = - ncmpEventKafkaTemplate.send(topicName, eventKey, ncmpEvent); - - ncmpEventFuture.addCallback(new ListenableFutureCallback<>() { - @Override - public void onFailure(final Throwable throwable) { - log.error("Unable to publish event to topic : {} due to {}", topicName, throwable.getMessage()); - } - - @Override - public void onSuccess(final SendResult result) { - log.debug("Successfully published event to topic : {} , NcmpEvent : {}", - result.getRecordMetadata().topic(), result.getProducerRecord().value()); - } - }); - } -} 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 deleted file mode 100644 index 5e02e0d94f..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/NcmpEventsService.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.event; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.ncmp.cmhandle.lcm.event.NcmpEvent; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -/** - * NcmpEventService to call the publisher and publish on the dedicated topic. - */ - -@Slf4j -@Service -@RequiredArgsConstructor -public class NcmpEventsService { - - private final NcmpEventsPublisher ncmpEventsPublisher; - - @Value("${app.ncmp.events.topic:ncmp-events}") - private String topicName; - - @Value("${notification.enabled:true}") - private boolean notificationsEnabled; - - /** - * Publish the NcmpEvent to the public topic. - * - * @param cmHandleId Cm Handle Id - * @param ncmpEvent Ncmp Event - */ - public void publishNcmpEvent(final String cmHandleId, final NcmpEvent ncmpEvent) { - if (notificationsEnabled) { - ncmpEventsPublisher.publishEvent(topicName, cmHandleId, ncmpEvent); - } else { - log.debug("Notifications disabled."); - } - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandler.java new file mode 100644 index 0000000000..8cab19405e --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandler.java @@ -0,0 +1,39 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 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.event.lcm; + +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; +import org.onap.cps.ncmp.api.inventory.CmHandleState; + +/** + * The implementation of it should handle the persisting of composite state and delegate the request to publish the + * corresponding lcm event. + */ +public interface LcmEventsCmHandleStateHandler { + + /** + * Updates the composite state of cmHandle based on cmHandleState. + * + * @param yangModelCmHandle cm handle represented as yang model + * @param targetCmHandleState target cm handle state + */ + void updateCmHandleState(final YangModelCmHandle yangModelCmHandle, final CmHandleState targetCmHandleState); +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandlerImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandlerImpl.java new file mode 100644 index 0000000000..111d5dcd58 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandlerImpl.java @@ -0,0 +1,102 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 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.event.lcm; + +import static org.onap.cps.ncmp.api.inventory.CmHandleState.ADVISED; +import static org.onap.cps.ncmp.api.inventory.CmHandleState.LOCKED; +import static org.onap.cps.ncmp.api.inventory.CmHandleState.READY; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; +import org.onap.cps.ncmp.api.inventory.CmHandleState; +import org.onap.cps.ncmp.api.inventory.CompositeStateUtils; +import org.onap.cps.ncmp.api.inventory.InventoryPersistence; +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; +import org.onap.ncmp.cmhandle.lcm.event.NcmpEvent; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class LcmEventsCmHandleStateHandlerImpl implements LcmEventsCmHandleStateHandler { + + private final InventoryPersistence inventoryPersistence; + private final LcmEventsCreator lcmEventsCreator; + private final LcmEventsService lcmEventsService; + + @Value("${data-sync.cache.enabled:false}") + private boolean isGlobalDataSyncCacheEnabled; + + + @Override + public void updateCmHandleState(final YangModelCmHandle yangModelCmHandle, + final CmHandleState targetCmHandleState) { + + if (yangModelCmHandle.getCompositeState().getCmHandleState() == targetCmHandleState) { + log.debug("CmHandle with id : {} already in state : {}", yangModelCmHandle.getId(), targetCmHandleState); + } else { + updateToSpecifiedCmHandleState(yangModelCmHandle, targetCmHandleState); + publishLcmEvent(yangModelCmHandle); + } + + } + + private void updateToSpecifiedCmHandleState(final YangModelCmHandle yangModelCmHandle, + final CmHandleState targetCmHandleState) { + + if (READY == targetCmHandleState) { + CompositeStateUtils.setCompositeStateToReadyWithInitialDataStoreSyncState(isGlobalDataSyncCacheEnabled) + .accept(yangModelCmHandle.getCompositeState()); + inventoryPersistence.saveCmHandleState(yangModelCmHandle.getId(), yangModelCmHandle.getCompositeState()); + } else if (ADVISED == targetCmHandleState) { + if (yangModelCmHandle.getCompositeState().getCmHandleState() == LOCKED) { + retryCmHandle(yangModelCmHandle); + } else { + registerNewCmHandle(yangModelCmHandle); + } + } else { + CompositeStateUtils.setCompositeState(targetCmHandleState).accept(yangModelCmHandle.getCompositeState()); + inventoryPersistence.saveCmHandleState(yangModelCmHandle.getId(), yangModelCmHandle.getCompositeState()); + } + + } + + private void retryCmHandle(final YangModelCmHandle yangModelCmHandle) { + CompositeStateUtils.setCompositeStateForRetry().accept(yangModelCmHandle.getCompositeState()); + inventoryPersistence.saveCmHandleState(yangModelCmHandle.getId(), yangModelCmHandle.getCompositeState()); + } + + private void registerNewCmHandle(final YangModelCmHandle yangModelCmHandle) { + CompositeStateUtils.setCompositeState(ADVISED).accept(yangModelCmHandle.getCompositeState()); + inventoryPersistence.saveCmHandle(yangModelCmHandle); + } + + private void publishLcmEvent(final YangModelCmHandle yangModelCmHandle) { + final NcmpServiceCmHandle ncmpServiceCmHandle = + YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle(yangModelCmHandle); + final String cmHandleId = ncmpServiceCmHandle.getCmHandleId(); + final NcmpEvent ncmpEvent = lcmEventsCreator.populateLcmEvent(cmHandleId, ncmpServiceCmHandle); + lcmEventsService.publishLcmEvent(cmHandleId, ncmpEvent); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCreator.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCreator.java new file mode 100644 index 0000000000..783b299511 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCreator.java @@ -0,0 +1,79 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 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.event.lcm; + +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.UUID; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; +import org.onap.ncmp.cmhandle.lcm.event.Event; +import org.onap.ncmp.cmhandle.lcm.event.NcmpEvent; +import org.springframework.stereotype.Component; + + +/** + * LcmEventsCreator to create LcmEvent based on relevant operation. + */ +@Slf4j +@Component +public class LcmEventsCreator { + + + /** + * Populate NcmpEvent. + * + * @param cmHandleId Cm Handle Identifier + * @param ncmpServiceCmHandle Ncmp CmHandle Data + * @return Populated NcmpEvent + */ + public NcmpEvent populateLcmEvent(final String cmHandleId, final NcmpServiceCmHandle ncmpServiceCmHandle) { + return createLcmEvent(cmHandleId, ncmpServiceCmHandle); + } + + private NcmpEvent createLcmEvent(final String cmHandleId, final NcmpServiceCmHandle ncmpServiceCmHandle) { + final NcmpEvent ncmpEvent = lcmEventHeader(cmHandleId); + ncmpEvent.setEvent(lcmEventPayload(cmHandleId, ncmpServiceCmHandle)); + return ncmpEvent; + } + + private Event lcmEventPayload(final String eventCorrelationId, final NcmpServiceCmHandle ncmpServiceCmHandle) { + final Event event = new Event(); + event.setCmHandleId(eventCorrelationId); + event.setCmhandleState( + Event.CmhandleState.fromValue(ncmpServiceCmHandle.getCompositeState().getCmHandleState().toString())); + event.setCmhandleProperties(List.of(ncmpServiceCmHandle.getPublicProperties())); + return event; + } + + private NcmpEvent lcmEventHeader(final String eventCorrelationId) { + final NcmpEvent ncmpEvent = new NcmpEvent(); + ncmpEvent.setEventId(UUID.randomUUID().toString()); + ncmpEvent.setEventCorrelationId(eventCorrelationId); + ncmpEvent.setEventTime(ZonedDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"))); + ncmpEvent.setEventSource("org.onap.ncmp"); + ncmpEvent.setEventType("org.onap.ncmp.cmhandle-lcm-event"); + ncmpEvent.setEventSchema("org.onap.ncmp:cmhandle-lcm-event:v1"); + return ncmpEvent; + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsPublisher.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsPublisher.java new file mode 100644 index 0000000000..2a946b1008 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsPublisher.java @@ -0,0 +1,67 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 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.event.lcm; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.ncmp.cmhandle.lcm.event.NcmpEvent; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.kafka.support.SendResult; +import org.springframework.stereotype.Service; +import org.springframework.util.concurrent.ListenableFuture; +import org.springframework.util.concurrent.ListenableFutureCallback; + +/** + * LcmEventsPublisher to publish the LcmEvents on event of CREATE, UPDATE and DELETE. + */ + +@Slf4j +@Service +@RequiredArgsConstructor +public class LcmEventsPublisher { + + private final KafkaTemplate lcmEventKafkaTemplate; + + /** + * LCM Event publisher. + * + * @param topicName valid topic name + * @param eventKey message key + * @param ncmpEvent message payload + */ + public void publishEvent(final String topicName, final String eventKey, final NcmpEvent ncmpEvent) { + final ListenableFuture> lcmEventFuture = + lcmEventKafkaTemplate.send(topicName, eventKey, ncmpEvent); + + lcmEventFuture.addCallback(new ListenableFutureCallback<>() { + @Override + public void onFailure(final Throwable throwable) { + log.error("Unable to publish event to topic : {} due to {}", topicName, throwable.getMessage()); + } + + @Override + public void onSuccess(final SendResult result) { + log.debug("Successfully published event to topic : {} , NcmpEvent : {}", + result.getRecordMetadata().topic(), result.getProducerRecord().value()); + } + }); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsService.java new file mode 100644 index 0000000000..d9c9b9a1ce --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsService.java @@ -0,0 +1,59 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 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.event.lcm; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.ncmp.cmhandle.lcm.event.NcmpEvent; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +/** + * NcmpEventService to call the publisher and publish on the dedicated topic. + */ + +@Slf4j +@Service +@RequiredArgsConstructor +public class LcmEventsService { + + private final LcmEventsPublisher lcmEventsPublisher; + + @Value("${app.lcm.events.topic:ncmp-events}") + private String topicName; + + @Value("${notification.enabled:true}") + private boolean notificationsEnabled; + + /** + * Publish the NcmpEvent to the public topic. + * + * @param cmHandleId Cm Handle Id + * @param ncmpEvent Ncmp Event + */ + public void publishLcmEvent(final String cmHandleId, final NcmpEvent ncmpEvent) { + if (notificationsEnabled) { + lcmEventsPublisher.publishEvent(topicName, cmHandleId, ncmpEvent); + } else { + log.debug("Notifications disabled."); + } + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java index af01fb4398..be26a58d58 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java @@ -182,13 +182,15 @@ public class InventoryPersistence { } /** - * Method to save list elements. + * Method to save cmHandle. * - * @param cmHandleJsonData cmHandle JSON data + * @param yangModelCmHandle cmHandle represented as Yang Model */ - public void saveListElements(final String cmHandleJsonData) { + public void saveCmHandle(final YangModelCmHandle yangModelCmHandle) { + final String cmHandleJsonData = + String.format("{\"cm-handles\":[%s]}", jsonObjectMapper.asJsonString(yangModelCmHandle)); cpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT, - cmHandleJsonData, NO_TIMESTAMP); + cmHandleJsonData, NO_TIMESTAMP); } /** 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 31cf31d777..dccba0be48 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 @@ -26,6 +26,8 @@ import org.onap.cps.api.CpsModuleService import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService import org.onap.cps.ncmp.api.impl.exception.DmiRequestException import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle +import org.onap.cps.ncmp.api.inventory.CmHandleState import org.onap.cps.ncmp.api.inventory.InventoryPersistence import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse import org.onap.cps.ncmp.api.models.DmiPluginRegistration @@ -150,10 +152,13 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { assert it.status == Status.SUCCESS assert it.cmHandle == 'cmhandle' } - and: 'save list elements is invoked once with the expected parameters' - 1 * mockInventoryPersistence.saveListElements(_) >> { + and: 'save cmhandle is invoked once with the expected parameters' + 1 * mockInventoryPersistence.saveCmHandle(_) >> { args -> { - assert args[0].startsWith('{"cm-handles":[{"id":"cmhandle","dmi-service-name":"my-server","state":{"cm-handle-state":"ADVISED","last-update-time":"20') + def result = (args[0] as YangModelCmHandle) + assert result.id == 'cmhandle' + assert result.dmiServiceName == 'my-server' + assert result.compositeState.cmHandleState == CmHandleState.ADVISED } } where: @@ -172,7 +177,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { new NcmpServiceCmHandle(cmHandleId: 'cmhandle2'), new NcmpServiceCmHandle(cmHandleId: 'cmhandle3')]) and: 'cm-handle creation is successful for 1st and 3rd; failed for 2nd' - mockInventoryPersistence.saveListElements(_) >> {} >> { throw new RuntimeException("Failed") } >> {} + mockInventoryPersistence.saveCmHandle(_) >> {} >> { throw new RuntimeException("Failed") } >> {} when: 'registration is updated to create cm-handles' def response = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration) then: 'a response is received for all cm-handles' @@ -200,7 +205,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server') dmiPluginRegistration.createdCmHandles = [new NcmpServiceCmHandle(cmHandleId: cmHandleId)] and: 'cm-handler registration fails: #scenario' - mockInventoryPersistence.saveListElements(_) >> { throw exception } + mockInventoryPersistence.saveCmHandle(_) >> { throw exception } when: 'registration is updated' def response = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration) then: 'a failure response is received' 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 1c8b561141..3febaa51bd 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 @@ -69,7 +69,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { @Shared def OPTIONS_PARAM = '(a=1,b=2)' @Shared - def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'some-cm-handle-id') + def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'test-cm-handle-id') def objectUnderTest = new NetworkCmProxyDataServiceImpl(spiedJsonObjectMapper, mockDmiDataOperations, nullNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, mockCpsCmHandlerQueryService) @@ -270,10 +270,12 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { mockDmiPluginRegistration.getCreatedCmHandles() >> [ncmpServiceCmHandle] when: 'parse and create cm handle in dmi registration then sync module' objectUnderTest.parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(mockDmiPluginRegistration) - then: 'validate params for creating anchor and list elements' - 1 * mockInventoryPersistence.saveListElements(_) >> { + then: 'system persists the cm handle state' + 1 * mockInventoryPersistence.saveCmHandle(_) >> { args -> { - assert args[0].startsWith('{"cm-handles":[{"id":"some-cm-handle-id","state":{"cm-handle-state":"ADVISED","last-update-time":"20') + def result = (args[0] as YangModelCmHandle) + assert result.id == 'test-cm-handle-id' + assert result.compositeState.cmHandleState == CmHandleState.ADVISED } } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsCmHandleStateHandlerImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsCmHandleStateHandlerImplSpec.groovy deleted file mode 100644 index f2e730d3a3..0000000000 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsCmHandleStateHandlerImplSpec.groovy +++ /dev/null @@ -1,122 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.event - -import com.fasterxml.jackson.databind.ObjectMapper -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle -import org.onap.cps.ncmp.api.inventory.CompositeState -import org.onap.cps.ncmp.api.inventory.DataStoreSyncState -import org.onap.cps.ncmp.api.inventory.InventoryPersistence -import org.onap.cps.utils.JsonObjectMapper -import spock.lang.Specification - -import static org.onap.cps.ncmp.api.inventory.CmHandleState.ADVISED -import static org.onap.cps.ncmp.api.inventory.CmHandleState.LOCKED -import static org.onap.cps.ncmp.api.inventory.CmHandleState.READY -import static org.onap.cps.ncmp.api.inventory.LockReasonCategory.LOCKED_MODULE_SYNC_FAILED - -class NcmpEventsCmHandleStateHandlerImplSpec extends Specification { - - def mockInventoryPersistence = Mock(InventoryPersistence) - def mockNcmpEventsCreator = Mock(NcmpEventsCreator) - def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper())) - def mockNcmpEventsService = Mock(NcmpEventsService) - - def objectUnderTest = new NcmpEventsCmHandleStateHandlerImpl(mockInventoryPersistence, mockNcmpEventsCreator, spiedJsonObjectMapper, mockNcmpEventsService) - - def 'Update and Publish Events on State Change #stateChange'() { - given: 'Cm Handle represented as YangModelCmHandle' - def cmHandleId = 'cmhandle-id-1' - def compositeState = new CompositeState(cmHandleState: fromCmHandleState) - def yangModelCmHandle = new YangModelCmHandle(id: cmHandleId, dmiProperties: [], publicProperties: [], compositeState: compositeState) - when: 'update state is invoked' - objectUnderTest.updateCmHandleState(yangModelCmHandle, toCmHandleState) - then: 'state is saved using inventory persistence' - expectedCallsToInventoryPersistence * mockInventoryPersistence.saveCmHandleState(cmHandleId, _) - and: 'event service is called to publish event' - expectedCallsToEventService * mockNcmpEventsService.publishNcmpEvent(cmHandleId, _) - where: 'state change parameters are provided' - stateChange | fromCmHandleState | toCmHandleState || expectedCallsToInventoryPersistence | expectedCallsToEventService - 'ADVISED to READY' | ADVISED | READY || 1 | 1 - 'READY to LOCKED' | READY | LOCKED || 1 | 1 - 'ADVISED to ADVISED' | ADVISED | ADVISED || 0 | 0 - 'READY to READY' | READY | READY || 0 | 0 - 'LOCKED to LOCKED' | LOCKED | LOCKED || 0 | 0 - - } - - def 'Update and Publish Events on State Change from NO_EXISTING state to ADVISED'() { - given: 'Cm Handle represented as YangModelCmHandle in READY state' - def cmHandleId = 'cmhandle-id-1' - def compositeState = new CompositeState() - def yangModelCmHandle = new YangModelCmHandle(id: cmHandleId, dmiProperties: [], publicProperties: [], compositeState: compositeState) - when: 'update state is invoked' - objectUnderTest.updateCmHandleState(yangModelCmHandle, ADVISED) - then: 'state is saved using inventory persistence' - 1 * mockInventoryPersistence.saveListElements(_) - and: 'event service is called to publish event' - 1 * mockNcmpEventsService.publishNcmpEvent(cmHandleId, _) - } - - def 'Update and Publish Events on State Change from LOCKED to ADVISED'() { - given: 'Cm Handle represented as YangModelCmHandle in LOCKED state' - def cmHandleId = 'cmhandle-id-1' - def compositeState = new CompositeState(cmHandleState: LOCKED, - lockReason: CompositeState.LockReason.builder().lockReasonCategory(LOCKED_MODULE_SYNC_FAILED).details('some lock details').build()) - def yangModelCmHandle = new YangModelCmHandle(id: cmHandleId, dmiProperties: [], publicProperties: [], compositeState: compositeState) - when: 'update state is invoked' - objectUnderTest.updateCmHandleState(yangModelCmHandle, ADVISED) - then: 'state is saved using inventory persistence and old lock reason details are retained' - 1 * mockInventoryPersistence.saveCmHandleState(cmHandleId, _) >> { - args -> { - assert (args[1] as CompositeState).lockReason.details == 'some lock details' - } - } - and: 'event service is called to publish event' - 1 * mockNcmpEventsService.publishNcmpEvent(cmHandleId, _) - } - - def 'Update and Publish Events on State Change to READY with #scenario'() { - given: 'Cm Handle represented as YangModelCmHandle' - def cmHandleId = 'cmhandle-id-1' - def compositeState = new CompositeState(cmHandleState: ADVISED) - def yangModelCmHandle = new YangModelCmHandle(id: cmHandleId, dmiProperties: [], publicProperties: [], compositeState: compositeState) - and: 'global sync flag is set' - objectUnderTest.isGlobalDataSyncCacheEnabled = dataSyncCacheEnabled - when: 'update cmhandle state is invoked' - objectUnderTest.updateCmHandleState(yangModelCmHandle, READY) - then: 'state is saved using inventory persistence with expected dataSyncState' - 1 * mockInventoryPersistence.saveCmHandleState(cmHandleId, _) >> { - args-> { - assert (args[1] as CompositeState).dataSyncEnabled == dataSyncCacheEnabled - assert (args[1] as CompositeState).dataStores.operationalDataStore.dataStoreSyncState == expectedDataStoreSyncState - - } - } - and: 'event service is called to publish event' - 1 * mockNcmpEventsService.publishNcmpEvent(cmHandleId, _) - where: - scenario | dataSyncCacheEnabled || expectedDataStoreSyncState - 'data sync cache enabled' | true || DataStoreSyncState.UNSYNCHRONIZED - 'data sync cache is not enabled' | false || DataStoreSyncState.NONE_REQUESTED - - } -} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsCreatorSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsCreatorSpec.groovy deleted file mode 100644 index 24362ee47c..0000000000 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsCreatorSpec.groovy +++ /dev/null @@ -1,46 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.event - -import org.onap.cps.ncmp.api.inventory.CmHandleState -import org.onap.cps.ncmp.api.inventory.CompositeStateBuilder -import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle -import spock.lang.Specification - -class NcmpEventsCreatorSpec extends Specification { - - def objectUnderTest = new NcmpEventsCreator() - def cmHandleId = 'test-cm-handle' - - def 'Map the NcmpEvent for operation #operation'() { - given: 'NCMP cm handle details' - def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: cmHandleId, compositeState: new CompositeStateBuilder().withCmHandleState(CmHandleState.READY).build(), - publicProperties: ['publicProperty1': 'value1', 'publicProperty2': 'value2']) - when: 'the event is populated' - def result = objectUnderTest.populateNcmpEvent(cmHandleId, ncmpServiceCmHandle) - then: 'event header is mapped correctly' - assert result.eventSource == 'org.onap.ncmp' - assert result.eventCorrelationId == cmHandleId - and: 'event payload is mapped correctly' - assert result.event.cmhandleProperties.size() == 1 - assert result.event.cmhandleProperties[0] == ['publicProperty1': 'value1', 'publicProperty2': 'value2'] - } -} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsPublisherSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsPublisherSpec.groovy deleted file mode 100644 index fa486d04e0..0000000000 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsPublisherSpec.groovy +++ /dev/null @@ -1,84 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.event - -import com.fasterxml.jackson.databind.ObjectMapper -import org.apache.kafka.clients.consumer.KafkaConsumer -import org.onap.cps.ncmp.api.utils.MessagingSpec -import org.onap.cps.ncmp.utils.TestUtils -import org.onap.cps.utils.JsonObjectMapper -import org.onap.ncmp.cmhandle.lcm.event.Event -import org.onap.ncmp.cmhandle.lcm.event.NcmpEvent -import org.spockframework.spring.SpringBean -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.test.annotation.DirtiesContext -import org.testcontainers.spock.Testcontainers - -import java.time.Duration - -@SpringBootTest(classes = [NcmpEventsPublisher, ObjectMapper, JsonObjectMapper]) -@Testcontainers -@DirtiesContext -class NcmpEventsPublisherSpec extends MessagingSpec { - - def kafkaConsumer = new KafkaConsumer<>(consumerConfigProperties('ncmp-group')) - - def testTopic = 'ncmp-events-test' - - @SpringBean - NcmpEventsPublisher ncmpEventsPublisher = new NcmpEventsPublisher(kafkaTemplate) - - @Autowired - JsonObjectMapper jsonObjectMapper - - - def 'Produce and Consume Ncmp Event'() { - given: 'event key and event data' - def eventKey = 'ncmp' - def eventData = new NcmpEvent(eventId: 'test-uuid', - eventCorrelationId: 'cmhandle-as-correlationid', - eventSchema: URI.create('org.onap.ncmp.cmhandle.lcm.event:v1'), - eventSource: URI.create('org.onap.ncmp'), - eventTime: '2022-12-31T20:30:40.000+0000', - eventType: 'org.onap.ncmp.cmhandle.lcm.event', - event: new Event(cmHandleId: 'cmhandle-test', cmhandleState: 'READY', cmhandleProperties: [['publicProperty1': 'value1'], ['publicProperty2': 'value2']])) - and: 'we have an expected NcmpEvent' - def expectedJsonString = TestUtils.getResourceFileContent('expectedNcmpEvent.json') - def expectedNcmpEvent = jsonObjectMapper.convertJsonString(expectedJsonString, NcmpEvent.class) - and: 'consumer has a subscription' - kafkaConsumer.subscribe([testTopic] as List) - when: 'an event is published' - ncmpEventsPublisher.publishEvent(testTopic, eventKey, eventData) - and: 'topic is polled' - def records = kafkaConsumer.poll(Duration.ofMillis(1500)) - then: 'no exception is thrown' - noExceptionThrown() - and: 'poll returns one record' - assert records.size() == 1 - and: 'record key matches the expected event key' - def record = records.iterator().next() - assert eventKey == record.key - and: 'record matches the expected event' - assert expectedNcmpEvent == jsonObjectMapper.convertJsonString(record.value, NcmpEvent.class) - - } -} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsServiceSpec.groovy deleted file mode 100644 index 8bf02c11c2..0000000000 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsServiceSpec.groovy +++ /dev/null @@ -1,49 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.event - - -import org.onap.ncmp.cmhandle.lcm.event.NcmpEvent -import spock.lang.Specification - -class NcmpEventsServiceSpec extends Specification { - - def mockNcmpEventsPublisher = Mock(NcmpEventsPublisher) - - def objectUnderTest = new NcmpEventsService(mockNcmpEventsPublisher) - - def 'Create and Publish ncmp event where events are #scenario'() { - given: 'a cm handle id and Ncmp Event' - def cmHandleId = 'test-cm-handle-id' - def ncmpEvent = new NcmpEvent(eventId: UUID.randomUUID().toString(), eventCorrelationId: cmHandleId) - and: 'notifications enabled is #notificationsEnabled' - objectUnderTest.notificationsEnabled = notificationsEnabled - when: 'service is called to publish ncmp event' - objectUnderTest.publishNcmpEvent('test-cm-handle-id', ncmpEvent) - then: 'publisher is called #expectedTimesMethodCalled times' - expectedTimesMethodCalled * mockNcmpEventsPublisher.publishEvent(_, cmHandleId, ncmpEvent) - where: 'the following values are used' - scenario | notificationsEnabled || expectedTimesMethodCalled - 'enabled' | true || 1 - 'disabled' | false || 0 - } - -} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy new file mode 100644 index 0000000000..7a4bde07ac --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy @@ -0,0 +1,120 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 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.event.lcm + +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle +import org.onap.cps.ncmp.api.inventory.CompositeState +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState +import org.onap.cps.ncmp.api.inventory.InventoryPersistence +import spock.lang.Specification + +import static org.onap.cps.ncmp.api.inventory.CmHandleState.ADVISED +import static org.onap.cps.ncmp.api.inventory.CmHandleState.LOCKED +import static org.onap.cps.ncmp.api.inventory.CmHandleState.READY +import static org.onap.cps.ncmp.api.inventory.LockReasonCategory.LOCKED_MODULE_SYNC_FAILED + +class LcmEventsCmHandleStateHandlerImplSpec extends Specification { + + def mockInventoryPersistence = Mock(InventoryPersistence) + def mockLcmEventsCreator = Mock(LcmEventsCreator) + def mockLcmEventsService = Mock(LcmEventsService) + + def objectUnderTest = new LcmEventsCmHandleStateHandlerImpl(mockInventoryPersistence, mockLcmEventsCreator, mockLcmEventsService) + + def 'Update and Publish Events on State Change #stateChange'() { + given: 'Cm Handle represented as YangModelCmHandle' + def cmHandleId = 'cmhandle-id-1' + def compositeState = new CompositeState(cmHandleState: fromCmHandleState) + def yangModelCmHandle = new YangModelCmHandle(id: cmHandleId, dmiProperties: [], publicProperties: [], compositeState: compositeState) + when: 'update state is invoked' + objectUnderTest.updateCmHandleState(yangModelCmHandle, toCmHandleState) + then: 'state is saved using inventory persistence' + expectedCallsToInventoryPersistence * mockInventoryPersistence.saveCmHandleState(cmHandleId, _) + and: 'event service is called to publish event' + expectedCallsToEventService * mockLcmEventsService.publishLcmEvent(cmHandleId, _) + where: 'state change parameters are provided' + stateChange | fromCmHandleState | toCmHandleState || expectedCallsToInventoryPersistence | expectedCallsToEventService + 'ADVISED to READY' | ADVISED | READY || 1 | 1 + 'READY to LOCKED' | READY | LOCKED || 1 | 1 + 'ADVISED to ADVISED' | ADVISED | ADVISED || 0 | 0 + 'READY to READY' | READY | READY || 0 | 0 + 'LOCKED to LOCKED' | LOCKED | LOCKED || 0 | 0 + + } + + def 'Update and Publish Events on State Change from NO_EXISTING state to ADVISED'() { + given: 'Cm Handle represented as YangModelCmHandle in READY state' + def cmHandleId = 'cmhandle-id-1' + def compositeState = new CompositeState() + def yangModelCmHandle = new YangModelCmHandle(id: cmHandleId, dmiProperties: [], publicProperties: [], compositeState: compositeState) + when: 'update state is invoked' + objectUnderTest.updateCmHandleState(yangModelCmHandle, ADVISED) + then: 'state is saved using inventory persistence' + 1 * mockInventoryPersistence.saveCmHandle(yangModelCmHandle) + and: 'event service is called to publish event' + 1 * mockLcmEventsService.publishLcmEvent(cmHandleId, _) + } + + def 'Update and Publish Events on State Change from LOCKED to ADVISED'() { + given: 'Cm Handle represented as YangModelCmHandle in LOCKED state' + def cmHandleId = 'cmhandle-id-1' + def compositeState = new CompositeState(cmHandleState: LOCKED, + lockReason: CompositeState.LockReason.builder().lockReasonCategory(LOCKED_MODULE_SYNC_FAILED).details('some lock details').build()) + def yangModelCmHandle = new YangModelCmHandle(id: cmHandleId, dmiProperties: [], publicProperties: [], compositeState: compositeState) + when: 'update state is invoked' + objectUnderTest.updateCmHandleState(yangModelCmHandle, ADVISED) + then: 'state is saved using inventory persistence and old lock reason details are retained' + 1 * mockInventoryPersistence.saveCmHandleState(cmHandleId, _) >> { + args -> { + assert (args[1] as CompositeState).lockReason.details == 'some lock details' + } + } + and: 'event service is called to publish event' + 1 * mockLcmEventsService.publishLcmEvent(cmHandleId, _) + } + + def 'Update and Publish Events on State Change to READY with #scenario'() { + given: 'Cm Handle represented as YangModelCmHandle' + def cmHandleId = 'cmhandle-id-1' + def compositeState = new CompositeState(cmHandleState: ADVISED) + def yangModelCmHandle = new YangModelCmHandle(id: cmHandleId, dmiProperties: [], publicProperties: [], compositeState: compositeState) + and: 'global sync flag is set' + objectUnderTest.isGlobalDataSyncCacheEnabled = dataSyncCacheEnabled + when: 'update cmhandle state is invoked' + objectUnderTest.updateCmHandleState(yangModelCmHandle, READY) + then: 'state is saved using inventory persistence with expected dataSyncState' + 1 * mockInventoryPersistence.saveCmHandleState(cmHandleId, _) >> { + args-> { + def result = (args[1] as CompositeState) + assert result.dataSyncEnabled == dataSyncCacheEnabled + assert result.dataStores.operationalDataStore.dataStoreSyncState == expectedDataStoreSyncState + + } + } + and: 'event service is called to publish event' + 1 * mockLcmEventsService.publishLcmEvent(cmHandleId, _) + where: + scenario | dataSyncCacheEnabled || expectedDataStoreSyncState + 'data sync cache enabled' | true || DataStoreSyncState.UNSYNCHRONIZED + 'data sync cache is not enabled' | false || DataStoreSyncState.NONE_REQUESTED + + } +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCreatorSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCreatorSpec.groovy new file mode 100644 index 0000000000..b578700a21 --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCreatorSpec.groovy @@ -0,0 +1,47 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 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.event.lcm + +import org.onap.cps.ncmp.api.impl.event.lcm.LcmEventsCreator +import org.onap.cps.ncmp.api.inventory.CmHandleState +import org.onap.cps.ncmp.api.inventory.CompositeStateBuilder +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle +import spock.lang.Specification + +class LcmEventsCreatorSpec extends Specification { + + def objectUnderTest = new LcmEventsCreator() + def cmHandleId = 'test-cm-handle' + + def 'Map the LcmEvent for operation #operation'() { + given: 'NCMP cm handle details' + def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: cmHandleId, compositeState: new CompositeStateBuilder().withCmHandleState(CmHandleState.READY).build(), + publicProperties: ['publicProperty1': 'value1', 'publicProperty2': 'value2']) + when: 'the event is populated' + def result = objectUnderTest.populateLcmEvent(cmHandleId, ncmpServiceCmHandle) + then: 'event header is mapped correctly' + assert result.eventSource == 'org.onap.ncmp' + assert result.eventCorrelationId == cmHandleId + and: 'event payload is mapped correctly' + assert result.event.cmhandleProperties.size() == 1 + assert result.event.cmhandleProperties[0] == ['publicProperty1': 'value1', 'publicProperty2': 'value2'] + } +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsPublisherSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsPublisherSpec.groovy new file mode 100644 index 0000000000..8b9addc119 --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsPublisherSpec.groovy @@ -0,0 +1,85 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 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.event.lcm + +import com.fasterxml.jackson.databind.ObjectMapper +import org.apache.kafka.clients.consumer.KafkaConsumer +import org.onap.cps.ncmp.api.impl.event.lcm.LcmEventsPublisher +import org.onap.cps.ncmp.api.utils.MessagingSpec +import org.onap.cps.ncmp.utils.TestUtils +import org.onap.cps.utils.JsonObjectMapper +import org.onap.ncmp.cmhandle.lcm.event.Event +import org.onap.ncmp.cmhandle.lcm.event.NcmpEvent +import org.spockframework.spring.SpringBean +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.annotation.DirtiesContext +import org.testcontainers.spock.Testcontainers + +import java.time.Duration + +@SpringBootTest(classes = [LcmEventsPublisher, ObjectMapper, JsonObjectMapper]) +@Testcontainers +@DirtiesContext +class LcmEventsPublisherSpec extends MessagingSpec { + + def kafkaConsumer = new KafkaConsumer<>(consumerConfigProperties('ncmp-group')) + + def testTopic = 'ncmp-events-test' + + @SpringBean + LcmEventsPublisher ncmpEventsPublisher = new LcmEventsPublisher(kafkaTemplate) + + @Autowired + JsonObjectMapper jsonObjectMapper + + + def 'Produce and Consume Ncmp Event'() { + given: 'event key and event data' + def eventKey = 'ncmp' + def eventData = new NcmpEvent(eventId: 'test-uuid', + eventCorrelationId: 'cmhandle-as-correlationid', + eventSchema: URI.create('org.onap.ncmp.cmhandle.lcm.event:v1'), + eventSource: URI.create('org.onap.ncmp'), + eventTime: '2022-12-31T20:30:40.000+0000', + eventType: 'org.onap.ncmp.cmhandle.lcm.event', + event: new Event(cmHandleId: 'cmhandle-test', cmhandleState: 'READY', cmhandleProperties: [['publicProperty1': 'value1'], ['publicProperty2': 'value2']])) + and: 'we have an expected NcmpEvent' + def expectedJsonString = TestUtils.getResourceFileContent('expectedNcmpEvent.json') + def expectedNcmpEvent = jsonObjectMapper.convertJsonString(expectedJsonString, NcmpEvent.class) + and: 'consumer has a subscription' + kafkaConsumer.subscribe([testTopic] as List) + when: 'an event is published' + ncmpEventsPublisher.publishEvent(testTopic, eventKey, eventData) + and: 'topic is polled' + def records = kafkaConsumer.poll(Duration.ofMillis(1500)) + then: 'no exception is thrown' + noExceptionThrown() + and: 'poll returns one record' + assert records.size() == 1 + and: 'record key matches the expected event key' + def record = records.iterator().next() + assert eventKey == record.key + and: 'record matches the expected event' + assert expectedNcmpEvent == jsonObjectMapper.convertJsonString(record.value, NcmpEvent.class) + + } +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsServiceSpec.groovy new file mode 100644 index 0000000000..3dab5aff17 --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsServiceSpec.groovy @@ -0,0 +1,48 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 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.event.lcm + +import org.onap.ncmp.cmhandle.lcm.event.NcmpEvent +import spock.lang.Specification + +class LcmEventsServiceSpec extends Specification { + + def mockLcmEventsPublisher = Mock(LcmEventsPublisher) + + def objectUnderTest = new LcmEventsService(mockLcmEventsPublisher) + + def 'Create and Publish lcm event where events are #scenario'() { + given: 'a cm handle id and Ncmp Event' + def cmHandleId = 'test-cm-handle-id' + def ncmpEvent = new NcmpEvent(eventId: UUID.randomUUID().toString(), eventCorrelationId: cmHandleId) + and: 'notifications enabled is #notificationsEnabled' + objectUnderTest.notificationsEnabled = notificationsEnabled + when: 'service is called to publish lcm event' + objectUnderTest.publishLcmEvent('test-cm-handle-id', ncmpEvent) + then: 'publisher is called #expectedTimesMethodCalled times' + expectedTimesMethodCalled * mockLcmEventsPublisher.publishEvent(_, cmHandleId, ncmpEvent) + where: 'the following values are used' + scenario | notificationsEnabled || expectedTimesMethodCalled + 'enabled' | true || 1 + 'disabled' | false || 0 + } + +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceSpec.groovy index 50494c0c37..7ac231c169 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceSpec.groovy @@ -227,11 +227,17 @@ class InventoryPersistenceSpec extends Specification { assert result == moduleReferences } - def 'Save list elements'() { - when: 'the method to save list elements is called' - objectUnderTest.saveListElements('sample Json data') + def 'Save Cmhandle'() { + given: 'cmHandle represented as Yang Model' + def yangModelCmHandle = new YangModelCmHandle(id: 'cmhandle', dmiProperties: [], publicProperties: []) + when: 'the method to save cmhandle is called' + objectUnderTest.saveCmHandle(yangModelCmHandle) then: 'the data service method to save list elements is called once' - 1 * mockCpsDataService.saveListElements('NCMP-Admin','ncmp-dmi-registry','/dmi-registry','sample Json data',null) + 1 * mockCpsDataService.saveListElements('NCMP-Admin','ncmp-dmi-registry','/dmi-registry',_,null) >> { + args -> { + assert args[3].startsWith('{"cm-handles":[{"id":"cmhandle","additional-properties":[],"public-properties":[]}]}') + } + } } def 'Delete list or list elements'() { -- cgit 1.2.3-korg