Fix undeploy issue after migration failure in ACM-R 76/139576/1
authorFrancescoFioraEst <francesco.fiora@est.tech>
Tue, 26 Nov 2024 14:23:39 +0000 (14:23 +0000)
committerFrancesco Fiora <francesco.fiora@est.tech>
Tue, 26 Nov 2024 17:45:52 +0000 (17:45 +0000)
Issue-ID: POLICY-5177
Change-Id: Ic49dc15a9fd2a92f358eb60a440a8efb5080bbde
Signed-off-by: FrancescoFioraEst <francesco.fiora@est.tech>
models/src/main/java/org/onap/policy/clamp/models/acm/concepts/ParticipantUtils.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcInstanceStateResolver.java
models/src/test/java/org/onap/policy/clamp/models/acm/concepts/ParticipantUtilsTest.java
participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/CacheProvider.java
participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/CacheProviderTest.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScanner.java
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java

index 9c827d7..12c21f5 100644 (file)
@@ -48,7 +48,9 @@ public final class ParticipantUtils {
         for (var element : automationComposition.getElements().values()) {
             var toscaNodeTemplate = toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates()
                 .get(element.getDefinition().getName());
-            int startPhase = ParticipantUtils.findStartPhase(toscaNodeTemplate.getProperties());
+            int startPhase = toscaNodeTemplate != null
+                    && element.getDefinition().getVersion().equals(toscaNodeTemplate.getVersion())
+                    ? ParticipantUtils.findStartPhase(toscaNodeTemplate.getProperties()) : 0;
             minStartPhase = Math.min(minStartPhase, startPhase);
             maxStartPhase = Math.max(maxStartPhase, startPhase);
         }
index 7bffdd9..9239b3a 100644 (file)
@@ -138,6 +138,8 @@ public class AcInstanceStateResolver {
 
         this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, SUB_NONE,
             UNDEPLOYING, STATE_LOCKED_NONE, SUB_STATE_NONE, TIMEOUT}, UNDEPLOY);
+        this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, SUB_NONE,
+            UNDEPLOYING, LOCKED, SUB_STATE_NONE, TIMEOUT}, UNDEPLOY);
         this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, SUB_NONE,
             UPDATING, LOCKED, SUB_STATE_NONE, TIMEOUT}, UNDEPLOY);
         this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, SUB_NONE,
index bac0842..9a8316c 100644 (file)
@@ -66,6 +66,45 @@ class ParticipantUtilsTest {
         assertThat(result).isEqualTo(1);
     }
 
+    @Test
+    void testGetFirstStartPhaseWithNull() throws CoderException {
+        var serviceTemplate = CommonTestData.getToscaServiceTemplate(TOSCA_TEMPLATE_YAML);
+        var automationComposition =
+            CODER.decode(ResourceUtils.getResourceAsString(AUTOMATION_COMPOSITION_JSON), AutomationCompositions.class)
+                    .getAutomationCompositionList().get(0);
+        automationComposition.setDeployState(DeployState.DEPLOYING);
+        automationComposition.setLockState(LockState.NONE);
+
+        serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().values()
+            .forEach(node -> node.setVersion("0.0.0"));
+        var result = ParticipantUtils.getFirstStartPhase(automationComposition, serviceTemplate);
+        assertThat(result).isZero();
+
+        automationComposition.setDeployState(DeployState.DEPLOYED);
+        automationComposition.setLockState(LockState.UNLOCKING);
+        result = ParticipantUtils.getFirstStartPhase(automationComposition, serviceTemplate);
+        assertThat(result).isZero();
+
+        automationComposition.setDeployState(DeployState.UNDEPLOYING);
+        automationComposition.setLockState(LockState.NONE);
+        result = ParticipantUtils.getFirstStartPhase(automationComposition, serviceTemplate);
+        assertThat(result).isZero();
+
+        serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().clear();
+        result = ParticipantUtils.getFirstStartPhase(automationComposition, serviceTemplate);
+        assertThat(result).isZero();
+
+        automationComposition.setDeployState(DeployState.DEPLOYED);
+        automationComposition.setLockState(LockState.UNLOCKING);
+        result = ParticipantUtils.getFirstStartPhase(automationComposition, serviceTemplate);
+        assertThat(result).isZero();
+
+        automationComposition.setDeployState(DeployState.UNDEPLOYING);
+        automationComposition.setLockState(LockState.NONE);
+        result = ParticipantUtils.getFirstStartPhase(automationComposition, serviceTemplate);
+        assertThat(result).isZero();
+    }
+
     @Test
     void testGetFirstStage() throws CoderException {
         var serviceTemplate = CommonTestData.getToscaServiceTemplate(TOSCA_TEMPLATE_YAML);
index 3837ec6..b9e33c9 100644 (file)
@@ -45,6 +45,7 @@ import org.onap.policy.clamp.models.acm.concepts.ParticipantSupportedElementType
 import org.onap.policy.clamp.models.acm.concepts.SubState;
 import org.onap.policy.models.base.PfUtils;
 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.springframework.stereotype.Component;
 
@@ -140,7 +141,8 @@ public class CacheProvider {
         var automationComposition = automationCompositions.get(instanceId);
         var map = acElementsDefinitions.get(automationComposition.getCompositionId());
         var element = automationComposition.getElements().get(acElementId);
-        return map.get(element.getDefinition()).getAutomationCompositionElementToscaNodeTemplate().getProperties();
+        return getAcElementDefinition(map, element.getDefinition())
+                .getAutomationCompositionElementToscaNodeTemplate().getProperties();
     }
 
     /**
@@ -152,8 +154,20 @@ public class CacheProvider {
      */
     public Map<String, Object> getCommonProperties(@NonNull UUID compositionId,
         @NonNull ToscaConceptIdentifier definition) {
-        return acElementsDefinitions.get(compositionId).get(definition)
-            .getAutomationCompositionElementToscaNodeTemplate().getProperties();
+        return getAcElementDefinition(acElementsDefinitions.get(compositionId), definition)
+                .getAutomationCompositionElementToscaNodeTemplate().getProperties();
+    }
+
+    private AutomationCompositionElementDefinition getAcElementDefinition(
+            Map<ToscaConceptIdentifier, AutomationCompositionElementDefinition> map,
+            ToscaConceptIdentifier definition) {
+        var nodeTemplate = map.get(definition);
+        if (nodeTemplate == null) {
+            nodeTemplate = new AutomationCompositionElementDefinition();
+            nodeTemplate.setAutomationCompositionElementToscaNodeTemplate(new ToscaNodeTemplate());
+            nodeTemplate.getAutomationCompositionElementToscaNodeTemplate().setProperties(new HashMap<>());
+        }
+        return nodeTemplate;
     }
 
     /**
@@ -273,8 +287,8 @@ public class CacheProvider {
      */
     public CompositionElementDto createCompositionElementDto(UUID compositionId, AutomationCompositionElement element,
             Map<String, Object> compositionInProperties) {
-        var compositionOutProperties = getAcElementsDefinitions()
-                .get(compositionId).get(element.getDefinition()).getOutProperties();
+        var compositionOutProperties = getAcElementDefinition(acElementsDefinitions
+                .get(compositionId)element.getDefinition()).getOutProperties();
         return new CompositionElementDto(compositionId,
                 element.getDefinition(), compositionInProperties, compositionOutProperties);
     }
@@ -291,7 +305,7 @@ public class CacheProvider {
         var definitions = acElementsDefinitions.get(compositionId);
         Map<UUID, CompositionElementDto> map = new HashMap<>();
         for (var element : automationComposition.getElements().values()) {
-            var definition = definitions.get(element.getDefinition());
+            var definition = getAcElementDefinition(definitions, element.getDefinition());
             var compositionElement = (definition != null)
                     ? new CompositionElementDto(compositionId, element.getDefinition(),
                             definition.getAutomationCompositionElementToscaNodeTemplate().getProperties(),
index ced2d81..96add20 100644 (file)
@@ -65,6 +65,8 @@ class CacheProviderTest {
                 .isInstanceOf(NullPointerException.class);
         assertThatThrownBy(() -> cacheProvider.getCommonProperties(instanceId, (UUID) null))
                 .isInstanceOf(NullPointerException.class);
+        assertThatThrownBy(() -> cacheProvider.getCommonProperties(null, instanceId))
+                .isInstanceOf(NullPointerException.class);
 
         assertThatThrownBy(() -> cacheProvider.removeAutomationComposition(null))
                 .isInstanceOf(NullPointerException.class);
index db67e5e..de2f375 100644 (file)
@@ -173,7 +173,9 @@ public class SupervisionScanner {
         for (var element : automationComposition.getElements().values()) {
             var toscaNodeTemplate = serviceTemplate.getToscaTopologyTemplate().getNodeTemplates()
                     .get(element.getDefinition().getName());
-            int startPhase = ParticipantUtils.findStartPhase(toscaNodeTemplate.getProperties());
+            int startPhase = toscaNodeTemplate != null
+                    && element.getDefinition().getVersion().equals(toscaNodeTemplate.getVersion())
+                    ? ParticipantUtils.findStartPhase(toscaNodeTemplate.getProperties()) : 0;
             defaultMin = Math.min(defaultMin, startPhase);
             defaultMax = Math.max(defaultMax, startPhase);
             if (AcmUtils.isInTransitionalState(element.getDeployState(), element.getLockState(),
index 17cc8ad..b425c4b 100644 (file)
@@ -338,6 +338,42 @@ class SupervisionScannerTest {
                 any(ToscaServiceTemplate.class), anyInt(), anyBoolean());
     }
 
+    @Test
+    void testStartPhaseWithNull() {
+        var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud");
+        automationComposition.setDeployState(DeployState.DEPLOYING);
+        automationComposition.setLockState(LockState.NONE);
+        automationComposition.setPhase(0);
+        automationComposition.setLastMsg(TimestampHelper.now());
+        automationComposition.setCompositionId(compositionId);
+        for (var element : automationComposition.getElements().values()) {
+            if (ELEMENT_NAME.equals(element.getDefinition().getName())) {
+                element.setDeployState(DeployState.DEPLOYING);
+                element.getDefinition().setName("NotExistElement");
+                element.setLockState(LockState.NONE);
+            } else {
+                element.setDeployState(DeployState.DEPLOYING);
+                element.getDefinition().setVersion("0.0.0");
+                element.setLockState(LockState.NONE);
+            }
+        }
+
+        var automationCompositionProvider = mock(AutomationCompositionProvider.class);
+        when(automationCompositionProvider.getAcInstancesInTransition()).thenReturn(List.of(automationComposition));
+
+        var automationCompositionDeployPublisher = mock(AutomationCompositionDeployPublisher.class);
+        var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
+
+        var supervisionScanner = new SupervisionScanner(automationCompositionProvider, createAcDefinitionProvider(),
+                mock(AutomationCompositionStateChangePublisher.class), automationCompositionDeployPublisher,
+                mock(ParticipantSyncPublisher.class), null, acRuntimeParameterGroup);
+
+        supervisionScanner.run();
+
+        verify(automationCompositionDeployPublisher, times(0)).send(any(AutomationComposition.class),
+                any(ToscaServiceTemplate.class), anyInt(), anyBoolean());
+    }
+
     @Test
     void testSendAutomationCompositionMigrate() {
         var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud");