Skip to content

Commit

Permalink
feat: add timeout option to install and upgrade (#203)
Browse files Browse the repository at this point in the history
* add failing test for upgrade with waitReady

* add timeout option for install and upgrade, fix waitReady for upgrade

* set image and fullnameOverride to make tests more stable
  • Loading branch information
miriSch authored Nov 14, 2024
1 parent 0ac78fa commit ce76bb1
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 8 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ Release result = installCommand
// minimum (Desired minus maxUnavailable) Pods in ready state and Services have an IP
// address (and Ingress if a LoadBalancer) before marking the release as successful.
.waitReady()
// Optionally specify the time (in seconds) to wait for any individual Kubernetes operation (like Jobs for hooks) (default 300)
.withTimeout(int timeout)
// Optionally set typed values for the chart (can be repeated)
.set("key", "value")
// Optionally specify the path to the kubeconfig file to use for CLI requests
Expand Down Expand Up @@ -707,6 +709,8 @@ Release result = upgradeCommand
// minimum (Desired minus maxUnavailable) Pods in ready state and Services have an IP
// address (and Ingress if a LoadBalancer) before marking the release as successful.
.waitReady()
// Optionally specify the time (in seconds) to wait for any individual Kubernetes operation (like Jobs for hooks) (default 300)
.withTimeout(int timeout)
// Optionally set typed values for the chart (can be repeated)
.set("key", "value")
// Optionally specify the path to the kubeconfig file to use for CLI requests
Expand Down
13 changes: 13 additions & 0 deletions helm-java/src/main/java/com/marcnuri/helm/InstallCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public class InstallCommand extends HelmCommand<Release> {
private boolean dryRun;
private DryRun dryRunOption;
private boolean wait;
private int timeout;
private final Map<String, String> values;
private Path kubeConfig;
private Path certFile;
Expand Down Expand Up @@ -83,6 +84,7 @@ public Release call() {
toInt(dryRun),
dryRunOption == null ? null : dryRunOption.name().toLowerCase(Locale.ROOT),
toInt(wait),
timeout,
urlEncode(values),
toString(kubeConfig),
toString(certFile),
Expand Down Expand Up @@ -264,6 +266,17 @@ public InstallCommand waitReady() {
return this;
}

/**
* Time (in seconds) to wait for any individual Kubernetes operation (like Jobs for hooks) (default 300).
*
* @param timeout the timeout in seconds.
* @return this {@link InstallCommand} instance.
*/
public InstallCommand withTimeout(int timeout) {
this.timeout = timeout;
return this;
}

/**
* Set values for the chart.
*
Expand Down
13 changes: 13 additions & 0 deletions helm-java/src/main/java/com/marcnuri/helm/UpgradeCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public class UpgradeCommand extends HelmCommand<Release> {
private boolean dryRun;
private DryRun dryRunOption;
private boolean wait;
private int timeout;
private final Map<String, String> values;
private Path kubeConfig;
private Path certFile;
Expand Down Expand Up @@ -91,6 +92,7 @@ public Release call() {
toInt(dryRun),
dryRunOption == null ? null : dryRunOption.name().toLowerCase(Locale.ROOT),
toInt(wait),
timeout,
urlEncode(values),
toString(kubeConfig),
toString(certFile),
Expand Down Expand Up @@ -316,6 +318,17 @@ public UpgradeCommand waitReady() {
return this;
}

/**
* Time (in seconds) to wait for any individual Kubernetes operation (like Jobs for hooks) (default 300).
*
* @param timeout the timeout in seconds.
* @return this {@link UpgradeCommand} instance.
*/
public UpgradeCommand withTimeout(int timeout) {
this.timeout = timeout;
return this;
}

/**
* Set values for the chart.
*
Expand Down
89 changes: 89 additions & 0 deletions helm-java/src/test/java/com/marcnuri/helm/HelmKubernetesTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,25 @@ void withWaitReady() {
);
}

@Test
void withWaitReadyAndCustomTimeout() {
final Release result = helm.install()
.withKubeConfig(kubeConfig)
.withName("helm-install-with-wait-ready-and-custom-timeout")
.set("fullnameOverride", "helm-install-with-wait-ready-and-custom-timeout")
.set("image.repository", "ghcr.io/linuxserver/nginx")
.set("image.tag", "latest")
.waitReady()
.withTimeout(330)
.debug()
.call();
assertThat(result)
.extracting(Release::getOutput).asString()
.contains(
"beginning wait for 3 resources with timeout of 5m30s"
);
}

@Test
void withNamespaceAndCreateNamespace() {
final Release result = helm.install()
Expand Down Expand Up @@ -154,6 +173,21 @@ void missingNamespace() {
.message()
.isEqualTo("create: failed to create: namespaces \"non-existent\" not found");
}

@Test
void lowTimeout() {
final InstallCommand installCommand = helm.install()
.withKubeConfig(kubeConfig)
.withName("helm-install-with-wait-ready-and-low-timeout")
.set("fullnameOverride", "helm-install-with-wait-ready-and-low-timeout")
.set("image.repository", "ghcr.io/linuxserver/nginx")
.set("image.tag", "latest")
.waitReady()
.withTimeout(1);
assertThatThrownBy(installCommand::call)
.message()
.contains("context deadline exceeded");
}
}

@Nested
Expand Down Expand Up @@ -459,6 +493,45 @@ void withPriorInstall() {
.returns("2", Release::getRevision)
.returns("deployed", Release::getStatus);
}

@Test
void withWaitReady() {
helm.install().withName("helm-upgrade-with-wait-ready").withKubeConfig(kubeConfig).call();
final Release result = helm.upgrade()
.withKubeConfig(kubeConfig)
.withName("helm-upgrade-with-wait-ready")
.set("fullnameOverride", "helm-upgrade-with-wait-ready")
.set("image.repository", "ghcr.io/linuxserver/nginx")
.set("image.tag", "latest")
.waitReady()
.debug()
.call();
assertThat(result)
.extracting(Release::getOutput).asString()
.contains(
"beginning wait for 3 resources with timeout of 5m0s"
);
}

@Test
void withWaitAndCustomTimeout() {
helm.install().withName("helm-upgrade-with-wait-ready-and-custom-timeout").withKubeConfig(kubeConfig).call();
final Release result = helm.upgrade()
.withKubeConfig(kubeConfig)
.withName("helm-upgrade-with-wait-ready-and-custom-timeout")
.set("fullnameOverride", "helm-upgrade-with-wait-ready-and-custom-timeout")
.set("image.repository", "ghcr.io/linuxserver/nginx")
.set("image.tag", "latest")
.waitReady()
.withTimeout(330)
.debug()
.call();
assertThat(result)
.extracting(Release::getOutput).asString()
.contains(
"beginning wait for 3 resources with timeout of 5m30s"
);
}
}

@Nested
Expand All @@ -472,6 +545,22 @@ void missingRelease() {
.message()
.isEqualTo("\"upgrade-missing-release\" has no deployed releases");
}

@Test
void lowTimeout() {
helm.install().withName("helm-upgrade-with-wait-ready-and-low-timeout").withKubeConfig(kubeConfig).call();
final UpgradeCommand upgrade = helm.upgrade()
.withKubeConfig(kubeConfig)
.withName("helm-upgrade-with-wait-ready-and-low-timeout")
.set("fullnameOverride", "helm-upgrade-with-wait-ready-and-low-timeout")
.set("image.repository", "ghcr.io/linuxserver/nginx")
.set("image.tag", "latest")
.waitReady()
.withTimeout(1);
assertThatThrownBy(upgrade::call)
.message()
.contains("context deadline exceeded");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"dryRun",
"dryRunOption",
"wait",
"timeout",
"values",
"kubeConfig",
"certFile",
Expand Down Expand Up @@ -63,6 +64,7 @@ public class InstallOptions extends Structure {
public int dryRun;
public String dryRunOption;
public int wait;
public int timeout;
public String values;
public String kubeConfig;
public String certFile;
Expand Down Expand Up @@ -91,6 +93,7 @@ public InstallOptions(
int dryRun,
String dryRunOption,
int wait,
int timeout,
String values,
String kubeConfig,
String certFile,
Expand Down Expand Up @@ -118,6 +121,7 @@ public InstallOptions(
this.dryRun = dryRun;
this.dryRunOption = dryRunOption;
this.wait = wait;
this.timeout = timeout;
this.values = values;
this.kubeConfig = kubeConfig;
this.certFile = certFile;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"dryRun",
"dryRunOption",
"wait",
"timeout",
"values",
"kubeConfig",
"certFile",
Expand Down Expand Up @@ -70,6 +71,7 @@ public class UpgradeOptions extends Structure {
public int dryRun;
public String dryRunOption;
public int wait;
public int timeout;
public String values;
public String kubeConfig;
public String certFile;
Expand Down Expand Up @@ -102,6 +104,7 @@ public UpgradeOptions(
int dryRun,
String dryRunOption,
int wait,
int timeout,
String values,
String kubeConfig,
String certFile,
Expand Down Expand Up @@ -133,6 +136,7 @@ public UpgradeOptions(
this.dryRun = dryRun;
this.dryRunOption = dryRunOption;
this.wait = wait;
this.timeout = timeout;
this.values = values;
this.kubeConfig = kubeConfig;
this.certFile = certFile;
Expand Down
5 changes: 1 addition & 4 deletions native/internal/helm/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,7 @@ func install(options *InstallOptions) (*release.Release, *installOutputs, error)
client.DryRun = options.DryRun
client.DryRunOption = dryRunOption(options.DryRunOption)
client.Wait = options.Wait
// Timeout defaults to 5 minutes (used when wait is enabled)
if options.Timeout == 0 {
client.Timeout = 300 * time.Second
}
client.Timeout = options.Timeout
client.ClientOnly = options.ClientOnly
client.CertFile = options.CertFile
client.KeyFile = options.KeyFile
Expand Down
4 changes: 0 additions & 4 deletions native/internal/helm/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,6 @@ func Upgrade(options *UpgradeOptions) (string, error) {
client.DryRun = options.DryRun
client.DryRunOption = dryRunOption(options.DryRunOption)
client.Wait = options.Wait
// Timeout defaults to 5 minutes (used when wait is enabled)
if options.Timeout == 0 {
client.Timeout = 300 * time.Second
}
client.Timeout = options.Timeout
client.CertFile = options.CertFile
client.KeyFile = options.KeyFile
Expand Down
16 changes: 16 additions & 0 deletions native/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ struct InstallOptions {
int dryRun;
char* dryRunOption;
int wait;
int timeout;
char* values;
char* kubeConfig;
char* certFile;
Expand Down Expand Up @@ -216,6 +217,7 @@ struct UpgradeOptions {
int dryRun;
char* dryRunOption;
int wait;
int timeout;
char* values;
char* kubeConfig;
char* certFile;
Expand Down Expand Up @@ -321,6 +323,12 @@ func DependencyUpdate(options *C.struct_DependencyOptions) C.Result {

//export Install
func Install(options *C.struct_InstallOptions) C.Result {
var timeout time.Duration
if options.timeout > 0 {
timeout = time.Duration(int(options.timeout)) * time.Second
} else {
timeout = time.Duration(300) * time.Second
}
return runCommand(func() (string, error) {
return helm.Install(&helm.InstallOptions{
Name: C.GoString(options.name),
Expand All @@ -338,6 +346,7 @@ func Install(options *C.struct_InstallOptions) C.Result {
DryRun: options.dryRun == 1,
DryRunOption: C.GoString(options.dryRunOption),
Wait: options.wait == 1,
Timeout: timeout,
Values: C.GoString(options.values),
KubeConfig: C.GoString(options.kubeConfig),
CertOptions: helm.CertOptions{
Expand Down Expand Up @@ -640,6 +649,12 @@ func Uninstall(options *C.struct_UninstallOptions) C.Result {

//export Upgrade
func Upgrade(options *C.struct_UpgradeOptions) C.Result {
var timeout time.Duration
if options.timeout > 0 {
timeout = time.Duration(int(options.timeout)) * time.Second
} else {
timeout = time.Duration(300) * time.Second
}
return runCommand(func() (string, error) {
return helm.Upgrade(&helm.UpgradeOptions{
Name: C.GoString(options.name),
Expand All @@ -661,6 +676,7 @@ func Upgrade(options *C.struct_UpgradeOptions) C.Result {
DryRun: options.dryRun == 1,
DryRunOption: C.GoString(options.dryRunOption),
Wait: options.wait == 1,
Timeout: timeout,
Values: C.GoString(options.values),
KubeConfig: C.GoString(options.kubeConfig),
CertOptions: helm.CertOptions{
Expand Down

0 comments on commit ce76bb1

Please sign in to comment.