Remove Thread support in kubernetes participant 30/135130/1
authorFrancescoFioraEst <francesco.fiora@est.tech>
Thu, 22 Jun 2023 15:15:11 +0000 (16:15 +0100)
committerLiam Fallon <liam.fallon@est.tech>
Tue, 27 Jun 2023 13:21:38 +0000 (13:21 +0000)
Due the Thread support in Intermediary, Thread support in kubernetes participant could be removed.

Issue-ID: POLICY-4741
Change-Id: Ia55697808c541991f99cc7630f25188937e15779
Signed-off-by: FrancescoFioraEst <francesco.fiora@est.tech>
(cherry picked from commit 567a8fd97c6b434f430d38c2d4af5a95b7cdb711)

participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/acm/participant/kubernetes/handler/AutomationCompositionElementHandler.java
participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/acm/participant/kubernetes/helm/PodStatusValidator.java
participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/acm/participant/kubernetes/handler/AutomationCompositionElementHandlerTest.java
participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/acm/participant/kubernetes/helm/PodStatusValidatorTest.java

index 7050dfd..7385a1f 100644 (file)
@@ -27,10 +27,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
 import lombok.AccessLevel;
 import lombok.Getter;
 import org.onap.policy.clamp.acm.participant.intermediary.api.AutomationCompositionElementListener;
@@ -39,6 +37,7 @@ import org.onap.policy.clamp.acm.participant.kubernetes.exception.ServiceExcepti
 import org.onap.policy.clamp.acm.participant.kubernetes.helm.PodStatusValidator;
 import org.onap.policy.clamp.acm.participant.kubernetes.models.ChartInfo;
 import org.onap.policy.clamp.acm.participant.kubernetes.service.ChartService;
+import org.onap.policy.clamp.common.acm.exception.AutomationCompositionException;
 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;
@@ -61,8 +60,6 @@ import org.springframework.stereotype.Component;
 public class AutomationCompositionElementHandler implements AutomationCompositionElementListener {
     private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-    private ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
-
     // Map of helm installation and the status of corresponding pods
     @Getter
     private static Map<String, Map<String, String>> podStatusMap = new ConcurrentHashMap<>();
@@ -118,26 +115,47 @@ public class AutomationCompositionElementHandler implements AutomationCompositio
     @Override
     public synchronized void deploy(UUID automationCompositionId, AcElementDeploy element,
             Map<String, Object> properties) throws PfModelException {
-        @SuppressWarnings("unchecked")
-        var chartData = (Map<String, Object>) properties.get("chart");
 
-        LOGGER.info("Installation request received for the Helm Chart {} ", chartData);
         try {
-            var chartInfo = CODER.convert(chartData, ChartInfo.class);
+            var chartInfo = getChartInfo(properties);
             if (chartService.installChart(chartInfo)) {
                 chartMap.put(element.getId(), chartInfo);
 
-                var config = CODER.convert(properties, ThreadConfig.class);
+                var config = getThreadConfig(properties);
                 checkPodStatus(automationCompositionId, element.getId(), chartInfo,
                         config.uninitializedToPassiveTimeout, config.podStatusCheckInterval);
+            } else {
+                intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(),
+                        DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Chart not installed");
             }
-        } catch (ServiceException | CoderException | IOException e) {
-            LOGGER.warn("Installation of Helm chart failed", e);
+        } catch (ServiceException | IOException e) {
+            throw new PfModelException(Response.Status.BAD_REQUEST, "Installation of Helm chart failed ", e);
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
             throw new PfModelException(Response.Status.BAD_REQUEST, "Error invoking ExecutorService ", e);
-        } catch (ExecutionException e) {
-            throw new PfModelException(Response.Status.BAD_REQUEST, "Error retrieving pod status result ", e);
+        } catch (AutomationCompositionException e) {
+            intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(),
+                    DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, e.getMessage());
+        }
+    }
+
+    private ThreadConfig getThreadConfig(Map<String, Object> properties) throws AutomationCompositionException {
+        try {
+            return CODER.convert(properties, ThreadConfig.class);
+        } catch (CoderException e) {
+            throw new AutomationCompositionException(Status.BAD_REQUEST, "Error extracting ThreadConfig ", e);
+        }
+    }
+
+    private ChartInfo getChartInfo(Map<String, Object> properties) throws AutomationCompositionException {
+        @SuppressWarnings("unchecked")
+        var chartData = (Map<String, Object>) properties.get("chart");
+
+        LOGGER.info("Installation request received for the Helm Chart {} ", chartData);
+        try {
+            return CODER.convert(chartData, ChartInfo.class);
+        } catch (CoderException e) {
+            throw new AutomationCompositionException(Status.BAD_REQUEST, "Error extracting ChartInfo ", e);
         }
     }
 
