Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(helm): Helm Uninstall functionality exposed via Maven Mojos / Gradle Tasks #3309

Merged
merged 1 commit into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.eclipse.jkube.gradle.plugin.task.KubernetesHelmLintTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesHelmPushTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesHelmTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesHelmUninstallTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesLogTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesPushTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesRemoteDevTask;
Expand Down Expand Up @@ -55,6 +56,7 @@ public Map<String, Collection<Class<? extends Task>>> getTaskPrecedence() {
ret.put("k8sHelmLint", Collections.singletonList(KubernetesHelmTask.class));
ret.put("k8sHelmDependencyUpdate", Collections.singletonList(KubernetesHelmTask.class));
ret.put("k8sHelmInstall", Collections.singletonList(KubernetesHelmTask.class));
ret.put("k8sHelmUninstall", Arrays.asList(KubernetesHelmTask.class, KubernetesHelmInstallTask.class));
return ret;
}

Expand All @@ -73,6 +75,7 @@ protected void jKubeApply(Project project) {
register(project, "k8sHelmLint", KubernetesHelmLintTask.class);
register(project, "k8sHelmDependencyUpdate", KubernetesHelmDependencyUpdateTask.class);
register(project, "k8sHelmInstall", KubernetesHelmInstallTask.class);
register(project, "k8sHelmUninstall", KubernetesHelmUninstallTask.class);
register(project, "k8sRemoteDev", KubernetesRemoteDevTask.class);
register(project, "k8sWatch", KubernetesWatchTask.class);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2019 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at:
*
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.jkube.gradle.plugin.task;

import org.eclipse.jkube.gradle.plugin.KubernetesExtension;

import javax.inject.Inject;

public class KubernetesHelmUninstallTask extends AbstractHelmTask {
@Inject
public KubernetesHelmUninstallTask(Class<? extends KubernetesExtension> extensionClass) {
super(extensionClass);
setDescription("Uninstalls the Helm release from Kubernetes cluster");
}

@Override
public void run() {
try {
jKubeServiceHub.getHelmService().uninstall(kubernetesExtension.helm);
} catch (Exception exp) {
kitLogger.error("Error performing helm uninstall", exp);
throw new IllegalStateException(exp.getMessage(), exp);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.eclipse.jkube.gradle.plugin.task.JKubeTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesApplyTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesBuildTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesHelmInstallTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesHelmTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesResourceTask;

Expand Down Expand Up @@ -81,7 +82,7 @@ void getTaskPrecedence_withValidProject_shouldReturnTaskPrecedence() {
final Map<String, Collection<Class<? extends Task>>> result = new KubernetesPlugin().getTaskPrecedence();
// Then
assertThat(result)
.hasSize(8)
.hasSize(9)
.containsEntry("k8sApply", Collections.singletonList(KubernetesResourceTask.class))
.containsEntry("k8sDebug",
Arrays.asList(KubernetesBuildTask.class, KubernetesResourceTask.class, KubernetesApplyTask.class))
Expand All @@ -90,6 +91,7 @@ void getTaskPrecedence_withValidProject_shouldReturnTaskPrecedence() {
.containsEntry("k8sHelmDependencyUpdate", Collections.singletonList(KubernetesHelmTask.class))
.containsEntry("k8sHelmPush", Collections.singletonList(KubernetesHelmTask.class))
.containsEntry("k8sHelmLint", Collections.singletonList(KubernetesHelmTask.class))
.containsEntry("k8sHelmInstall", Collections.singletonList(KubernetesHelmTask.class));
.containsEntry("k8sHelmInstall", Collections.singletonList(KubernetesHelmTask.class))
.containsEntry("k8sHelmUninstall", Arrays.asList(KubernetesHelmTask.class, KubernetesHelmInstallTask.class));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright (c) 2019 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at:
*
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.jkube.gradle.plugin.task;

import com.marcnuri.helm.Helm;
import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.api.model.SecretListBuilder;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient;
import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer;
import org.apache.commons.io.FileUtils;
import org.eclipse.jkube.gradle.plugin.KubernetesExtension;
import org.eclipse.jkube.gradle.plugin.TestKubernetesExtension;
import org.eclipse.jkube.kit.common.access.ClusterConfiguration;
import org.eclipse.jkube.kit.resource.helm.HelmConfig;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.eclipse.jkube.kit.common.util.KubernetesMockServerUtil.prepareMockWebServerExpectationsForAggregatedDiscoveryEndpoints;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@EnableKubernetesMockClient(crud = true)
class KubernetesHelmUninstallTaskTest {
@RegisterExtension
private final TaskEnvironmentExtension taskEnvironment = new TaskEnvironmentExtension();
private KubernetesClient kubernetesClient;
private KubernetesMockServer server;
private TestKubernetesExtension extension;

@BeforeEach
void setUp() throws IOException {
extension = new TestKubernetesExtension();
// Remove after https://github.com/fabric8io/kubernetes-client/issues/6062 is fixed
prepareMockWebServerExpectationsForAggregatedDiscoveryEndpoints(server);
Helm.create().withDir(taskEnvironment.getRoot().toPath()).withName("empty-project").call();
Path helmChartOutputDir = taskEnvironment.getRoot().toPath().resolve("build").resolve("jkube").resolve("helm");
Files.createDirectories(helmChartOutputDir.resolve("kubernetes"));
FileUtils.copyDirectory(taskEnvironment.getRoot().toPath().resolve("empty-project").toFile(), helmChartOutputDir.resolve("kubernetes").toFile());
System.setProperty("jkube.kubernetesTemplate", taskEnvironment.getRoot().getAbsolutePath());
extension.helm = HelmConfig.builder()
.chartExtension("tgz")
.disableOpenAPIValidation(true)
.outputDir(helmChartOutputDir.toString()).build();
extension.access = ClusterConfiguration.from(kubernetesClient.getConfiguration()).build();
extension.isUseColor = false;
when(taskEnvironment.project.getName()).thenReturn("empty-project");
when(taskEnvironment.project.getVersion()).thenReturn("0.1.0");
when(taskEnvironment.project.getExtensions().getByType(KubernetesExtension.class)).thenReturn(extension);
}

@AfterEach
void tearDown() {
System.clearProperty("jkube.kubernetesTemplate");
}

@Test
@DisplayName("when Helm Release Installed on Kubernetes Cluster, then uninstall Helm Release")
void runTask_withHelmReleasePresentInKubernetesCluster_shouldSucceed() {
// Given
KubernetesHelmUninstallTask kubernetesHelmUninstallTask = new KubernetesHelmUninstallTask(KubernetesExtension.class);
kubernetesHelmUninstallTask.init();
kubernetesHelmUninstallTask.jKubeServiceHub.getHelmService().install(extension.helm);
// Should be removed once https://github.com/fabric8io/kubernetes-client/issues/6220 gets fixed
Secret secret = kubernetesClient.secrets().withName("sh.helm.release.v1.empty-project.v1").get();
server.expect().get().withPath("/api/v1/namespaces/test/secrets?labelSelector=name%3Dempty-project%2Cowner%3Dhelm")
.andReturn(200, new SecretListBuilder()
.addToItems(secret)
.build())
.once();

// When
kubernetesHelmUninstallTask.runTask();
// Then
verify(taskEnvironment.logger).lifecycle("k8s: release \"empty-project\" uninstalled");
}

@Test
@DisplayName("Helm Release not installed on Kubernetes cluster, then throw exception")
void execute_whenReleaseNotPresent_thenThrowException() {
// Given
KubernetesHelmUninstallTask kubernetesHelmUninstallTask = new KubernetesHelmUninstallTask(KubernetesExtension.class);

// When + Then
assertThatIllegalStateException()
.isThrownBy(kubernetesHelmUninstallTask::runTask)
.withMessageContaining(" not found");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.eclipse.jkube.gradle.plugin.task.KubernetesApplyTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesBuildTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesConfigViewTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesHelmInstallTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesHelmTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesLogTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesResourceTask;
Expand All @@ -32,6 +33,7 @@
import org.eclipse.jkube.gradle.plugin.task.OpenShiftHelmLintTask;
import org.eclipse.jkube.gradle.plugin.task.OpenShiftHelmPushTask;
import org.eclipse.jkube.gradle.plugin.task.OpenShiftHelmTask;
import org.eclipse.jkube.gradle.plugin.task.OpenShiftHelmUninstallTask;
import org.eclipse.jkube.gradle.plugin.task.OpenShiftPushTask;
import org.eclipse.jkube.gradle.plugin.task.OpenShiftRemoteDevTask;
import org.eclipse.jkube.gradle.plugin.task.OpenShiftResourceTask;
Expand Down Expand Up @@ -59,6 +61,7 @@ public Map<String, Collection<Class<? extends Task>>> getTaskPrecedence() {
ret.put("ocHelmLint", Arrays.asList(KubernetesHelmTask.class, OpenShiftHelmTask.class));
ret.put("ocHelmDependencyUpdate", Arrays.asList(KubernetesHelmTask.class, OpenShiftHelmTask.class));
ret.put("ocHelmInstall", Arrays.asList(KubernetesHelmTask.class, OpenShiftHelmTask.class));
ret.put("ocHelmUninstall", Arrays.asList(KubernetesHelmTask.class, OpenShiftHelmTask.class, KubernetesHelmInstallTask.class, OpenShiftHelmInstallTask.class));
return ret;
}

Expand All @@ -77,6 +80,7 @@ protected void jKubeApply(Project project) {
register(project, "ocHelmLint", OpenShiftHelmLintTask.class);
register(project, "ocHelmDependencyUpdate", OpenShiftHelmDependencyUpdateTask.class);
register(project, "ocHelmInstall", OpenShiftHelmInstallTask.class);
register(project, "ocHelmUninstall", OpenShiftHelmUninstallTask.class);
register(project, "ocRemoteDev", OpenShiftRemoteDevTask.class);
register(project, "ocWatch", OpenShiftWatchTask.class);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2019 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at:
*
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.jkube.gradle.plugin.task;

import org.eclipse.jkube.gradle.plugin.OpenShiftExtension;

import javax.inject.Inject;

public class OpenShiftHelmUninstallTask extends KubernetesHelmUninstallTask implements OpenShiftJKubeTask {
@Inject
public OpenShiftHelmUninstallTask(Class<? extends OpenShiftExtension> extensionClass) {
super(extensionClass);
setDescription("Uninstalls the Helm release from OpenShift cluster");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@

import org.eclipse.jkube.gradle.plugin.task.KubernetesApplyTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesBuildTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesHelmInstallTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesHelmTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesResourceTask;
import org.eclipse.jkube.gradle.plugin.task.OpenShiftApplyTask;
import org.eclipse.jkube.gradle.plugin.task.OpenShiftBuildTask;
import org.eclipse.jkube.gradle.plugin.task.OpenShiftHelmInstallTask;
import org.eclipse.jkube.gradle.plugin.task.OpenShiftHelmTask;
import org.eclipse.jkube.gradle.plugin.task.OpenShiftResourceTask;

Expand All @@ -39,7 +41,7 @@ void configurePrecedence_withValidProject_shouldReturnTaskPrecedence() {
final Map<String, Collection<Class<? extends Task>>> result = new OpenShiftPlugin().getTaskPrecedence();
// Then
assertThat(result)
.hasSize(8)
.hasSize(9)
.containsEntry("ocApply", Arrays.asList(KubernetesResourceTask.class, OpenShiftResourceTask.class))
.containsEntry("ocDebug", Arrays.asList(KubernetesBuildTask.class, OpenShiftBuildTask.class,
KubernetesResourceTask.class, OpenShiftResourceTask.class, KubernetesApplyTask.class, OpenShiftApplyTask.class))
Expand All @@ -48,6 +50,7 @@ void configurePrecedence_withValidProject_shouldReturnTaskPrecedence() {
.containsEntry("ocHelmDependencyUpdate", Arrays.asList(KubernetesHelmTask.class, OpenShiftHelmTask.class))
.containsEntry("ocHelmPush", Arrays.asList(KubernetesHelmTask.class, OpenShiftHelmTask.class))
.containsEntry("ocHelmLint", Arrays.asList(KubernetesHelmTask.class, OpenShiftHelmTask.class))
.containsEntry("ocHelmInstall", Arrays.asList(KubernetesHelmTask.class, OpenShiftHelmTask.class));
.containsEntry("ocHelmInstall", Arrays.asList(KubernetesHelmTask.class, OpenShiftHelmTask.class))
.containsEntry("ocHelmUninstall", Arrays.asList(KubernetesHelmTask.class, OpenShiftHelmTask.class, KubernetesHelmInstallTask.class, OpenShiftHelmInstallTask.class));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright (c) 2019 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at:
*
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.jkube.gradle.plugin.task;

import com.marcnuri.helm.Helm;
import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.api.model.SecretListBuilder;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient;
import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer;
import org.apache.commons.io.FileUtils;
import org.eclipse.jkube.gradle.plugin.OpenShiftExtension;
import org.eclipse.jkube.gradle.plugin.TestOpenShiftExtension;
import org.eclipse.jkube.kit.common.access.ClusterConfiguration;
import org.eclipse.jkube.kit.resource.helm.HelmConfig;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.eclipse.jkube.kit.common.util.KubernetesMockServerUtil.prepareMockWebServerExpectationsForAggregatedDiscoveryEndpoints;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@EnableKubernetesMockClient(crud = true)
class OpenShiftHelmUninstallTaskTest {
@RegisterExtension
private final TaskEnvironmentExtension taskEnvironment = new TaskEnvironmentExtension();
private KubernetesClient kubernetesClient;
private KubernetesMockServer server;
private TestOpenShiftExtension extension;

@BeforeEach
void setUp() throws IOException {
extension = new TestOpenShiftExtension();
// Remove after https://github.com/fabric8io/kubernetes-client/issues/6062 is fixed
prepareMockWebServerExpectationsForAggregatedDiscoveryEndpoints(server);
Helm.create().withDir(taskEnvironment.getRoot().toPath()).withName("empty-project").call();
Path helmChartOutputDir = taskEnvironment.getRoot().toPath().resolve("build").resolve("jkube").resolve("helm");
Files.createDirectories(helmChartOutputDir.resolve("openshift"));
FileUtils.copyDirectory(taskEnvironment.getRoot().toPath().resolve("empty-project").toFile(), helmChartOutputDir.resolve("openshift").toFile());
System.setProperty("jkube.kubernetesTemplate", taskEnvironment.getRoot().getAbsolutePath());
extension.helm = HelmConfig.builder()
.chartExtension("tgz")
.disableOpenAPIValidation(true)
.outputDir(helmChartOutputDir.toString()).build();
extension.access = ClusterConfiguration.from(kubernetesClient.getConfiguration()).build();
extension.isUseColor = false;
when(taskEnvironment.project.getName()).thenReturn("empty-project");
when(taskEnvironment.project.getVersion()).thenReturn("0.1.0");
when(taskEnvironment.project.getExtensions().getByType(OpenShiftExtension.class)).thenReturn(extension);
}

@AfterEach
void tearDown() {
System.clearProperty("jkube.kubernetesTemplate");
}

@Test
@DisplayName("when Helm Release Installed on Kubernetes Cluster, then uninstall Helm Release")
void runTask_withHelmReleasePresentInKubernetesCluster_shouldSucceed() {
// Given
OpenShiftHelmUninstallTask openShiftHelmUninstallTask = new OpenShiftHelmUninstallTask(OpenShiftExtension.class);
openShiftHelmUninstallTask.init();
openShiftHelmUninstallTask.jKubeServiceHub.getHelmService().install(extension.helm);
// Should be removed once https://github.com/fabric8io/kubernetes-client/issues/6220 gets fixed
Secret secret = kubernetesClient.secrets().withName("sh.helm.release.v1.empty-project.v1").get();
server.expect().get().withPath("/api/v1/namespaces/test/secrets?labelSelector=name%3Dempty-project%2Cowner%3Dhelm")
.andReturn(200, new SecretListBuilder()
.addToItems(secret)
.build())
.once();

// When
openShiftHelmUninstallTask.runTask();
// Then
verify(taskEnvironment.logger).lifecycle("oc: release \"empty-project\" uninstalled");
}

@Test
@DisplayName("Helm Release not installed on Kubernetes cluster, then throw exception")
void execute_whenReleaseNotPresent_thenThrowException() {
// Given
OpenShiftHelmUninstallTask openShiftHelmUninstallTask = new OpenShiftHelmUninstallTask(OpenShiftExtension.class);

// When + Then
assertThatIllegalStateException()
.isThrownBy(openShiftHelmUninstallTask::runTask)
.withMessageContaining(" not found");
}
}
Loading