From d65aa6abc70ad9dff9c74984f2a600607892f831 Mon Sep 17 00:00:00 2001 From: FrancescoFioraEst Date: Fri, 10 Feb 2023 12:54:14 +0000 Subject: Initial support for Implement recording of Operational State Remove AutomationCompositionState and AutomationCompositionOrderedState in Jpa classes add validation to not update deployed instances Issue-ID: POLICY-4550 Change-Id: If18915a4be6b67dda83ff3ca5457ed52d0e8ddf2 Signed-off-by: FrancescoFioraEst --- ...AutomationCompositionInstantiationProvider.java | 16 ++- ...mationCompositionInstantiationProviderTest.java | 140 +++++++++++++++++++-- .../test/resources/rest/acm/PassiveCommand.json | 7 -- 3 files changed, 137 insertions(+), 26 deletions(-) delete mode 100644 runtime-acm/src/test/resources/rest/acm/PassiveCommand.json (limited to 'runtime-acm') 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 62a769fdb..02e5b1ac6 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 @@ -29,8 +29,8 @@ import lombok.AllArgsConstructor; import org.onap.policy.clamp.acm.runtime.supervision.SupervisionAcHandler; 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.AutomationCompositionState; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions; +import org.onap.policy.clamp.models.acm.concepts.DeployState; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.AcInstanceStateUpdate; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationResponse; import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; @@ -106,6 +106,10 @@ public class AutomationCompositionInstantiationProvider { throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId); } + if (!DeployState.UNDEPLOYED.equals(acToUpdate.getDeployState())) { + throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, + "Not allow to update for state in " + acToUpdate.getDeployState()); + } acToUpdate.setElements(automationComposition.getElements()); acToUpdate.setName(automationComposition.getName()); acToUpdate.setVersion(automationComposition.getVersion()); @@ -139,8 +143,8 @@ public class AutomationCompositionInstantiationProvider { return result; } if (!AcTypeState.PRIMED.equals(acDefinitionOpt.get().getState())) { - result.addResult(new ObjectValidationResult("ServiceTemplate", "", ValidationStatus.INVALID, - "Commissioned automation composition definition not primed")); + result.addResult(new ObjectValidationResult("ServiceTemplate", acDefinitionOpt.get().getState(), + ValidationStatus.INVALID, "Commissioned automation composition definition not primed")); return result; } result.addResult(AcmUtils.validateAutomationComposition(automationComposition, @@ -169,7 +173,7 @@ public class AutomationCompositionInstantiationProvider { var automationComposition = automationCompositionProvider.getAutomationComposition(instanceId); if (!automationComposition.getCompositionId().equals(compositionId)) { throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, - "Composition Id " + compositionId + DO_NOT_MATCH + automationComposition.getCompositionId()); + automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId); } return automationComposition; } @@ -187,9 +191,9 @@ public class AutomationCompositionInstantiationProvider { throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId); } - if (!AutomationCompositionState.UNINITIALISED.equals(automationComposition.getState())) { + if (!DeployState.UNDEPLOYED.equals(automationComposition.getDeployState())) { throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, - "Automation composition state is still " + automationComposition.getState()); + "Automation composition state is still " + automationComposition.getDeployState()); } var response = new InstantiationResponse(); automationComposition = 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 1acaebea6..9f39d8dc6 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 @@ -23,6 +23,7 @@ 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.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -33,12 +34,19 @@ import java.util.Optional; import java.util.UUID; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.onap.policy.clamp.acm.runtime.supervision.SupervisionAcHandler; import org.onap.policy.clamp.acm.runtime.util.CommonTestData; import org.onap.policy.clamp.common.acm.exception.AutomationCompositionException; 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.AutomationCompositionState; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition; +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.messages.rest.instantiation.AcInstanceStateUpdate; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.LockOrder; import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.AcInstanceStateResolver; import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider; import org.onap.policy.clamp.models.acm.persistence.provider.ProviderUtils; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; @@ -151,20 +159,21 @@ class AutomationCompositionInstantiationProviderTest { assertThatThrownBy(() -> instantiationProvider.deleteAutomationComposition(wrongCompositionId, instanceId)) .hasMessageMatching(compositionId + DO_NOT_MATCH + wrongCompositionId); - for (var state : AutomationCompositionState.values()) { - if (!AutomationCompositionState.UNINITIALISED.equals(state)) { - assertThatDeleteThrownBy(automationComposition, state); - } - } - automationComposition.setState(AutomationCompositionState.UNINITIALISED); + assertThatDeleteThrownBy(automationComposition, DeployState.DEPLOYED, LockState.LOCKED); + assertThatDeleteThrownBy(automationComposition, DeployState.DEPLOYING, LockState.NONE); + assertThatDeleteThrownBy(automationComposition, DeployState.UNDEPLOYING, LockState.LOCKED); + + automationComposition.setDeployState(DeployState.UNDEPLOYED); + automationComposition.setLockState(LockState.NONE); when(acProvider.deleteAutomationComposition(instanceId)).thenReturn(automationComposition); instantiationProvider.deleteAutomationComposition(compositionId, instanceId); } private void assertThatDeleteThrownBy(AutomationComposition automationComposition, - AutomationCompositionState state) { - automationComposition.setState(state); + DeployState deployState, LockState lockState) { + automationComposition.setDeployState(deployState); + automationComposition.setLockState(lockState); var acProvider = mock(AutomationCompositionProvider.class); var acDefinitionProvider = mock(AcDefinitionProvider.class); @@ -177,7 +186,7 @@ class AutomationCompositionInstantiationProviderTest { var compositionId = automationComposition.getCompositionId(); var instanceId = automationComposition.getInstanceId(); assertThatThrownBy(() -> instantiationProvider.deleteAutomationComposition(compositionId, instanceId)) - .hasMessageMatching(String.format(DELETE_BAD_REQUEST, state)); + .hasMessageMatching(String.format(DELETE_BAD_REQUEST, deployState)); } @Test @@ -236,16 +245,15 @@ class AutomationCompositionInstantiationProviderTest { } @Test - void testCreateAutomationCompositions_CommissionedAcNotFound() { + void testAcDefinitionNotFound() { var automationComposition = InstantiationUtils .getAutomationCompositionFromResource(AC_INSTANTIATION_AC_DEFINITION_NOT_FOUND_JSON, "AcNotFound"); var acProvider = mock(AutomationCompositionProvider.class); when(acProvider.getAutomationComposition(automationComposition.getInstanceId())) .thenReturn(automationComposition); - var acDefinitionProvider = mock(AcDefinitionProvider.class); var provider = new AutomationCompositionInstantiationProvider(acProvider, - acDefinitionProvider, null, null); + mock(AcDefinitionProvider.class), null, null); var compositionId = automationComposition.getCompositionId(); assertThatThrownBy(() -> provider.createAutomationComposition(compositionId, automationComposition)) @@ -253,12 +261,118 @@ class AutomationCompositionInstantiationProviderTest { assertThatThrownBy(() -> provider.updateAutomationComposition(compositionId, automationComposition)) .hasMessageMatching(AC_DEFINITION_NOT_FOUND); + } + + @Test + void testCompositionIdDoNotMatch() { + var automationComposition = InstantiationUtils + .getAutomationCompositionFromResource(AC_INSTANTIATION_AC_DEFINITION_NOT_FOUND_JSON, "AcNotFound"); + + var acProvider = mock(AutomationCompositionProvider.class); + when(acProvider.getAutomationComposition(automationComposition.getInstanceId())) + .thenReturn(automationComposition); + var provider = new AutomationCompositionInstantiationProvider(acProvider, + mock(AcDefinitionProvider.class), null, null); + var compositionId = automationComposition.getCompositionId(); var wrongCompositionId = UUID.randomUUID(); assertThatThrownBy(() -> provider.createAutomationComposition(wrongCompositionId, automationComposition)) .hasMessageMatching(compositionId + DO_NOT_MATCH + wrongCompositionId); assertThatThrownBy(() -> provider.updateAutomationComposition(wrongCompositionId, automationComposition)) .hasMessageMatching(compositionId + DO_NOT_MATCH + wrongCompositionId); + + assertThatThrownBy( + () -> provider.getAutomationComposition(wrongCompositionId, automationComposition.getInstanceId())) + .hasMessageMatching(compositionId + DO_NOT_MATCH + wrongCompositionId); + assertThatThrownBy(() -> provider.compositionInstanceState(wrongCompositionId, + automationComposition.getInstanceId(), new AcInstanceStateUpdate())) + .hasMessageMatching(compositionId + DO_NOT_MATCH + wrongCompositionId); + } + + @Test + void testCompositionNotPrimed() { + var acDefinitionProvider = mock(AcDefinitionProvider.class); + var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.COMMISSIONED); + var compositionId = acDefinition.getCompositionId(); + when(acDefinitionProvider.findAcDefinition(compositionId)).thenReturn(Optional.of(acDefinition)); + var acProvider = mock(AutomationCompositionProvider.class); + var provider = + new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, null, null); + + var automationComposition = + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Crud"); + automationComposition.setCompositionId(compositionId); + assertThatThrownBy(() -> provider.createAutomationComposition(compositionId, automationComposition)) + .hasMessageMatching("\"AutomationComposition\" INVALID, item has status INVALID\n" + + " item \"ServiceTemplate\" value \"COMMISSIONED\" INVALID," + + " Commissioned automation composition definition not primed\n"); + } + + @Test + void testUpdateBadRequest() { + var automationComposition = InstantiationUtils + .getAutomationCompositionFromResource(AC_INSTANTIATION_AC_DEFINITION_NOT_FOUND_JSON, "AcNotFound"); + + var acProvider = mock(AutomationCompositionProvider.class); + automationComposition.setDeployState(DeployState.DEPLOYED); + when(acProvider.getAutomationComposition(automationComposition.getInstanceId())) + .thenReturn(automationComposition); + var provider = new AutomationCompositionInstantiationProvider(acProvider, + mock(AcDefinitionProvider.class), null, null); + + assertThatThrownBy(() -> provider.updateAutomationComposition(automationComposition.getCompositionId(), + automationComposition)).hasMessageMatching("Not allow to update for state in DEPLOYED"); + } + + @Test + void testCompositionInstanceState() { + var acDefinitionProvider = mock(AcDefinitionProvider.class); + var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.COMMISSIONED); + var compositionId = acDefinition.getCompositionId(); + when(acDefinitionProvider.getAcDefinition(compositionId)).thenReturn(acDefinition); + + var automationComposition = InstantiationUtils + .getAutomationCompositionFromResource(AC_INSTANTIATION_AC_DEFINITION_NOT_FOUND_JSON, "AcNotFound"); + var instanceId = UUID.randomUUID(); + automationComposition.setCompositionId(compositionId); + automationComposition.setInstanceId(instanceId); + var acProvider = mock(AutomationCompositionProvider.class); + when(acProvider.getAutomationComposition(instanceId)) + .thenReturn(automationComposition); + + var supervisionAcHandler = mock(SupervisionAcHandler.class); + var provider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, + new AcInstanceStateResolver(), supervisionAcHandler); + + var acInstanceStateUpdate = new AcInstanceStateUpdate(); + acInstanceStateUpdate.setDeployOrder(DeployOrder.DEPLOY); + acInstanceStateUpdate.setLockOrder(LockOrder.NONE); + provider.compositionInstanceState(compositionId, instanceId, acInstanceStateUpdate); + verify(supervisionAcHandler).deploy(any(AutomationComposition.class), + any(AutomationCompositionDefinition.class)); + + automationComposition.setDeployState(DeployState.DEPLOYED); + automationComposition.setLockState(LockState.LOCKED); + acInstanceStateUpdate.setDeployOrder(DeployOrder.UNDEPLOY); + provider.compositionInstanceState(compositionId, instanceId, acInstanceStateUpdate); + verify(supervisionAcHandler).undeploy(any(AutomationComposition.class), + any(AutomationCompositionDefinition.class)); + + automationComposition.setDeployState(DeployState.DEPLOYED); + automationComposition.setLockState(LockState.LOCKED); + acInstanceStateUpdate.setDeployOrder(DeployOrder.NONE); + acInstanceStateUpdate.setLockOrder(LockOrder.UNLOCK); + provider.compositionInstanceState(compositionId, instanceId, acInstanceStateUpdate); + verify(supervisionAcHandler).unlock(any(AutomationComposition.class), + any(AutomationCompositionDefinition.class)); + + automationComposition.setDeployState(DeployState.DEPLOYED); + automationComposition.setLockState(LockState.UNLOCKED); + acInstanceStateUpdate.setDeployOrder(DeployOrder.NONE); + acInstanceStateUpdate.setLockOrder(LockOrder.LOCK); + provider.compositionInstanceState(compositionId, instanceId, acInstanceStateUpdate); + verify(supervisionAcHandler).lock(any(AutomationComposition.class), + any(AutomationCompositionDefinition.class)); } } diff --git a/runtime-acm/src/test/resources/rest/acm/PassiveCommand.json b/runtime-acm/src/test/resources/rest/acm/PassiveCommand.json deleted file mode 100644 index 93f131cd8..000000000 --- a/runtime-acm/src/test/resources/rest/acm/PassiveCommand.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "orderedState": "PASSIVE", - "automationCompositionIdentifier": { - "name": "PMSHInstance0", - "version": "1.0.1" - } -} \ No newline at end of file -- cgit 1.2.3-korg