From 2be3275749ba2c30e618784ac6f578dfe527a913 Mon Sep 17 00:00:00 2001 From: Marc Nuri Date: Sat, 7 Feb 2026 07:39:44 +0100 Subject: [PATCH] refactor: improve helm get values and fix withKubeConfig javadoc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Simplify YAML serialization using yaml.Marshal directly - Add comprehensive Go tests for GetValues (envtest) - Add Java test for withKubeConfigContents - Add README documentation for helm get values command - Fix withKubeConfig javadoc typo across all commands (./kube/config → ~/.kube/config) Signed-off-by: Marc Nuri --- README.md | 27 ++++ .../java/com/marcnuri/helm/GetCommand.java | 2 +- .../com/marcnuri/helm/InstallCommand.java | 2 +- .../java/com/marcnuri/helm/ListCommand.java | 2 +- .../java/com/marcnuri/helm/TestCommand.java | 2 +- .../com/marcnuri/helm/UninstallCommand.java | 2 +- .../com/marcnuri/helm/UpgradeCommand.java | 2 +- .../com/marcnuri/helm/HelmKubernetesTest.java | 14 ++ native/internal/helm/envtest_test.go | 139 ++++++++++++++++++ native/internal/helm/get.go | 8 +- 10 files changed, 187 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index ef9a855a..31059915 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,33 @@ new Helm(Paths.get("path", "to", "chart")).dependency().update() .call(); ``` +### Get + +Equivalent of [`helm get`](https://helm.sh/docs/helm/helm_get/). + +This command consists of multiple subcommands which can be used to get extended information about the release, including: + +#### Get values + +Equivalent of [`helm get values`](https://helm.sh/docs/helm/helm_get_values/). + +Downloads a values file for a given release. + +``` java +String values = Helm.get("release-name").values() + // Optionally dump all (computed) values, including those from the chart's default values + .allValues() + // Optionally get the named release with a specific revision + .withRevision(1) + // Optionally specify the Kubernetes namespace + .withNamespace("namespace") + // Optionally specify the path to the kubeconfig file to use for CLI requests + .withKubeConfig(Paths.get("path", "to", "kubeconfig")) + // Optionally set the contents of the kubeconfig file as a string (takes precedence over the path) + .withKubeConfigContents("apiVersion: v1\nkind: Config\nclusters:\n...") + .call(); +``` + ### Install Equivalent of [`helm install`](https://helm.sh/docs/helm/helm_install/). diff --git a/helm-java/src/main/java/com/marcnuri/helm/GetCommand.java b/helm-java/src/main/java/com/marcnuri/helm/GetCommand.java index e25199d1..d160fb82 100644 --- a/helm-java/src/main/java/com/marcnuri/helm/GetCommand.java +++ b/helm-java/src/main/java/com/marcnuri/helm/GetCommand.java @@ -113,7 +113,7 @@ public GetValuesSubcommand withNamespace(String namespace) { } /** - * Set the path ./kube/config file to use. + * Set the path to the ~/.kube/config file to use. * * @param kubeConfig the path to kube config file. * @return this {@link GetValuesSubcommand} instance. diff --git a/helm-java/src/main/java/com/marcnuri/helm/InstallCommand.java b/helm-java/src/main/java/com/marcnuri/helm/InstallCommand.java index 92cef666..5f71d45b 100644 --- a/helm-java/src/main/java/com/marcnuri/helm/InstallCommand.java +++ b/helm-java/src/main/java/com/marcnuri/helm/InstallCommand.java @@ -365,7 +365,7 @@ public InstallCommand withValuesFile(Path valuesFile) { } /** - * Set the path ./kube/config file to use. + * Set the path to the ~/.kube/config file to use. * * @param kubeConfig the path to kube config file. * @return this {@link InstallCommand} instance. diff --git a/helm-java/src/main/java/com/marcnuri/helm/ListCommand.java b/helm-java/src/main/java/com/marcnuri/helm/ListCommand.java index c3e07afb..889c4d13 100644 --- a/helm-java/src/main/java/com/marcnuri/helm/ListCommand.java +++ b/helm-java/src/main/java/com/marcnuri/helm/ListCommand.java @@ -155,7 +155,7 @@ public ListCommand withNamespace(String namespace) { } /** - * Set the path ./kube/config file to use. + * Set the path to the ~/.kube/config file to use. * * @param kubeConfig the path to kube config file. * @return this {@link ListCommand} instance. diff --git a/helm-java/src/main/java/com/marcnuri/helm/TestCommand.java b/helm-java/src/main/java/com/marcnuri/helm/TestCommand.java index 172e8e0c..03d5b72a 100644 --- a/helm-java/src/main/java/com/marcnuri/helm/TestCommand.java +++ b/helm-java/src/main/java/com/marcnuri/helm/TestCommand.java @@ -76,7 +76,7 @@ public TestCommand withNamespace(String namespace) { } /** - * Set the path ./kube/config file to use. + * Set the path to the ~/.kube/config file to use. * * @param kubeConfig the path to kube config file. * @return this {@link TestCommand} instance. diff --git a/helm-java/src/main/java/com/marcnuri/helm/UninstallCommand.java b/helm-java/src/main/java/com/marcnuri/helm/UninstallCommand.java index 8d0c9720..ac42c40f 100644 --- a/helm-java/src/main/java/com/marcnuri/helm/UninstallCommand.java +++ b/helm-java/src/main/java/com/marcnuri/helm/UninstallCommand.java @@ -128,7 +128,7 @@ public UninstallCommand withNamespace(String namespace) { } /** - * Set the path ./kube/config file to use. + * Set the path to the ~/.kube/config file to use. * * @param kubeConfig the path to kube config file. * @return this {@link UninstallCommand} instance. diff --git a/helm-java/src/main/java/com/marcnuri/helm/UpgradeCommand.java b/helm-java/src/main/java/com/marcnuri/helm/UpgradeCommand.java index f2f83680..bb4394c0 100644 --- a/helm-java/src/main/java/com/marcnuri/helm/UpgradeCommand.java +++ b/helm-java/src/main/java/com/marcnuri/helm/UpgradeCommand.java @@ -417,7 +417,7 @@ public UpgradeCommand withValuesFile(Path valuesFile) { } /** - * Set the path ./kube/config file to use. + * Set the path to the ~/.kube/config file to use. * * @param kubeConfig the path to kube config file. * @return this {@link UpgradeCommand} instance. diff --git a/helm-java/src/test/java/com/marcnuri/helm/HelmKubernetesTest.java b/helm-java/src/test/java/com/marcnuri/helm/HelmKubernetesTest.java index a8ec8e54..1aec2338 100644 --- a/helm-java/src/test/java/com/marcnuri/helm/HelmKubernetesTest.java +++ b/helm-java/src/test/java/com/marcnuri/helm/HelmKubernetesTest.java @@ -850,6 +850,20 @@ void withNamespace() { .call(); assertThat(result).isNotNull(); } + + @Test + void withKubeConfigContents() { + helm.install() + .withKubeConfigContents(kubeConfigContents) + .withName("get-values-kube-config-contents") + .set("replicaCount", "4") + .call(); + final String result = Helm.get("get-values-kube-config-contents").values() + .withKubeConfigContents(kubeConfigContents) + .call(); + assertThat(result) + .contains("replicaCount: 4"); + } } @Nested diff --git a/native/internal/helm/envtest_test.go b/native/internal/helm/envtest_test.go index 3a78eeff..82731b58 100644 --- a/native/internal/helm/envtest_test.go +++ b/native/internal/helm/envtest_test.go @@ -426,3 +426,142 @@ func TestUpgradeInstall(t *testing.T) { return } } + +func TestGetValues(t *testing.T) { + cleanUp, kubeConfigFile := setupEnvTest() + defer cleanUp() + create, _ := Create(&CreateOptions{ + Name: "test-get-values", + Dir: t.TempDir(), + }) + _, _ = Install(&InstallOptions{ + KubeConfig: kubeConfigFile.Name(), + Chart: create, + Name: "test-get-values", + Values: "replicaCount=3", + }) + out, err := GetValues(&GetValuesOptions{ + KubeConfig: kubeConfigFile.Name(), + ReleaseName: "test-get-values", + }) + if err != nil { + t.Errorf("Expected get values to succeed, got %s", err) + return + } + if !strings.Contains(out, "replicaCount: 3") { + t.Errorf("Expected get values to include replicaCount, got %s", out) + return + } +} + +func TestGetValuesAllValues(t *testing.T) { + cleanUp, kubeConfigFile := setupEnvTest() + defer cleanUp() + create, _ := Create(&CreateOptions{ + Name: "test-get-all-values", + Dir: t.TempDir(), + }) + _, _ = Install(&InstallOptions{ + KubeConfig: kubeConfigFile.Name(), + Chart: create, + Name: "test-get-all-values", + Values: "replicaCount=2", + }) + out, err := GetValues(&GetValuesOptions{ + KubeConfig: kubeConfigFile.Name(), + ReleaseName: "test-get-all-values", + AllValues: true, + }) + if err != nil { + t.Errorf("Expected get values to succeed, got %s", err) + return + } + if !strings.Contains(out, "replicaCount: 2") { + t.Errorf("Expected get values to include replicaCount, got %s", out) + return + } + // AllValues should include chart defaults like serviceAccount + if !strings.Contains(out, "serviceAccount:") { + t.Errorf("Expected get all values to include serviceAccount, got %s", out) + return + } +} + +func TestGetValuesWithRevision(t *testing.T) { + cleanUp, kubeConfigFile := setupEnvTest() + defer cleanUp() + chart, _ := Create(&CreateOptions{ + Name: "test-get-revision", + Dir: t.TempDir(), + }) + _, _ = Install(&InstallOptions{ + KubeConfig: kubeConfigFile.Name(), + Chart: chart, + Name: "test-get-revision", + Values: "replicaCount=1", + }) + _, _ = Upgrade(&UpgradeOptions{ + KubeConfig: kubeConfigFile.Name(), + Chart: chart, + Name: "test-get-revision", + Values: "replicaCount=5", + }) + out, err := GetValues(&GetValuesOptions{ + KubeConfig: kubeConfigFile.Name(), + ReleaseName: "test-get-revision", + Revision: 1, + }) + if err != nil { + t.Errorf("Expected get values to succeed, got %s", err) + return + } + if !strings.Contains(out, "replicaCount: 1") { + t.Errorf("Expected get values for revision 1 to include replicaCount: 1, got %s", out) + return + } +} + +func TestGetValuesUsingKubeConfigContents(t *testing.T) { + cleanUp, kubeConfigFile := setupEnvTest() + defer cleanUp() + kubeConfigContents, _ := os.ReadFile(kubeConfigFile.Name()) + create, _ := Create(&CreateOptions{ + Name: "test-get-values-contents", + Dir: t.TempDir(), + }) + _, _ = Install(&InstallOptions{ + KubeConfigContents: string(kubeConfigContents), + Chart: create, + Name: "test-get-values-contents", + Values: "replicaCount=4", + }) + out, err := GetValues(&GetValuesOptions{ + KubeConfigContents: string(kubeConfigContents), + ReleaseName: "test-get-values-contents", + }) + if err != nil { + t.Errorf("Expected get values to succeed, got %s", err) + return + } + if !strings.Contains(out, "replicaCount: 4") { + t.Errorf("Expected get values to include replicaCount, got %s", out) + return + } +} + +func TestGetValuesNonExistentRelease(t *testing.T) { + cleanUp, kubeConfigFile := setupEnvTest() + defer cleanUp() + _, err := GetValues(&GetValuesOptions{ + KubeConfig: kubeConfigFile.Name(), + ReleaseName: "non-existent-release", + }) + if err == nil { + t.Error("Expected get values to fail for non-existent release") + return + } + if !strings.Contains(err.Error(), "not found") { + t.Errorf("Expected error to contain 'not found', got %s", err.Error()) + return + } +} diff --git a/native/internal/helm/get.go b/native/internal/helm/get.go index 0d4a927e..d2e5119c 100644 --- a/native/internal/helm/get.go +++ b/native/internal/helm/get.go @@ -17,8 +17,6 @@ package helm import ( - "encoding/json" - "helm.sh/helm/v3/pkg/action" "sigs.k8s.io/yaml" ) @@ -53,11 +51,7 @@ func GetValues(options *GetValuesOptions) (string, error) { } // Convert values to YAML format (default Helm output format) - jsonBytes, err := json.Marshal(values) - if err != nil { - return "", err - } - yamlBytes, err := yaml.JSONToYAML(jsonBytes) + yamlBytes, err := yaml.Marshal(values) if err != nil { return "", err }