From dfd1e716f8e840f7caaf42e14572d18c8acc9d38 Mon Sep 17 00:00:00 2001 From: rameshiyer27 Date: Wed, 7 Jul 2021 20:37:54 +0100 Subject: Support override parameters for k8s-participant 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 Change-Id: Ibcbe79d07caa9bff12de341c3d88c36a144796bc --- .../kubernetes/configurations/SecurityConfig.java | 45 ++++++++ .../handler/ControlLoopElementHandler.java | 60 ++++++++--- .../participant/kubernetes/helm/HelmClient.java | 74 ++++++------- .../kubernetes/helm/PodStatusValidator.java | 119 +++++++++++++++++++++ .../participant/kubernetes/models/ChartInfo.java | 11 +- .../kubernetes/service/ChartService.java | 7 +- .../participant/kubernetes/service/ChartStore.java | 31 +++--- .../src/main/resources/config/application.yaml | 8 +- .../handler/ControlLoopElementHandlerTest.java | 6 +- .../helm/HelmClientTest.java | 17 ++- .../helm/PodStatusValidatorTest.java | 108 +++++++++++++++++++ .../rest/ChartControllerTest.java | 21 ++-- .../service/ChartServiceTest.java | 6 +- .../service/ChartStoreTest.java | 34 +++--- .../src/test/resources/ChartList.json | 18 ++-- .../resources/servicetemplates/KubernetesHelm.yaml | 31 ++++-- 16 files changed, 469 insertions(+), 127 deletions(-) create mode 100644 participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/configurations/SecurityConfig.java create mode 100644 participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/helm/PodStatusValidator.java create mode 100644 participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/helm/PodStatusValidatorTest.java (limited to 'participant/participant-impl/participant-impl-kubernetes') 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 index 000000000..6b4fb0a75 --- /dev/null +++ b/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/configurations/SecurityConfig.java @@ -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(); + } + } +} diff --git a/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/handler/ControlLoopElementHandler.java b/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/handler/ControlLoopElementHandler.java index 4f654832d..20a23ca32 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/handler/ControlLoopElementHandler.java +++ b/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/handler/ControlLoopElementHandler.java @@ -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> 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 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 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 chartData = - (Map) nodeTemplate.getValue().getProperties().get("chart"); + (Map) 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. * diff --git a/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/helm/HelmClient.java b/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/helm/HelmClient.java index 90d7218da..b38fbeb81 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/helm/HelmClient.java +++ b/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/helm/HelmClient.java @@ -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 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 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 index 000000000..d55fd6658 --- /dev/null +++ b/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/helm/PodStatusValidator.java @@ -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 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 mapPodStatus(String output) throws IOException, ServiceException { + Map 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"); + } + } +} diff --git a/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/models/ChartInfo.java b/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/models/ChartInfo.java index 6bfb7aed5..b53f2075a 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/models/ChartInfo.java +++ b/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/models/ChartInfo.java @@ -18,28 +18,27 @@ 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 overrideParams; + } diff --git a/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/service/ChartService.java b/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/service/ChartService.java index adb6cf0d1..a1522188d 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/service/ChartService.java +++ b/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/service/ChartService.java @@ -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); } - } diff --git a/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/service/ChartStore.java b/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/service/ChartStore.java index 03b35161d..975671705 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/service/ChartStore.java +++ b/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/service/ChartStore.java @@ -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() { @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; } - } diff --git a/participant/participant-impl/participant-impl-kubernetes/src/main/resources/config/application.yaml b/participant/participant-impl/participant-impl-kubernetes/src/main/resources/config/application.yaml index 63ec8a295..5a2903c56 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/main/resources/config/application.yaml +++ b/participant/participant-impl/participant-impl-kubernetes/src/main/resources/config/application.yaml @@ -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 diff --git a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/handler/ControlLoopElementHandlerTest.java b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/handler/ControlLoopElementHandlerTest.java index f3d27a63c..f8381ee7f 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/handler/ControlLoopElementHandlerTest.java +++ b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/handler/ControlLoopElementHandlerTest.java @@ -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); diff --git a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/helm/HelmClientTest.java b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/helm/HelmClientTest.java index 5f8b7dc78..370bfa6ce 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/helm/HelmClientTest.java +++ b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/helm/HelmClientTest.java @@ -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 index 000000000..f72a53403 --- /dev/null +++ b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/helm/PodStatusValidatorTest.java @@ -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 charts; + private static int timeout = 60; + private static int statusCheckInterval = 30; + + + @InjectMocks + private static PodStatusValidator podStatusValidator; + + private static MockedStatic 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(); + } + +} diff --git a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/rest/ChartControllerTest.java b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/rest/ChartControllerTest.java index 1a1bdae5b..a28fd9ebe 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/rest/ChartControllerTest.java +++ b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/rest/ChartControllerTest.java @@ -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()); diff --git a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/service/ChartServiceTest.java b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/service/ChartServiceTest.java index 957a69a08..8e7943410 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/service/ChartServiceTest.java +++ b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/service/ChartServiceTest.java @@ -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()); } diff --git a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/service/ChartStoreTest.java b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/service/ChartStoreTest.java index 2d05a7a0e..eb4e7a173 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/service/ChartStoreTest.java +++ b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org.onap.policy.clamp.controlloop.participant.kubernetes/service/ChartStoreTest.java @@ -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 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()); } } diff --git a/participant/participant-impl/participant-impl-kubernetes/src/test/resources/ChartList.json b/participant/participant-impl/participant-impl-kubernetes/src/test/resources/ChartList.json index 4e355c38e..2f4ec2827 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/test/resources/ChartList.json +++ b/participant/participant-impl/participant-impl-kubernetes/src/test/resources/ChartList.json @@ -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" } ] } diff --git a/participant/participant-impl/participant-impl-kubernetes/src/test/resources/servicetemplates/KubernetesHelm.yaml b/participant/participant-impl/participant-impl-kubernetes/src/test/resources/servicetemplates/KubernetesHelm.yaml index 3212b5ad2..69886cdb1 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/test/resources/servicetemplates/KubernetesHelm.yaml +++ b/participant/participant-impl/participant-impl-kubernetes/src/test/resources/servicetemplates/KubernetesHelm.yaml @@ -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: -- cgit 1.2.3-korg