Support override parameters for k8s-participant 52/122552/7
authorrameshiyer27 <ramesh.murugan.iyer@est.tech>
Wed, 7 Jul 2021 19:37:54 +0000 (20:37 +0100)
committerrameshiyer27 <ramesh.murugan.iyer@est.tech>
Wed, 14 Jul 2021 16:25:56 +0000 (17:25 +0100)
Add support for helm chart override parameters in TOSCA.
Add support for monitoring Pod status after deployment.

Note: ONAP Helm charts from OOM repository needs a global master password
to be provided along with the helm command. Looking for suggestions here
to avoid passing clear text password in TOSCA (KubernetesHelm.yaml). Thanks

Issue-ID: POLICY-3433
Signed-off-by: zrrmmua <ramesh.murugan.iyer@est.tech>
Change-Id: Ibcbe79d07caa9bff12de341c3d88c36a144796bc

16 files changed:
participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/configurations/SecurityConfig.java [new file with mode: 0644]
participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/handler/ControlLoopElementHandler.java
participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/helm/HelmClient.java
participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/helm/PodStatusValidator.java [new file with mode: 0644]
participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/models/ChartInfo.java
participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/service/ChartService.java
participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/service/ChartStore.java
participant/participant-impl/participant-impl-kubernetes/src/main/resources/config/application.yaml
participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/handler/ControlLoopElementHandlerTest.java
participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/helm/HelmClientTest.java
participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/helm/PodStatusValidatorTest.java [new file with mode: 0644]
participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/rest/ChartControllerTest.java
participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/service/ChartServiceTest.java
participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/service/ChartStoreTest.java
participant/participant-impl/participant-impl-kubernetes/src/test/resources/ChartList.json
participant/participant-impl/participant-impl-kubernetes/src/test/resources/servicetemplates/KubernetesHelm.yaml

diff --git a/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/configurations/SecurityConfig.java b/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/configurations/SecurityConfig.java
new file mode 100644 (file)
index 0000000..6b4fb0a
--- /dev/null
@@ -0,0 +1,45 @@
+/*-
+ * ========================LICENSE_START=================================
+ * Copyright (C) 2021 Nordix Foundation. All rights reserved.
+ * ======================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================LICENSE_END===================================
+ */
+
+package org.onap.policy.clamp.controlloop.participant.kubernetes.configurations;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+
+@Configuration
+public class SecurityConfig extends WebSecurityConfigurerAdapter {
+
+    @Value("${security.enable-csrf:true}")
+    private boolean csrfEnabled = true;
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        // @formatter:off
+        http.authorizeRequests()
+            .antMatchers().authenticated()
+            .anyRequest().authenticated()
+            .and().httpBasic();
+        // @formatter:on
+
+        if (!csrfEnabled) {
+            http.csrf().disable();
+        }
+    }
+}
index 4f65483..20a23ca 100644 (file)
@@ -26,6 +26,7 @@ import java.lang.invoke.MethodHandles;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
 import lombok.AccessLevel;
 import lombok.Getter;
 import lombok.Setter;
@@ -35,8 +36,12 @@ import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop
 import org.onap.policy.clamp.controlloop.participant.intermediary.api.ControlLoopElementListener;
 import org.onap.policy.clamp.controlloop.participant.intermediary.api.ParticipantIntermediaryApi;
 import org.onap.policy.clamp.controlloop.participant.kubernetes.exception.ServiceException;
+import org.onap.policy.clamp.controlloop.participant.kubernetes.helm.PodStatusValidator;
 import org.onap.policy.clamp.controlloop.participant.kubernetes.models.ChartInfo;
 import org.onap.policy.clamp.controlloop.participant.kubernetes.service.ChartService;
+import org.onap.policy.common.utils.coder.Coder;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
 import org.onap.policy.models.base.PfModelException;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
@@ -45,6 +50,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+
 /**
  * This class handles implementation of controlLoopElement updates.
  */
