From 17f38e127c693095b6bef7f79ce6e9ecb45d67cc Mon Sep 17 00:00:00 2001 From: FrancescoFioraEst Date: Mon, 30 Jun 2025 09:08:59 +0100 Subject: [PATCH] Add rollback for ACM Migration Fix the full rollback flow. Issue-ID: POLICY-5194 Change-Id: Ia2f33f4a585762a06d398b8faae6bfec823f70bd Signed-off-by: FrancescoFioraEst --- .../concepts/AutomationCompositionRollback.java | 1 - .../AutomationCompositionElementHandler.java | 20 ++- .../sim/main/handler/SimulatorService.java | 44 ++++-- .../AutomationCompositionElementHandlerTest.java | 92 +++++++++--- .../api/AutomationCompositionElementListener.java | 22 +-- .../intermediary/api/impl/AcElementListenerV4.java | 7 +- .../handler/AutomationCompositionHandler.java | 161 +++++++++------------ .../intermediary/handler/ThreadHandler.java | 19 ++- .../api/impl/AcElementListenerV3Test.java | 47 +++--- .../handler/AutomationCompositionHandlerTest.java | 2 +- .../intermediary/handler/ThreadHandlerTest.java | 15 +- ...AutomationCompositionInstantiationProvider.java | 3 +- .../src/main/resources/openapi/openapi.yaml | 8 - .../rest/InstantiationControllerTest.java | 67 ++++++--- 14 files changed, 296 insertions(+), 212 deletions(-) diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionRollback.java b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionRollback.java index 988a7d5bf..d2f631914 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionRollback.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionRollback.java @@ -23,7 +23,6 @@ package org.onap.policy.clamp.models.acm.concepts; import java.util.LinkedHashMap; import java.util.Map; import java.util.UUID; -import java.util.function.UnaryOperator; import lombok.Data; import lombok.NoArgsConstructor; import lombok.NonNull; diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandler.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandler.java index 270aa0385..5e03bc4af 100644 --- a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandler.java +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandler.java @@ -159,8 +159,22 @@ public class AutomationCompositionElementHandler extends AcElementListenerV4 { @Override public void rollbackMigration(CompositionElementDto compositionElement, - InstanceElementDto instanceElement, int nextStage) { - LOGGER.debug("rollback call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement); - simulatorService.rollback(instanceElement.instanceId(), instanceElement.elementId()); + CompositionElementDto compositionElementRollback, InstanceElementDto instanceElement, + InstanceElementDto instanceElementRollback, int stage) { + LOGGER.debug("rollback call compositionElement: {}, compositionElementRollback: {}, instanceElement: {}," + + " instanceElementRollback: {}, stage: {}", + compositionElement, compositionElementRollback, instanceElement, instanceElementRollback, stage); + + if (ElementState.NEW.equals(instanceElementRollback.state())) { + LOGGER.debug("new element scenario"); + } + if (ElementState.REMOVED.equals(instanceElementRollback.state())) { + simulatorService.undeploy(instanceElement.instanceId(), instanceElement.elementId(), + instanceElement.outProperties()); + simulatorService.delete(instanceElement.instanceId(), instanceElement.elementId()); + } else { + simulatorService.rollback(instanceElementRollback.instanceId(), instanceElementRollback.elementId(), stage, + compositionElementRollback.inProperties(), instanceElementRollback.outProperties()); + } } } diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/SimulatorService.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/SimulatorService.java index 282d81d1b..20979adbf 100644 --- a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/SimulatorService.java +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/SimulatorService.java @@ -57,7 +57,9 @@ public class SimulatorService { private static final Logger LOGGER = LoggerFactory.getLogger(SimulatorService.class); private static final String INTERNAL_STATE = "InternalState"; private static final String MIGRATION_PROPERTY = "stage"; + private static final String ROLLBACK_PROPERTY = "rollbackStage"; private static final String PREPARE_PROPERTY = "prepareStage"; + private static final String STAGE_MSG = "stage %d %s"; @Getter @Setter @@ -391,7 +393,7 @@ public class SimulatorService { } else { intermediaryApi.updateAutomationCompositionElementStage( instanceId, elementId, - StateChangeResult.NO_ERROR, nextStage, "stage " + stage + " Migrated"); + StateChangeResult.NO_ERROR, nextStage, String.format(STAGE_MSG, stage, "Migrated")); } } else { intermediaryApi.updateAutomationCompositionElementState( @@ -456,7 +458,7 @@ public class SimulatorService { } else { intermediaryApi.updateAutomationCompositionElementStage( instanceId, elementId, - StateChangeResult.NO_ERROR, nextStage, "stage " + stage + " Prepared"); + StateChangeResult.NO_ERROR, nextStage, String.format(STAGE_MSG, stage, "Prepared")); } } else { intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, @@ -488,10 +490,14 @@ public class SimulatorService { /** * Handle rollback of an automation composition. * - * @param instanceId AC instance ID - * @param elementId AC element ID + * @param instanceId the instanceId + * @param elementId the elementId + * @param stage the stage + * @param compositionInProperties in Properties from composition definition element + * @param instanceOutProperties in Properties from instance element */ - public void rollback(UUID instanceId, UUID elementId) { + public void rollback(UUID instanceId, UUID elementId, int stage, Map compositionInProperties, + Map instanceOutProperties) { if (isInterrupted(getConfig().getRollbackTimerMs(), "Current Thread for rollback was Interrupted during execution {}", instanceId)) { LOGGER.debug("Rollback interrupted"); @@ -499,11 +505,31 @@ public class SimulatorService { } if (config.isRollback()) { - intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, DeployState.DEPLOYED, null, - StateChangeResult.NO_ERROR, "Migration rollback done"); + var stageSet = ParticipantUtils.findStageSetMigrate(compositionInProperties); + var nextStage = 1000; + for (var s : stageSet) { + if (s > stage) { + nextStage = Math.min(s, nextStage); + } + } + instanceOutProperties.putIfAbsent(ROLLBACK_PROPERTY, new ArrayList<>()); + @SuppressWarnings("unchecked") + var stageList = (List) instanceOutProperties.get(ROLLBACK_PROPERTY); + stageList.add(stage); + intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, instanceOutProperties); + if (nextStage == 1000) { + intermediaryApi.updateAutomationCompositionElementState( + instanceId, elementId, + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migration rollback done"); + } else { + intermediaryApi.updateAutomationCompositionElementStage( + instanceId, elementId, + StateChangeResult.NO_ERROR, nextStage, String.format(STAGE_MSG, stage, "Migration rollback")); + } } else { - intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, DeployState.DEPLOYED, null, - StateChangeResult.FAILED, "Migration rollback failed"); + intermediaryApi.updateAutomationCompositionElementState( + instanceId, elementId, + DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migration rollback failed"); } } } diff --git a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerTest.java b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerTest.java index baf1b2a9e..4b2ea5668 100644 --- a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerTest.java +++ b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerTest.java @@ -20,15 +20,8 @@ package org.onap.policy.clamp.acm.participant.sim.main.handler; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doCallRealMethod; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.Mockito.withSettings; import java.util.HashMap; import java.util.List; @@ -372,35 +365,88 @@ class AutomationCompositionElementHandlerTest { var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); - - acElementHandler.rollbackMigration(COMPOSITION_ELEMENT, INSTANCE_ELEMENT, DeployState.DEPLOYED.ordinal()); + var compositionElementRollback = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of()); + var instanceElementRollback = new InstanceElementDto( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + Map.of("key", "value"), new HashMap<>()); + acElementHandler.rollbackMigration(COMPOSITION_ELEMENT, compositionElementRollback, INSTANCE_ELEMENT, + instanceElementRollback, 0); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, - null, StateChangeResult.NO_ERROR, "Migration rollback done"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, + null, StateChangeResult.NO_ERROR, "Migration rollback done"); config.setRollback(false); - acElementHandler.rollbackMigration(COMPOSITION_ELEMENT, INSTANCE_ELEMENT, DeployState.DEPLOYED.ordinal()); + acElementHandler.rollbackMigration(COMPOSITION_ELEMENT, compositionElementRollback, INSTANCE_ELEMENT, + instanceElementRollback, 0); verify(intermediaryApi).updateAutomationCompositionElementState( INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migration rollback failed"); } + @Test - void testRollbackTimeout() { + void testRollbackStage() { var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); - var simulatorService = mock(SimulatorService.class, withSettings().useConstructor(intermediaryApi)); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + var compositionElementRollback = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of("stage", List.of(1, 2)), Map.of()); + var instanceElementRollback = new InstanceElementDto(INSTANCE_ELEMENT.instanceId(), + INSTANCE_ELEMENT.elementId(), Map.of(), new HashMap<>()); + acElementHandler.rollbackMigration(COMPOSITION_ELEMENT, compositionElementRollback, INSTANCE_ELEMENT, + instanceElementRollback, 1); + verify(intermediaryApi).updateAutomationCompositionElementStage( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + StateChangeResult.NO_ERROR, 2, "stage 1 Migration rollback"); + } - when(simulatorService.getConfig()).thenReturn(config); - when(simulatorService.isInterrupted(anyInt(), anyString(), any())).thenReturn(true); - doCallRealMethod().when(simulatorService).rollback(INSTANCE_ELEMENT.instanceId(), - INSTANCE_ELEMENT.elementId()); + @Test + void testRollbackAdd() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + var compositionElement = new CompositionElementDto( + UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of(), ElementState.NOT_PRESENT); + var instanceElement = new InstanceElementDto( + UUID.randomUUID(), UUID.randomUUID(), Map.of(), Map.of(), ElementState.NOT_PRESENT); + + var compoElRollbackAdd = new CompositionElementDto( + UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of(), ElementState.NEW); + var inElRollbackAdd = new InstanceElementDto(instanceElement.instanceId(), instanceElement.elementId(), + Map.of(), new HashMap<>(), ElementState.NEW); + acElementHandler + .rollbackMigration(compositionElement, compoElRollbackAdd, instanceElement, inElRollbackAdd, 0); + verify(intermediaryApi).updateAutomationCompositionElementState( + instanceElement.instanceId(), instanceElement.elementId(), + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migration rollback done"); + } + + @Test + void testRollbackRemove() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); - acElementHandler.rollbackMigration(COMPOSITION_ELEMENT, INSTANCE_ELEMENT, DeployState.DEPLOYED.ordinal()); - verify(simulatorService).rollback(INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId()); - verify(intermediaryApi, times(0)).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, - null, StateChangeResult.NO_ERROR, "Migration rollback done"); + simulatorService.setConfig(config); + + var compoElRollbackRemove = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of(), ElementState.REMOVED); + var inElRollbackRemove = new InstanceElementDto( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + Map.of("key", "value"), Map.of(), ElementState.REMOVED); + acElementHandler + .rollbackMigration(COMPOSITION_ELEMENT, compoElRollbackRemove, INSTANCE_ELEMENT, inElRollbackRemove, 0); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed"); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted"); } } diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/AutomationCompositionElementListener.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/AutomationCompositionElementListener.java index 63db854ab..7eccf5084 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/AutomationCompositionElementListener.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/AutomationCompositionElementListener.java @@ -89,10 +89,10 @@ public interface AutomationCompositionElementListener { /** * Handle an update on an automation composition element. * - * @param compositionElement the information of the Automation Composition Definition Element - * @param compositionElementTarget the information of the Automation Composition Definition Element Target - * @param instanceElement the information of the Automation Composition Instance Element - * @param instanceElementMigrate the information of the Automation Composition Instance Element updated + * @param compositionElement the information of the Composition Definition Element + * @param compositionElementTarget the information of the Composition Definition Element Target + * @param instanceElement the information of the Instance Element + * @param instanceElementMigrate the information of the Instance Element updated * @param nextStage the next stage * @throws PfModelException from Policy framework */ @@ -113,12 +113,14 @@ public interface AutomationCompositionElementListener { /** * Rollback migration changes done to a composition. * - * @param compositionElement the composition to roll back the changes - * @param instanceElement instance to roll back the changes - * @param nextStage in which stage should the instance be after the rollback - * @throws PfModelException if anything goes wrong + * @param compositionElement the information of the Automation Composition Definition Element + * @param compositionElementRollback the information of the Automation Composition Definition Element Target + * @param instanceElement the information of the Automation Composition Instance Element + * @param instanceElementRollback the information of the Automation Composition Instance Element updated + * @param stage the stage + * @throws PfModelException from Policy framework */ - void rollbackMigration(CompositionElementDto compositionElement, - InstanceElementDto instanceElement, int nextStage) + void rollbackMigration(CompositionElementDto compositionElement, CompositionElementDto compositionElementRollback, + InstanceElementDto instanceElement, InstanceElementDto instanceElementRollback, int stage) throws PfModelException; } diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV4.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV4.java index a167085b0..2695da1fd 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV4.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV4.java @@ -119,9 +119,10 @@ public abstract class AcElementListenerV4 implements AutomationCompositionElemen @Override public void rollbackMigration(CompositionElementDto compositionElement, - InstanceElementDto instanceElement, int nextStage) { - intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), - instanceElement.elementId(), DeployState.DEPLOYED, null, + CompositionElementDto compositionElementRollback, InstanceElementDto instanceElement, + InstanceElementDto instanceElementRollback, int stage) { + intermediaryApi.updateAutomationCompositionElementState(instanceElementRollback.instanceId(), + instanceElementRollback.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migration rollback done"); } } diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandler.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandler.java index b281ece46..01c4428c0 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandler.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandler.java @@ -119,8 +119,8 @@ public class AutomationCompositionHandler { for (var participantDeploy : updateMsg.getParticipantUpdatesList()) { if (cacheProvider.getParticipantId().equals(participantDeploy.getParticipantId())) { - var automationComposition = cacheProvider.getAutomationComposition( - updateMsg.getAutomationCompositionId()); + var automationComposition = + cacheProvider.getAutomationComposition(updateMsg.getAutomationCompositionId()); automationComposition.setDeployState(DeployState.UPDATING); var acCopy = new AutomationComposition(automationComposition); updateExistingElementsOnThisParticipant(updateMsg.getAutomationCompositionId(), participantDeploy); @@ -154,39 +154,41 @@ public class AutomationCompositionHandler { } } - private void callParticipanDeploy(UUID messageId, List acElementDeployList, - Integer startPhaseMsg, UUID instanceId) { + private void callParticipanDeploy(UUID messageId, List acElementDeployList, Integer startPhaseMsg, + UUID instanceId) { var automationComposition = cacheProvider.getAutomationComposition(instanceId); automationComposition.setDeployState(DeployState.DEPLOYING); for (var elementDeploy : acElementDeployList) { var element = automationComposition.getElements().get(elementDeploy.getId()); - var compositionInProperties = cacheProvider - .getCommonProperties(automationComposition.getCompositionId(), element.getDefinition()); + var compositionInProperties = cacheProvider.getCommonProperties(automationComposition.getCompositionId(), + element.getDefinition()); int startPhase = ParticipantUtils.findStartPhase(compositionInProperties); if (startPhaseMsg.equals(startPhase)) { - var compositionElement = cacheProvider.createCompositionElementDto( - automationComposition.getCompositionId(), element, compositionInProperties); - var instanceElement = new InstanceElementDto(instanceId, elementDeploy.getId(), - elementDeploy.getProperties(), element.getOutProperties()); + var compositionElement = + cacheProvider.createCompositionElementDto(automationComposition.getCompositionId(), element, + compositionInProperties); + var instanceElement = + new InstanceElementDto(instanceId, elementDeploy.getId(), elementDeploy.getProperties(), + element.getOutProperties()); listener.deploy(messageId, compositionElement, instanceElement); } } } private void callParticipantUpdateProperty(UUID messageId, List acElements, - AutomationComposition acCopy) { + AutomationComposition acCopy) { var instanceElementDtoMap = cacheProvider.getInstanceElementDtoMap(acCopy); - var instanceElementDtoMapUpdated = cacheProvider.getInstanceElementDtoMap( - cacheProvider.getAutomationComposition(acCopy.getInstanceId())); + var instanceElementDtoMapUpdated = + cacheProvider.getInstanceElementDtoMap(cacheProvider.getAutomationComposition(acCopy.getInstanceId())); var compositionElementDtoMap = cacheProvider.getCompositionElementDtoMap(acCopy); for (var acElement : acElements) { listener.update(messageId, compositionElementDtoMap.get(acElement.getId()), - instanceElementDtoMap.get(acElement.getId()), instanceElementDtoMapUpdated.get(acElement.getId())); + instanceElementDtoMap.get(acElement.getId()), instanceElementDtoMapUpdated.get(acElement.getId())); } } private void migrateExistingElementsOnThisParticipant(UUID instanceId, UUID compositionTargetId, - ParticipantDeploy participantDeploy, int stage) { + ParticipantDeploy participantDeploy, int stage) { var automationComposition = cacheProvider.getAutomationComposition(instanceId); var acElementList = automationComposition.getElements(); for (var element : participantDeploy.getAcElementList()) { @@ -231,8 +233,8 @@ public class AutomationCompositionHandler { } } - private List findElementsToRemove(List acElementDeployList, Map acElementList) { + private List findElementsToRemove(List acElementDeployList, + Map acElementList) { var acElementDeploySet = acElementDeployList.stream().map(AcElementDeploy::getId).collect(Collectors.toSet()); return acElementList.keySet().stream().filter(id -> !acElementDeploySet.contains(id)).toList(); } @@ -240,22 +242,23 @@ public class AutomationCompositionHandler { /** * Method to handle when the new state from participant is UNINITIALISED state. * - * @param messageId the messageId + * @param messageId the messageId * @param automationComposition participant response - * @param startPhaseMsg startPhase from message + * @param startPhaseMsg startPhase from message */ private void handleUndeployState(UUID messageId, final AutomationComposition automationComposition, Integer startPhaseMsg) { automationComposition.setCompositionTargetId(null); automationComposition.setDeployState(DeployState.UNDEPLOYING); for (var element : automationComposition.getElements().values()) { - var compositionInProperties = cacheProvider - .getCommonProperties(automationComposition.getCompositionId(), element.getDefinition()); + var compositionInProperties = cacheProvider.getCommonProperties(automationComposition.getCompositionId(), + element.getDefinition()); int startPhase = ParticipantUtils.findStartPhase(compositionInProperties); if (startPhaseMsg.equals(startPhase)) { element.setDeployState(DeployState.UNDEPLOYING); - var compositionElement = cacheProvider.createCompositionElementDto( - automationComposition.getCompositionId(), element, compositionInProperties); + var compositionElement = + cacheProvider.createCompositionElementDto(automationComposition.getCompositionId(), element, + compositionInProperties); var instanceElement = new InstanceElementDto(automationComposition.getInstanceId(), element.getId(), element.getProperties(), element.getOutProperties()); listener.undeploy(messageId, compositionElement, instanceElement); @@ -267,14 +270,15 @@ public class AutomationCompositionHandler { Integer startPhaseMsg) { automationComposition.setDeployState(DeployState.DELETING); for (var element : automationComposition.getElements().values()) { - var compositionInProperties = cacheProvider - .getCommonProperties(automationComposition.getCompositionId(), element.getDefinition()); + var compositionInProperties = cacheProvider.getCommonProperties(automationComposition.getCompositionId(), + element.getDefinition()); int startPhase = ParticipantUtils.findStartPhase(compositionInProperties); if (startPhaseMsg.equals(startPhase)) { element.setDeployState(DeployState.DELETING); element.setSubState(SubState.NONE); - var compositionElement = cacheProvider.createCompositionElementDto( - automationComposition.getCompositionId(), element, compositionInProperties); + var compositionElement = + cacheProvider.createCompositionElementDto(automationComposition.getCompositionId(), element, + compositionInProperties); var instanceElement = new InstanceElementDto(automationComposition.getInstanceId(), element.getId(), element.getProperties(), element.getOutProperties()); listener.delete(messageId, compositionElement, instanceElement); @@ -307,50 +311,47 @@ public class AutomationCompositionHandler { migrateExistingElementsOnThisParticipant(migrationMsg.getAutomationCompositionId(), migrationMsg.getCompositionTargetId(), participantDeploy, migrationMsg.getStage()); - if (Boolean.TRUE.equals(migrationMsg.getRollback())) { - callParticipantRollback(migrationMsg.getMessageId(), participantDeploy.getAcElementList(), - acCopy, migrationMsg.getCompositionTargetId(), migrationMsg.getStage()); - } else { - callParticipantMigrate(migrationMsg.getMessageId(), participantDeploy.getAcElementList(), - acCopy, migrationMsg.getCompositionTargetId(), migrationMsg.getStage()); - } + callParticipantMigrate(migrationMsg.getMessageId(), participantDeploy.getAcElementList(), acCopy, + migrationMsg.getCompositionTargetId(), migrationMsg.getStage(), + Boolean.TRUE.equals(migrationMsg.getRollback())); } } } - private void callParticipantMigrate(UUID messageId, List acElements, - AutomationComposition acCopy, UUID compositionTargetId, int stage) { + private void callParticipantMigrate(UUID messageId, List acElements, AutomationComposition acCopy, + UUID compositionTargetId, int stage, boolean rollback) { var compositionElementMap = cacheProvider.getCompositionElementDtoMap(acCopy); var instanceElementMap = cacheProvider.getInstanceElementDtoMap(acCopy); var automationComposition = cacheProvider.getAutomationComposition(acCopy.getInstanceId()); - var compositionElementTargetMap = cacheProvider.getCompositionElementDtoMap(automationComposition, - compositionTargetId); + var compositionElementTargetMap = + cacheProvider.getCompositionElementDtoMap(automationComposition, compositionTargetId); var instanceElementMigrateMap = cacheProvider.getInstanceElementDtoMap(automationComposition); // Call migrate for newly added and updated elements for (var acElement : acElements) { - var compositionInProperties = cacheProvider - .getCommonProperties(compositionTargetId, acElement.getDefinition()); + var compositionInProperties = + cacheProvider.getCommonProperties(compositionTargetId, acElement.getDefinition()); var stageSet = ParticipantUtils.findStageSetMigrate(compositionInProperties); if (stageSet.contains(stage)) { if (instanceElementMap.get(acElement.getId()) == null) { var compositionElementDto = - new CompositionElementDto(acCopy.getCompositionId(), acElement.getDefinition(), - Map.of(), Map.of(), ElementState.NOT_PRESENT); - var instanceElementDto = new InstanceElementDto(acCopy.getInstanceId(), acElement.getId(), - Map.of(), Map.of(), ElementState.NOT_PRESENT); - var compositionElementTargetDto = CacheProvider.changeStateToNew( - compositionElementTargetMap.get(acElement.getId())); - var instanceElementMigrateDto = CacheProvider - .changeStateToNew(instanceElementMigrateMap.get(acElement.getId())); - - listener.migrate(messageId, compositionElementDto, compositionElementTargetDto, - instanceElementDto, instanceElementMigrateDto, stage); + new CompositionElementDto(acCopy.getCompositionId(), acElement.getDefinition(), Map.of(), + Map.of(), ElementState.NOT_PRESENT); + var instanceElementDto = + new InstanceElementDto(acCopy.getInstanceId(), acElement.getId(), Map.of(), Map.of(), + ElementState.NOT_PRESENT); + var compositionElementTargetDto = + CacheProvider.changeStateToNew(compositionElementTargetMap.get(acElement.getId())); + var instanceElementMigrateDto = + CacheProvider.changeStateToNew(instanceElementMigrateMap.get(acElement.getId())); + + listenerMigrate(messageId, compositionElementDto, compositionElementTargetDto, instanceElementDto, + instanceElementMigrateDto, stage, rollback); } else { - listener.migrate(messageId, compositionElementMap.get(acElement.getId()), + listenerMigrate(messageId, compositionElementMap.get(acElement.getId()), compositionElementTargetMap.get(acElement.getId()), - instanceElementMap.get(acElement.getId()), instanceElementMigrateMap - .get(acElement.getId()), stage); + instanceElementMap.get(acElement.getId()), instanceElementMigrateMap.get(acElement.getId()), + stage, rollback); } } } @@ -359,48 +360,24 @@ public class AutomationCompositionHandler { List removedElements = findElementsToRemove(acElements, acCopy.getElements()); for (var elementId : removedElements) { var compositionDtoTarget = new CompositionElementDto(compositionTargetId, - acCopy.getElements().get(elementId).getDefinition(), - Map.of(), Map.of(), ElementState.REMOVED); - var instanceDtoTarget = new InstanceElementDto(acCopy.getInstanceId(), elementId, Map.of(), - Map.of(), ElementState.REMOVED); - listener.migrate(messageId, compositionElementMap.get(elementId), compositionDtoTarget, - instanceElementMap.get(elementId), instanceDtoTarget, 0); + acCopy.getElements().get(elementId).getDefinition(), Map.of(), Map.of(), ElementState.REMOVED); + var instanceDtoTarget = new InstanceElementDto(acCopy.getInstanceId(), elementId, Map.of(), Map.of(), + ElementState.REMOVED); + listenerMigrate(messageId, compositionElementMap.get(elementId), compositionDtoTarget, + instanceElementMap.get(elementId), instanceDtoTarget, 0, rollback); } } } - private void callParticipantRollback(UUID messageId, List acElements, - AutomationComposition acCopy, UUID compositionTargetId, int stage) { - var compositionElementMap = cacheProvider.getCompositionElementDtoMap(acCopy); - var instanceElementMap = cacheProvider.getInstanceElementDtoMap(acCopy); - - for (var acElement : acElements) { - var compositionInProperties = cacheProvider - .getCommonProperties(compositionTargetId, acElement.getDefinition()); - var stageSet = ParticipantUtils.findStageSetMigrate(compositionInProperties); - if (stageSet.contains(stage)) { - if (instanceElementMap.get(acElement.getId()) == null) { - var compositionElementDto = - new CompositionElementDto(acCopy.getCompositionId(), acElement.getDefinition(), - Map.of(), Map.of(), ElementState.NOT_PRESENT); - var instanceElementDto = new InstanceElementDto(acCopy.getInstanceId(), acElement.getId(), - Map.of(), Map.of(), ElementState.NOT_PRESENT); - - listener.rollback(messageId, compositionElementDto, - instanceElementDto, stage); - } else { - listener.rollback(messageId, compositionElementMap.get(acElement.getId()), - instanceElementMap.get(acElement.getId()), stage); - } - } - } - if (stage == 0) { - // Call rollback for removed elements - List removedElements = findElementsToRemove(acElements, acCopy.getElements()); - for (var elementId : removedElements) { - listener.rollback(messageId, compositionElementMap.get(elementId), - instanceElementMap.get(elementId), 0); - } + private void listenerMigrate(UUID messageId, CompositionElementDto compositionElement, + CompositionElementDto compositionElementTarget, InstanceElementDto instanceElement, + InstanceElementDto instanceElementMigrate, int stage, boolean rollback) { + if (rollback) { + listener.rollback(messageId, compositionElement, compositionElementTarget, instanceElement, + instanceElementMigrate, stage); + } else { + listener.migrate(messageId, compositionElement, compositionElementTarget, instanceElement, + instanceElementMigrate, stage); } } } diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandler.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandler.java index fa69442da..097f94ab5 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandler.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandler.java @@ -438,25 +438,28 @@ public class ThreadHandler implements Closeable { /** * Handles AutomationComposition Rollback. * - * @param messageId the messageId * @param compositionElement the information of the Automation Composition Definition Element + * @param compositionElementRollback the information of the Automation Composition Definition Element Target * @param instanceElement the information of the Automation Composition Instance Element + * @param instanceElementRollback the information of the Automation Composition Instance Element updated * @param stage the stage */ public void rollback(UUID messageId, CompositionElementDto compositionElement, - InstanceElementDto instanceElement, - int stage) { + CompositionElementDto compositionElementRollback, InstanceElementDto instanceElement, + InstanceElementDto instanceElementRollback, int stage) { cleanExecution(instanceElement.elementId(), messageId); var result = executor.submit(() -> - this.rollbackProcess(compositionElement, - instanceElement, stage)); + this.rollbackProcess(compositionElement, compositionElementRollback, instanceElement, + instanceElementRollback, stage)); executionMap.put(instanceElement.elementId(), result); } - private void rollbackProcess(CompositionElementDto compositionElement, InstanceElementDto instanceElement, - int stage) { + private void rollbackProcess(CompositionElementDto compositionElement, + CompositionElementDto compositionElementRollback, InstanceElementDto instanceElement, + InstanceElementDto instanceElementRollback, int stage) { try { - listener.rollbackMigration(compositionElement, instanceElement, stage); + listener.rollbackMigration(compositionElement, compositionElementRollback, instanceElement, + instanceElementRollback, stage); } catch (PfModelException e) { LOGGER.error("Automation composition element rollback failed {} {}", instanceElement.elementId(), e.getMessage()); diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV3Test.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV3Test.java index a2b652120..4856d03bf 100644 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV3Test.java +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV3Test.java @@ -42,11 +42,11 @@ class AcElementListenerV3Test { @Test void lockTest() throws PfModelException { var intermediaryApi = mock(ParticipantIntermediaryApi.class); - var acElementListenerV2 = createAcElementListenerV3(intermediaryApi); + var acElementListener = createAcElementListenerV3(intermediaryApi); var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of()); var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), Map.of(), Map.of()); - acElementListenerV2.lock(compositionElement, instanceElement); + acElementListener.lock(compositionElement, instanceElement); verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), null, LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked"); } @@ -54,11 +54,11 @@ class AcElementListenerV3Test { @Test void deleteTest() throws PfModelException { var intermediaryApi = mock(ParticipantIntermediaryApi.class); - var acElementListenerV2 = createAcElementListenerV3(intermediaryApi); + var acElementListener = createAcElementListenerV3(intermediaryApi); var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of()); var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), Map.of(), Map.of()); - acElementListenerV2.delete(compositionElement, instanceElement); + acElementListener.delete(compositionElement, instanceElement); verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted"); } @@ -66,11 +66,11 @@ class AcElementListenerV3Test { @Test void updateTest() throws PfModelException { var intermediaryApi = mock(ParticipantIntermediaryApi.class); - var acElementListenerV2 = createAcElementListenerV3(intermediaryApi); + var acElementListener = createAcElementListenerV3(intermediaryApi); var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of()); var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), Map.of(), Map.of()); - acElementListenerV2.update(compositionElement, instanceElement, instanceElement); + acElementListener.update(compositionElement, instanceElement, instanceElement); verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Update not supported"); @@ -79,11 +79,11 @@ class AcElementListenerV3Test { @Test void unlockTest() throws PfModelException { var intermediaryApi = mock(ParticipantIntermediaryApi.class); - var acElementListenerV2 = createAcElementListenerV3(intermediaryApi); + var acElementListener = createAcElementListenerV3(intermediaryApi); var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of()); var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), Map.of(), Map.of()); - acElementListenerV2.unlock(compositionElement, instanceElement); + acElementListener.unlock(compositionElement, instanceElement); verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), null, LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked"); } @@ -91,11 +91,11 @@ class AcElementListenerV3Test { @Test void primeTest() throws PfModelException { var intermediaryApi = mock(ParticipantIntermediaryApi.class); - var acElementListenerV2 = createAcElementListenerV3(intermediaryApi); + var acElementListener = createAcElementListenerV3(intermediaryApi); var compositionId = UUID.randomUUID(); var toscaConceptIdentifier = new ToscaConceptIdentifier(); var composition = new CompositionDto(compositionId, Map.of(toscaConceptIdentifier, Map.of()), Map.of()); - acElementListenerV2.prime(composition); + acElementListener.prime(composition); verify(intermediaryApi) .updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.NO_ERROR, "Primed"); } @@ -103,11 +103,11 @@ class AcElementListenerV3Test { @Test void deprimeTest() throws PfModelException { var intermediaryApi = mock(ParticipantIntermediaryApi.class); - var acElementListenerV2 = createAcElementListenerV3(intermediaryApi); + var acElementListener = createAcElementListenerV3(intermediaryApi); var compositionId = UUID.randomUUID(); var toscaConceptIdentifier = new ToscaConceptIdentifier(); var composition = new CompositionDto(compositionId, Map.of(toscaConceptIdentifier, Map.of()), Map.of()); - acElementListenerV2.deprime(composition); + acElementListener.deprime(composition); verify(intermediaryApi) .updateCompositionState(compositionId, AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR, "Deprimed"); } @@ -115,11 +115,11 @@ class AcElementListenerV3Test { @Test void migrateTest() throws PfModelException { var intermediaryApi = mock(ParticipantIntermediaryApi.class); - var acElementListenerV2 = createAcElementListenerV3(intermediaryApi); + var acElementListener = createAcElementListenerV3(intermediaryApi); var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of()); var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), Map.of(), Map.of()); - acElementListenerV2.migrate(compositionElement, compositionElement, instanceElement, instanceElement, 0); + acElementListener.migrate(compositionElement, compositionElement, instanceElement, instanceElement, 0); verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); @@ -128,11 +128,11 @@ class AcElementListenerV3Test { @Test void migratePrecheckTest() throws PfModelException { var intermediaryApi = mock(ParticipantIntermediaryApi.class); - var acElementListenerV1 = createAcElementListenerV3(intermediaryApi); + var acElementListener = createAcElementListenerV3(intermediaryApi); var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of()); var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), Map.of(), Map.of()); - acElementListenerV1.migratePrecheck(compositionElement, compositionElement, instanceElement, instanceElement); + acElementListener.migratePrecheck(compositionElement, compositionElement, instanceElement, instanceElement); verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migration Precheck completed"); @@ -141,11 +141,11 @@ class AcElementListenerV3Test { @Test void reviewTest() throws PfModelException { var intermediaryApi = mock(ParticipantIntermediaryApi.class); - var acElementListenerV1 = createAcElementListenerV3(intermediaryApi); + var acElementListener = createAcElementListenerV3(intermediaryApi); var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of()); var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), Map.of(), Map.of()); - acElementListenerV1.review(compositionElement, instanceElement); + acElementListener.review(compositionElement, instanceElement); verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Review completed"); @@ -154,11 +154,11 @@ class AcElementListenerV3Test { @Test void prepareTest() throws PfModelException { var intermediaryApi = mock(ParticipantIntermediaryApi.class); - var acElementListenerV1 = createAcElementListenerV3(intermediaryApi); + var acElementListener = createAcElementListenerV3(intermediaryApi); var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of()); var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), Map.of(), Map.of()); - acElementListenerV1.prepare(compositionElement, instanceElement); + acElementListener.prepare(compositionElement, instanceElement); verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Prepare completed"); @@ -171,10 +171,11 @@ class AcElementListenerV3Test { var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of()); var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), Map.of(), Map.of()); - acElementListenerV3.rollbackMigration(compositionElement, instanceElement, 1); + acElementListenerV3.rollbackMigration(compositionElement, compositionElement, instanceElement, + instanceElement, 0); verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), - instanceElement.elementId(), DeployState.DEPLOYED, null, - StateChangeResult.NO_ERROR, "Migration rollback done"); + instanceElement.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Migration rollback done"); } private AcElementListenerV3 createAcElementListenerV3(ParticipantIntermediaryApi intermediaryApi) { diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandlerTest.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandlerTest.java index b9a499bef..3fe549ff9 100644 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandlerTest.java +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandlerTest.java @@ -393,7 +393,7 @@ class AutomationCompositionHandlerTest { if (!rollback) { verify(listener, times(expectedMigrated)).migrate(any(), any(), any(), any(), any(), anyInt()); } else { - verify(listener, times(expectedMigrated)).rollback(any(), any(), any(), anyInt()); + verify(listener, times(expectedMigrated)).rollback(any(), any(), any(), any(), any(), anyInt()); } } } diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandlerTest.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandlerTest.java index f03990a63..8846442e2 100644 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandlerTest.java +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandlerTest.java @@ -129,9 +129,10 @@ class ThreadHandlerTest { instanceElement, instanceElementUpdated, 0); clearInvocations(listener); - threadHandler.rollback(messageId, compositionElement, instanceElement, 0); - verify(listener, timeout(TIMEOUT)).rollbackMigration(compositionElement, instanceElement, 0); - + threadHandler.rollback(messageId, compositionElement, compositionElementTarget, + instanceElement, instanceElementUpdated, 0); + verify(listener, timeout(TIMEOUT)).rollbackMigration(compositionElement, compositionElementTarget, + instanceElement, instanceElementUpdated, 0); clearInvocations(listener); threadHandler.undeploy(messageId, compositionElement, instanceElement); @@ -335,14 +336,6 @@ class ThreadHandlerTest { verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId, DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Automation composition element migrate precheck failed"); - - clearInvocations(listener); - doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener) - .rollbackMigration(compositionElement, instanceElement, 0); - threadHandler.rollback(compositionElement.compositionId(), compositionElement, instanceElement, 0); - verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId, - DeployState.DEPLOYED, null, StateChangeResult.FAILED, - "Automation composition element migrate precheck failed"); } } } 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 e1093c7a3..dfeb7f39c 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 @@ -25,7 +25,6 @@ import jakarta.validation.Valid; import jakarta.ws.rs.core.Response.Status; import java.util.List; import java.util.UUID; -import java.util.function.UnaryOperator; import java.util.stream.Collectors; import lombok.NonNull; import lombok.RequiredArgsConstructor; @@ -476,7 +475,7 @@ public class AutomationCompositionInstantiationProvider { } var automationCompositionToRollback = - automationCompositionProvider.getAutomationCompositionRollback(instanceId); + automationCompositionProvider.getAutomationCompositionRollback(instanceId); var acToBeUpdated = new AutomationComposition(automationComposition); acToBeUpdated.setCompositionTargetId(automationCompositionToRollback.getCompositionId()); acToBeUpdated.setElements(automationCompositionToRollback.getElements().values().stream() diff --git a/runtime-acm/src/main/resources/openapi/openapi.yaml b/runtime-acm/src/main/resources/openapi/openapi.yaml index 2f81a8f29..68e43e6e6 100644 --- a/runtime-acm/src/main/resources/openapi/openapi.yaml +++ b/runtime-acm/src/main/resources/openapi/openapi.yaml @@ -1637,14 +1637,6 @@ paths: schema: type: string format: uuid - requestBody: - description: Parameters for the rollback (e.g., target version) - required: true - content: - application/json: - schema: - application/yaml: - schema: responses: 202: description: Rollback initiated diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/rest/InstantiationControllerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/rest/InstantiationControllerTest.java index 30286db60..fe1775f97 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/rest/InstantiationControllerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/rest/InstantiationControllerTest.java @@ -29,6 +29,7 @@ import static org.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_SERVIC import static org.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_VERSIONING; import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import java.util.UUID; import org.junit.jupiter.api.BeforeAll; @@ -93,12 +94,12 @@ class InstantiationControllerTest extends CommonRestController { private int randomServerPort; @BeforeAll - public static void setUpBeforeClass() { + static void setUpBeforeClass() { serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); } @BeforeEach - public void setUpPort() { + void setUpPort() { super.setHttpPrefix(randomServerPort); } @@ -287,6 +288,7 @@ class InstantiationControllerTest extends CommonRestController { var rawresp = invocationBuilder.buildGet().invoke(); assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); var automationCompositionGet = rawresp.readEntity(AutomationComposition.class); + rawresp.close(); assertNotNull(automationCompositionGet); automationComposition.setLastMsg(automationCompositionGet.getLastMsg()); assertEquals(automationComposition, automationCompositionGet); @@ -309,12 +311,12 @@ class InstantiationControllerTest extends CommonRestController { .forEach(element -> element.setParticipantId(CommonTestData.getParticipantId())); var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId)); - var resp = invocationBuilder.post(Entity.json(automationComposition)); - assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); - - var instResponse = resp.readEntity(InstantiationResponse.class); - InstantiationUtils.assertInstantiationResponse(instResponse, automationComposition); + try (var resp = invocationBuilder.post(Entity.json(automationComposition))) { + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + var instResponse = resp.readEntity(InstantiationResponse.class); + InstantiationUtils.assertInstantiationResponse(instResponse, automationComposition); + } var automationCompositionsFromDb = instantiationProvider.getAutomationCompositions( compositionId, automationComposition.getKey().getName(), automationComposition.getKey().getVersion(), Pageable.unpaged()); @@ -337,9 +339,10 @@ class InstantiationControllerTest extends CommonRestController { instantiationProvider.createAutomationComposition(compositionId, automationCompositionFromRsc); var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId, instResponse.getInstanceId())); - var resp = invocationBuilder.delete(); - assertEquals(Response.Status.ACCEPTED.getStatusCode(), resp.getStatus()); - instResponse = resp.readEntity(InstantiationResponse.class); + try (var resp = invocationBuilder.delete()) { + assertEquals(Response.Status.ACCEPTED.getStatusCode(), resp.getStatus()); + instResponse = resp.readEntity(InstantiationResponse.class); + } InstantiationUtils.assertInstantiationResponse(instResponse, automationCompositionFromRsc); var automationCompositionsFromDb = instantiationProvider.getAutomationCompositions(compositionId, @@ -359,16 +362,42 @@ class InstantiationControllerTest extends CommonRestController { instantiationProvider.createAutomationComposition(compositionId, automationCompositionFromRsc); var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId, UUID.randomUUID())); - var resp = invocationBuilder.delete(); - assertEquals(Response.Status.NOT_FOUND.getStatusCode(), resp.getStatus()); + try (var resp = invocationBuilder.delete()) { + assertEquals(Response.Status.NOT_FOUND.getStatusCode(), resp.getStatus()); + } + } + + @Test + void testRollbackNotValid() { + var compositionId = createAcDefinitionInDB("RollbackNotFound"); + + // instance not found + var url = getInstanceEndPoint(compositionId, UUID.randomUUID()) + "/rollback"; + var invocationBuilder = super.sendRequest(url); + try (var resp = invocationBuilder.post(Entity.entity("", MediaType.APPLICATION_JSON))) { + assertEquals(Response.Status.NOT_FOUND.getStatusCode(), resp.getStatus()); + } + + // instance not valid state + var automationCompositionFromRsc = + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "NotValid"); + automationCompositionFromRsc.setCompositionId(compositionId); + var instanceResponce = + instantiationProvider.createAutomationComposition(compositionId, automationCompositionFromRsc); + url = getInstanceEndPoint(compositionId, instanceResponce.getInstanceId()) + "/rollback"; + invocationBuilder = super.sendRequest(url); + try (var resp = invocationBuilder.post(Entity.entity("", MediaType.APPLICATION_JSON))) { + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus()); + } } @Test void testDeploy_NotFound() { var compositionId = createAcDefinitionInDB("Deploy_NotFound"); var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId, UUID.randomUUID())); - var resp = invocationBuilder.put(Entity.json(new AcInstanceStateUpdate())); - assertEquals(Response.Status.NOT_FOUND.getStatusCode(), resp.getStatus()); + try (var resp = invocationBuilder.put(Entity.json(new AcInstanceStateUpdate()))) { + assertEquals(Response.Status.NOT_FOUND.getStatusCode(), resp.getStatus()); + } } @Test @@ -385,8 +414,9 @@ class InstantiationControllerTest extends CommonRestController { command.setLockOrder(null); var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId, instResponse.getInstanceId())); - var resp = invocationBuilder.put(Entity.json(command)); - assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus()); + try (var resp = invocationBuilder.put(Entity.json(command))) { + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus()); + } } @Test @@ -402,8 +432,9 @@ class InstantiationControllerTest extends CommonRestController { instantiationUpdate.setLockOrder(null); var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId, instResponse.getInstanceId())); - var resp = invocationBuilder.put(Entity.json(instantiationUpdate)); - assertEquals(Response.Status.ACCEPTED.getStatusCode(), resp.getStatus()); + try (var resp = invocationBuilder.put(Entity.json(instantiationUpdate))) { + assertEquals(Response.Status.ACCEPTED.getStatusCode(), resp.getStatus()); + } } private UUID createAcDefinitionInDB(String name) { -- 2.16.6