diff options
author | Ramesh Murugan Iyer <ramesh.murugan.iyer@est.tech> | 2024-08-09 16:10:33 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@onap.org> | 2024-08-09 16:10:33 +0000 |
commit | 036e873dea28748ded7a735b2aa3456865643af9 (patch) | |
tree | cd4e83c619845d59cb7284969a7241d5bb6e3de8 | |
parent | 3f7d3771a0e5a5d8f186a966963d28528250fc6f (diff) | |
parent | a944487231ad341d8d6b0f302c47bad20169c107 (diff) |
Merge "Add validation for state set by the participant"
8 files changed, 294 insertions, 114 deletions
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 aaf41ddeb..172de34fe 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 @@ -65,6 +65,8 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; import org.onap.policy.models.tosca.authorative.concepts.ToscaTopologyTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Utility functions used in acm-runtime and participants. @@ -75,6 +77,8 @@ public final class AcmUtils { public static final String ENTRY = "entry "; private static final StringToMapConverter MAP_CONVERTER = new StringToMapConverter(); + private static final Logger LOGGER = LoggerFactory.getLogger(AcmUtils.class); + /** * Get the Policy information in the service template for the deploy message to participants. * @@ -536,6 +540,19 @@ public final class AcmUtils { return list; } + /** + * Validated the Message field. + * + * @param message the message + * @return a validated message + */ + public static String validatedMessage(String message) { + if (message != null && message.length() > 255) { + LOGGER.warn("message too long {}", message); + return message.substring(0, 255); + } + return message; + } /** * Recursive Merge. 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 5d0a7d95a..97af64cf7 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 @@ -238,6 +238,16 @@ class AcmUtilsTest { assertEquals(element.getOutProperties(), result.getOutProperties()); } + @Test + void testValidatedMessage() { + var message = "completed"; + assertEquals(message, AcmUtils.validatedMessage(message)); + + var serviceTemplate = CommonTestData.getToscaServiceTemplate(TOSCA_TEMPLATE_YAML); + message = serviceTemplate.toString(); + assertEquals(message.substring(0, 255), AcmUtils.validatedMessage(message)); + } + private AutomationComposition getDummyAutomationComposition() { var automationComposition = new AutomationComposition(); automationComposition.setCompositionId(UUID.randomUUID()); diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandler.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandler.java index 77bcb19ef..7cf83db9d 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandler.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandler.java @@ -42,6 +42,7 @@ import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCom import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantMessageType; import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantPrimeAck; import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantStatus; +import org.onap.policy.clamp.models.acm.utils.AcmUtils; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -66,9 +67,7 @@ public class AutomationCompositionOutHandler { */ public void updateAutomationCompositionElementStage(UUID instance, UUID elementId, StateChangeResult stateChangeResult, int stage, String message) { - - if (instance == null || elementId == null) { - LOGGER.error("Cannot update Automation composition element stage, id is null"); + if (!validateData(instance, elementId, stateChangeResult)) { return; } @@ -86,12 +85,10 @@ public class AutomationCompositionOutHandler { return; } - element.setRestarting(null); - var automationCompositionStateChangeAck = new AutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK); automationCompositionStateChangeAck.setParticipantId(cacheProvider.getParticipantId()); - automationCompositionStateChangeAck.setMessage(message); + automationCompositionStateChangeAck.setMessage(AcmUtils.validatedMessage(message)); automationCompositionStateChangeAck.setResponseTo(cacheProvider.getMsgIdentification().get(element.getId())); automationCompositionStateChangeAck.setStateChangeResult(stateChangeResult); automationCompositionStateChangeAck.setStage(stage); @@ -105,6 +102,23 @@ public class AutomationCompositionOutHandler { cacheProvider.getMsgIdentification().remove(element.getId()); } + private boolean validateData(UUID instance, UUID elementId, StateChangeResult stateChangeResult) { + if (instance == null || elementId == null) { + LOGGER.error("Not valid Ac instance, id is null"); + return false; + } + if (stateChangeResult == null) { + LOGGER.error("Not valid Ac instance, stateChangeResult is null"); + return false; + } + if (!StateChangeResult.NO_ERROR.equals(stateChangeResult) + && !StateChangeResult.FAILED.equals(stateChangeResult)) { + LOGGER.error("Not valid Ac instance, stateChangeResult is not valid"); + return false; + } + return true; + } + /** * Handle a automation composition element state change message. * @@ -117,9 +131,13 @@ public class AutomationCompositionOutHandler { */ public void updateAutomationCompositionElementState(UUID instance, UUID elementId, DeployState deployState, LockState lockState, StateChangeResult stateChangeResult, String message) { + if (!validateData(instance, elementId, stateChangeResult)) { + return; + } - if (instance == null || elementId == null) { - LOGGER.error("Cannot update Automation composition element state, id is null"); + if ((deployState != null && lockState != null) || (deployState == null && lockState == null) + || AcmUtils.isInTransitionalState(deployState, lockState, SubState.NONE)) { + LOGGER.error("state error {} and {} cannot be handled", deployState, lockState); return; } @@ -137,13 +155,6 @@ public class AutomationCompositionOutHandler { return; } - if ((element.getRestarting() == null) - && ((deployState != null && lockState != null) || (deployState == null && lockState == null))) { - LOGGER.error("state error {} and {} cannot be handled", deployState, lockState); - return; - } - element.setRestarting(null); - if (deployState != null && !SubState.NONE.equals(element.getSubState())) { handleSubState(automationComposition, element); if (!StateChangeResult.NO_ERROR.equals(stateChangeResult)) { @@ -161,7 +172,7 @@ public class AutomationCompositionOutHandler { new AutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK); automationCompositionStateChangeAck.setParticipantId(cacheProvider.getParticipantId()); automationCompositionStateChangeAck.setReplicaId(cacheProvider.getReplicaId()); - automationCompositionStateChangeAck.setMessage(message); + automationCompositionStateChangeAck.setMessage(AcmUtils.validatedMessage(message)); automationCompositionStateChangeAck.setResponseTo(cacheProvider.getMsgIdentification().get(element.getId())); automationCompositionStateChangeAck.setStateChangeResult(stateChangeResult); automationCompositionStateChangeAck.setAutomationCompositionId(instance); @@ -289,9 +300,29 @@ public class AutomationCompositionOutHandler { */ public void updateCompositionState(UUID compositionId, AcTypeState state, StateChangeResult stateChangeResult, String message) { + if (compositionId == null) { + LOGGER.error("Cannot update Automation composition definition state, id is null"); + return; + } + + if (stateChangeResult == null) { + LOGGER.error("Cannot update Automation composition definition state, stateChangeResult is null"); + return; + } + if (!StateChangeResult.NO_ERROR.equals(stateChangeResult) + && !StateChangeResult.FAILED.equals(stateChangeResult)) { + LOGGER.error("Cannot update Automation composition definition state, stateChangeResult is not valid"); + return; + } + + if ((state == null) || AcTypeState.PRIMING.equals(state) || AcTypeState.DEPRIMING.equals(state)) { + LOGGER.error("state invalid {} cannot be handled", state); + return; + } + var participantPrimeAck = new ParticipantPrimeAck(); participantPrimeAck.setCompositionId(compositionId); - participantPrimeAck.setMessage(message); + participantPrimeAck.setMessage(AcmUtils.validatedMessage(message)); participantPrimeAck.setResult(true); participantPrimeAck.setResponseTo(cacheProvider.getMsgIdentification().get(compositionId)); participantPrimeAck.setCompositionState(state); diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandlerTest.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandlerTest.java index dd8747ff4..202f25c6f 100644 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandlerTest.java +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandlerTest.java @@ -20,7 +20,6 @@ package org.onap.policy.clamp.acm.participant.intermediary.handler; -import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; @@ -50,15 +49,25 @@ class AutomationCompositionOutHandlerTest { @Test void updateAutomationCompositionElementStateNullTest() { var cacheProvider = mock(CacheProvider.class); - var acOutHandler = new AutomationCompositionOutHandler(mock(ParticipantMessagePublisher.class), cacheProvider); + var publisher = mock(ParticipantMessagePublisher.class); + var acOutHandler = new AutomationCompositionOutHandler(publisher, cacheProvider); assertDoesNotThrow( () -> acOutHandler.updateAutomationCompositionElementState(null, null, null, null, null, null)); + assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState(null, + UUID.randomUUID(), null, null, null, null)); + + assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState(UUID.randomUUID(), + null, null, null, null, null)); + assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState(UUID.randomUUID(), UUID.randomUUID(), null, null, null, null)); assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState(UUID.randomUUID(), + UUID.randomUUID(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, null)); + + assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState(UUID.randomUUID(), UUID.randomUUID(), DeployState.DEPLOYED, null, null, null)); var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next(); @@ -66,20 +75,33 @@ class AutomationCompositionOutHandlerTest { .thenReturn(automationComposition); assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState( automationComposition.getInstanceId(), UUID.randomUUID(), DeployState.DEPLOYED, - null, null, null)); + null, StateChangeResult.NO_ERROR, null)); var elementId = automationComposition.getElements().values().iterator().next().getId(); assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState( - automationComposition.getInstanceId(), elementId, null, null, null, null)); + automationComposition.getInstanceId(), elementId, null, null, + StateChangeResult.NO_ERROR, null)); assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementStage( - elementId, null, null, 0, null)); + elementId, null, StateChangeResult.NO_ERROR, 0, null)); assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementStage( - null, elementId, null, 0, null)); + null, elementId, StateChangeResult.NO_ERROR, 0, null)); assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementStage( - UUID.randomUUID(), elementId, null, 0, null)); + UUID.randomUUID(), elementId, StateChangeResult.NO_ERROR, 0, null)); assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementStage( - automationComposition.getInstanceId(), UUID.randomUUID(), null, 0, null)); + automationComposition.getInstanceId(), UUID.randomUUID(), + StateChangeResult.NO_ERROR, 0, null)); + assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState( + automationComposition.getInstanceId(), elementId, DeployState.DEPLOYED, LockState.LOCKED, + StateChangeResult.NO_ERROR, null)); + assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState( + automationComposition.getInstanceId(), elementId, DeployState.DEPLOYING, null, + StateChangeResult.NO_ERROR, "")); + assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState( + automationComposition.getInstanceId(), elementId, DeployState.DEPLOYED, null, + StateChangeResult.TIMEOUT, "")); + + verify(publisher, times(0)).sendAutomationCompositionAck(any()); } @Test @@ -144,23 +166,6 @@ class AutomationCompositionOutHandlerTest { } @Test - void updateAutomationCompositionElementStateRestartedTest() { - var publisher = mock(ParticipantMessagePublisher.class); - var cacheProvider = mock(CacheProvider.class); - var acOutHandler = new AutomationCompositionOutHandler(publisher, cacheProvider); - - var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next(); - when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId())) - .thenReturn(automationComposition); - var element = automationComposition.getElements().values().iterator().next(); - element.setRestarting(true); - acOutHandler.updateAutomationCompositionElementState(automationComposition.getInstanceId(), element.getId(), - DeployState.DEPLOYED, LockState.LOCKED, StateChangeResult.NO_ERROR, "Restarted"); - verify(publisher).sendAutomationCompositionAck(any(AutomationCompositionDeployAck.class)); - assertThat(element.getRestarting()).isNull(); - } - - @Test void updateAutomationCompositionElementStateDeleteTest() { var publisher = mock(ParticipantMessagePublisher.class); var cacheProvider = mock(CacheProvider.class); @@ -211,6 +216,28 @@ class AutomationCompositionOutHandlerTest { } @Test + void updateCompositionStateNullTest() { + var publisher = mock(ParticipantMessagePublisher.class); + var cacheProvider = mock(CacheProvider.class); + var acOutHandler = new AutomationCompositionOutHandler(publisher, cacheProvider); + + assertDoesNotThrow( + () -> acOutHandler.updateCompositionState(null, null, null, null)); + assertDoesNotThrow(() -> acOutHandler.updateCompositionState(UUID.randomUUID(), null, + StateChangeResult.NO_ERROR, null)); + assertDoesNotThrow( + () -> acOutHandler.updateCompositionState(UUID.randomUUID(), AcTypeState.PRIMED, null, null)); + assertDoesNotThrow(() -> acOutHandler.updateCompositionState(UUID.randomUUID(), AcTypeState.PRIMING, + StateChangeResult.NO_ERROR, null)); + assertDoesNotThrow(() -> acOutHandler.updateCompositionState(UUID.randomUUID(), AcTypeState.DEPRIMING, + StateChangeResult.NO_ERROR, null)); + assertDoesNotThrow(() -> acOutHandler.updateCompositionState(UUID.randomUUID(), AcTypeState.PRIMED, + StateChangeResult.TIMEOUT, null)); + + verify(publisher, times(0)).sendParticipantPrimeAck(any()); + } + + @Test void updateCompositionStatePrimedTest() { var cacheProvider = mock(CacheProvider.class); when(cacheProvider.getParticipantId()).thenReturn(UUID.randomUUID()); diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandler.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandler.java index 66f035e5e..6a56a2c2b 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandler.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandler.java @@ -23,7 +23,6 @@ package org.onap.policy.clamp.acm.runtime.supervision; import io.micrometer.core.annotation.Timed; import io.opentelemetry.context.Context; import java.util.Map; -import java.util.Objects; import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutorService; @@ -38,7 +37,6 @@ import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantSyncPublish import org.onap.policy.clamp.models.acm.concepts.AcElementDeployAck; 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.AutomationCompositionElement; 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.ParticipantUtils; @@ -259,10 +257,14 @@ public class SupervisionAcHandler { } private void setAcElementStateInDb(AutomationCompositionDeployAck automationCompositionAckMessage) { + if (!validateMessage(automationCompositionAckMessage)) { + return; + } + var automationCompositionOpt = automationCompositionProvider .findAutomationComposition(automationCompositionAckMessage.getAutomationCompositionId()); if (automationCompositionOpt.isEmpty()) { - LOGGER.warn("AutomationComposition not found in database {}", + LOGGER.error("AutomationComposition not found in database {}", automationCompositionAckMessage.getAutomationCompositionId()); return; } @@ -271,13 +273,7 @@ public class SupervisionAcHandler { if (automationCompositionAckMessage.getAutomationCompositionResultMap() == null || automationCompositionAckMessage.getAutomationCompositionResultMap().isEmpty()) { if (DeployState.DELETING.equals(automationComposition.getDeployState())) { - // scenario when Automation Composition instance has never been deployed - for (var element : automationComposition.getElements().values()) { - if (element.getParticipantId().equals(automationCompositionAckMessage.getParticipantId())) { - element.setDeployState(DeployState.DELETED); - automationCompositionProvider.updateAutomationCompositionElement(element); - } - } + deleteAcInstance(automationComposition, automationCompositionAckMessage.getParticipantId()); } else { LOGGER.warn("Empty AutomationCompositionResultMap {} {}", automationCompositionAckMessage.getAutomationCompositionId(), @@ -296,6 +292,40 @@ public class SupervisionAcHandler { } } + private boolean validateMessage(AutomationCompositionDeployAck acAckMessage) { + if (acAckMessage.getAutomationCompositionId() == null + || acAckMessage.getStateChangeResult() == null) { + LOGGER.error("Not valid AutomationCompositionDeployAck message"); + return false; + } + if (!StateChangeResult.NO_ERROR.equals(acAckMessage.getStateChangeResult()) + && !StateChangeResult.FAILED.equals(acAckMessage.getStateChangeResult())) { + LOGGER.error("Not valid AutomationCompositionDeployAck message, stateChangeResult is not valid {} ", + acAckMessage.getStateChangeResult()); + return false; + } + + if (acAckMessage.getStage() == null) { + for (var el : acAckMessage.getAutomationCompositionResultMap().values()) { + if (AcmUtils.isInTransitionalState(el.getDeployState(), el.getLockState(), SubState.NONE)) { + LOGGER.error("Not valid AutomationCompositionDeployAck message, states are not valid"); + return false; + } + } + } + return true; + } + + private void deleteAcInstance(AutomationComposition automationComposition, UUID participantId) { + // scenario when Automation Composition instance has never been deployed + for (var element : automationComposition.getElements().values()) { + if (element.getParticipantId().equals(participantId)) { + element.setDeployState(DeployState.DELETED); + automationCompositionProvider.updateAutomationCompositionElement(element); + } + } + } + private boolean updateState(AutomationComposition automationComposition, Set<Map.Entry<UUID, AcElementDeployAck>> automationCompositionResultSet, StateChangeResult stateChangeResult, Integer stage) { @@ -309,28 +339,20 @@ public class SupervisionAcHandler { for (var acElementAck : automationCompositionResultSet) { var element = automationComposition.getElements().get(acElementAck.getKey()); if (element != null) { - element.setMessage(acElementAck.getValue().getMessage()); + element.setMessage(AcmUtils.validatedMessage(acElementAck.getValue().getMessage())); element.setOutProperties(acElementAck.getValue().getOutProperties()); element.setOperationalState(acElementAck.getValue().getOperationalState()); element.setUseState(acElementAck.getValue().getUseState()); - element.setSubState(SubState.NONE); + if (stage == null) { + element.setSubState(SubState.NONE); + } element.setDeployState(acElementAck.getValue().getDeployState()); element.setLockState(acElementAck.getValue().getLockState()); element.setStage(stage); - element.setRestarting(null); automationCompositionProvider.updateAutomationCompositionElement(element); } } - if (automationComposition.getRestarting() != null) { - var restarting = automationComposition.getElements().values().stream() - .map(AutomationCompositionElement::getRestarting).filter(Objects::nonNull).findAny(); - if (restarting.isEmpty()) { - automationComposition.setRestarting(null); - updated = true; - } - } - return updated; } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandler.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandler.java index a4e470495..95294285e 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandler.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandler.java @@ -30,6 +30,7 @@ import org.onap.policy.clamp.models.acm.concepts.NodeTemplateState; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantPrimeAck; import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; +import org.onap.policy.clamp.models.acm.utils.AcmUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @@ -53,6 +54,22 @@ public class SupervisionHandler { */ @Timed(value = "listener.participant_prime_ack", description = "PARTICIPANT_PRIME_ACK messages received") public void handleParticipantMessage(ParticipantPrimeAck participantPrimeAckMessage) { + if (participantPrimeAckMessage.getCompositionId() == null + || participantPrimeAckMessage.getCompositionState() == null + || participantPrimeAckMessage.getStateChangeResult() == null) { + LOGGER.error("Not valid ParticipantPrimeAck message"); + return; + } + if (AcTypeState.PRIMING.equals(participantPrimeAckMessage.getCompositionState()) + || AcTypeState.DEPRIMING.equals(participantPrimeAckMessage.getCompositionState())) { + LOGGER.error("Not valid state {}", participantPrimeAckMessage.getCompositionState()); + return; + } + if (!StateChangeResult.NO_ERROR.equals(participantPrimeAckMessage.getStateChangeResult()) + && !StateChangeResult.FAILED.equals(participantPrimeAckMessage.getStateChangeResult())) { + LOGGER.error("Vot valid stateChangeResult {} ", participantPrimeAckMessage.getStateChangeResult()); + return; + } var acDefinitionOpt = acDefinitionProvider.findAcDefinition(participantPrimeAckMessage.getCompositionId()); if (acDefinitionOpt.isEmpty()) { LOGGER.warn("AC Definition not found in database {}", participantPrimeAckMessage.getCompositionId()); @@ -60,7 +77,7 @@ public class SupervisionHandler { } var acDefinition = acDefinitionOpt.get(); if (!AcTypeState.PRIMING.equals(acDefinition.getState()) - && !AcTypeState.DEPRIMING.equals(acDefinition.getState()) && acDefinition.getRestarting() == null) { + && !AcTypeState.DEPRIMING.equals(acDefinition.getState())) { LOGGER.error("AC Definition {} already primed/deprimed with participant {}", participantPrimeAckMessage.getCompositionId(), participantPrimeAckMessage.getParticipantId()); return; @@ -81,15 +98,11 @@ public class SupervisionHandler { } boolean completed = true; - boolean restarting = false; for (var element : acDefinition.getElementStateMap().values()) { handlePrimeAckElement(participantPrimeAckMessage, element); if (!finalState.equals(element.getState())) { completed = false; } - if (element.getRestarting() != null) { - restarting = true; - } } if (inProgress && !msgInErrors && completed) { @@ -99,13 +112,9 @@ public class SupervisionHandler { acDefinition.setStateChangeResult(StateChangeResult.NO_ERROR); } } - if (!restarting && acDefinition.getRestarting() != null) { - toUpdate = true; - acDefinition.setRestarting(null); - } if (toUpdate) { acDefinitionProvider.updateAcDefinitionState(acDefinition.getCompositionId(), acDefinition.getState(), - acDefinition.getStateChangeResult(), acDefinition.getRestarting()); + acDefinition.getStateChangeResult(), null); if (!participantPrimeAckMessage.getParticipantId().equals(participantPrimeAckMessage.getReplicaId())) { participantSyncPublisher.sendSync(acDefinition, participantPrimeAckMessage.getReplicaId()); } @@ -114,9 +123,8 @@ public class SupervisionHandler { private void handlePrimeAckElement(ParticipantPrimeAck participantPrimeAckMessage, NodeTemplateState element) { if (participantPrimeAckMessage.getParticipantId().equals(element.getParticipantId())) { - element.setMessage(participantPrimeAckMessage.getMessage()); + element.setMessage(AcmUtils.validatedMessage(participantPrimeAckMessage.getMessage())); element.setState(participantPrimeAckMessage.getCompositionState()); - element.setRestarting(null); acDefinitionProvider.updateAcDefinitionElement(element, participantPrimeAckMessage.getCompositionId()); } } diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandlerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandlerTest.java index 5f87db30c..b104084a8 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandlerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandlerTest.java @@ -60,6 +60,68 @@ class SupervisionAcHandlerTest { private static final UUID IDENTIFIER = UUID.randomUUID(); @Test + void testAutomationCompositionDeployAckNull() { + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + var handler = new SupervisionAcHandler(automationCompositionProvider, mock(AcDefinitionProvider.class), + mock(AutomationCompositionDeployPublisher.class), mock(AutomationCompositionStateChangePublisher.class), + mock(AcElementPropertiesPublisher.class), null, + mock(ParticipantSyncPublisher.class), null); + + var automationComposition = + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Crud"); + automationComposition.setInstanceId(IDENTIFIER); + var automationCompositionAckMessage = + getAutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK, + automationComposition, DeployState.DEPLOYED, LockState.UNLOCKED); + automationCompositionAckMessage.setStateChangeResult(null); + handler.handleAutomationCompositionStateChangeAckMessage(automationCompositionAckMessage); + + automationCompositionAckMessage.setStateChangeResult(StateChangeResult.NO_ERROR); + automationCompositionAckMessage.setAutomationCompositionId(null); + handler.handleAutomationCompositionStateChangeAckMessage(automationCompositionAckMessage); + + automationCompositionAckMessage.setAutomationCompositionId(automationComposition.getInstanceId()); + handler.handleAutomationCompositionStateChangeAckMessage(automationCompositionAckMessage); + + automationCompositionAckMessage = + getAutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK, + automationComposition, DeployState.DEPLOYING, LockState.UNLOCKED); + handler.handleAutomationCompositionStateChangeAckMessage(automationCompositionAckMessage); + + verify(automationCompositionProvider, times(0)).updateAutomationCompositionElement(any()); + } + + @Test + void testHandleAcMigrationWithStage() { + var automationComposition = + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Crud"); + automationComposition.setInstanceId(IDENTIFIER); + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + when(automationCompositionProvider.findAutomationComposition(IDENTIFIER)) + .thenReturn(Optional.of(automationComposition)); + when(automationCompositionProvider.updateAcState(any(AutomationComposition.class))) + .thenReturn(automationComposition); + + var acDefinitionProvider = mock(AcDefinitionProvider.class); + when(acDefinitionProvider.getAcDefinition(automationComposition.getCompositionId())) + .thenReturn(new AutomationCompositionDefinition()); + + var handler = new SupervisionAcHandler(automationCompositionProvider, acDefinitionProvider, + mock(AutomationCompositionDeployPublisher.class), mock(AutomationCompositionStateChangePublisher.class), + mock(AcElementPropertiesPublisher.class), null, + mock(ParticipantSyncPublisher.class), null); + + var automationCompositionAckMessage = + getAutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK, + automationComposition, DeployState.MIGRATING, LockState.LOCKED); + automationCompositionAckMessage.setStage(1); + handler.handleAutomationCompositionStateChangeAckMessage(automationCompositionAckMessage); + + verify(automationCompositionProvider, times(3)) + .updateAutomationCompositionElement(any(AutomationCompositionElement.class)); + } + + @Test void testHandleAutomationCompositionStateChangeAckMessage() { var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Crud"); @@ -319,6 +381,7 @@ class SupervisionAcHandlerTest { automationCompositionAckMessage .setParticipantId(automationComposition.getElements().values().iterator().next().getParticipantId()); automationCompositionAckMessage.setAutomationCompositionId(IDENTIFIER); + automationCompositionAckMessage.setStateChangeResult(StateChangeResult.NO_ERROR); var handler = new SupervisionAcHandler(automationCompositionProvider, mock(AcDefinitionProvider.class), mock(AutomationCompositionDeployPublisher.class), mock(AutomationCompositionStateChangePublisher.class), diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandlerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandlerTest.java index e8be3b6b7..e689e6467 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandlerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandlerTest.java @@ -28,12 +28,12 @@ import static org.mockito.Mockito.when; import static org.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_SERVICE_TEMPLATE_YAML; import java.util.Optional; +import java.util.UUID; import org.junit.jupiter.api.Test; import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils; import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantSyncPublisher; 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.ParticipantState; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantPrimeAck; import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; @@ -41,22 +41,55 @@ import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvide class SupervisionHandlerTest { @Test + void testParticipantPrimeAckNull() { + var acDefinitionProvider = mock(AcDefinitionProvider.class); + var handler = new SupervisionHandler(acDefinitionProvider, mock(ParticipantSyncPublisher.class)); + + var participantPrimeAckMessage = new ParticipantPrimeAck(); + participantPrimeAckMessage.setParticipantId(CommonTestData.getParticipantId()); + handler.handleParticipantMessage(participantPrimeAckMessage); + + participantPrimeAckMessage.setCompositionId(UUID.randomUUID()); + handler.handleParticipantMessage(participantPrimeAckMessage); + + participantPrimeAckMessage.setStateChangeResult(StateChangeResult.NO_ERROR); + handler.handleParticipantMessage(participantPrimeAckMessage); + + participantPrimeAckMessage.setStateChangeResult(null); + participantPrimeAckMessage.setCompositionState(AcTypeState.PRIMED); + handler.handleParticipantMessage(participantPrimeAckMessage); + + participantPrimeAckMessage.setStateChangeResult(StateChangeResult.NO_ERROR); + participantPrimeAckMessage.setCompositionState(AcTypeState.PRIMING); + handler.handleParticipantMessage(participantPrimeAckMessage); + + participantPrimeAckMessage.setCompositionState(AcTypeState.DEPRIMING); + handler.handleParticipantMessage(participantPrimeAckMessage); + + verify(acDefinitionProvider, times(0)).findAcDefinition(any()); + verify(acDefinitionProvider, times(0)).updateAcDefinitionElement(any(), any()); + } + + @Test void testParticipantPrimeAckNotFound() { var participantPrimeAckMessage = new ParticipantPrimeAck(); participantPrimeAckMessage.setParticipantId(CommonTestData.getParticipantId()); - participantPrimeAckMessage.setState(ParticipantState.ON_LINE); + participantPrimeAckMessage.setStateChangeResult(StateChangeResult.NO_ERROR); + participantPrimeAckMessage.setCompositionId(UUID.randomUUID()); + participantPrimeAckMessage.setCompositionState(AcTypeState.PRIMED); var acDefinitionProvider = mock(AcDefinitionProvider.class); var handler = new SupervisionHandler(acDefinitionProvider, mock(ParticipantSyncPublisher.class)); - handler.handleParticipantMessage(participantPrimeAckMessage); - verify(acDefinitionProvider).findAcDefinition(any()); + verify(acDefinitionProvider).findAcDefinition(participantPrimeAckMessage.getCompositionId()); + verify(acDefinitionProvider, times(0)).updateAcDefinitionElement(any(), any()); } @Test void testParticipantPrimeAckPrimed() { var participantPrimeAckMessage = new ParticipantPrimeAck(); participantPrimeAckMessage.setParticipantId(CommonTestData.getParticipantId()); - participantPrimeAckMessage.setState(ParticipantState.ON_LINE); + participantPrimeAckMessage.setStateChangeResult(StateChangeResult.NO_ERROR); + participantPrimeAckMessage.setCompositionState(AcTypeState.PRIMED); var acDefinition = CommonTestData.createAcDefinition( InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML), AcTypeState.PRIMED); @@ -76,7 +109,7 @@ class SupervisionHandlerTest { var participantPrimeAckMessage = new ParticipantPrimeAck(); participantPrimeAckMessage.setParticipantId(CommonTestData.getParticipantId()); participantPrimeAckMessage.setCompositionState(AcTypeState.PRIMED); - participantPrimeAckMessage.setState(ParticipantState.ON_LINE); + participantPrimeAckMessage.setStateChangeResult(StateChangeResult.NO_ERROR); var acDefinition = CommonTestData.createAcDefinition( InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML), AcTypeState.PRIMING); @@ -104,7 +137,7 @@ class SupervisionHandlerTest { void testParticipantPrimeAckFailed() { var participantPrimeAckMessage = new ParticipantPrimeAck(); participantPrimeAckMessage.setParticipantId(CommonTestData.getParticipantId()); - participantPrimeAckMessage.setState(ParticipantState.ON_LINE); + participantPrimeAckMessage.setCompositionState(AcTypeState.COMMISSIONED); participantPrimeAckMessage.setStateChangeResult(StateChangeResult.FAILED); var acDefinition = CommonTestData.createAcDefinition( @@ -125,35 +158,4 @@ class SupervisionHandlerTest { verify(acDefinitionProvider).updateAcDefinitionState(acDefinition.getCompositionId(), AcTypeState.PRIMING, StateChangeResult.FAILED, null); } - - @Test - void testParticipantPrimeAckRestarted() { - var participantPrimeAckMessage = new ParticipantPrimeAck(); - participantPrimeAckMessage.setParticipantId(CommonTestData.getParticipantId()); - participantPrimeAckMessage.setCompositionState(AcTypeState.PRIMED); - participantPrimeAckMessage.setState(ParticipantState.ON_LINE); - - var acDefinition = CommonTestData.createAcDefinition( - InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML), AcTypeState.PRIMED); - acDefinition.setStateChangeResult(StateChangeResult.TIMEOUT); - acDefinition.setRestarting(true); - participantPrimeAckMessage.setCompositionId(acDefinition.getCompositionId()); - for (var element : acDefinition.getElementStateMap().values()) { - element.setParticipantId(CommonTestData.getParticipantId()); - element.setRestarting(true); - } - - var acDefinitionProvider = mock(AcDefinitionProvider.class); - when(acDefinitionProvider.findAcDefinition(acDefinition.getCompositionId())) - .thenReturn(Optional.of(acDefinition)); - - var handler = new SupervisionHandler(acDefinitionProvider, mock(ParticipantSyncPublisher.class)); - - handler.handleParticipantMessage(participantPrimeAckMessage); - verify(acDefinitionProvider).findAcDefinition(any()); - verify(acDefinitionProvider, times(acDefinition.getElementStateMap().size())) - .updateAcDefinitionElement(any(), any()); - verify(acDefinitionProvider).updateAcDefinitionState(acDefinition.getCompositionId(), AcTypeState.PRIMED, - StateChangeResult.NO_ERROR, null); - } } |