@@ -145,16 +163,17 @@ public class AutomationCompositionElementHandler implements AutomationCompositio
      * Invoke a new thread to check the status of deployed pods.
      *
      * @param chart ChartInfo
+     * @throws ServiceException in case of an exception
      */
     public void checkPodStatus(UUID automationCompositionId, UUID elementId, ChartInfo chart, int timeout,
-            int podStatusCheckInterval) throws ExecutionException, InterruptedException {
-        // Invoke runnable thread to check pod status
-        var result = executor.submit(new PodStatusValidator(chart, timeout, podStatusCheckInterval), "Done");
-        if (!result.get().isEmpty()) {
-            LOGGER.info("Pod Status Validator Completed: {}", result.isDone());
-            intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, elementId,
-                    DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed");
-        }
+            int podStatusCheckInterval) throws InterruptedException, ServiceException {
+
+        var result = new PodStatusValidator(chart, timeout, podStatusCheckInterval);
+        result.run();
+        LOGGER.info("Pod Status Validator Completed");
+        intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, elementId,
+                DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed");
+
     }
 
     @Override
index 89eb284..0a14241 100644 (file)
@@ -25,7 +25,6 @@ import java.lang.invoke.MethodHandles;
 import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
-import lombok.SneakyThrows;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.onap.policy.clamp.acm.participant.kubernetes.exception.ServiceException;
@@ -35,7 +34,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 
-public class PodStatusValidator implements Runnable {
+public class PodStatusValidator {
 
     private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
@@ -50,6 +49,7 @@ public class PodStatusValidator implements Runnable {
 
     /**
      * Constructor for PodStatusValidator.
+     *
      * @param chart chartInfo
      * @param timeout timeout for the thread to exit
      * @param statusCheckInterval Interval to check pod status
@@ -60,15 +60,18 @@ public class PodStatusValidator implements Runnable {
         this.statusCheckInterval = statusCheckInterval;
     }
 
-
-    @SneakyThrows
-    @Override
-    public void run() {
+    /**
+     * Run the execution.
+     *
+     * @throws InterruptedException in case of an exception
+     * @throws ServiceException in case of an exception
+     */
+    public void run() throws InterruptedException, ServiceException {
         logger.info("Polling the status of deployed pods for the chart {}", chart.getChartId().getName());
 
         try {
             verifyPodStatus();
-        } catch (ServiceException | IOException e) {
+        } catch (IOException e) {
             throw new ServiceException("Error verifying the status of the pod. Exiting", e);
         }
     }
index d9702ab..6b24c0f 100644 (file)
@@ -23,6 +23,7 @@ package org.onap.policy.clamp.acm.participant.kubernetes.handler;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doNothing;
@@ -68,17 +69,17 @@ class AutomationCompositionElementHandlerTest {
     private static final Coder CODER = new StandardCoder();
     private static final String CHART_INFO_YAML = "src/test/resources/ChartList.json";
     private static final String KEY_NAME =
-        "org.onap.domain.database.HelloWorld_K8SMicroserviceAutomationCompositionElement";
+            "org.onap.domain.database.HelloWorld_K8SMicroserviceAutomationCompositionElement";
     private static List<ChartInfo> charts;
     private static ToscaServiceTemplate toscaServiceTemplate;
     private static final String K8S_AUTOMATION_COMPOSITION_ELEMENT =
-        "org.onap.domain.database.PMSH_K8SMicroserviceAutomationCompositionElement";
+            "org.onap.domain.database.PMSH_K8SMicroserviceAutomationCompositionElement";
     private final CommonTestData commonTestData = new CommonTestData();
 
     @InjectMocks
     @Spy
     private AutomationCompositionElementHandler automationCompositionElementHandler =
-        new AutomationCompositionElementHandler();
+            new AutomationCompositionElementHandler();
 
     @Mock
     private ChartService chartService;
@@ -107,19 +108,18 @@ class AutomationCompositionElementHandlerTest {
 
         doNothing().when(chartService).uninstallChart(charts.get(0));
 
-        automationCompositionElementHandler.undeploy(
-            commonTestData.getAutomationCompositionId(), automationCompositionElementId1);
+        automationCompositionElementHandler.undeploy(commonTestData.getAutomationCompositionId(),
+                automationCompositionElementId1);
 
         doThrow(new ServiceException("Error uninstalling the chart")).when(chartService).uninstallChart(charts.get(0));
 
-        assertDoesNotThrow(() -> automationCompositionElementHandler.undeploy(
-            commonTestData.getAutomationCompositionId(), automationCompositionElementId1));
+        assertDoesNotThrow(() -> automationCompositionElementHandler
+                .undeploy(commonTestData.getAutomationCompositionId(), automationCompositionElementId1));
     }
 
     @Test
-    void test_AutomationCompositionElementUpdate() throws PfModelException, IOException, ServiceException,
-        ExecutionException, InterruptedException {
-        doReturn(true).when(chartService).installChart(any());
+    void test_AutomationCompositionElementUpdate()
+            throws PfModelException, IOException, ServiceException, ExecutionException, InterruptedException {
         doNothing().when(automationCompositionElementHandler).checkPodStatus(any(), any(), any(), anyInt(), anyInt());
         var elementId1 = UUID.randomUUID();
         var element = new AcElementDeploy();
@@ -127,11 +127,15 @@ class AutomationCompositionElementHandlerTest {
         element.setDefinition(new ToscaConceptIdentifier(KEY_NAME, "1.0.1"));
         element.setOrderedState(DeployOrder.DEPLOY);
 
-        var nodeTemplatesMap =
-            toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates();
-        automationCompositionElementHandler.deploy(
-            commonTestData.getAutomationCompositionId(), element,
-            nodeTemplatesMap.get(K8S_AUTOMATION_COMPOSITION_ELEMENT).getProperties());
+        var nodeTemplatesMap = toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates();
+
+        doReturn(false).when(chartService).installChart(any());
+        assertDoesNotThrow(() -> automationCompositionElementHandler.deploy(commonTestData.getAutomationCompositionId(),
+                element, nodeTemplatesMap.get(K8S_AUTOMATION_COMPOSITION_ELEMENT).getProperties()));
+
+        doReturn(true).when(chartService).installChart(any());
+        automationCompositionElementHandler.deploy(commonTestData.getAutomationCompositionId(), element,
+                nodeTemplatesMap.get(K8S_AUTOMATION_COMPOSITION_ELEMENT).getProperties());
 
         assertThat(automationCompositionElementHandler.getChartMap()).hasSize(1).containsKey(elementId1);
 
@@ -139,24 +143,20 @@ class AutomationCompositionElementHandlerTest {
 
         var elementId2 = UUID.randomUUID();
         element.setId(elementId2);
-        automationCompositionElementHandler.deploy(
-            commonTestData.getAutomationCompositionId(), element,
-            nodeTemplatesMap.get(K8S_AUTOMATION_COMPOSITION_ELEMENT).getProperties());
+        assertThrows(PfModelException.class,
+                () -> automationCompositionElementHandler.deploy(commonTestData.getAutomationCompositionId(), element,
+                        nodeTemplatesMap.get(K8S_AUTOMATION_COMPOSITION_ELEMENT).getProperties()));
 
         assertThat(automationCompositionElementHandler.getChartMap().containsKey(elementId2)).isFalse();
     }
 
     @Test
     void test_checkPodStatus() throws ExecutionException, InterruptedException {
-        doReturn(result).when(executor).submit(any(Runnable.class), any());
-        doReturn("Done").when(result).get();
-        doReturn(true).when(result).isDone();
         var chartInfo = charts.get(0);
         var automationCompositionId = UUID.randomUUID();
         var element = new AutomationCompositionElement();
-        assertDoesNotThrow(
-            () -> automationCompositionElementHandler.checkPodStatus(automationCompositionId,
-                    element.getId(), chartInfo, 1, 1));
+        assertThrows(ServiceException.class, () -> automationCompositionElementHandler
+                .checkPodStatus(automationCompositionId, element.getId(), chartInfo, 1, 1));
     }
 
     @Test
index 6cec605..91aff83 100644 (file)
@@ -22,8 +22,8 @@
 package org.onap.policy.clamp.acm.participant.kubernetes.helm;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
 
@@ -92,8 +92,7 @@ class PodStatusValidatorTest {
     void test_InvalidPodState() throws ServiceException {
         String invalidPod = "NAME\tREADY\tSTATUS\tRESTARTS\tAGE\nhellofromdocker-54777df9f8-qpzqr\t1/1\tInit\t0\t9h";
         doReturn(invalidPod).when(client).executeCommand(any());
-        assertThatThrownBy(() -> podStatusValidator.run())
-            .isInstanceOf(ServiceException.class).hasMessage("Error verifying the status of the pod. Exiting");
+        assertThrows(ServiceException.class, () -> podStatusValidator.run());
         assertThat(AutomationCompositionElementHandler.getPodStatusMap()).isEmpty();
     }