Skip to content

Commit

Permalink
feat : Helm Install functionality exposed via Maven Mojos / Gradle Tasks
Browse files Browse the repository at this point in the history
Signed-off-by: Rohan Kumar <rohaan@redhat.com>
  • Loading branch information
rohanKanojia committed Jul 15, 2024
1 parent 3db16fd commit e08f6ae
Show file tree
Hide file tree
Showing 19 changed files with 707 additions and 6 deletions.
8 changes: 8 additions & 0 deletions gradle-plugin/kubernetes/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,18 @@
</dependency>

<!-- test -->
<dependency>
<groupId>org.eclipse.jkube</groupId>
<artifactId>jkube-kit-common</artifactId>
<scope>test</scope>
<type>test-jar</type>
</dependency>

<dependency>
<groupId>io.fabric8</groupId>
<artifactId>mockwebserver</artifactId>
</dependency>

<dependency>
<groupId>io.fabric8</groupId>
<artifactId>openshift-server-mock</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.eclipse.jkube.gradle.plugin.task.KubernetesConfigViewTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesDebugTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesHelmDependencyUpdateTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesHelmInstallTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesHelmLintTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesHelmPushTask;
import org.eclipse.jkube.gradle.plugin.task.KubernetesHelmTask;
Expand Down Expand Up @@ -53,6 +54,7 @@ public Map<String, Collection<Class<? extends Task>>> getTaskPrecedence() {
ret.put("k8sHelmPush", Collections.singletonList(KubernetesHelmTask.class));
ret.put("k8sHelmLint", Collections.singletonList(KubernetesHelmTask.class));
ret.put("k8sHelmDependencyUpdate", Collections.singletonList(KubernetesHelmTask.class));
ret.put("k8sHelmInstall", Collections.singletonList(KubernetesHelmTask.class));
return ret;
}

