diff --git a/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/HelmClient.java b/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/HelmClient.java index 3afac8067..8c38a2574 100644 --- a/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/HelmClient.java +++ b/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/HelmClient.java @@ -22,6 +22,7 @@ import com.hedera.fullstack.helm.client.model.Repository; import com.hedera.fullstack.helm.client.model.chart.Release; import com.hedera.fullstack.helm.client.model.install.InstallChartOptions; +import com.hedera.fullstack.helm.client.model.test.TestChartOptions; import java.util.List; /** @@ -92,6 +93,14 @@ default Release installChart(String releaseName, Chart chart) { */ void uninstallChart(String releaseName); + /** + * Executes the Helm CLI {@code test} sub-command and tests the specified Helm chart. + * + * @param releaseName the name of the release to test. + * @param options the options to pass to the Helm CLI command. + */ + void testChart(String releaseName, TestChartOptions options); + /** * Creates a new {@link HelmClientBuilder} instance with the default configuration. * diff --git a/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/impl/DefaultHelmClient.java b/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/impl/DefaultHelmClient.java index 1d134c09f..bad753a0c 100644 --- a/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/impl/DefaultHelmClient.java +++ b/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/impl/DefaultHelmClient.java @@ -25,9 +25,11 @@ import com.hedera.fullstack.helm.client.model.Version; import com.hedera.fullstack.helm.client.model.chart.Release; import com.hedera.fullstack.helm.client.model.install.InstallChartOptions; +import com.hedera.fullstack.helm.client.model.test.TestChartOptions; import com.hedera.fullstack.helm.client.proxy.request.HelmRequest; import com.hedera.fullstack.helm.client.proxy.request.authentication.KubeAuthentication; import com.hedera.fullstack.helm.client.proxy.request.chart.ChartInstallRequest; +import com.hedera.fullstack.helm.client.proxy.request.chart.ChartTestRequest; import com.hedera.fullstack.helm.client.proxy.request.chart.ChartUninstallRequest; import com.hedera.fullstack.helm.client.proxy.request.common.VersionRequest; import com.hedera.fullstack.helm.client.proxy.request.repository.RepositoryAddRequest; @@ -120,6 +122,14 @@ public void uninstallChart(final String releaseName) { }); } + @Override + public void testChart(final String releaseName, final TestChartOptions options) { + executeInternal(new ChartTestRequest(releaseName, options), Void.class, (b, c) -> { + b.call(); + return null; + }); + } + /** * Applies the default namespace and authentication configuration to the given builder. * diff --git a/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/model/test/TestChartOptions.java b/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/model/test/TestChartOptions.java new file mode 100644 index 000000000..184440e70 --- /dev/null +++ b/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/model/test/TestChartOptions.java @@ -0,0 +1,58 @@ +/* + * 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.helm.client.model.test; + +import com.hedera.fullstack.helm.client.execution.HelmExecutionBuilder; +import com.hedera.fullstack.helm.client.model.Options; + +/** + * Represents the options to use when testing a chart. + * + * @param filter specify tests by attribute (currently "name") using attribute=value syntax or '!attribute=value' to + * exclude a test (can specify multiple or separate values with commas: name=test1,name=test2) + * @param timeout Time to wait for any individual Kubernetes operation (like Jobs for hooks) (default 5m0s). + */ +public record TestChartOptions(String filter, String timeout) implements Options { + /** + * Returns an instance of the TestChartOptionsBuilder. + * + * @return the TestChartOptionsBuilder. + */ + public static TestChartOptionsBuilder builder() { + return TestChartOptionsBuilder.builder(); + } + + /** + * Returns an instance of the default TestChartOptions. + * + * @return the default TestChartOptions. + */ + public static TestChartOptions defaults() { + return builder().build(); + } + + @Override + public void apply(final HelmExecutionBuilder builder) { + if (filter() != null) { + builder.argument("filter", filter()); + } + + if (timeout() != null) { + builder.argument("timeout", timeout()); + } + } +} diff --git a/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/model/test/TestChartOptionsBuilder.java b/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/model/test/TestChartOptionsBuilder.java new file mode 100644 index 000000000..899dba9f1 --- /dev/null +++ b/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/model/test/TestChartOptionsBuilder.java @@ -0,0 +1,68 @@ +/* + * 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.helm.client.model.test; + +/** + * The builder for the {@link TestChartOptions}. + */ +public class TestChartOptionsBuilder { + private String filter; + private String timeout; + + /** + * Returns an instance of the TestChartOptionsBuilder. + * + * @return the TestChartOptionsBuilder. + */ + public static TestChartOptionsBuilder builder() { + return new TestChartOptionsBuilder(); + } + + /** + * Specify tests by attribute (currently "name") using attribute=value syntax or '!attribute=value' to exclude a + * test (can specify multiple or separate values with commas: name=test1,name=test2) + * + * @param filter Specify tests by attribute (currently "name") using attribute=value syntax or '!attribute=value' to + * exclude a test (can specify multiple or separate values with commas: name=test1,name=test2) + * @return the current TestChartOptionsBuilder. + */ + public TestChartOptionsBuilder filter(String filter) { + this.filter = filter; + return this; + } + + /** + * Time to wait for any individual Kubernetes operation (like Jobs for hooks) (default 5m0s). + * + * @param timeout Time to wait for any individual Kubernetes operation (like Jobs for hooks) (default 5m0s). + *
+ * return the current TestChartOptionsBuilder. + */ + public TestChartOptionsBuilder timeout(String timeout) { + this.timeout = timeout; + return this; + } + + /** + * builds the {@link TestChartOptions} instance. + * + * @return the {@link TestChartOptions} instance. + */ + public TestChartOptions build() { + return new TestChartOptions(filter, timeout); + } +} diff --git a/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/proxy/request/chart/ChartTestRequest.java b/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/proxy/request/chart/ChartTestRequest.java new file mode 100644 index 000000000..c691d0642 --- /dev/null +++ b/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/proxy/request/chart/ChartTestRequest.java @@ -0,0 +1,58 @@ +/* + * 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.helm.client.proxy.request.chart; + +import com.hedera.fullstack.helm.client.execution.HelmExecutionBuilder; +import com.hedera.fullstack.helm.client.model.test.TestChartOptions; +import com.hedera.fullstack.helm.client.proxy.request.HelmRequest; +import java.util.Objects; + +/** + * A request to uninstall a chart. + * + * @param releaseName the name of the release to uninstall. + */ +public record ChartTestRequest(String releaseName, TestChartOptions options) implements HelmRequest { + + public ChartTestRequest { + Objects.requireNonNull(releaseName, "releaseName must not be null"); + Objects.requireNonNull(options, "options must not be null"); + + if (releaseName.isBlank()) { + throw new IllegalArgumentException("releaseName must not be null or blank"); + } + } + + /** + * Creates a new install request with the given chart and default options. + * @param releaseName The name of the release. + */ + public ChartTestRequest(String releaseName) { + this(releaseName, TestChartOptions.defaults()); + } + + @Override + public void apply(HelmExecutionBuilder builder) { + builder.subcommands("test"); + + if (options != null) { + options.apply(builder); + } + + builder.positional(releaseName); + } +} diff --git a/fullstack-helm-client/src/main/java/module-info.java b/fullstack-helm-client/src/main/java/module-info.java index 51d202231..6e97afa97 100644 --- a/fullstack-helm-client/src/main/java/module-info.java +++ b/fullstack-helm-client/src/main/java/module-info.java @@ -3,6 +3,7 @@ exports com.hedera.fullstack.helm.client.model; exports com.hedera.fullstack.helm.client.model.chart; exports com.hedera.fullstack.helm.client.model.install; + exports com.hedera.fullstack.helm.client.model.test; exports com.hedera.fullstack.helm.client.execution; exports com.hedera.fullstack.helm.client.proxy.request.chart to com.hedera.fullstack.helm.client.test; diff --git a/fullstack-helm-client/src/test/java/com/hedera/fullstack/helm/client/test/HelmClientTest.java b/fullstack-helm-client/src/test/java/com/hedera/fullstack/helm/client/test/HelmClientTest.java index 475baa18e..b0023216e 100644 --- a/fullstack-helm-client/src/test/java/com/hedera/fullstack/helm/client/test/HelmClientTest.java +++ b/fullstack-helm-client/src/test/java/com/hedera/fullstack/helm/client/test/HelmClientTest.java @@ -26,6 +26,7 @@ import com.hedera.fullstack.helm.client.model.Repository; import com.hedera.fullstack.helm.client.model.chart.Release; import com.hedera.fullstack.helm.client.model.install.InstallChartOptions; +import com.hedera.fullstack.helm.client.model.test.TestChartOptions; import com.jcovalent.junit.logging.JCovalentLoggingSupport; import com.jcovalent.junit.logging.LogEntry; import com.jcovalent.junit.logging.LogEntryBuilder; @@ -344,4 +345,18 @@ void testInstallChartWithProvenanceValidation(final LoggingOutput loggingOutput) testChartInstallWithCleanup(options, EXPECTED_LOG_ENTRIES, loggingOutput); } + + @Test + @DisplayName("Helm Test subcommand with options") + void testTestChartWithOptions() { + addRepoIfMissing(helmClient, HAPROXYTECH_REPOSITORY); + final TestChartOptions options = + TestChartOptions.builder().timeout("60s").filter("haproxy").build(); + suppressExceptions(() -> helmClient.installChart(HAPROXY_RELEASE_NAME, HAPROXY_CHART)); + try { + helmClient.testChart(HAPROXY_RELEASE_NAME, options); + } finally { + suppressExceptions(() -> helmClient.uninstallChart(HAPROXY_RELEASE_NAME)); + } + } } diff --git a/fullstack-helm-client/src/test/java/com/hedera/fullstack/helm/client/test/model/TestChartOptionsBuilderTest.java b/fullstack-helm-client/src/test/java/com/hedera/fullstack/helm/client/test/model/TestChartOptionsBuilderTest.java new file mode 100644 index 000000000..350d8d5c6 --- /dev/null +++ b/fullstack-helm-client/src/test/java/com/hedera/fullstack/helm/client/test/model/TestChartOptionsBuilderTest.java @@ -0,0 +1,51 @@ +/* + * 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.helm.client.test.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import com.hedera.fullstack.helm.client.execution.HelmExecutionBuilder; +import com.hedera.fullstack.helm.client.model.test.TestChartOptions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class TestChartOptionsBuilderTest { + @Mock + private HelmExecutionBuilder builderMock; + + @Test + @DisplayName("Test TestChartOptionsBuilder") + void testTestChartOptionsBuilder() { + TestChartOptions options = + TestChartOptions.builder().filter("filter").timeout("timeout").build(); + assertNotNull(options); + assertEquals("timeout", options.timeout()); + assertEquals("filter", options.filter()); + + options.apply(builderMock); + + verify(builderMock, times(2)).argument(anyString(), anyString()); + } +} diff --git a/fullstack-helm-client/src/test/java/com/hedera/fullstack/helm/client/test/proxy/request/chart/ChartTestRequestTest.java b/fullstack-helm-client/src/test/java/com/hedera/fullstack/helm/client/test/proxy/request/chart/ChartTestRequestTest.java new file mode 100644 index 000000000..ff17dbb6c --- /dev/null +++ b/fullstack-helm-client/src/test/java/com/hedera/fullstack/helm/client/test/proxy/request/chart/ChartTestRequestTest.java @@ -0,0 +1,46 @@ +/* + * 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.helm.client.test.proxy.request.chart; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.hedera.fullstack.helm.client.model.test.TestChartOptions; +import com.hedera.fullstack.helm.client.proxy.request.chart.ChartTestRequest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class ChartTestRequestTest { + @Test + @DisplayName("Test ChartTestRequest Chart constructor") + void testChartTestRequestChartConstructor() { + final ChartTestRequest chartTestRequest = new ChartTestRequest("apache"); + assertThat(chartTestRequest.options()).isNotNull().isEqualTo(TestChartOptions.defaults()); + assertThat(chartTestRequest.releaseName()).isEqualTo("apache"); + + final TestChartOptions opts = + TestChartOptions.builder().timeout("9m0s").filter("filter").build(); + final ChartTestRequest nonDefaultOptRequest = new ChartTestRequest("apache", opts); + + assertThat(nonDefaultOptRequest.options()) + .isNotNull() + .isEqualTo(opts) + .isNotEqualTo(TestChartOptions.defaults()); + } +}