From 0b7ae17f70be7fc393975b5f992f18b0a85dbad7 Mon Sep 17 00:00:00 2001 From: Jeromy Cannon Date: Mon, 9 Oct 2023 07:01:27 -0500 Subject: [PATCH] feat: add gradle Helm release exists task (#389) Signed-off-by: Jeromy Cannon --- fullstack-examples/build.gradle.kts | 8 ++ fullstack-gradle-plugin/build.gradle.kts | 1 + .../gradle/plugin/HelmReleaseExistsTask.java | 82 +++++++++++++++++++ .../plugin/HelmInstallChartTaskTest.java | 21 +++-- .../plugin/HelmReleaseExistsTaskTest.java | 63 ++++++++++++++ 5 files changed, 168 insertions(+), 7 deletions(-) create mode 100644 fullstack-gradle-plugin/src/main/java/com/hedera/fullstack/gradle/plugin/HelmReleaseExistsTask.java create mode 100644 fullstack-gradle-plugin/src/test/java/com/hedera/fullstack/gradle/plugin/HelmReleaseExistsTaskTest.java diff --git a/fullstack-examples/build.gradle.kts b/fullstack-examples/build.gradle.kts index 54b447777..fa565a645 100644 --- a/fullstack-examples/build.gradle.kts +++ b/fullstack-examples/build.gradle.kts @@ -15,6 +15,7 @@ */ import com.hedera.fullstack.gradle.plugin.HelmInstallChartTask +import com.hedera.fullstack.gradle.plugin.HelmReleaseExistsTask import com.hedera.fullstack.gradle.plugin.HelmUninstallChartTask plugins { @@ -52,7 +53,14 @@ tasks.register("helmUninstallNginxChart") { release.set("nginx-release") } +tasks.register("helmNginxExists") { + allNamespaces.set(true) + namespace.set("nginx-ns") + release.set("nginx-release") +} + tasks.check { dependsOn("helmInstallNginxChart") + dependsOn("helmNginxExists") dependsOn("helmUninstallNginxChart") } diff --git a/fullstack-gradle-plugin/build.gradle.kts b/fullstack-gradle-plugin/build.gradle.kts index 6a2dc21fd..b530a24aa 100644 --- a/fullstack-gradle-plugin/build.gradle.kts +++ b/fullstack-gradle-plugin/build.gradle.kts @@ -24,6 +24,7 @@ plugins { dependencies { api(platform(project(":fullstack-bom"))) implementation(project(":fullstack-helm-client")) + testImplementation("org.assertj:assertj-core:3.24.2") } gradlePlugin { diff --git a/fullstack-gradle-plugin/src/main/java/com/hedera/fullstack/gradle/plugin/HelmReleaseExistsTask.java b/fullstack-gradle-plugin/src/main/java/com/hedera/fullstack/gradle/plugin/HelmReleaseExistsTask.java new file mode 100644 index 000000000..5cafd599e --- /dev/null +++ b/fullstack-gradle-plugin/src/main/java/com/hedera/fullstack/gradle/plugin/HelmReleaseExistsTask.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * 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. + */ + +package com.hedera.fullstack.gradle.plugin; + +import com.hedera.fullstack.helm.client.HelmClient; +import com.hedera.fullstack.helm.client.HelmClientBuilder; +import com.hedera.fullstack.helm.client.model.release.ReleaseItem; +import java.util.List; +import java.util.Objects; +import org.gradle.api.DefaultTask; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.Optional; +import org.gradle.api.tasks.TaskAction; +import org.gradle.api.tasks.options.Option; + +public abstract class HelmReleaseExistsTask extends DefaultTask { + @Input + @Option(option = "release", description = "The release to verify exists") + public abstract Property getRelease(); + + @Input + @Optional + @Option(option = "namespace", description = "The namespace to use when listing the releases") + public abstract Property getNamespace(); + + @Input + @Optional + @Option(option = "allNamespaces", description = "True if we should list releases in all namespaces") + public abstract Property getAllNamespaces(); + + @TaskAction + void releaseExists() { + ReleaseItem releaseItem; + try { + final String release = getRelease().getOrNull(); + Objects.requireNonNull(release, "release must not be null"); + + HelmClientBuilder helmClientBuilder = HelmClient.builder(); + if (getNamespace().isPresent()) { + helmClientBuilder.defaultNamespace(getNamespace().get()); + } + + HelmClient helmClient = helmClientBuilder.build(); + List releaseItems = + helmClient.listReleases(getAllNamespaces().getOrElse(false)); + releaseItem = releaseItems.stream() + .filter(item -> item.name().equals(release)) + .findFirst() + .orElse(null); + } catch (Exception e) { + this.getProject() + .getLogger() + .error( + "HelmReleaseExistsTask.releaseExists() An ERROR occurred while listing the releases: " + + e.getMessage(), + e); + throw e; + } + + if (releaseItem == null) { + final String errorMessage = "HelmReleaseExistsTask.releaseExists(): Release " + + getRelease().get() + " does not exist"; + this.getProject().getLogger().error(errorMessage); + throw new RuntimeException(errorMessage); + } + } +} diff --git a/fullstack-gradle-plugin/src/test/java/com/hedera/fullstack/gradle/plugin/HelmInstallChartTaskTest.java b/fullstack-gradle-plugin/src/test/java/com/hedera/fullstack/gradle/plugin/HelmInstallChartTaskTest.java index 101eb4a15..358874ab0 100644 --- a/fullstack-gradle-plugin/src/test/java/com/hedera/fullstack/gradle/plugin/HelmInstallChartTaskTest.java +++ b/fullstack-gradle-plugin/src/test/java/com/hedera/fullstack/gradle/plugin/HelmInstallChartTaskTest.java @@ -17,7 +17,8 @@ package com.hedera.fullstack.gradle.plugin; import static com.hedera.fullstack.base.api.util.ExceptionUtils.suppressExceptions; -import static org.junit.jupiter.api.Assertions.*; +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertThrows; import com.hedera.fullstack.helm.client.HelmClient; import com.hedera.fullstack.helm.client.HelmExecutionException; @@ -68,7 +69,7 @@ void testHelmInstallChartTaskForHederaNetworkChart() throws IOException { task.getSet().add("defaults.root.image.repository=hashgraph/full-stack-testing/ubi8-init-dind"); task.getValues().add(valuesFilePath); }); - assertEquals("fst", helmInstallChartTask.getRelease().get()); + assertThat(helmInstallChartTask.getRelease().get()).isEqualTo("fst"); helmInstallChartTask.installChart(); } finally { // TODO: comment this out as workaround until we no longer need manual use of make command @@ -79,8 +80,8 @@ void testHelmInstallChartTaskForHederaNetworkChart() throws IOException { @Test @DisplayName("Simple Helm Install Chart Task") void testHelmInstallChartTaskSimple() { - HelmClient helmClient = - HelmClient.builder().defaultNamespace("simple-test").build(); + final String namespace = "simple-test"; + HelmClient helmClient = HelmClient.builder().defaultNamespace(namespace).build(); suppressExceptions(() -> helmClient.uninstallChart(RELEASE_NAME)); suppressExceptions(() -> helmClient.removeRepository(REPOSITORY)); final List repositories = helmClient.listRepositories(); @@ -92,15 +93,21 @@ void testHelmInstallChartTaskSimple() { .create("helmInstallChart", HelmInstallChartTask.class, task -> { task.getChart().set(CHART.name()); task.getCreateNamespace().set(true); - task.getNamespace().set("simple-test"); + task.getNamespace().set(namespace); task.getRelease().set(RELEASE_NAME); task.getRepo().set(CHART.repoName()); }); - assertEquals(RELEASE_NAME, helmInstallChartTask.getRelease().get()); + assertThat(helmInstallChartTask.getRelease().get()).isEqualTo(RELEASE_NAME); helmInstallChartTask.installChart(); + HelmReleaseExistsTask helmReleaseExistsTask = project.getTasks() + .create("helmReleaseExists", HelmReleaseExistsTask.class, task -> { + task.getNamespace().set(namespace); + task.getRelease().set(RELEASE_NAME); + }); + helmReleaseExistsTask.releaseExists(); HelmUninstallChartTask helmUninstallChartTask = project.getTasks() .create("helmUninstallChart", HelmUninstallChartTask.class, task -> { - task.getNamespace().set("simple-test"); + task.getNamespace().set(namespace); task.getRelease().set(RELEASE_NAME); }); helmUninstallChartTask.uninstallChart(); diff --git a/fullstack-gradle-plugin/src/test/java/com/hedera/fullstack/gradle/plugin/HelmReleaseExistsTaskTest.java b/fullstack-gradle-plugin/src/test/java/com/hedera/fullstack/gradle/plugin/HelmReleaseExistsTaskTest.java new file mode 100644 index 000000000..31e8db2b8 --- /dev/null +++ b/fullstack-gradle-plugin/src/test/java/com/hedera/fullstack/gradle/plugin/HelmReleaseExistsTaskTest.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * 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. + */ + +package com.hedera.fullstack.gradle.plugin; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.gradle.api.Project; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class HelmReleaseExistsTaskTest { + private static Project project; + + @BeforeAll + static void beforeAll() { + project = ProjectBuilder.builder().build(); + } + + @Test + @DisplayName("test an error is thrown when the release is not found") + void testErrorThrownWhenReleaseNotFound() { + RuntimeException e = assertThrows(RuntimeException.class, () -> { + HelmReleaseExistsTask helmReleaseExistsTask = project.getTasks() + .create("helmReleaseExistsV1", HelmReleaseExistsTask.class, task -> { + task.getAllNamespaces().set(true); + task.getRelease().set("not-a-release"); + }); + helmReleaseExistsTask.releaseExists(); + }); + assertThat(e.getMessage()) + .isEqualTo("HelmReleaseExistsTask.releaseExists(): Release not-a-release does not exist"); + } + + @Test + @DisplayName("test an error is thrown when the release is not set") + void testErrorThrownWhenReleaseNotSet() { + NullPointerException npe = assertThrows(NullPointerException.class, () -> { + HelmReleaseExistsTask helmReleaseExistsTask = project.getTasks() + .create("helmReleaseExistsV2", HelmReleaseExistsTask.class, task -> { + task.getAllNamespaces().set(true); + }); + helmReleaseExistsTask.releaseExists(); + }); + assertThat(npe.getMessage()).isEqualTo("release must not be null"); + } +}