Expand All @@ -70,6 +72,7 @@ protected void jKubeApply(Project project) {
register(project, "k8sHelmPush", KubernetesHelmPushTask.class);
register(project, "k8sHelmLint", KubernetesHelmLintTask.class);
register(project, "k8sHelmDependencyUpdate", KubernetesHelmDependencyUpdateTask.class);
register(project, "k8sHelmInstall", KubernetesHelmInstallTask.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 KubernetesHelmInstallTask extends AbstractHelmTask {
@Inject
public KubernetesHelmInstallTask(Class<? extends KubernetesExtension> extensionClass) {
super(extensionClass);
setDescription("Installs a helm chart onto Kubernetes cluster");
}

@Override
public void run() {
try {
jKubeServiceHub.getHelmService().install(kubernetesExtension.helm);
} catch (Exception exp) {
kitLogger.error("Error performing helm install", exp);
throw new IllegalStateException(exp.getMessage(), exp);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,15 @@ void getTaskPrecedence_withValidProject_shouldReturnTaskPrecedence() {
final Map<String, Collection<Class<? extends Task>>> result = new KubernetesPlugin().getTaskPrecedence();
// Then
assertThat(result)
.hasSize(7)
.hasSize(8)
.containsEntry("k8sApply", Collections.singletonList(KubernetesResourceTask.class))
.containsEntry("k8sDebug",
Arrays.asList(KubernetesBuildTask.class, KubernetesResourceTask.class, KubernetesApplyTask.class))
.containsEntry("k8sPush", Collections.singletonList(KubernetesBuildTask.class))
.containsEntry("k8sHelm", Collections.singletonList(KubernetesResourceTask.class))
.containsEntry("k8sHelmDependencyUpdate", Collections.singletonList(KubernetesHelmTask.class))
.containsEntry("k8sHelmPush", Collections.singletonList(KubernetesHelmTask.class))
.containsEntry("k8sHelmLint", Collections.singletonList(KubernetesHelmTask.class));
.containsEntry("k8sHelmLint", Collections.singletonList(KubernetesHelmTask.class))
.containsEntry("k8sHelmInstall", Collections.singletonList(KubernetesHelmTask.class));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
* 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.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.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;

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 KubernetesHelmInstallTaskTest {
@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());
Files.write(helmChartOutputDir.resolve("kubernetes").resolve("Chart.yaml"),
("\ndependencies:\n" +
" - name: the-dependency\n" +
" version: 0.1.0\n" +
" repository: file://../../../../the-dependency\n").getBytes(StandardCharsets.UTF_8),
StandardOpenOption.APPEND);
System.setProperty("jkube.kubernetesTemplate", taskEnvironment.getRoot().getAbsolutePath());
extension.helm = HelmConfig.builder()
.chartExtension("tgz")
.installDependencyUpdate(true)
.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
void runTask_withHelmDependencyPresent_shouldSucceed() {
// Given
KubernetesHelmInstallTask kubernetesHelmInstallTask = new KubernetesHelmInstallTask(KubernetesExtension.class);
Helm.create().withName("the-dependency").withDir(taskEnvironment.getRoot().toPath()).call();

// When
kubernetesHelmInstallTask.runTask();
// Then
verify(taskEnvironment.logger).lifecycle("k8s: NAME : empty-project");
verify(taskEnvironment.logger).lifecycle("k8s: NAMESPACE : ");
verify(taskEnvironment.logger).lifecycle("k8s: STATUS : deployed");
verify(taskEnvironment.logger).lifecycle("k8s: REVISION : 1");
verify(taskEnvironment.logger).lifecycle("k8s: Saving 1 charts");
verify(taskEnvironment.logger).lifecycle("k8s: Deleting outdated charts");
}

@Test
void runTask_withHelmDependencyAbsent_shouldThrowException() {
// Given
KubernetesHelmInstallTask kubernetesHelmInstallTask = new KubernetesHelmInstallTask(KubernetesExtension.class);
// When + Then
assertThatIllegalStateException()
.isThrownBy(kubernetesHelmInstallTask::runTask)
.withMessageContaining("the-dependency not found");
}

@Test
void runTask_withInstallDependencyUpdateDisabled_shouldThrowException() {
// Given
extension.helm = extension.helm.toBuilder()
.installDependencyUpdate(false)
.build();
when(taskEnvironment.project.getExtensions().getByType(KubernetesExtension.class)).thenReturn(extension);
KubernetesHelmInstallTask kubernetesHelmInstallTask = new KubernetesHelmInstallTask(KubernetesExtension.class);
// When + Then
assertThatIllegalStateException()
.isThrownBy(kubernetesHelmInstallTask::runTask)
.withMessage("An error occurred while checking for chart dependencies. " +
"You may need to run `helm dependency build` to fetch missing dependencies: found in Chart.yaml, but missing in charts/ directory: the-dependency");
}
}
8 changes: 8 additions & 0 deletions gradle-plugin/openshift/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,18 @@
</dependency>

<!-- test -->
<dependency>
<groupId>org.eclipse.jkube</groupId>
<artifactId>jkube-kit-common</artifactId>
<scope>test</scope>
<type>test-jar</type>
</dependency>

<dependency>
<groupId>io.fabric8</groupId>
<artifactId>mockwebserver</artifactId>
</dependency>

<dependency>
<groupId>io.fabric8</groupId>
<artifactId>openshift-server-mock</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.eclipse.jkube.gradle.plugin.task.OpenShiftBuildTask;
import org.eclipse.jkube.gradle.plugin.task.OpenShiftDebugTask;
import org.eclipse.jkube.gradle.plugin.task.OpenShiftHelmDependencyUpdateTask;
import org.eclipse.jkube.gradle.plugin.task.OpenShiftHelmInstallTask;
import org.eclipse.jkube.gradle.plugin.task.OpenShiftHelmLintTask;
import org.eclipse.jkube.gradle.plugin.task.OpenShiftHelmPushTask;
import org.eclipse.jkube.gradle.plugin.task.OpenShiftHelmTask;
Expand Down Expand Up @@ -57,6 +58,7 @@ public Map<String, Collection<Class<? extends Task>>> getTaskPrecedence() {
ret.put("ocHelmPush", Arrays.asList(KubernetesHelmTask.class, OpenShiftHelmTask.class));
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));
return ret;
}

Expand All @@ -74,6 +76,7 @@ protected void jKubeApply(Project project) {
register(project, "ocHelmPush", OpenShiftHelmPushTask.class);
register(project, "ocHelmLint", OpenShiftHelmLintTask.class);
register(project, "ocHelmDependencyUpdate", OpenShiftHelmDependencyUpdateTask.class);
register(project, "ocHelmInstall", OpenShiftHelmInstallTask.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 OpenShiftHelmInstallTask extends KubernetesHelmInstallTask implements OpenShiftJKubeTask {
@Inject
public OpenShiftHelmInstallTask(Class<? extends OpenShiftExtension> extensionClass) {
super(extensionClass);
setDescription("Installs a helm chart onto Kubernetes cluster");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,15 @@ void configurePrecedence_withValidProject_shouldReturnTaskPrecedence() {
final Map<String, Collection<Class<? extends Task>>> result = new OpenShiftPlugin().getTaskPrecedence();
// Then
assertThat(result)
.hasSize(7)
.hasSize(8)
.containsEntry("ocApply", Arrays.asList(KubernetesResourceTask.class, OpenShiftResourceTask.class))
.containsEntry("ocDebug", Arrays.asList(KubernetesBuildTask.class, OpenShiftBuildTask.class,
KubernetesResourceTask.class, OpenShiftResourceTask.class, KubernetesApplyTask.class, OpenShiftApplyTask.class))
.containsEntry("ocPush", Arrays.asList(KubernetesBuildTask.class, OpenShiftBuildTask.class))
.containsEntry("ocHelm", Arrays.asList(KubernetesResourceTask.class, OpenShiftResourceTask.class))
.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("ocHelmLint", Arrays.asList(KubernetesHelmTask.class, OpenShiftHelmTask.class))
.containsEntry("ocHelmInstall", Arrays.asList(KubernetesHelmTask.class, OpenShiftHelmTask.class));
}
}
Loading

0 comments on commit e08f6ae

Please sign in to comment.