Add rollback for ACM Migration 06/141406/2
authorFrancescoFioraEst <francesco.fiora@est.tech>
Mon, 30 Jun 2025 08:08:59 +0000 (09:08 +0100)
committerFrancescoFioraEst <francesco.fiora@est.tech>
Thu, 3 Jul 2025 11:56:06 +0000 (12:56 +0100)
Fix the full rollback flow.

Issue-ID: POLICY-5194
Change-Id: Ia2f33f4a585762a06d398b8faae6bfec823f70bd
Signed-off-by: FrancescoFioraEst <francesco.fiora@est.tech>
14 files changed:
models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionRollback.java
participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandler.java
participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/SimulatorService.java
participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerTest.java
participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/AutomationCompositionElementListener.java
participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV4.java
participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandler.java
participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandler.java
participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV3Test.java
participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandlerTest.java
participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandlerTest.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java
runtime-acm/src/main/resources/openapi/openapi.yaml
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/rest/InstantiationControllerTest.java

index 988a7d5..d2f6319 100644 (file)
@@ -23,7 +23,6 @@ package org.onap.policy.clamp.models.acm.concepts;
 import java.util.LinkedHashMap;\r
 import java.util.Map;\r
 import java.util.UUID;\r
-import java.util.function.UnaryOperator;\r
 import lombok.Data;\r
 import lombok.NoArgsConstructor;\r
 import lombok.NonNull;\r
index 270aa03..5e03bc4 100644 (file)
@@ -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());
+        }
     }
 }
index 282d81d..20979ad 100644 (file)
@@ -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<String, Object> compositionInProperties,
+            Map<String, Object> 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<Integer>) 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");
         }
     }
 }
index baf1b2a..4b2ea56 100644 (file)
 
 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");
     }
 }
index 63db854..7eccf50 100644 (file)
@@ -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;
 }
index a167085..2695da1 100644 (file)
@@ -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");
     }
 }
index b281ece..01c4428 100644 (file)
@@ -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<AcElementDeploy> acElementDeployList,
-            Integer startPhaseMsg, UUID instanceId) {
+    private void callParticipanDeploy(UUID messageId, List<AcElementDeploy> 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<AcElementDeploy> 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<UUID> findElementsToRemove(List<AcElementDeploy> acElementDeployList, Map<UUID,
-            AutomationCompositionElement> acElementList) {
+    private List<UUID> findElementsToRemove(List<AcElementDeploy> acElementDeployList,
+            Map<UUID, AutomationCompositionElement> 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<AcElementDeploy> acElements,
-            AutomationComposition acCopy, UUID compositionTargetId, int stage) {
+    private void callParticipantMigrate(UUID messageId, List<AcElementDeploy> 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<UUID> 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<AcElementDeploy> 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<UUID> 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);
         }
     }
 }
index fa69442..097f94a 100644 (file)
@@ -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());
index a2b6521..4856d03 100644 (file)
@@ -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) {
index b9a499b..3fe549f 100644 (file)
@@ -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());
         }
     }
 }
index f03990a..8846442 100644 (file)
@@ -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");
         }
     }
 }
index e1093c7..dfeb7f3 100644 (file)
@@ -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()
index 2f81a8f..68e43e6 100644 (file)
@@ -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
index 30286db..fe1775f 100644 (file)
@@ -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) {