Skip to content

Commit

Permalink
feat: add helm test subcommand with options (#376)
Browse files Browse the repository at this point in the history
Signed-off-by: Jeromy Cannon <jeromy@swirldslabs.com>
  • Loading branch information
jeromy-cannon authored Oct 5, 2023
1 parent ba6cc63 commit 5d08a32
Show file tree
Hide file tree
Showing 9 changed files with 316 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -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());
}
}
}
Original file line number Diff line number Diff line change
@@ -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).
* <p>
* 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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
1 change: 1 addition & 0 deletions fullstack-helm-client/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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));
}
}
}
Original file line number Diff line number Diff line change
@@ -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());
}
}
Original file line number Diff line number Diff line change
@@ -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());
}
}

0 comments on commit 5d08a32

Please sign in to comment.