Add validation for state set by the participant 47/138647/2
authorFrancescoFioraEst <francesco.fiora@est.tech>
Wed, 7 Aug 2024 09:52:23 +0000 (10:52 +0100)
committerFrancescoFioraEst <francesco.fiora@est.tech>
Thu, 8 Aug 2024 09:59:04 +0000 (10:59 +0100)
Issue-ID: POLICY-5097
Change-Id: I7520b7220c8525448eff707e2e57debca63520fe
Signed-off-by: FrancescoFioraEst <francesco.fiora@est.tech>
models/src/main/java/org/onap/policy/clamp/models/acm/utils/AcmUtils.java
models/src/test/java/org/onap/policy/clamp/models/acm/utils/AcmUtilsTest.java
participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandler.java
participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandlerTest.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandler.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandler.java
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandlerTest.java
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandlerTest.java

index aaf41dd..172de34 100644 (file)
@@ -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.
index 5d0a7d9..97af64c 100644 (file)
@@ -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());
index 77bcb19..7cf83db 100644 (file)
@@ -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);
index dd8747f..202f25c 100644 (file)
@@ -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,14 +49,24 @@ 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));
 
@@ -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
@@ -143,23 +165,6 @@ class AutomationCompositionOutHandlerTest {
         verify(publisher).sendAutomationCompositionAck(any(AutomationCompositionDeployAck.class));
     }
 
-    @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);
@@ -210,6 +215,28 @@ class AutomationCompositionOutHandlerTest {
         verify(publisher).sendParticipantStatus(any(ParticipantStatus.class));
     }
 
+    @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);
index 66f035e..6a56a2c 100644 (file)
@@ -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;
     }
 
index a4e4704..9529428 100644 (file)
@@ -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());
         }
     }
index 5f87db3..b104084 100644 (file)
@@ -59,6 +59,68 @@ class SupervisionAcHandlerTest {
     private static final String AC_INSTANTIATION_CREATE_JSON = "src/test/resources/rest/acm/AutomationComposition.json";
     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 =
@@ -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),
index e8be3b6..e689e64 100644 (file)
@@ -28,35 +28,68 @@ 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;
 
 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);
-    }
 }