@@ -52,6 +58,11 @@ import org.springframework.stereotype.Component;
 public class ControlLoopElementHandler implements ControlLoopElementListener {
     private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
+    // Map of helm installation and the status of corresponding pods
+    @Getter
+    private static Map<String, Map<String, String>> podStatusMap = new ConcurrentHashMap<>();
+    private static final Coder CODER = new StandardCoder();
+
     @Autowired
     private ChartService chartService;
 
@@ -62,6 +73,12 @@ public class ControlLoopElementHandler implements ControlLoopElementListener {
     @Getter(AccessLevel.PACKAGE)
     private final Map<UUID, ChartInfo> chartMap = new HashMap<>();
 
+    // Default thread config values
+    private static class ThreadConfig {
+        private int uninitializedToPassiveTimeout = 60;
+        private int podStatusCheckInterval = 30;
+    }
+
     /**
      * Callback method to handle a control loop element state change.
      *
@@ -71,7 +88,7 @@ public class ControlLoopElementHandler implements ControlLoopElementListener {
      */
     @Override
     public synchronized void controlLoopElementStateChange(UUID controlLoopElementId, ControlLoopState currentState,
-            ControlLoopOrderedState newState) {
+                                                           ControlLoopOrderedState newState) {
         switch (newState) {
             case UNINITIALISED:
                 ChartInfo chart = chartMap.get(controlLoopElementId);
@@ -80,7 +97,9 @@ public class ControlLoopElementHandler implements ControlLoopElementListener {
                     try {
                         chartService.uninstallChart(chart);
                         intermediaryApi.updateControlLoopElementState(controlLoopElementId, newState,
-                                ControlLoopState.UNINITIALISED);
+                            ControlLoopState.UNINITIALISED);
+                        chartMap.remove(controlLoopElementId);
+                        podStatusMap.remove(chart.getReleaseName());
                     } catch (ServiceException se) {
                         LOGGER.warn("deletion of Helm deployment failed", se);
                     }
@@ -108,36 +127,49 @@ public class ControlLoopElementHandler implements ControlLoopElementListener {
      */
     @Override
     public synchronized void controlLoopElementUpdate(ControlLoopElement element,
-            ToscaServiceTemplate controlLoopDefinition) throws PfModelException {
+                                                      ToscaServiceTemplate controlLoopDefinition)
+        throws PfModelException {
 
         for (Map.Entry<String, ToscaNodeTemplate> nodeTemplate : controlLoopDefinition.getToscaTopologyTemplate()
-                .getNodeTemplates().entrySet()) {
+            .getNodeTemplates().entrySet()) {
 
             // Fetching the node template of corresponding CL element
             if (element.getDefinition().getName().equals(nodeTemplate.getKey())
-                    && nodeTemplate.getValue().getProperties().containsKey("chart")) {
+                && nodeTemplate.getValue().getProperties().containsKey("chart")) {
                 @SuppressWarnings("unchecked")
                 Map<String, Object> chartData =
-                        (Map<String, Object>) nodeTemplate.getValue().getProperties().get("chart");
+                    (Map<String, Object>) nodeTemplate.getValue().getProperties().get("chart");
 
                 LOGGER.info("Installation request received for the Helm Chart {} ", chartData);
-                var chart = new ChartInfo(String.valueOf(chartData.get("release_name")),
-                        String.valueOf(chartData.get("chart_name")), String.valueOf(chartData.get("version")),
-                        String.valueOf(chartData.get("namespace")));
                 try {
+                    var chartInfo =  CODER.decode(String.valueOf(chartData), ChartInfo.class);
                     var repositoryValue = chartData.get("repository");
                     if (repositoryValue != null) {
-                        chart.setRepository(String.valueOf(repositoryValue));
+                        chartInfo.setRepository(repositoryValue.toString());
                     }
-                    chartService.installChart(chart);
-                    chartMap.put(element.getId(), chart);
-                } catch (IOException | ServiceException ise) {
-                    LOGGER.warn("installation of Helm chart failed", ise);
+                    chartService.installChart(chartInfo);
+                    chartMap.put(element.getId(), chartInfo);
+
+                    var config = CODER.convert(nodeTemplate.getValue().getProperties(), ThreadConfig.class);
+                    checkPodStatus(chartInfo, config.uninitializedToPassiveTimeout, config.podStatusCheckInterval);
+
+                } catch (ServiceException | CoderException | IOException e) {
+                    LOGGER.warn("Installation of Helm chart failed", e);
                 }
             }
         }
     }
 
+    /**
+     * Invoke a new thread to check the status of deployed pods.
+     * @param chart ChartInfo
+     */
+    public void checkPodStatus(ChartInfo chart, int timeout, int podStatusCheckInterval) {
+        // Invoke runnable thread to check pod status
+        var runnableThread = new Thread(new PodStatusValidator(chart, timeout, podStatusCheckInterval));
+        runnableThread.start();
+    }
+
     /**
      * Overridden method.
      *
index 90d7218..b38fbeb 100644 (file)
@@ -19,6 +19,7 @@
 package org.onap.policy.clamp.controlloop.participant.kubernetes.helm;
 
 import java.io.BufferedReader;
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.lang.invoke.MethodHandles;
@@ -26,6 +27,7 @@ import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 import org.apache.commons.io.IOUtils;
 import org.onap.policy.clamp.controlloop.participant.kubernetes.exception.ServiceException;
 import org.onap.policy.clamp.controlloop.participant.kubernetes.models.ChartInfo;
@@ -60,9 +62,10 @@ public class HelmClient {
             logger.warn("Namespace not created", e);
         }
         processBuilder = prepareInstallCommand(chart);
-        logger.info("Installing helm chart {} from the repository {} ", chart.getChartName(), chart.getRepository());
+        logger.info("Installing helm chart {} from the repository {} ", chart.getChartId().getName(),
+            chart.getRepository());
         executeCommand(processBuilder);
-        logger.info("Chart {} installed successfully", chart.getChartName());
+        logger.info("Chart {} installed successfully", chart.getChartId().getName());
     }
 
     /**
@@ -79,9 +82,9 @@ public class HelmClient {
         if (repository != null) {
             return repository;
         }
-        var localHelmChartDir = chartStore.getAppPath(chart.getChartName(), chart.getVersion()).toString();
+        var localHelmChartDir = chartStore.getAppPath(chart.getChartId()).toString();
         logger.info("Chart not found in helm repositories, verifying local repo {} ", localHelmChartDir);
-        if (verifyLocalHelmRepo(localHelmChartDir + "/" + chart.getChartName())) {
+        if (verifyLocalHelmRepo(new File(localHelmChartDir + "/" + chart.getChartId().getName()))) {
             repository = localHelmChartDir;
         }
 
@@ -96,15 +99,15 @@ public class HelmClient {
      * @throws ServiceException incase of error
      */
     public String verifyConfiguredRepo(ChartInfo chart) throws IOException, ServiceException {
-        logger.info("Looking for helm chart {} in all the configured helm repositories", chart.getChartName());
+        logger.info("Looking for helm chart {} in all the configured helm repositories", chart.getChartId().getName());
         String repository = null;
-        var builder = helmRepoVerifyCommand(chart.getChartName());
+        var builder = helmRepoVerifyCommand(chart.getChartId().getName());
         String output = executeCommand(builder);
         try (var reader = new BufferedReader(new InputStreamReader(IOUtils.toInputStream(output,
-                StandardCharsets.UTF_8)))) {
+            StandardCharsets.UTF_8)))) {
             String line = reader.readLine();
             while (line != null) {
-                if (line.contains(chart.getChartName())) {
+                if (line.contains(chart.getChartId().getName())) {
                     repository = line.split("/")[0];
                     logger.info("Helm chart located in the repository {} ", repository);
                     return repository;
@@ -125,6 +128,7 @@ public class HelmClient {
         executeCommand(prepareUnInstallCommand(chart));
     }
 
+
     /**
      * Execute helm cli bash commands .
      * @param processBuilder processbuilder
@@ -141,7 +145,9 @@ public class HelmClient {
 
             if (exitValue != 0) {
                 var error = IOUtils.toString(process.getErrorStream(), StandardCharsets.UTF_8);
-                throw new ServiceException("Command execution failed: " + commandStr + " " + error);
+                if (! error.isEmpty()) {
+                    throw new ServiceException("Command execution failed: " + commandStr + " " + error);
+                }
             }
 
             var output = IOUtils.toString(process.getInputStream(), StandardCharsets.UTF_8);
@@ -151,7 +157,7 @@ public class HelmClient {
         } catch (InterruptedException ie) {
             Thread.currentThread().interrupt();
             throw new ServiceException("Failed to execute the Command: " + commandStr + ", the command was interrupted",
-                    ie);
+                ie);
         } catch (Exception exc) {
             throw new ServiceException("Failed to execute the Command: " + commandStr, exc);
         }
@@ -161,27 +167,34 @@ public class HelmClient {
 
         // @formatter:off
         List<String> helmArguments = new ArrayList<>(
-                Arrays.asList(
-                        "helm",
-                        "install", chart.getReleaseName(), chart.getRepository() + "/" + chart.getChartName(),
-                        "--version", chart.getVersion(),
-                        "--namespace", chart.getNamespace()
-                )
+            List.of(
+                "helm",
+                "install", chart.getReleaseName(), chart.getRepository() + "/" + chart.getChartId().getName(),
+                "--version", chart.getChartId().getVersion(),
+                "--namespace", chart.getNamespace()
+            )
         );
         // @formatter:on
 
-        // Verify if values.yaml available for the chart
-        var overrideFile = chartStore.getOverrideFile(chart).getPath();
-        if (verifyLocalHelmRepo(overrideFile)) {
-            logger.info("Override yaml file available for the helm chart");
-            helmArguments.addAll(Arrays.asList("--values", overrideFile));
+        // Verify if values.yaml/override parameters available for the chart
+        var localOverrideYaml = chartStore.getOverrideFile(chart);
+
+        if (verifyLocalHelmRepo(localOverrideYaml)) {
+            logger.info("Override yaml available for the helm chart");
+            helmArguments.addAll(List.of("--values", localOverrideYaml.getPath()));
         }
 
+        if (chart.getOverrideParams() != null) {
+            for (Map.Entry<String, String> entry : chart.getOverrideParams().entrySet()) {
+                helmArguments.addAll(List.of("--set", entry.getKey() + "=" + entry.getValue()));
+            }
+        }
         return new ProcessBuilder().command(helmArguments);
     }
 
     private ProcessBuilder prepareUnInstallCommand(ChartInfo chart) {
-        return new ProcessBuilder("helm", "delete", chart.getReleaseName(), "--namespace", chart.getNamespace());
+        return new ProcessBuilder("helm", "delete", chart.getReleaseName(), "--namespace",
+            chart.getNamespace());
     }
 
     private ProcessBuilder prepareCreateNamespaceCommand(String namespace) {
@@ -189,12 +202,9 @@ public class HelmClient {
     }
 
     private ProcessBuilder helmRepoVerifyCommand(String chartName) {
-        return new ProcessBuilder().command("bash", "-c", "helm search repo | grep " + chartName);
+        return new ProcessBuilder().command("sh", "-c", "helm search repo | grep " + chartName);
     }
 
-    private ProcessBuilder localRepoVerifyCommand(String localFile) {
-        return new ProcessBuilder().command("bash", "-c", "ls " + localFile);
-    }
 
     private void updateHelmRepo() throws ServiceException {
         logger.info("Updating local helm repositories before verifying the chart");
@@ -202,16 +212,8 @@ public class HelmClient {
         logger.debug("Helm repositories updated successfully");
     }
 
-    private boolean verifyLocalHelmRepo(String localFile) {
-        var isVerified = false;
-        var processBuilder = localRepoVerifyCommand(localFile);
-        try {
-            executeCommand(processBuilder);
-            isVerified = true;
-        } catch (ServiceException e) {
-            logger.error("Unable to verify file in local repository", e);
-        }
-        return isVerified;
+    private boolean verifyLocalHelmRepo(File localFile) {
+        return localFile.exists();
     }
 
     protected static String toString(ProcessBuilder processBuilder) {
diff --git a/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/helm/PodStatusValidator.java b/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/helm/PodStatusValidator.java
new file mode 100644 (file)
index 0000000..d55fd66
--- /dev/null
@@ -0,0 +1,119 @@
+/*-
+ * ========================LICENSE_START=================================
+ * Copyright (C) 2021 Nordix Foundation. All rights reserved.
+ * ======================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================LICENSE_END===================================
+ */
+
+package org.onap.policy.clamp.controlloop.participant.kubernetes.helm;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+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.onap.policy.clamp.controlloop.participant.kubernetes.exception.ServiceException;
+import org.onap.policy.clamp.controlloop.participant.kubernetes.handler.ControlLoopElementHandler;
+import org.onap.policy.clamp.controlloop.participant.kubernetes.models.ChartInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class PodStatusValidator implements Runnable {
+
+    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    private final int statusCheckInterval;
+
+    //Timeout for the thread to exit.
+    private final int timeout;
+
+    private ChartInfo chart;
+
+    /**
+     * Constructor for PodStatusValidator.
+     * @param chart chartInfo
+     * @param timeout timeout for the thread to exit
+     * @param statusCheckInterval Interval to check pod status
+     */
+    public PodStatusValidator(ChartInfo chart, int timeout, int statusCheckInterval) {
+        this.chart = chart;
+        this.timeout = timeout;
+        this.statusCheckInterval = statusCheckInterval;
+    }
+
+
+    @SneakyThrows
+    @Override
+    public void run() {
+        logger.info("Polling the status of deployed pods for the chart {}", chart.getChartId().getName());
+        Map<String, String> podStatusMap;
+        String output = null;
+        var isVerified = false;
+        long endTime = System.currentTimeMillis() + (timeout * 1000L);
+
+        while (!isVerified && System.currentTimeMillis() < endTime) {
+            try {
+                output = HelmClient.executeCommand(verifyPodStatusCommand(chart));
+                podStatusMap = mapPodStatus(output);
+                isVerified = podStatusMap.values()
+                    .stream()
+                    .allMatch("Running"::equals);
+                if (! isVerified) {
+                    logger.info("Waiting for the pods to be active for the chart {}", chart.getChartId().getName());
+                    podStatusMap.forEach((key, value) -> logger.info("Pod: {} , state: {}", key, value));
+                    ControlLoopElementHandler.getPodStatusMap().put(chart.getReleaseName(), podStatusMap);
+                    // Recheck status of pods in specific intervals.
+                    Thread.sleep(statusCheckInterval * 1000L);
+                } else {
+                    logger.info("All pods are in running state for the helm chart {}", chart.getChartId().getName());
+                    ControlLoopElementHandler.getPodStatusMap().put(chart.getReleaseName(), podStatusMap);
+                }
+            } catch (ServiceException | IOException  e) {
+                throw new ServiceException("Error verifying the status of the pod. Exiting", e);
+            }
+        }
+    }
+
+    private ProcessBuilder verifyPodStatusCommand(ChartInfo chart) {
+        String podName = chart.getReleaseName() + "-" + chart.getChartId().getName();
+        String cmd = "kubectl get pods --namespace " +  chart.getNamespace() + " | grep " + podName;
+        return new ProcessBuilder("sh", "-c", cmd);
+    }
+
+
+    private Map<String, String> mapPodStatus(String output) throws IOException, ServiceException {
+        Map<String, String> podStatusMap = new HashMap<>();
+        try (var reader = new BufferedReader(new InputStreamReader(IOUtils.toInputStream(output,
+            StandardCharsets.UTF_8)))) {
+            var line = reader.readLine();
+            while (line != null) {
+                if (line.contains(chart.getChartId().getName())) {
+                    var result = line.split("\\s+");
+                    podStatusMap.put(result[0], result[2]);
+                }
+                line = reader.readLine();
+            }
+        }
+        if (!podStatusMap.isEmpty()) {
+            return podStatusMap;
+        } else {
+            throw new ServiceException("Status of Pod is empty");
+        }
+    }
+}
index 6bfb7ae..b53f207 100644 (file)
 
 package org.onap.policy.clamp.controlloop.participant.kubernetes.models;
 
+import java.util.Map;
 import lombok.Data;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
-import org.immutables.gson.Gson;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 
 @Data
 @RequiredArgsConstructor
-@Gson.TypeAdapters
 public class ChartInfo {
 
     @NonNull
     private String releaseName;
 
     @NonNull
-    private String chartName;
-
-    @NonNull
-    private String version;
+    private ToscaConceptIdentifier chartId;
 
     @NonNull
     private String namespace;
 
     private String repository;
 
+    private Map<String, String> overrideParams;
+
 }
index adb6cf0..a152218 100644 (file)
@@ -68,7 +68,7 @@ public class ChartService {
      * @throws ServiceException in case of error
      */
     public ChartInfo saveChart(ChartInfo chartInfo, MultipartFile chartFile, MultipartFile overrideFile)
-            throws IOException, ServiceException {
+        throws IOException, ServiceException {
         return chartStore.saveChart(chartInfo, chartFile, overrideFile);
     }
 
@@ -91,7 +91,7 @@ public class ChartService {
             String repository = findChartRepo(chart);
             if (repository == null) {
                 logger.error("Chart repository could not be found. Skipping chart Installation "
-                        + "for the chart {} ", chart.getChartName());
+                    + "for the chart {} ", chart.getChartId().getName());
                 return;
             } else {
                 chart.setRepository(repository);
@@ -108,7 +108,7 @@ public class ChartService {
      * @throws IOException in case of IO errors
      */
     public String findChartRepo(ChartInfo chart) throws ServiceException, IOException {
-        logger.info("Fetching helm chart repository for the given chart {} ", chart.getChartName());
+        logger.info("Fetching helm chart repository for the given chart {} ", chart.getChartId().getName());
         return helmClient.findChartRepository(chart);
     }
 
@@ -121,5 +121,4 @@ public class ChartService {
         logger.info("Uninstalling helm deployment {}", chart.getReleaseName());
         helmClient.uninstallChart(chart);
     }
-
 }
index 03b3516..9756717 100644 (file)
@@ -40,6 +40,7 @@ import org.onap.policy.clamp.controlloop.participant.kubernetes.models.ChartInfo
 import org.onap.policy.clamp.controlloop.participant.kubernetes.parameters.ParticipantK8sParameters;
 import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
@@ -73,8 +74,8 @@ public class ChartStore {
      * @return the chart file.
      */
     public File getHelmChartFile(ChartInfo chart) {
-        var appPath = getAppPath(chart.getChartName(), chart.getVersion());
-        return new File(appPath.toFile(), chart.getChartName());
+        var appPath = getAppPath(chart.getChartId());
+        return new File(appPath.toFile(), chart.getChartId().getName());
     }
 
     /**
@@ -84,7 +85,7 @@ public class ChartStore {
      * @return the override yaml file
      */
     public File getOverrideFile(ChartInfo chart) {
-        var appPath = getAppPath(chart.getChartName(), chart.getVersion());
+        var appPath = getAppPath(chart.getChartId());
         return new File(appPath.toFile(), "values.yaml");
     }
 
@@ -100,11 +101,11 @@ public class ChartStore {
      * @throws ServiceException incase of error.
      */
     public synchronized ChartInfo saveChart(ChartInfo chartInfo, MultipartFile chartFile, MultipartFile overrideFile)
-            throws IOException, ServiceException {
-        if (localChartMap.containsKey(key(chartInfo.getChartName(), chartInfo.getVersion()))) {
+        throws IOException, ServiceException {
+        if (localChartMap.containsKey(key(chartInfo))) {
             throw new ServiceException("Chart already exist");
         }
-        var appPath = getAppPath(chartInfo.getChartName(), chartInfo.getVersion());
+        var appPath = getAppPath(chartInfo.getChartId());
         Files.createDirectories(appPath);
 
         chartFile.transferTo(getHelmChartFile(chartInfo));
@@ -143,7 +144,7 @@ public class ChartStore {
      * @param chart chart info
      */
     public synchronized void deleteChart(ChartInfo chart) {
-        var appPath = getAppPath(chart.getChartName(), chart.getVersion());
+        var appPath = getAppPath(chart.getChartId());
         try {
             FileSystemUtils.deleteRecursively(appPath);
         } catch (IOException exc) {
@@ -156,24 +157,23 @@ public class ChartStore {
     /**
      * Fetch the local chart directory of specific chart.
      *
-     * @param chartName name of the chart
-     * @param chartVersion version of the chart
+     * @param chartId Id of the chart
      * @return path
      */
-    public Path getAppPath(String chartName, String chartVersion) {
-        return Path.of(participantK8sParameters.getLocalChartDirectory(), chartName, chartVersion);
+    public Path getAppPath(ToscaConceptIdentifier chartId) {
+        return Path.of(participantK8sParameters.getLocalChartDirectory(), chartId.getName(), chartId.getVersion());
     }
 
     private void storeChartInFile(ChartInfo chart) {
         try (var out = new PrintStream(new FileOutputStream(getFile(chart)))) {
             out.print(STANDARD_CODER.encode(chart));
         } catch (Exception exc) {
-            LOGGER.warn("Could not store chart: {} {}", chart.getChartName(), exc);
+            LOGGER.warn("Could not store chart: {} {}", chart.getChartId(), exc);
         }
     }
 
     private File getFile(ChartInfo chart) {
-        var appPath = getAppPath(chart.getChartName(), chart.getVersion()).toString();
+        var appPath = getAppPath(chart.getChartId()).toString();
         return Path.of(appPath, participantK8sParameters.getInfoFileName()).toFile();
     }
 
@@ -188,7 +188,7 @@ public class ChartStore {
     }
 
     private synchronized void restoreFromLocalFileSystem(Path localChartDirectoryPath)
-            throws IOException {
+        throws IOException {
 
         Files.walkFileTree(localChartDirectoryPath, new SimpleFileVisitor<Path>() {
             @Override
@@ -208,11 +208,10 @@ public class ChartStore {
     }
 
     private String key(ChartInfo chart) {
-        return key(chart.getChartName(), chart.getVersion());
+        return key(chart.getChartId().getName(), chart.getChartId().getVersion());
     }
 
     private String key(String chartName, String chartVersion) {
         return chartName + "_" + chartVersion;
     }
-
 }
index 63ec8a2..5a2903c 100644 (file)
@@ -1,6 +1,10 @@
 spring:
-  profiles:
-    active: prod
+  security:
+    user:
+      name: healthcheck
+      password: zb!XztG34
+security:
+  enable-csrf: false
 
 participant:
   localChartDirectory: /var/helm-manager/local-charts
index f3d27a6..f8381ee 100644 (file)
@@ -22,6 +22,8 @@ package org.onap.policy.clamp.controlloop.participant.kubernetes.handler;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doThrow;
 
@@ -35,6 +37,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Mockito;
+import org.mockito.Spy;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopOrderedState;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState;
@@ -64,6 +67,7 @@ class ControlLoopElementHandlerTest {
 
 
     @InjectMocks
+    @Spy
     private ControlLoopElementHandler controlLoopElementHandler = new ControlLoopElementHandler();
 
     @Mock
@@ -107,7 +111,7 @@ class ControlLoopElementHandlerTest {
 
     @Test
     void test_ControlLoopElementUpdate() throws PfModelException, IOException, ServiceException {
-
+        doNothing().when(controlLoopElementHandler).checkPodStatus(any(), anyInt(), anyInt());
         UUID elementId1 = UUID.randomUUID();
         ControlLoopElement element = new ControlLoopElement();
         element.setId(elementId1);
index 5f8b7dc..370bfa6 100644 (file)
@@ -33,6 +33,7 @@ import java.io.File;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.util.List;
+import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -49,6 +50,7 @@ import org.onap.policy.common.utils.coder.Coder;
 import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.common.utils.coder.StandardCoder;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.util.FileSystemUtils;
 
 
 @ExtendWith(SpringExtension.class)
@@ -74,6 +76,12 @@ class HelmClientTest {
         mockedClient = mockStatic(HelmClient.class);
     }
 
+    @AfterAll
+    public static void close() throws IOException {
+        mockedClient.close();
+        FileSystemUtils.deleteRecursively(Path.of("target/tmp"));
+    }
+
     @Test
     void test_installChart() throws IOException {
         mockedClient.when(() -> HelmClient.executeCommand(any()))
@@ -85,21 +93,22 @@ class HelmClientTest {
 
     @Test
     void test_findChartRepository() throws IOException, ServiceException {
+        String tmpPath = "target/tmp/dummyChart/1.0/";
         mockedClient.when(() -> HelmClient.executeCommand(Mockito.any()))
             .thenReturn("nginx-stable/nginx-ingress\t0.9.3\t1.11.3"
                 + " \tNGINX Ingress Controller");
         String configuredRepo = helmClient.findChartRepository(charts.get(1));
-
         assertThat(configuredRepo).isEqualTo("nginx-stable");
 
-        doReturn(Path.of("/target/tmp/dummyChart/1.0")).when(chartStore).getAppPath(charts.get(1).getChartName(),
-            charts.get(1).getVersion());
+        File tmpFile = new File(tmpPath + charts.get(1).getChartId().getName());
+        tmpFile.mkdirs();
+        doReturn(Path.of(tmpPath)).when(chartStore).getAppPath(charts.get(1).getChartId());
 
         doReturn(null).when(helmClient).verifyConfiguredRepo(charts.get(1));
 
         String localRepoName = helmClient.findChartRepository(charts.get(1));
         assertNotNull(localRepoName);
-        assertThat(localRepoName).endsWith(charts.get(0).getVersion());
+        assertThat(localRepoName).endsWith(charts.get(0).getChartId().getVersion());
     }
 
     @Test
diff --git a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/helm/PodStatusValidatorTest.java b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/helm/PodStatusValidatorTest.java
new file mode 100644 (file)
index 0000000..f72a534
--- /dev/null
@@ -0,0 +1,108 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.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.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mockStatic;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.MockedStatic;
+import org.onap.policy.clamp.controlloop.participant.kubernetes.exception.ServiceException;
+import org.onap.policy.clamp.controlloop.participant.kubernetes.handler.ControlLoopElementHandler;
+import org.onap.policy.clamp.controlloop.participant.kubernetes.models.ChartInfo;
+import org.onap.policy.clamp.controlloop.participant.kubernetes.models.ChartList;
+import org.onap.policy.common.utils.coder.Coder;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+@ExtendWith(SpringExtension.class)
+class PodStatusValidatorTest {
+
+
+    private static final Coder CODER = new StandardCoder();
+    private static final String CHART_INFO_YAML = "src/test/resources/ChartList.json";
+    private static List<ChartInfo> charts;
+    private static int timeout = 60;
+    private static int statusCheckInterval = 30;
+
+
+    @InjectMocks
+    private static PodStatusValidator podStatusValidator;
+
+    private static MockedStatic<HelmClient> mockedClient;
+
+
+    @BeforeAll
+    static void init() throws CoderException {
+        charts = CODER.decode(new File(CHART_INFO_YAML), ChartList.class).getCharts();
+        mockedClient = mockStatic(HelmClient.class);
+        podStatusValidator = new PodStatusValidator(charts.get(0), timeout, statusCheckInterval);
+    }
+
+    @AfterEach
+    void clearPodStatusMap() {
+        ControlLoopElementHandler.getPodStatusMap().clear();
+    }
+
+    @AfterAll
+    public static void close() {
+        mockedClient.close();
+    }
+
+
+    @Test
+    void test_RunningPodState() {
+        String runningPod = "NAME\tREADY\tSTATUS\tRESTARTS\tAGE\r\nHelloWorld-54777df9f8-qpzqr\t1/1\tRunning\t0\t9h";
+        mockedClient.when(() -> HelmClient.executeCommand(any()))
+            .thenReturn(runningPod);
+        assertDoesNotThrow(() -> podStatusValidator.run());
+        assertThat(ControlLoopElementHandler.getPodStatusMap()).hasSize(1);
+        assertThat(ControlLoopElementHandler.getPodStatusMap()).containsKey(charts.get(0).getReleaseName());
+        assertThat(ControlLoopElementHandler.getPodStatusMap())
+            .containsValue(Map.of("HelloWorld-54777df9f8-qpzqr", "Running"));
+    }
+
+
+    @Test
+    void test_InvalidPodState() {
+        String invalidPod = "NAME\tREADY\tSTATUS\tRESTARTS\tAGE\nhellofromdocker-54777df9f8-qpzqr\t1/1\tInit\t0\t9h";
+        mockedClient.when(() -> HelmClient.executeCommand(any()))
+            .thenReturn(invalidPod);
+        assertThatThrownBy(() -> podStatusValidator.run())
+            .isInstanceOf(ServiceException.class).hasMessage("Error verifying the status of the pod. Exiting");
+        assertThat(ControlLoopElementHandler.getPodStatusMap()).isEmpty();
+    }
+
+}
index 1a1bdae..a28fd9e 100644 (file)
@@ -93,7 +93,7 @@ class ChartControllerTest {
     @BeforeEach
     void mockServiceClass() {
         when(chartService.getAllCharts()).thenReturn(charts);
-        when(chartService.getChart(charts.get(0).getChartName(), charts.get(0).getVersion()))
+        when(chartService.getChart(charts.get(0).getChartId().getName(), charts.get(0).getChartId().getVersion()))
             .thenReturn(charts.get(0));
 
         this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
@@ -110,7 +110,7 @@ class ChartControllerTest {
 
         mockMvc.perform(requestBuilder).andExpect(status().isOk())
             .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
-            .andExpect(jsonPath("$.charts.[0].chartName", is("HelloWorld")));
+            .andExpect(jsonPath("$.charts.[0].chartId.name", is("HelloWorld")));
     }
 
     /**
@@ -125,7 +125,7 @@ class ChartControllerTest {
         doNothing().when(chartService).installChart(charts.get(0));
 
         requestBuilder = MockMvcRequestBuilders.post(INSTALL_CHART_URL).accept(MediaType.APPLICATION_JSON_VALUE)
-            .content(getInstallationJson(charts.get(0).getChartName(), charts.get(0).getVersion()))
+            .content(getInstallationJson(charts.get(0).getChartId().getName(), charts.get(0).getChartId().getVersion()))
             .contentType(MediaType.APPLICATION_JSON_VALUE);
 
         mockMvc.perform(requestBuilder).andExpect(status().isCreated());
@@ -149,9 +149,9 @@ class ChartControllerTest {
         //Mocking successful scenario for void uninstall method
         doNothing().when(chartService).uninstallChart(charts.get(0));
 
-        requestBuilder = MockMvcRequestBuilders.delete(UNINSTALL_CHART_URL + charts.get(0).getChartName()
-            + "/" + charts.get(0).getVersion()).accept(MediaType.APPLICATION_JSON_VALUE)
-            .contentType(MediaType.APPLICATION_JSON_VALUE);
+        requestBuilder = MockMvcRequestBuilders.delete(UNINSTALL_CHART_URL + charts.get(0)
+            .getChartId().getName() + "/" + charts.get(0).getChartId().getVersion())
+            .accept(MediaType.APPLICATION_JSON_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE);
 
         mockMvc.perform(requestBuilder).andExpect(status().isNoContent());
 
@@ -196,8 +196,9 @@ class ChartControllerTest {
         //Mocking successful scenario for void uninstall method
         doNothing().when(chartService).deleteChart(charts.get(0));
 
-        requestBuilder = MockMvcRequestBuilders.delete(DEFAULT_CHART_URL + "/" + charts.get(0).getChartName()
-            + "/" + charts.get(0).getVersion()).accept(MediaType.APPLICATION_JSON_VALUE)
+        requestBuilder = MockMvcRequestBuilders.delete(DEFAULT_CHART_URL + "/" + charts.get(0)
+            .getChartId().getName() + "/" + charts.get(0).getChartId().getVersion())
+            .accept(MediaType.APPLICATION_JSON_VALUE)
             .contentType(MediaType.APPLICATION_JSON_VALUE);
 
         mockMvc.perform(requestBuilder).andExpect(status().isNoContent());
@@ -219,8 +220,8 @@ class ChartControllerTest {
 
     private String getChartInfoJson() {
         JSONObject jsonObj = new JSONObject();
-        jsonObj.put("chartName", charts.get(0).getChartName());
-        jsonObj.put("version", charts.get(0).getVersion());
+        jsonObj.put("chartName", charts.get(0).getChartId().getName());
+        jsonObj.put("version", charts.get(0).getChartId().getVersion());
         jsonObj.put("namespace", charts.get(0).getNamespace());
         jsonObj.put("repository", charts.get(0).getRepository());
         jsonObj.put("releaseName", charts.get(0).getReleaseName());
index 957a69a..8e79434 100644 (file)
@@ -88,8 +88,8 @@ class ChartServiceTest {
         assertNull(chartService.getChart("dummyName", "dummyversion"));
 
         doReturn(charts.get(0)).when(chartStore).getChart(any(), any());
-        ChartInfo chart = chartService.getChart(charts.get(0).getChartName(),
-            charts.get(0).getVersion());
+        ChartInfo chart = chartService.getChart(charts.get(0).getChartId().getName(),
+            charts.get(0).getChartId().getVersion());
         assertNotNull(chart);
         assertThat(chart.getNamespace()).isEqualTo(charts.get(0).getNamespace());
     }
@@ -107,7 +107,7 @@ class ChartServiceTest {
 
         ChartInfo chart = chartService.saveChart(charts.get(0), mockChartFile, mockOverrideFile);
         assertNotNull(chart);
-        assertThat(chart.getChartName()).isEqualTo(charts.get(0).getChartName());
+        assertThat(chart.getChartId().getName()).isEqualTo(charts.get(0).getChartId().getName());
 
     }
 
index 2d05a7a..eb4e7a1 100644 (file)
@@ -46,6 +46,7 @@ import org.onap.policy.clamp.controlloop.participant.kubernetes.parameters.Parti
 import org.onap.policy.common.utils.coder.Coder;
 import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.springframework.mock.web.MockMultipartFile;
 import org.springframework.util.FileSystemUtils;
 
@@ -88,7 +89,7 @@ class ChartStoreTest {
     void test_getHelmChartFile() {
         File file = chartStore.getHelmChartFile(charts.get(0));
         assertNotNull(file);
-        assertThat(file.getPath()).endsWith(charts.get(0).getChartName());
+        assertThat(file.getPath()).endsWith(charts.get(0).getChartId().getName());
     }
 
     @Test
@@ -103,10 +104,10 @@ class ChartStoreTest {
         MockMultipartFile mockChartFile = new MockMultipartFile("chart", "dummy".getBytes());
         MockMultipartFile mockOverrideFile = new MockMultipartFile("override", "dummy".getBytes());
         ChartInfo testChart = charts.get(0);
-        testChart.setChartName("testChart");
+        testChart.setChartId(new ToscaConceptIdentifier("testChart", "1.0.0"));
         ChartInfo result = chartStore.saveChart(charts.get(0), mockChartFile, mockOverrideFile);
 
-        assertThat(result.getChartName()).isEqualTo("testChart");
+        assertThat(result.getChartId().getName()).isEqualTo("testChart");
         assertThat(chartStore.getLocalChartMap()).hasSize(1);
 
         assertThatThrownBy(() -> chartStore.saveChart(charts.get(0), mockChartFile, mockOverrideFile))
@@ -116,11 +117,12 @@ class ChartStoreTest {
 
     @Test
     void test_getChart() {
-        assertNull(chartStore.getChart(charts.get(0).getChartName(), charts.get(0).getVersion()));
-        chartStore.getLocalChartMap().put(charts.get(0).getChartName() + "_" + charts.get(0).getVersion(),
-            charts.get(0));
-        ChartInfo chart = chartStore.getChart(charts.get(0).getChartName(), charts.get(0).getVersion());
-        assertThat(chart.getChartName()).isEqualTo(charts.get(0).getChartName());
+        assertNull(chartStore.getChart(charts.get(0).getChartId().getName(), charts.get(0).getChartId().getVersion()));
+        chartStore.getLocalChartMap().put(charts.get(0).getChartId().getName() + "_" + charts.get(0).getChartId()
+                .getVersion(), charts.get(0));
+        ChartInfo chart = chartStore.getChart(charts.get(0).getChartId().getName(),
+            charts.get(0).getChartId().getVersion());
+        assertThat(chart.getChartId().getName()).isEqualTo(charts.get(0).getChartId().getName());
     }
 
     @Test
@@ -129,7 +131,8 @@ class ChartStoreTest {
         assertThat(chartStore.getAllCharts()).isEmpty();
 
         for (ChartInfo chart : charts) {
-            chartStore.getLocalChartMap().put(chart.getChartName() + "_" + chart.getVersion(), chart);
+            chartStore.getLocalChartMap().put(chart.getChartId().getName() + "_" + chart.getChartId().getVersion(),
+                chart);
         }
         List<ChartInfo> retrievedChartList = chartStore.getAllCharts();
         assertThat(retrievedChartList).isNotEmpty();
@@ -138,8 +141,8 @@ class ChartStoreTest {
 
     @Test
     void test_deleteChart() {
-        chartStore.getLocalChartMap().put(charts.get(0).getChartName() + "_" + charts.get(0).getVersion(),
-            charts.get(0));
+        chartStore.getLocalChartMap().put(charts.get(0).getChartId().getName() + "_" + charts.get(0).getChartId()
+                .getVersion(), charts.get(0));
         assertThat(chartStore.getLocalChartMap()).hasSize(1);
         chartStore.deleteChart(charts.get(0));
         assertThat(chartStore.getLocalChartMap()).isEmpty();
@@ -147,9 +150,9 @@ class ChartStoreTest {
 
     @Test
     void test_getAppPath() {
-        Path path = chartStore.getAppPath(charts.get(0).getChartName(), charts.get(0).getVersion());
+        Path path = chartStore.getAppPath(charts.get(0).getChartId());
         assertNotNull(path);
-        assertThat(path.toString()).endsWith(charts.get(0).getVersion());
+        assertThat(path.toString()).endsWith(charts.get(0).getChartId().getVersion());
         assertThat(path.toString()).startsWith("target");
     }
 
@@ -158,13 +161,14 @@ class ChartStoreTest {
         MockMultipartFile mockChartFile = new MockMultipartFile("HelmChartFile", "dummyData".getBytes());
         MockMultipartFile mockOverrideFile = new MockMultipartFile("overrideFile.yaml", "dummyData".getBytes());
         ChartInfo testChart = charts.get(0);
-        testChart.setChartName("dummyChart");
+        testChart.setChartId(new ToscaConceptIdentifier("dummyChart", "1.0.0"));
 
         //Creating a dummy chart in local dir.
         chartStore.saveChart(charts.get(0), mockChartFile, mockOverrideFile);
 
         //Instantiating a new chartStore object with pre available chart in local.
         ChartStore chartStore2 = new ChartStore(parameters);
-        assertThat(chartStore2.getLocalChartMap()).hasSize(1).containsKey("dummyChart_" + charts.get(0).getVersion());
+        assertThat(chartStore2.getLocalChartMap()).hasSize(1).containsKey("dummyChart_" + charts.get(0).getChartId()
+            .getVersion());
     }
 }
index 4e355c3..2f4ec28 100644 (file)
@@ -1,15 +1,21 @@
 {
   "charts" : [
     {
-      "chartName" : "HelloWorld",
-      "version" :   "1.0",
+      "chartId" : {
+        "name" : "HelloWorld",
+        "version" :   "1.0"
+      },
       "namespace" : "onap",
-      "repository" : "chartMuseum"
+      "repository" : "chartMuseum",
+      "releaseName" : "helloworld"
     },
     {
-      "chartName" : "nginx",
-      "version" :   "1.1",
-      "namespace" : "onap"
+      "chartId" : {
+        "name" : "nginx",
+        "version" :   "1.1"
+      },
+      "namespace" : "onap",
+      "releaseName" : "nginxapp"
     }
   ]
 }
index 3212b5a..69886cd 100644 (file)
@@ -97,12 +97,15 @@ topology_template:
         participant_id:
           name: org.onap.k8s.controlloop.K8SControlLoopParticipant
           version: 2.3.4
+        uninitializedToPassiveTimeout: 180
+        podStatusCheckInterval: 30
         chart:
-          release_name: helloworld
-          chart_name: hello
-          version: 0.1.0
-          repository: chartMuseum
+          chartId:
+            name: hello
+            version: 0.1.0
+          releaseName: helloworld
           namespace: onap
+          repository: chartMuseum
 
     org.onap.domain.database.PMSH_K8SMicroserviceControlLoopElement:
       # Chart from local file system
@@ -115,11 +118,16 @@ topology_template:
         participant_id:
           name: org.onap.k8s.controlloop.K8SControlLoopParticipant
           version: 2.3.4
+        uninitializedToPassiveTimeout: 180
+        podStatusCheckInterval: 30
         chart:
-          release_name: pmshmicroservice
-          chart_name: test
-          version: 1.0.1
+          chartId:
+            name: dcae-pmsh
+            version: 8.0.0
           namespace: onap
+          releaseName: pmshms
+          overrideParams:
+            global.masterPassword: test
 
     org.onap.domain.database.Local_K8SMicroserviceControlLoopElement:
       # Chart installation without passing repository name
@@ -132,10 +140,13 @@ topology_template:
         participant_id:
           name: org.onap.k8s.controlloop.K8SControlLoopParticipant
           version: 2.3.4
+        uninitializedToPassiveTimeout: 180
+        podStatusCheckInterval: 30
         chart:
-          release_name: nginxms
-          chart_name: nginx-ingress
-          version: 0.9.1
+          chartId:
+            name: nginx-ingress
+            version: 0.9.1
+          releaseName: nginxms
           namespace: onap
 
     org.onap.domain.sample.GenericK8s_ControlLoopDefinition: