From: akenihan Date: Fri, 27 Jun 2025 10:54:42 +0000 (+0100) Subject: update job monitoring to support rollback X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F02%2F141402%2F4;p=policy%2Fclamp.git update job monitoring to support rollback Issue-ID: POLICY-5406 Change-Id: Ibef8e8ea31df91fc12c141ebd0c6dd97b30807ef Signed-off-by: akenihan --- 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 c11d5b89d..988a7d5bf 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 @@ -50,7 +50,7 @@ public class AutomationCompositionRollback { public AutomationCompositionRollback(final AutomationCompositionRollback otherAcmRollback) { this.instanceId = otherAcmRollback.instanceId; this.compositionId = otherAcmRollback.compositionId; - this.elements = PfUtils.mapMap(otherAcmRollback.elements, UnaryOperator.identity()); + this.elements = PfUtils.mapMap(otherAcmRollback.elements, AutomationCompositionElement::new); } /** @@ -61,6 +61,6 @@ public class AutomationCompositionRollback { public AutomationCompositionRollback(final AutomationComposition automationComposition) { this.instanceId = automationComposition.getInstanceId(); this.compositionId = automationComposition.getCompositionId(); - this.elements = PfUtils.mapMap(automationComposition.getElements(), UnaryOperator.identity()); + this.elements = PfUtils.mapMap(automationComposition.getElements(), AutomationCompositionElement::new); } } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/instantiation/DeployOrder.java b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/instantiation/DeployOrder.java index 758a5057f..5a4f84a08 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/instantiation/DeployOrder.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/instantiation/DeployOrder.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation. + * Copyright (C) 2023-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,5 +27,6 @@ public enum DeployOrder { DELETE, UPDATE, RESTARTING, - MIGRATE + MIGRATE, + MIGRATION_REVERT } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcInstanceStateResolver.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcInstanceStateResolver.java index defa804ca..539a19af9 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcInstanceStateResolver.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcInstanceStateResolver.java @@ -34,6 +34,7 @@ import org.springframework.stereotype.Component; public class AcInstanceStateResolver { private final StateDefinition graph; + // DeployState private static final String DEPLOYED = DeployState.DEPLOYED.name(); private static final String DEPLOYING = DeployState.DEPLOYING.name(); private static final String UNDEPLOYED = DeployState.UNDEPLOYED.name(); @@ -41,37 +42,48 @@ public class AcInstanceStateResolver { private static final String UPDATING = DeployState.UPDATING.name(); private static final String DELETING = DeployState.DELETING.name(); private static final String MIGRATING = DeployState.MIGRATING.name(); - private static final String MIGRATION_PRECHECKING = SubState.MIGRATION_PRECHECKING.name(); private static final String MIGRATION_REVERTING = DeployState.MIGRATION_REVERTING.name(); + + // SubState + private static final String MIGRATION_PRECHECKING = SubState.MIGRATION_PRECHECKING.name(); private static final String SUB_STATE_NONE = SubState.NONE.name(); private static final String PREPARING = SubState.PREPARING.name(); private static final String REVIEWING = SubState.REVIEWING.name(); + // LockState private static final String LOCKED = LockState.LOCKED.name(); private static final String LOCKING = LockState.LOCKING.name(); private static final String UNLOCKED = LockState.UNLOCKED.name(); private static final String UNLOCKING = LockState.UNLOCKING.name(); private static final String STATE_LOCKED_NONE = LockState.NONE.name(); + // NONE Order private static final String DEPLOY_NONE = DeployOrder.NONE.name(); private static final String LOCK_NONE = LockOrder.NONE.name(); private static final String SUB_NONE = SubOrder.NONE.name(); - private static final String NO_ERROR = StateChangeResult.NO_ERROR.name(); - private static final String FAILED = StateChangeResult.FAILED.name(); - private static final String TIMEOUT = StateChangeResult.TIMEOUT.name(); - - // list of results + // DeployOrder public static final String DEPLOY = DeployOrder.DEPLOY.name(); public static final String UNDEPLOY = DeployOrder.UNDEPLOY.name(); public static final String DELETE = DeployOrder.DELETE.name(); + public static final String MIGRATE = DeployOrder.MIGRATE.name(); + public static final String MIGRATION_REVERT = DeployOrder.MIGRATION_REVERT.name(); + public static final String UPDATE = DeployOrder.UPDATE.name(); + + // LockOrder public static final String LOCK = LockOrder.LOCK.name(); public static final String UNLOCK = LockOrder.UNLOCK.name(); - public static final String MIGRATE = DeployOrder.MIGRATE.name(); + + // SubOrder public static final String MIGRATE_PRECHECK = SubOrder.MIGRATE_PRECHECK.name(); public static final String PREPARE = SubOrder.PREPARE.name(); public static final String REVIEW = SubOrder.REVIEW.name(); - public static final String UPDATE = DeployOrder.UPDATE.name(); + + // StateChangeResult + private static final String NO_ERROR = StateChangeResult.NO_ERROR.name(); + private static final String FAILED = StateChangeResult.FAILED.name(); + private static final String TIMEOUT = StateChangeResult.TIMEOUT.name(); + public static final String NONE = "NONE"; /** @@ -129,7 +141,7 @@ public class AcInstanceStateResolver { addSubOrderWithFail(REVIEW, DEPLOYED, LOCKED, REVIEWING); // rollback - addDeployOrderWithFail(MIGRATION_REVERTING, MIGRATING, LOCKED, SUB_STATE_NONE); + addDeployOrderWithFail(MIGRATION_REVERT, MIGRATING, LOCKED, SUB_STATE_NONE); addDeployOrderWithFail(UNDEPLOY, MIGRATION_REVERTING, LOCKED, SUB_STATE_NONE); } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProvider.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProvider.java index 225c95a9e..d12d78d16 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProvider.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProvider.java @@ -157,7 +157,8 @@ public class AutomationCompositionProvider { @Transactional(readOnly = true) public Set getAcInstancesInTransition() { var jpaList = automationCompositionRepository.findByDeployStateIn(List.of(DeployState.DEPLOYING, - DeployState.UNDEPLOYING, DeployState.DELETING, DeployState.UPDATING, DeployState.MIGRATING)); + DeployState.UNDEPLOYING, DeployState.DELETING, DeployState.UPDATING, DeployState.MIGRATING, + DeployState.MIGRATION_REVERTING)); jpaList.addAll(automationCompositionRepository.findByLockStateIn( List.of(LockState.LOCKING, LockState.UNLOCKING))); jpaList.addAll(automationCompositionRepository.findBySubStateIn( diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/utils/AcmUtils.java b/models/src/main/java/org/onap/policy/clamp/models/acm/utils/AcmUtils.java index 09d4dced9..6b5c4f9f2 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/utils/AcmUtils.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/utils/AcmUtils.java @@ -290,7 +290,8 @@ public final class AcmUtils { return DeployState.DEPLOYING.equals(deployState) || DeployState.UNDEPLOYING.equals(deployState) || LockState.LOCKING.equals(lockState) || LockState.UNLOCKING.equals(lockState) || DeployState.DELETING.equals(deployState) || DeployState.UPDATING.equals(deployState) - || DeployState.MIGRATING.equals(deployState) || !SubState.NONE.equals(subState); + || DeployState.MIGRATING.equals(deployState) || DeployState.MIGRATION_REVERTING.equals(deployState) + || !SubState.NONE.equals(subState); } /** @@ -331,7 +332,7 @@ public final class AcmUtils { */ public static DeployState deployCompleted(DeployState deployState) { return switch (deployState) { - case MIGRATING, UPDATING, DEPLOYING -> DeployState.DEPLOYED; + case MIGRATING, MIGRATION_REVERTING, UPDATING, DEPLOYING -> DeployState.DEPLOYED; case UNDEPLOYING -> DeployState.UNDEPLOYED; case DELETING -> DeployState.DELETED; default -> deployState; diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AcInstanceStateResolverTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AcInstanceStateResolverTest.java index c9c4f0dd4..09de72410 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AcInstanceStateResolverTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AcInstanceStateResolverTest.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation. + * Copyright (C) 2023-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -77,9 +77,9 @@ class AcInstanceStateResolverTest { assertThat(result).isEqualTo(AcInstanceStateResolver.REVIEW); // rollback - result = acTypeStateResolver.resolve(DeployOrder.MIGRATE, LockOrder.NONE, SubOrder.REVIEW, - DeployState.MIGRATION_REVERTING, LockState.LOCKED, SubState.NONE, StateChangeResult.NO_ERROR); - assertThat(result).isEqualTo(AcInstanceStateResolver.NONE); + result = acTypeStateResolver.resolve(DeployOrder.MIGRATION_REVERT, LockOrder.NONE, SubOrder.NONE, + DeployState.MIGRATING, LockState.LOCKED, SubState.NONE, StateChangeResult.FAILED); + assertThat(result).isEqualTo(AcInstanceStateResolver.MIGRATION_REVERT); result = acTypeStateResolver.resolve(DeployOrder.UNDEPLOY, LockOrder.NONE, SubOrder.NONE, DeployState.MIGRATION_REVERTING, LockState.LOCKED, SubState.NONE, StateChangeResult.FAILED); diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProviderTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProviderTest.java index 40c26393b..6ddf965ab 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProviderTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProviderTest.java @@ -218,7 +218,8 @@ class AutomationCompositionProviderTest { var automationCompositionRepository = mock(AutomationCompositionRepository.class); when(automationCompositionRepository.findByDeployStateIn(List.of(DeployState.DEPLOYING, - DeployState.UNDEPLOYING, DeployState.DELETING, DeployState.UPDATING, DeployState.MIGRATING))) + DeployState.UNDEPLOYING, DeployState.DELETING, DeployState.UPDATING, DeployState.MIGRATING, + DeployState.MIGRATION_REVERTING))) .thenReturn(res1); when(automationCompositionRepository.findByLockStateIn(List.of(LockState.LOCKING, LockState.UNLOCKING))) .thenReturn(List.of(inputAutomationCompositionsJpa.get(1))); diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/utils/AcmUtilsTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/utils/AcmUtilsTest.java index 8feeb876e..fb0f683ac 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/utils/AcmUtilsTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/utils/AcmUtilsTest.java @@ -74,6 +74,8 @@ class AcmUtilsTest { assertThat(AcmUtils.isInTransitionalState(DeployState.DELETING, LockState.NONE, SubState.NONE)).isTrue(); assertThat(AcmUtils.isInTransitionalState(DeployState.UPDATING, LockState.LOCKED, SubState.NONE)).isTrue(); assertThat(AcmUtils.isInTransitionalState(DeployState.MIGRATING, LockState.LOCKED, SubState.NONE)).isTrue(); + assertThat(AcmUtils.isInTransitionalState(DeployState.MIGRATION_REVERTING, LockState.LOCKED, + SubState.NONE)).isTrue(); assertThat(AcmUtils.isInTransitionalState(DeployState.DEPLOYED, LockState.LOCKED, SubState.MIGRATION_PRECHECKING)).isTrue(); } 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 ee1a47a2e..e1093c7a3 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 @@ -228,7 +228,7 @@ public class AutomationCompositionInstantiationProvider { var elementsRemoved = updateElementsProperties(automationComposition, acToBeUpdated); var acDefinition = acDefinitionProvider.getAcDefinition(automationComposition.getCompositionTargetId()); - updateAcForMigration(acToBeUpdated, acDefinition); + updateAcForMigration(acToBeUpdated, acDefinition, DeployState.MIGRATING); var acToPublish = new AutomationComposition(acToBeUpdated); @@ -243,8 +243,8 @@ public class AutomationCompositionInstantiationProvider { } private void updateAcForMigration(AutomationComposition acToBeUpdated, - AutomationCompositionDefinition acDefinition) { - AcmUtils.setCascadedState(acToBeUpdated, DeployState.MIGRATING, LockState.LOCKED); + AutomationCompositionDefinition acDefinition, DeployState deployState) { + AcmUtils.setCascadedState(acToBeUpdated, deployState, LockState.LOCKED); acToBeUpdated.setStateChangeResult(StateChangeResult.NO_ERROR); var stage = ParticipantUtils.getFirstStage(acToBeUpdated, acDefinition.getServiceTemplate()); acToBeUpdated.setPhase(stage); @@ -461,26 +461,39 @@ public class AutomationCompositionInstantiationProvider { /** * Rollback AC Instance. * - * @param instanceId the instanceId + * @param compositionId The UUID of the automation composition definition + * @param instanceId The UUID of the automation composition instance */ public void rollback(UUID compositionId, UUID instanceId) { var automationComposition = automationCompositionProvider.getAutomationComposition(instanceId); validateCompositionRequested(compositionId, automationComposition); - var automationCompositionToRollback = - automationCompositionProvider.getAutomationCompositionRollback(instanceId); - - if (DeployState.DEPLOYED.equals(automationComposition.getDeployState()) - && SubState.NONE.equals(automationComposition.getSubState()) - && StateChangeResult.NO_ERROR.equals(automationComposition.getStateChangeResult())) { - automationComposition.setCompositionId(automationCompositionToRollback.getCompositionId()); - automationComposition.setElements(automationCompositionToRollback.getElements().values().stream() - .collect(Collectors.toMap(AutomationCompositionElement::getId, UnaryOperator.identity()))); - automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR); - AcmUtils.setCascadedState(automationComposition, DeployState.MIGRATION_REVERTING, LockState.LOCKED); - automationCompositionProvider.updateAutomationComposition(automationComposition); - } else { + + if (!DeployOrder.MIGRATION_REVERT.name().equals(acInstanceStateResolver.resolve( + DeployOrder.MIGRATION_REVERT, LockOrder.NONE, + SubOrder.NONE, automationComposition.getDeployState(), automationComposition.getLockState(), + automationComposition.getSubState(), automationComposition.getStateChangeResult()))) { throw new PfModelRuntimeException(Status.BAD_REQUEST, "Invalid state for rollback"); } + + var automationCompositionToRollback = + automationCompositionProvider.getAutomationCompositionRollback(instanceId); + var acToBeUpdated = new AutomationComposition(automationComposition); + acToBeUpdated.setCompositionTargetId(automationCompositionToRollback.getCompositionId()); + acToBeUpdated.setElements(automationCompositionToRollback.getElements().values().stream() + .collect(Collectors.toMap(AutomationCompositionElement::getId, AutomationCompositionElement::new))); + + var acDefinition = acDefinitionProvider.getAcDefinition(acToBeUpdated.getCompositionTargetId()); + var validationResult = + validateAutomationComposition(acToBeUpdated, acToBeUpdated.getCompositionTargetId()); + if (!validationResult.isValid()) { + throw new PfModelRuntimeException(Status.BAD_REQUEST, validationResult.getResult()); + } + + updateAcForMigration(acToBeUpdated, acDefinition, DeployState.MIGRATION_REVERTING); + var elementsRemoved = getElementRemoved(automationComposition, acToBeUpdated); + automationCompositionProvider.updateAutomationComposition(acToBeUpdated); + elementsRemoved.forEach(automationCompositionProvider::deleteAutomationCompositionElement); + supervisionAcHandler.migrate(acToBeUpdated); } private List updateElementsProperties(AutomationComposition automationComposition, diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/AutomationCompositionMigrationPublisher.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/AutomationCompositionMigrationPublisher.java index 572f7b1fe..4aef404fc 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/AutomationCompositionMigrationPublisher.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/AutomationCompositionMigrationPublisher.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation. + * Copyright (C) 2023-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ package org.onap.policy.clamp.acm.runtime.supervision.comm; import io.micrometer.core.annotation.Timed; import java.util.UUID; import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; +import org.onap.policy.clamp.models.acm.concepts.DeployState; import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionMigration; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder; import org.onap.policy.clamp.models.acm.utils.AcmUtils; @@ -43,6 +44,7 @@ public class AutomationCompositionMigrationPublisher description = "AUTOMATION_COMPOSITION_MIGRATION messages published") public void send(AutomationComposition automationComposition, int stage) { var acMigration = new AutomationCompositionMigration(); + acMigration.setRollback(DeployState.MIGRATION_REVERTING.equals(automationComposition.getDeployState())); acMigration.setPrecheck(Boolean.TRUE.equals(automationComposition.getPrecheck())); acMigration.setCompositionId(automationComposition.getCompositionId()); acMigration.setAutomationCompositionId(automationComposition.getInstanceId()); @@ -51,7 +53,6 @@ public class AutomationCompositionMigrationPublisher acMigration.setStage(stage); acMigration.setParticipantUpdatesList( AcmUtils.createParticipantDeployList(automationComposition, DeployOrder.MIGRATE)); - super.send(acMigration); } } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/AbstractScanner.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/AbstractScanner.java index 655abcde9..84b5a9eb3 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/AbstractScanner.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/AbstractScanner.java @@ -59,7 +59,8 @@ public abstract class AbstractScanner { automationComposition.getSubState()); var deployState = automationComposition.getDeployState(); - if (DeployState.MIGRATING.equals(automationComposition.getDeployState())) { + if (DeployState.MIGRATING.equals(automationComposition.getDeployState()) + || DeployState.MIGRATION_REVERTING.equals(automationComposition.getDeployState())) { // migration scenario automationComposition.setCompositionId(automationComposition.getCompositionTargetId()); automationComposition.setCompositionTargetId(null); diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/MonitoringScanner.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/MonitoringScanner.java index dcf0881c1..84367788a 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/MonitoringScanner.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/MonitoringScanner.java @@ -110,6 +110,7 @@ public class MonitoringScanner { } if (DeployState.MIGRATING.equals(automationComposition.getDeployState()) + || DeployState.MIGRATION_REVERTING.equals(automationComposition.getDeployState()) || SubState.PREPARING.equals(automationComposition.getSubState())) { stageScanner.scanStage(automationComposition, serviceTemplate, updateSync); } else if (DeployState.UPDATING.equals(automationComposition.getDeployState()) diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/StageScanner.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/StageScanner.java index 65caa87d2..b9eae8963 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/StageScanner.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/StageScanner.java @@ -79,6 +79,7 @@ public class StageScanner extends AbstractScanner { var toscaNodeTemplate = serviceTemplate.getToscaTopologyTemplate().getNodeTemplates() .get(element.getDefinition().getName()); var stageSet = DeployState.MIGRATING.equals(automationComposition.getDeployState()) + || DeployState.MIGRATION_REVERTING.equals(automationComposition.getDeployState()) ? ParticipantUtils.findStageSetMigrate(toscaNodeTemplate.getProperties()) : ParticipantUtils.findStageSetPrepare(toscaNodeTemplate.getProperties()); var minStage = stageSet.stream().min(Comparator.comparing(Integer::valueOf)).orElse(0); @@ -109,7 +110,8 @@ public class StageScanner extends AbstractScanner { } private void sendNextStage(final AutomationComposition automationComposition, int minStageNotCompleted) { - if (DeployState.MIGRATING.equals(automationComposition.getDeployState())) { + if (DeployState.MIGRATING.equals(automationComposition.getDeployState()) + || DeployState.MIGRATION_REVERTING.equals(automationComposition.getDeployState())) { LOGGER.debug("retry message AutomationCompositionMigration"); acMigrationPublisher.send(automationComposition, minStageNotCompleted); } diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java index 0cfd08ec7..c28c7871c 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java @@ -24,7 +24,6 @@ package org.onap.policy.clamp.acm.runtime.instantiation; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doNothing; @@ -47,6 +46,7 @@ import org.onap.policy.clamp.acm.runtime.util.CommonTestData; import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionRollback; import org.onap.policy.clamp.models.acm.concepts.DeployState; import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; @@ -221,7 +221,8 @@ class AutomationCompositionInstantiationProviderTest { element.setId(UUID.randomUUID()); automationCompositionUpdate.getElements().put(element.getId(), element); } - acmFromDb.getElements().values().forEach(element -> element.setDeployState(DeployState.DEPLOYED)); + acmFromDb.getElements().values().forEach(element -> + element.setDeployState(DeployState.DEPLOYED)); acmFromDb.setDeployState(DeployState.DEPLOYED); assertThatThrownBy( () -> instantiationProvider.updateAutomationComposition(compositionId, automationCompositionUpdate)) @@ -241,23 +242,24 @@ class AutomationCompositionInstantiationProviderTest { .thenReturn(automationCompositionUpdate); var instantiationProvider = - new AutomationCompositionInstantiationProvider(acProvider, mock(AcDefinitionProvider.class), - new AcInstanceStateResolver(), mock(SupervisionAcHandler.class), mock(ParticipantProvider.class), - mock(AcRuntimeParameterGroup.class), encryptionUtils); + new AutomationCompositionInstantiationProvider(acProvider, mock(AcDefinitionProvider.class), + new AcInstanceStateResolver(), mock(SupervisionAcHandler.class), + mock(ParticipantProvider.class), + mock(AcRuntimeParameterGroup.class), encryptionUtils); var compositionId = automationCompositionUpdate.getCompositionId(); assertThatThrownBy( () -> instantiationProvider.updateAutomationComposition(compositionId, automationCompositionUpdate)) - .hasMessageMatching( - "Not allowed to UPDATE in the state " + automationCompositionUpdate.getDeployState()); + .hasMessageMatching( + "Not allowed to UPDATE in the state " + automationCompositionUpdate.getDeployState()); automationCompositionUpdate.setDeployState(DeployState.UPDATING); automationCompositionUpdate.setLockState(LockState.LOCKED); automationCompositionUpdate.setCompositionTargetId(UUID.randomUUID()); assertThatThrownBy( () -> instantiationProvider.updateAutomationComposition(compositionId, automationCompositionUpdate)) - .hasMessageMatching( - "Not allowed to MIGRATE in the state " + automationCompositionUpdate.getDeployState()); + .hasMessageMatching( + "Not allowed to MIGRATE in the state " + automationCompositionUpdate.getDeployState()); } @Test @@ -306,7 +308,7 @@ class AutomationCompositionInstantiationProviderTest { AcmUtils.setCascadedState(automationComposition, DeployState.DEPLOYED, LockState.LOCKED, SubState.NONE); var instantiationResponse = instantiationProvider.updateAutomationComposition(compositionId, - automationCompositionTarget); + automationCompositionTarget); verify(supervisionAcHandler).migrate(any()); InstantiationUtils.assertInstantiationResponse(instantiationResponse, automationCompositionTarget); @@ -360,13 +362,13 @@ class AutomationCompositionInstantiationProviderTest { var participantProvider = mock(ParticipantProvider.class); var encryptionUtils = new EncryptionUtils(CommonTestData.getTestParamaterGroup()); var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, - new AcInstanceStateResolver(), supervisionAcHandler, participantProvider, new AcRuntimeParameterGroup(), + new AcInstanceStateResolver(), supervisionAcHandler, participantProvider, new AcRuntimeParameterGroup(), encryptionUtils); assertThatThrownBy(() -> instantiationProvider .updateAutomationComposition(automationComposition.getCompositionId(), automationComposition)) - .hasMessageMatching( - String.format(AC_DEFINITION_NOT_FOUND, automationComposition.getCompositionTargetId())); + .hasMessageMatching( + String.format(AC_DEFINITION_NOT_FOUND, automationComposition.getCompositionTargetId())); var acDefinitionTarget = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); var compositionTargetId = acDefinitionTarget.getCompositionId(); @@ -391,7 +393,7 @@ class AutomationCompositionInstantiationProviderTest { when(acDefinitionProvider.findAcDefinition(compositionId)).thenReturn(Optional.of(acDefinition)); var automationComposition = - InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Crud"); + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Crud"); automationComposition.setCompositionId(compositionId); automationComposition.setDeployState(DeployState.DEPLOYED); automationComposition.setLockState(LockState.LOCKED); @@ -399,20 +401,20 @@ class AutomationCompositionInstantiationProviderTest { automationComposition.setPrecheck(true); var acProvider = mock(AutomationCompositionProvider.class); when(acProvider.getAutomationComposition(automationComposition.getInstanceId())) - .thenReturn(automationComposition); + .thenReturn(automationComposition); when(acProvider.updateAutomationComposition(automationComposition)).thenReturn(automationComposition); var supervisionAcHandler = mock(SupervisionAcHandler.class); var acmParticipantProvider = mock(ParticipantProvider.class); var encryptionUtils = mock(EncryptionUtils.class); var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, - new AcInstanceStateResolver(), supervisionAcHandler, acmParticipantProvider, new AcRuntimeParameterGroup(), - encryptionUtils); + new AcInstanceStateResolver(), supervisionAcHandler, acmParticipantProvider, + new AcRuntimeParameterGroup(), encryptionUtils); assertThatThrownBy(() -> instantiationProvider - .updateAutomationComposition(automationComposition.getCompositionId(), automationComposition)) - .hasMessageMatching( - String.format(AC_DEFINITION_NOT_FOUND, automationComposition.getCompositionTargetId())); + .updateAutomationComposition(automationComposition.getCompositionId(), automationComposition)) + .hasMessageMatching( + String.format(AC_DEFINITION_NOT_FOUND, automationComposition.getCompositionTargetId())); var acDefinitionTarget = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); var compositionTargetId = acDefinitionTarget.getCompositionId(); @@ -421,7 +423,7 @@ class AutomationCompositionInstantiationProviderTest { automationComposition.setCompositionTargetId(compositionTargetId); var instantiationResponse = instantiationProvider - .updateAutomationComposition(automationComposition.getCompositionId(), automationComposition); + .updateAutomationComposition(automationComposition.getCompositionId(), automationComposition); verify(supervisionAcHandler).migratePrecheck(any()); verify(acProvider).updateAutomationComposition(automationComposition); @@ -555,7 +557,7 @@ class AutomationCompositionInstantiationProviderTest { var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); var compositionId = acDefinition.getCompositionId(); var automationComposition = - InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Rollback"); + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Rollback"); automationComposition.setCompositionId(compositionId); automationComposition.setInstanceId(UUID.randomUUID()); automationComposition.setDeployState(DeployState.MIGRATION_REVERTING); @@ -563,7 +565,7 @@ class AutomationCompositionInstantiationProviderTest { var acProvider = mock(AutomationCompositionProvider.class); when(acProvider.getAutomationComposition(automationComposition.getInstanceId())) - .thenReturn(automationComposition); + .thenReturn(automationComposition); var rollbackRecord = new JpaAutomationCompositionRollback(); when(acProvider.getAutomationCompositionRollback(any(UUID.class))).thenReturn(rollbackRecord.toAuthorative()); @@ -572,15 +574,15 @@ class AutomationCompositionInstantiationProviderTest { final var participantProvider = mock(ParticipantProvider.class); final var encryptionUtils = new EncryptionUtils(CommonTestData.getTestParamaterGroup()); var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, - new AcInstanceStateResolver(), supervisionAcHandler, participantProvider, new AcRuntimeParameterGroup(), - encryptionUtils); + new AcInstanceStateResolver(), supervisionAcHandler, participantProvider, new AcRuntimeParameterGroup(), + encryptionUtils); var instanceId = automationComposition.getInstanceId(); assertThrows(PfModelRuntimeException.class, () -> instantiationProvider.rollback(compositionId, instanceId)); // DeployState != MIGRATION_REVERTING when(acProvider.getAutomationComposition(automationComposition.getInstanceId())) - .thenReturn(automationComposition); + .thenReturn(automationComposition); when(acProvider.getAutomationCompositionRollback(any(UUID.class))).thenReturn(rollbackRecord.toAuthorative()); automationComposition.setDeployState(DeployState.DELETING); @@ -605,44 +607,53 @@ class AutomationCompositionInstantiationProviderTest { @Test void testRollbackSuccess() { - final var acDefinitionProvider = mock(AcDefinitionProvider.class); - final var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); - final var compositionId = acDefinition.getCompositionId(); + var acDefinitionProvider = mock(AcDefinitionProvider.class); + var acDefinition = CommonTestData.createAcDefinition(serviceTemplateMigration, AcTypeState.PRIMED); + var compositionId = acDefinition.getCompositionId(); + when(acDefinitionProvider.findAcDefinition(compositionId)).thenReturn(Optional.of(acDefinition)); var automationComposition = - InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Rollback"); - automationComposition.setInstanceId(UUID.randomUUID()); + InstantiationUtils.getAutomationCompositionFromResource(AC_MIGRATE_JSON, "Crud"); + var instanceId = UUID.randomUUID(); + automationComposition.setInstanceId(instanceId); automationComposition.setCompositionId(compositionId); - automationComposition.setDeployState(DeployState.DEPLOYED); - automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR); + automationComposition.setDeployState(DeployState.MIGRATING); + automationComposition.setLockState(LockState.LOCKED); + automationComposition.setStateChangeResult(StateChangeResult.FAILED); automationComposition.setSubState(SubState.NONE); - automationComposition.setCompositionTargetId(UUID.randomUUID()); - var acProvider = mock(AutomationCompositionProvider.class); - when(acProvider.getAutomationComposition(automationComposition.getInstanceId())) - .thenReturn(automationComposition); - final var supervisionAcHandler = mock(SupervisionAcHandler.class); - final var participantProvider = mock(ParticipantProvider.class); - final var encryptionUtils = new EncryptionUtils(CommonTestData.getTestParamaterGroup()); - final var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, - acDefinitionProvider, new AcInstanceStateResolver(), supervisionAcHandler, - participantProvider, new AcRuntimeParameterGroup(), encryptionUtils); + when(acProvider.getAutomationComposition(instanceId)).thenReturn(automationComposition); + when(acProvider.updateAutomationComposition(automationComposition)).thenReturn(automationComposition); - var rollbackRecord = new JpaAutomationCompositionRollback(); - rollbackRecord.setCompositionId(automationComposition.getCompositionId().toString()); + var acRollback = + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Crud"); - when(acProvider.getAutomationComposition(automationComposition.getInstanceId())) - .thenReturn(automationComposition); - when(acProvider.getAutomationCompositionRollback(any(UUID.class))).thenReturn(rollbackRecord.toAuthorative()); + var rollbackRecord = new AutomationCompositionRollback(); + var compositionTargetId = UUID.randomUUID(); + rollbackRecord.setCompositionId(compositionTargetId); + rollbackRecord.setInstanceId(instanceId); + rollbackRecord.setElements(acRollback.getElements()); + when(acProvider.getAutomationCompositionRollback(instanceId)).thenReturn(rollbackRecord); - instantiationProvider.rollback(compositionId, automationComposition.getInstanceId()); + var supervisionAcHandler = mock(SupervisionAcHandler.class); + var participantProvider = mock(ParticipantProvider.class); + var encryptionUtils = new EncryptionUtils(CommonTestData.getTestParamaterGroup()); + var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, + new AcInstanceStateResolver(), supervisionAcHandler, participantProvider, new AcRuntimeParameterGroup(), + encryptionUtils); + assertThatThrownBy(() -> instantiationProvider.rollback(compositionId, instanceId)) + .hasMessageMatching(String.format(AC_DEFINITION_NOT_FOUND, compositionTargetId)); - verify(acProvider).updateAutomationComposition(automationComposition); - assertEquals(DeployState.MIGRATION_REVERTING, automationComposition.getDeployState()); + var acDefinitionTarget = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); + when(acDefinitionProvider.findAcDefinition(compositionTargetId)).thenReturn(Optional.of(acDefinitionTarget)); + when(acDefinitionProvider.getAcDefinition(compositionTargetId)).thenReturn(acDefinitionTarget); + + instantiationProvider.rollback(compositionId, automationComposition.getInstanceId()); + verify(acProvider).updateAutomationComposition(any(AutomationComposition.class)); } private void assertThatDeleteThrownBy(AutomationComposition automationComposition, DeployState deployState, - LockState lockState) { + LockState lockState) { automationComposition.setDeployState(deployState); automationComposition.setLockState(lockState); var acProvider = mock(AutomationCompositionProvider.class); @@ -697,7 +708,7 @@ class AutomationCompositionInstantiationProviderTest { assertThatThrownBy( () -> instantiationProvider.createAutomationComposition(compositionId, automationCompositionCreate)) - .hasMessageMatching(automationCompositionCreate.getKey().asIdentifier() + " already defined"); + .hasMessageMatching(automationCompositionCreate.getKey().asIdentifier() + " already defined"); } @Test @@ -768,16 +779,16 @@ class AutomationCompositionInstantiationProviderTest { assertThatThrownBy( () -> provider.getAutomationComposition(wrongCompositionId, automationComposition.getInstanceId())) - .hasMessageMatching(compositionId + DO_NOT_MATCH + wrongCompositionId); + .hasMessageMatching(compositionId + DO_NOT_MATCH + wrongCompositionId); assertThatThrownBy(() -> provider.compositionInstanceState(wrongCompositionId, automationComposition.getInstanceId(), new AcInstanceStateUpdate())) - .hasMessageMatching(compositionId + DO_NOT_MATCH + wrongCompositionId); + .hasMessageMatching(compositionId + DO_NOT_MATCH + wrongCompositionId); var compositionTargetId = UUID.randomUUID(); automationComposition.setCompositionTargetId(compositionTargetId); assertThatThrownBy( () -> provider.getAutomationComposition(wrongCompositionId, automationComposition.getInstanceId())) - .hasMessageMatching(compositionId + DO_NOT_MATCH + wrongCompositionId); + .hasMessageMatching(compositionId + DO_NOT_MATCH + wrongCompositionId); var result = provider.getAutomationComposition(compositionTargetId, automationComposition.getInstanceId()); assertThat(result).isNotNull(); @@ -873,4 +884,4 @@ class AutomationCompositionInstantiationProviderTest { provider.compositionInstanceState(compositionId, instanceId, acInstanceStateUpdate); verify(supervisionAcHandler).review(any(AutomationComposition.class)); } -} +} \ No newline at end of file diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java index dd015b968..44582d656 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java @@ -292,6 +292,49 @@ class SupervisionScannerTest { verify(messageProvider).removeJob(JOB_ID); } + @Test + void testSendAutomationCompositionMigrationReverting() { + var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud"); + automationComposition.setDeployState(DeployState.MIGRATION_REVERTING); + automationComposition.setInstanceId(INSTANCE_ID); + automationComposition.setCompositionId(COMPOSITION_ID); + var compositionTargetId = UUID.randomUUID(); + automationComposition.setCompositionTargetId(compositionTargetId); + automationComposition.setLockState(LockState.LOCKED); + automationComposition.setLastMsg(TimestampHelper.now()); + automationComposition.setPhase(0); + for (var element : automationComposition.getElements().values()) { + element.setDeployState(DeployState.DEPLOYED); + element.setLockState(LockState.LOCKED); + } + + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + Set set = new HashSet<>(); + set.add(automationComposition.getInstanceId()); + when(automationCompositionProvider.getAcInstancesInTransition()).thenReturn(set); + when(automationCompositionProvider.findAutomationComposition(automationComposition.getInstanceId())) + .thenReturn(Optional.of(automationComposition)); + + var definitionTarget = createAutomationCompositionDefinition(AcTypeState.PRIMED); + definitionTarget.setCompositionId(compositionTargetId); + var acDefinitionProvider = createAcDefinitionProvider(AcTypeState.PRIMED); + when(acDefinitionProvider.getAcDefinition(compositionTargetId)).thenReturn(definitionTarget); + var stageScanner = mock(StageScanner.class); + + var messageProvider = mock(MessageProvider.class); + when(messageProvider.createJob(automationComposition.getInstanceId())).thenReturn(Optional.of(JOB_ID)); + var monitoringScanner = new MonitoringScanner(automationCompositionProvider, acDefinitionProvider, + mock(AcDefinitionScanner.class), stageScanner, mock(SimpleScanner.class), mock(PhaseScanner.class), + messageProvider); + var supervisionScanner = new SupervisionScanner(automationCompositionProvider, acDefinitionProvider, + messageProvider, monitoringScanner); + + supervisionScanner.run(); + verify(stageScanner).scanStage(automationComposition, definitionTarget.getServiceTemplate(), + new UpdateSync()); + verify(messageProvider).removeJob(JOB_ID); + } + @Test void testSendAutomationCompositionSimpleScan() { var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud"); diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/StageScannerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/StageScannerTest.java index 1cd1146a5..f51d43d52 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/StageScannerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/StageScannerTest.java @@ -101,6 +101,57 @@ class StageScannerTest { assertEquals(compositionTargetId, automationComposition.getCompositionId()); } + @Test + void testSendAutomationCompositionMigrationReverting() { + var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud"); + automationComposition.setInstanceId(UUID.randomUUID()); + automationComposition.setDeployState(DeployState.MIGRATION_REVERTING); + automationComposition.setCompositionId(COMPOSITION_ID); + var compositionTargetId = UUID.randomUUID(); + automationComposition.setCompositionTargetId(compositionTargetId); + automationComposition.setLockState(LockState.LOCKED); + automationComposition.setLastMsg(TimestampHelper.now()); + automationComposition.setPhase(0); + for (var element : automationComposition.getElements().values()) { + element.setDeployState(DeployState.DEPLOYED); + element.setLockState(LockState.LOCKED); + } + // first element is not migrated yet + var element = automationComposition.getElements().entrySet().iterator().next().getValue(); + element.setDeployState(DeployState.MIGRATION_REVERTING); + + var acProvider = mock(AutomationCompositionProvider.class); + when(acProvider.updateAutomationComposition(any())).thenReturn(automationComposition); + var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner"); + var encryptionUtils = new EncryptionUtils(acRuntimeParameterGroup); + var supervisionScanner = new StageScanner(acProvider, mock(ParticipantSyncPublisher.class), + mock(AutomationCompositionMigrationPublisher.class), mock(AcPreparePublisher.class), + acRuntimeParameterGroup, encryptionUtils); + var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); + supervisionScanner.scanStage(automationComposition, serviceTemplate, new UpdateSync()); + verify(acProvider, times(0)).updateAutomationComposition(any(AutomationComposition.class)); + assertEquals(DeployState.MIGRATION_REVERTING, automationComposition.getDeployState()); + + // send message for next stage + clearInvocations(acProvider); + var toscaNodeTemplate = serviceTemplate.getToscaTopologyTemplate().getNodeTemplates() + .get(element.getDefinition().getName()); + toscaNodeTemplate.setProperties(Map.of("stage", List.of(1))); + + supervisionScanner.scanStage(automationComposition, serviceTemplate, new UpdateSync()); + verify(acProvider).updateAutomationComposition(any(AutomationComposition.class)); + assertEquals(DeployState.MIGRATION_REVERTING, automationComposition.getDeployState()); + + // first element is migrated + clearInvocations(acProvider); + element.setDeployState(DeployState.DEPLOYED); + supervisionScanner.scanStage(automationComposition, serviceTemplate, new UpdateSync()); + verify(acProvider).updateAutomationComposition(any(AutomationComposition.class)); + + assertEquals(DeployState.DEPLOYED, automationComposition.getDeployState()); + assertEquals(compositionTargetId, automationComposition.getCompositionId()); + } + @Test void testSendAutomationCompositionPrepare() { var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud");