From d58c0ca04ae993702b2c399afd52b01e503ec0fe Mon Sep 17 00:00:00 2001 From: FrancescoFioraEst Date: Fri, 2 Jun 2023 12:36:45 +0100 Subject: Add Failure handling support in all ACM-participants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In any transition (like deploy, undeploy,  lock, unlock, update, delete) a participant should respond with the final state of transition, a status indicator (stateChaneResult) indicating if error has occurred and a message. Issue-ID: POLICY-4706 Change-Id: I424bc6d620f476392baee8904e21d3a6c7aa8d6b Signed-off-by: FrancescoFioraEst --- .../AutomationCompositionElementHandler.java | 58 +++++++++++++-- .../AutomationCompositionElementHandlerTest.java | 86 ++++++++++++++++++++-- 2 files changed, 131 insertions(+), 13 deletions(-) (limited to 'participant/participant-impl/participant-impl-policy') diff --git a/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandler.java b/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandler.java index 5eb997e52..0b8ffe2a3 100644 --- a/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandler.java +++ b/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandler.java @@ -23,10 +23,10 @@ package org.onap.policy.clamp.acm.participant.policy.main.handler; import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import javax.ws.rs.core.Response.Status; import lombok.RequiredArgsConstructor; import lombok.Setter; @@ -36,7 +36,11 @@ import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantInterme import org.onap.policy.clamp.acm.participant.policy.client.PolicyApiHttpClient; import org.onap.policy.clamp.acm.participant.policy.client.PolicyPapHttpClient; import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition; 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; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.pdp.concepts.DeploymentSubGroup; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; @@ -54,7 +58,7 @@ public class AutomationCompositionElementHandler implements AutomationCompositio private static final Logger LOGGER = LoggerFactory.getLogger(AutomationCompositionElementHandler.class); - private final Map serviceTemplateMap = new LinkedHashMap<>(); + private final Map serviceTemplateMap = new ConcurrentHashMap<>(); private final PolicyApiHttpClient apiHttpClient; private final PolicyPapHttpClient papHttpClient; @@ -74,7 +78,8 @@ public class AutomationCompositionElementHandler implements AutomationCompositio if (automationCompositionDefinition == null) { LOGGER.debug("No policies to undeploy to {}", automationCompositionElementId); intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, - automationCompositionElementId, DeployState.UNDEPLOYED, null, "Undeployed"); + automationCompositionElementId, DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, + "Undeployed"); return; } var policyList = getPolicyList(automationCompositionDefinition); @@ -82,8 +87,8 @@ public class AutomationCompositionElementHandler implements AutomationCompositio var policyTypeList = getPolicyTypeList(automationCompositionDefinition); deletePolicyData(policyTypeList, policyList); serviceTemplateMap.remove(automationCompositionElementId); - intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, - automationCompositionElementId, DeployState.UNDEPLOYED, null, "Undeployed"); + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, automationCompositionElementId, + DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed"); } private void deletePolicyData(List policyTypeList, @@ -119,7 +124,7 @@ public class AutomationCompositionElementHandler implements AutomationCompositio intermediaryApi.sendAcElementInfo(automationCompositionId, automationCompositionElementId, "IDLE", "ENABLED", Map.of()); intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, - automationCompositionElementId, DeployState.DEPLOYED, null, "Deployed"); + automationCompositionElementId, DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed"); } else { throw new PfModelException(Status.BAD_REQUEST, "Deploy of Policy failed."); } @@ -155,7 +160,7 @@ public class AutomationCompositionElementHandler implements AutomationCompositio var automationCompositionDefinition = element.getToscaServiceTemplateFragment(); if (automationCompositionDefinition.getToscaTopologyTemplate() == null) { intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(), - DeployState.UNDEPLOYED, null, "ToscaTopologyTemplate not defined"); + DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "ToscaTopologyTemplate not defined"); return; } serviceTemplateMap.put(element.getId(), automationCompositionDefinition); @@ -177,7 +182,7 @@ public class AutomationCompositionElementHandler implements AutomationCompositio deployPolicies(policyList, automationCompositionId, element.getId()); } else { intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(), - DeployState.UNDEPLOYED, null, + DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Creation of PolicyTypes/Policies failed. Policies will not be deployed."); } } @@ -205,4 +210,41 @@ public class AutomationCompositionElementHandler implements AutomationCompositio return policyList; } + + @Override + public void lock(UUID instanceId, UUID elementId) throws PfModelException { + intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, null, LockState.LOCKED, + StateChangeResult.NO_ERROR, "Locked"); + } + + @Override + public void unlock(UUID instanceId, UUID elementId) throws PfModelException { + intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, null, LockState.UNLOCKED, + StateChangeResult.NO_ERROR, "Unlocked"); + } + + @Override + public void delete(UUID instanceId, UUID elementId) throws PfModelException { + intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, DeployState.DELETED, null, + StateChangeResult.NO_ERROR, "Deleted"); + } + + @Override + public void update(UUID instanceId, AcElementDeploy element, Map properties) + throws PfModelException { + intermediaryApi.updateAutomationCompositionElementState(instanceId, element.getId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Update not supported"); + } + + @Override + public void prime(UUID compositionId, List elementDefinitionList) + throws PfModelException { + intermediaryApi.updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.NO_ERROR, "Primed"); + } + + @Override + public void deprime(UUID compositionId) throws PfModelException { + intermediaryApi.updateCompositionState(compositionId, AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR, + "Deprimed"); + } } diff --git a/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandlerTest.java b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandlerTest.java index 4cf5a5847..ec55c178f 100644 --- a/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandlerTest.java +++ b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandlerTest.java @@ -35,7 +35,10 @@ import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantInterme import org.onap.policy.clamp.acm.participant.policy.client.PolicyApiHttpClient; import org.onap.policy.clamp.acm.participant.policy.client.PolicyPapHttpClient; import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; 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; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; @@ -61,7 +64,7 @@ class AutomationCompositionElementHandlerTest { handler.undeploy(AC_ID, automationCompositionElementId); verify(intermediaryApi).updateAutomationCompositionElementState(AC_ID, automationCompositionElementId, - DeployState.UNDEPLOYED, null, "Undeployed"); + DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed"); } private AcElementDeploy getTestingAcElement() { @@ -93,11 +96,11 @@ class AutomationCompositionElementHandlerTest { handler.deploy(AC_ID, getTestingAcElement(), Map.of()); verify(intermediaryApi).updateAutomationCompositionElementState(AC_ID, automationCompositionElementId, - DeployState.DEPLOYED, null, "Deployed"); + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed"); handler.undeploy(AC_ID, automationCompositionElementId); verify(intermediaryApi).updateAutomationCompositionElementState(AC_ID, automationCompositionElementId, - DeployState.UNDEPLOYED, null, "Undeployed"); + DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed"); } @Test @@ -111,7 +114,7 @@ class AutomationCompositionElementHandlerTest { acElement.getToscaServiceTemplateFragment().setToscaTopologyTemplate(null); handler.deploy(AC_ID, acElement, Map.of()); verify(intermediaryApi).updateAutomationCompositionElementState(AC_ID, automationCompositionElementId, - DeployState.UNDEPLOYED, null, "ToscaTopologyTemplate not defined"); + DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "ToscaTopologyTemplate not defined"); } @Test @@ -131,7 +134,7 @@ class AutomationCompositionElementHandlerTest { // Mock failure in policy type creation handler.deploy(AC_ID, element, Map.of()); verify(intermediaryApi).updateAutomationCompositionElementState(AC_ID, automationCompositionElementId, - DeployState.UNDEPLOYED, null, + DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Creation of PolicyTypes/Policies failed. Policies will not be deployed."); } @@ -151,4 +154,77 @@ class AutomationCompositionElementHandlerTest { assertThatThrownBy(() -> handler.deploy(AC_ID, element, Map.of())) .hasMessageMatching("Deploy of Policy failed."); } + + @Test + void testUpdate() throws Exception { + var handler = new AutomationCompositionElementHandler(mock(PolicyApiHttpClient.class), + mock(PolicyPapHttpClient.class)); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + handler.setIntermediaryApi(intermediaryApi); + + var acElement = getTestingAcElement(); + acElement.getToscaServiceTemplateFragment().setToscaTopologyTemplate(null); + handler.update(AC_ID, acElement, Map.of()); + verify(intermediaryApi).updateAutomationCompositionElementState(AC_ID, automationCompositionElementId, + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Update not supported"); + } + + @Test + void testLock() throws Exception { + var handler = new AutomationCompositionElementHandler(mock(PolicyApiHttpClient.class), + mock(PolicyPapHttpClient.class)); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + handler.setIntermediaryApi(intermediaryApi); + + handler.lock(AC_ID, automationCompositionElementId); + verify(intermediaryApi).updateAutomationCompositionElementState(AC_ID, automationCompositionElementId, null, + LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked"); + } + + @Test + void testUnlock() throws Exception { + var handler = new AutomationCompositionElementHandler(mock(PolicyApiHttpClient.class), + mock(PolicyPapHttpClient.class)); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + handler.setIntermediaryApi(intermediaryApi); + + handler.unlock(AC_ID, automationCompositionElementId); + verify(intermediaryApi).updateAutomationCompositionElementState(AC_ID, automationCompositionElementId, null, + LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked"); + } + + @Test + void testDelete() throws Exception { + var handler = new AutomationCompositionElementHandler(mock(PolicyApiHttpClient.class), + mock(PolicyPapHttpClient.class)); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + handler.setIntermediaryApi(intermediaryApi); + + handler.delete(AC_ID, automationCompositionElementId); + verify(intermediaryApi).updateAutomationCompositionElementState(AC_ID, automationCompositionElementId, + DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted"); + } + + @Test + void testPrime() throws Exception { + var handler = new AutomationCompositionElementHandler(mock(PolicyApiHttpClient.class), + mock(PolicyPapHttpClient.class)); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + handler.setIntermediaryApi(intermediaryApi); + + handler.prime(AC_ID, List.of()); + verify(intermediaryApi).updateCompositionState(AC_ID, AcTypeState.PRIMED, StateChangeResult.NO_ERROR, "Primed"); + } + + @Test + void testDeprime() throws Exception { + var handler = new AutomationCompositionElementHandler(mock(PolicyApiHttpClient.class), + mock(PolicyPapHttpClient.class)); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + handler.setIntermediaryApi(intermediaryApi); + + handler.deprime(AC_ID); + verify(intermediaryApi).updateCompositionState(AC_ID, AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR, + "Deprimed"); + } } -- cgit 1.2.3-korg