From: rameshiyer27 Date: Wed, 6 Aug 2025 13:56:33 +0000 (+0100) Subject: Fix issue in Migration remove elements X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;p=policy%2Fclamp.git Fix issue in Migration remove elements Problem: If the only element associated with a participant is removed in migration, Acmr ignores the participant Id in the migrate event. Issue-ID: POLICY-5438 Signed-off-by: rameshiyer27 Change-Id: Ib44efb9d62185b38153896277185f26ad1b71307 --- diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/utils/AcmUtils.java b/models/src/main/java/org/onap/policy/clamp/models/acm/utils/AcmUtils.java index 5bcac7e3b..cb9961305 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/utils/AcmUtils.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/utils/AcmUtils.java @@ -429,7 +429,7 @@ public final class AcmUtils { * @param deployOrder the DeployOrder */ public static List createParticipantDeployList(AutomationComposition automationComposition, - DeployOrder deployOrder) { + DeployOrder deployOrder, List removedElements) { Map> map = new HashMap<>(); for (var element : automationComposition.getElements().values()) { var acElementDeploy = createAcElementDeploy(element, deployOrder); @@ -443,6 +443,16 @@ public final class AcmUtils { participantDeploy.setAcElementList(entry.getValue()); participantDeploys.add(participantDeploy); } + // Include the participantIds for the removed elements + for (var element : removedElements) { + if (map.get(element.getParticipantId()) == null) { + var participantDeploy = new ParticipantDeploy(); + participantDeploy.setParticipantId(element.getParticipantId()); + participantDeploys.add(participantDeploy); + map.put(element.getParticipantId(), new ArrayList<>()); + } + + } return participantDeploys; } diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/utils/AcmUtilsTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/utils/AcmUtilsTest.java index fb0f683ac..f7f379ecd 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/utils/AcmUtilsTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/utils/AcmUtilsTest.java @@ -41,6 +41,7 @@ import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement; import org.onap.policy.clamp.models.acm.concepts.DeployState; import org.onap.policy.clamp.models.acm.concepts.LockState; +import org.onap.policy.clamp.models.acm.concepts.ParticipantDeploy; import org.onap.policy.clamp.models.acm.concepts.SubState; import org.onap.policy.clamp.models.acm.document.concepts.DocToscaServiceTemplate; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder; @@ -212,7 +213,7 @@ class AcmUtilsTest { @Test void testCreateAcElementDeployList() { var automationComposition = getDummyAutomationComposition(); - var result = AcmUtils.createParticipantDeployList(automationComposition, DeployOrder.DEPLOY); + var result = AcmUtils.createParticipantDeployList(automationComposition, DeployOrder.DEPLOY, List.of()); assertThat(result).hasSameSizeAs(automationComposition.getElements().values()); for (var participantDeploy : result) { for (var element : participantDeploy.getAcElementList()) { @@ -221,6 +222,26 @@ class AcmUtilsTest { } } + @Test + void testAcDeployListWithRemovedElements() { + var removedElement1 = CommonTestData.getJsonObject( + "src/test/resources/json/AutomationCompositionElementNoOrderedState.json", + AutomationCompositionElement.class); + var participantId1 = UUID.randomUUID(); + var participantId2 = UUID.randomUUID(); + assert removedElement1 != null; + removedElement1.setParticipantId(participantId1); + var removedElement2 = new AutomationCompositionElement(removedElement1); + removedElement2.setParticipantId(participantId2); + + var automationComposition = getDummyAutomationComposition(); + var result = AcmUtils.createParticipantDeployList(automationComposition, DeployOrder.DEPLOY, + List.of(removedElement1, removedElement2)); + assertThat(result).hasSize(automationComposition.getElements().values().size() + 2); + var participantIds = result.stream().map(ParticipantDeploy::getParticipantId).toList(); + assertThat(participantIds).containsAll(List.of(participantId1, participantId2)); + } + @Test void testCreateAcElementRestart() { var element = getDummyAutomationComposition().getElements().values().iterator().next(); diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java index 9a79549c7..c6190153a 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java @@ -51,14 +51,12 @@ import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvide import org.onap.policy.clamp.models.acm.persistence.provider.AcInstanceStateResolver; import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider; import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider; -import org.onap.policy.clamp.models.acm.persistence.provider.ProviderUtils; import org.onap.policy.clamp.models.acm.utils.AcmUtils; import org.onap.policy.common.parameters.BeanValidationResult; import org.onap.policy.models.base.PfModelRuntimeException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -232,10 +230,13 @@ public class AutomationCompositionInstantiationProvider { encryptInstanceProperties(acToBeUpdated, acToBeUpdated.getCompositionTargetId()); var ac = automationCompositionProvider.updateAutomationComposition(acToBeUpdated); - elementsRemoved.forEach(automationCompositionProvider::deleteAutomationCompositionElement); + for (var element : elementsRemoved) { + automationCompositionProvider.deleteAutomationCompositionElement(element.getId()); + } // Publish migrate event to the participants - supervisionAcHandler.migrate(acToPublish, acDefinition.getRevisionId(), acDefinitionTarget.getRevisionId()); + supervisionAcHandler.migrate(acToPublish, acDefinition.getRevisionId(), acDefinitionTarget.getRevisionId(), + elementsRemoved); return createInstantiationResponse(ac); } @@ -252,9 +253,10 @@ public class AutomationCompositionInstantiationProvider { acToBeUpdated.setStateChangeResult(StateChangeResult.NO_ERROR); } - private List getElementRemoved(AutomationComposition acFromDb, AutomationComposition acFromMigration) { - return acFromDb.getElements().keySet().stream() - .filter(id -> acFromMigration.getElements().get(id) == null).toList(); + private List getElementRemoved(AutomationComposition acFromDb, + AutomationComposition acFromMigration) { + return acFromDb.getElements().values().stream() + .filter(element -> acFromMigration.getElements().get(element.getId()) == null).toList(); } @@ -267,10 +269,11 @@ public class AutomationCompositionInstantiationProvider { var acDefinitionTarget = acDefinitionProvider.getAcDefinition(automationComposition.getCompositionTargetId()); AcDefinitionProvider.checkPrimedComposition(acDefinitionTarget); // Iterate and update the element property values - updateElementsProperties(automationComposition, copyAc, acDefinitionTarget); + var removedElements = updateElementsProperties(automationComposition, copyAc, acDefinitionTarget); // Publish migrate event to the participants - supervisionAcHandler.migratePrecheck(copyAc, acDefinition.getRevisionId(), acDefinitionTarget.getRevisionId()); + supervisionAcHandler.migratePrecheck(copyAc, acDefinition.getRevisionId(), acDefinitionTarget.getRevisionId(), + removedElements); AcmUtils.setCascadedState(acToBeUpdated, DeployState.DEPLOYED, LockState.LOCKED, SubState.MIGRATION_PRECHECKING); @@ -458,12 +461,15 @@ public class AutomationCompositionInstantiationProvider { updateAcForMigration(acToBeUpdated, acDefinitionTarget, DeployState.MIGRATION_REVERTING); var elementsRemoved = getElementRemoved(automationComposition, acToBeUpdated); automationCompositionProvider.updateAutomationComposition(acToBeUpdated); - elementsRemoved.forEach(automationCompositionProvider::deleteAutomationCompositionElement); + for (var element : elementsRemoved) { + automationCompositionProvider.deleteAutomationCompositionElement(element.getId()); + } var acDefinition = acDefinitionProvider.getAcDefinition(acToBeUpdated.getCompositionId()); - supervisionAcHandler.migrate(acToBeUpdated, acDefinition.getRevisionId(), acDefinitionTarget.getRevisionId()); + supervisionAcHandler.migrate(acToBeUpdated, acDefinition.getRevisionId(), acDefinitionTarget.getRevisionId(), + elementsRemoved); } - private List updateElementsProperties(AutomationComposition automationComposition, + private List updateElementsProperties(AutomationComposition automationComposition, AutomationComposition acToBeUpdated, AutomationCompositionDefinition acDefinitionTarget) { for (var element : automationComposition.getElements().entrySet()) { var elementId = element.getKey(); @@ -483,7 +489,7 @@ public class AutomationCompositionInstantiationProvider { } // Remove element which is not present in the new Ac instance var elementsRemoved = getElementRemoved(acToBeUpdated, automationComposition); - elementsRemoved.forEach(uuid -> acToBeUpdated.getElements().remove(uuid)); + elementsRemoved.forEach(element -> acToBeUpdated.getElements().remove(element.getId())); var validationResult = validateAutomationComposition(acToBeUpdated, acDefinitionTarget); if (!validationResult.isValid()) { diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandler.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandler.java index 37c386627..9d6529dd2 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandler.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandler.java @@ -23,6 +23,7 @@ package org.onap.policy.clamp.acm.runtime.supervision; import io.micrometer.core.annotation.Timed; import io.opentelemetry.context.Context; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.ExecutorService; @@ -37,6 +38,7 @@ import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionS import org.onap.policy.clamp.models.acm.concepts.AcElementDeployAck; import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement; import org.onap.policy.clamp.models.acm.concepts.DeployState; import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.clamp.models.acm.concepts.ParticipantUtils; @@ -345,11 +347,11 @@ public class SupervisionAcHandler { * @param revisionIdCompositionTarget the last Update from Composition Target */ public void migrate(AutomationComposition automationComposition, UUID revisionIdComposition, - UUID revisionIdCompositionTarget) { + UUID revisionIdCompositionTarget, List removedElements) { executor.execute(() -> { encryptionUtils.decryptInstanceProperties(automationComposition); acCompositionMigrationPublisher.send(automationComposition, automationComposition.getPhase(), - revisionIdComposition, revisionIdCompositionTarget); + revisionIdComposition, revisionIdCompositionTarget, removedElements); }); } @@ -361,8 +363,8 @@ public class SupervisionAcHandler { * @param revisionIdCompositionTarget the last Update from Composition Target */ public void migratePrecheck(AutomationComposition automationComposition, UUID revisionIdComposition, - UUID revisionIdCompositionTarget) { + UUID revisionIdCompositionTarget, List removedElements) { executor.execute(() -> acCompositionMigrationPublisher.send(automationComposition, 0, - revisionIdComposition, revisionIdCompositionTarget)); + revisionIdComposition, revisionIdCompositionTarget, removedElements)); } } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/AcElementPropertiesPublisher.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/AcElementPropertiesPublisher.java index 68a70fa01..3f7704f0b 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/AcElementPropertiesPublisher.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/AcElementPropertiesPublisher.java @@ -22,6 +22,7 @@ package org.onap.policy.clamp.acm.runtime.supervision.comm; import io.micrometer.core.annotation.Timed; import java.time.Instant; +import java.util.List; import java.util.UUID; import java.util.stream.Collectors; import lombok.AllArgsConstructor; @@ -58,7 +59,8 @@ public class AcElementPropertiesPublisher extends AbstractParticipantPublisher

removedElements) { var acMigration = new AutomationCompositionMigration(); acMigration.setRollback(DeployState.MIGRATION_REVERTING.equals(automationComposition.getDeployState())); acMigration.setPrecheck(Boolean.TRUE.equals(automationComposition.getPrecheck())); @@ -59,7 +61,8 @@ public class AutomationCompositionMigrationPublisher acMigration.setRevisionIdInstance(automationComposition.getRevisionId()); acMigration.setRevisionIdComposition(revisionIdComposition); acMigration.setRevisionIdCompositionTarget(revisionIdCompositionTarget); - var participantUpdatesList = AcmUtils.createParticipantDeployList(automationComposition, DeployOrder.MIGRATE); + var participantUpdatesList = AcmUtils.createParticipantDeployList(automationComposition, DeployOrder.MIGRATE, + removedElements); acMigration.setParticipantUpdatesList(participantUpdatesList); acMigration.setParticipantIdList(participantUpdatesList.stream() .map(ParticipantDeploy::getParticipantId).collect(Collectors.toSet())); diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/StageScanner.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/StageScanner.java index 9791d5e52..777130f94 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/StageScanner.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/StageScanner.java @@ -21,6 +21,7 @@ package org.onap.policy.clamp.acm.runtime.supervision.scanner; import java.util.Comparator; +import java.util.List; import java.util.UUID; import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup; import org.onap.policy.clamp.acm.runtime.main.utils.EncryptionUtils; @@ -118,7 +119,7 @@ public class StageScanner extends AbstractScanner { LOGGER.debug("retry message AutomationCompositionMigration"); // acDefinition for migration is the Composition target acMigrationPublisher.send(automationComposition, minStageNotCompleted, revisionIdComposition, - acDefinition.getRevisionId()); + acDefinition.getRevisionId(), List.of()); } if (SubState.PREPARING.equals(automationComposition.getSubState())) { LOGGER.debug("retry message AutomationCompositionPrepare"); diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java index 325f3a902..ee745682f 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java @@ -307,7 +307,7 @@ class AutomationCompositionInstantiationProviderTest { automationCompositionTarget.setPrecheck(true); var preCheckResponse = instantiationProvider.updateAutomationComposition(compositionId, automationCompositionTarget); - verify(supervisionAcHandler).migratePrecheck(any(), any(), any()); + verify(supervisionAcHandler).migratePrecheck(any(), any(), any(), any()); InstantiationUtils.assertInstantiationResponse(preCheckResponse, automationCompositionTarget); automationCompositionTarget.setPrecheck(false); @@ -316,7 +316,7 @@ class AutomationCompositionInstantiationProviderTest { var instantiationResponse = instantiationProvider.updateAutomationComposition(compositionId, automationCompositionTarget); - verify(supervisionAcHandler).migrate(any(), any(), any()); + verify(supervisionAcHandler).migrate(any(), any(), any(), any()); InstantiationUtils.assertInstantiationResponse(instantiationResponse, automationCompositionTarget); } @@ -362,7 +362,7 @@ class AutomationCompositionInstantiationProviderTest { var instantiationResponse = instantiationProvider .updateAutomationComposition(automationComposition.getCompositionId(), automationComposition); - verify(supervisionAcHandler).migrate(any(), any(), any()); + verify(supervisionAcHandler).migrate(any(), any(), any(), any()); verify(acProvider).updateAutomationComposition(automationComposition); InstantiationUtils.assertInstantiationResponse(instantiationResponse, automationComposition); } @@ -401,7 +401,7 @@ class AutomationCompositionInstantiationProviderTest { var instantiationResponse = instantiationProvider .updateAutomationComposition(automationComposition.getCompositionId(), automationComposition); - verify(supervisionAcHandler).migratePrecheck(any(), any(), any()); + verify(supervisionAcHandler).migratePrecheck(any(), any(), any(), any()); verify(acProvider).updateAutomationComposition(automationComposition); InstantiationUtils.assertInstantiationResponse(instantiationResponse, automationComposition); diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandlerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandlerTest.java index d9ffb0abe..b434a0128 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandlerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandlerTest.java @@ -30,6 +30,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_SERVICE_TEMPLATE_YAML; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; @@ -513,9 +514,9 @@ class SupervisionAcHandlerTest { InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Migrate"); assert automationComposition != null; automationComposition.setPhase(0); - handler.migrate(automationComposition, UUID.randomUUID(), UUID.randomUUID()); + handler.migrate(automationComposition, UUID.randomUUID(), UUID.randomUUID(), List.of()); verify(acCompositionMigrationPublisher, timeout(1000)) - .send(any(AutomationComposition.class), anyInt(), any(UUID.class), any(UUID.class)); + .send(any(AutomationComposition.class), anyInt(), any(UUID.class), any(UUID.class), any()); } @Test @@ -528,9 +529,9 @@ class SupervisionAcHandlerTest { mock(AcPreparePublisher.class), mock(MessageProvider.class), mock(EncryptionUtils.class)); var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Migrate"); - handler.migratePrecheck(automationComposition, UUID.randomUUID(), UUID.randomUUID()); + handler.migratePrecheck(automationComposition, UUID.randomUUID(), UUID.randomUUID(), List.of()); verify(acCompositionMigrationPublisher, timeout(1000)) - .send(any(AutomationComposition.class), anyInt(), any(UUID.class), any(UUID.class)); + .send(any(AutomationComposition.class), anyInt(), any(UUID.class), any(UUID.class), any()); } @Test diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/comm/SupervisionMessagesTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/comm/SupervisionMessagesTest.java index 84b80ae56..54c3ded96 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/comm/SupervisionMessagesTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/comm/SupervisionMessagesTest.java @@ -235,7 +235,7 @@ class SupervisionMessagesTest { publisher.active(topicSink); var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Crud"); - publisher.send(automationComposition, 0, UUID.randomUUID(), UUID.randomUUID()); + publisher.send(automationComposition, 0, UUID.randomUUID(), UUID.randomUUID(), List.of()); verify(topicSink).send(anyString()); }