Skip to content

Commit 3fcf96a

Browse files
feat: add support for "helm get values" command (#345)
1 parent 1be6919 commit 3fcf96a

File tree

7 files changed

+372
-0
lines changed

7 files changed

+372
-0
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
* Copyright 2026 Marc Nuri
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.marcnuri.helm;
18+
19+
import com.marcnuri.helm.jni.GetValuesOptions;
20+
import com.marcnuri.helm.jni.HelmLib;
21+
22+
import java.nio.file.Path;
23+
24+
/**
25+
* This command consists of multiple subcommands which can be used to get extended information about the release.
26+
*
27+
* @author Antonio Fernandez Alhambra
28+
*/
29+
public class GetCommand {
30+
31+
private final HelmLib helmLib;
32+
private final String releaseName;
33+
34+
GetCommand(HelmLib helmLib, String releaseName) {
35+
this.helmLib = helmLib;
36+
this.releaseName = releaseName;
37+
}
38+
39+
/**
40+
* This command downloads the values file for a given release.
41+
*
42+
* @return the {@link GetValuesSubcommand} subcommand.
43+
*/
44+
public GetValuesSubcommand values() {
45+
return new GetValuesSubcommand(helmLib, releaseName);
46+
}
47+
48+
public static final class GetValuesSubcommand extends HelmCommand<String> {
49+
50+
private final String releaseName;
51+
private boolean allValues;
52+
private int revision;
53+
private String namespace;
54+
private Path kubeConfig;
55+
private String kubeConfigContents;
56+
57+
private GetValuesSubcommand(HelmLib helmLib, String releaseName) {
58+
super(helmLib);
59+
this.releaseName = releaseName;
60+
}
61+
62+
/**
63+
* Execute the get values subcommand.
64+
*
65+
* @return a {@link String} containing the values in YAML format.
66+
*/
67+
@Override
68+
public String call() {
69+
return run(hl -> hl.GetValues(new GetValuesOptions(
70+
releaseName,
71+
toInt(allValues),
72+
revision,
73+
namespace,
74+
toString(kubeConfig),
75+
kubeConfigContents
76+
))).out;
77+
}
78+
79+
/**
80+
* Dump all (computed) values.
81+
* <p>
82+
* When set, all computed values are returned, including the default values from the chart.
83+
*
84+
* @return this {@link GetValuesSubcommand} instance.
85+
*/
86+
public GetValuesSubcommand allValues() {
87+
this.allValues = true;
88+
return this;
89+
}
90+
91+
/**
92+
* Get the named release with revision.
93+
* <p>
94+
* If not specified, the latest release is returned.
95+
*
96+
* @param revision the revision number.
97+
* @return this {@link GetValuesSubcommand} instance.
98+
*/
99+
public GetValuesSubcommand withRevision(int revision) {
100+
this.revision = revision;
101+
return this;
102+
}
103+
104+
/**
105+
* Kubernetes namespace scope for this request.
106+
*
107+
* @param namespace the Kubernetes namespace for this request.
108+
* @return this {@link GetValuesSubcommand} instance.
109+
*/
110+
public GetValuesSubcommand withNamespace(String namespace) {
111+
this.namespace = namespace;
112+
return this;
113+
}
114+
115+
/**
116+
* Set the path ./kube/config file to use.
117+
*
118+
* @param kubeConfig the path to kube config file.
119+
* @return this {@link GetValuesSubcommand} instance.
120+
*/
121+
public GetValuesSubcommand withKubeConfig(Path kubeConfig) {
122+
this.kubeConfig = kubeConfig;
123+
return this;
124+
}
125+
126+
/**
127+
* Set the kube config to use.
128+
*
129+
* @param kubeConfigContents the contents of the kube config file.
130+
* @return this {@link GetValuesSubcommand} instance.
131+
*/
132+
public GetValuesSubcommand withKubeConfigContents(String kubeConfigContents) {
133+
this.kubeConfigContents = kubeConfigContents;
134+
return this;
135+
}
136+
}
137+
}

helm-java/src/main/java/com/marcnuri/helm/Helm.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
/**
2525
* @author Marc Nuri
2626
* @author Andres F. Vallecilla
27+
* @author Antonio Fernandez Alhambra
2728
*/
2829
public class Helm {
2930

@@ -96,6 +97,16 @@ public static ListCommand list() {
9697
return new ListCommand(HelmLibHolder.INSTANCE);
9798
}
9899

100+
/**
101+
* This command consists of multiple subcommands which can be used to get extended information about the release.
102+
*
103+
* @param releaseName the name of the release.
104+
* @return the {@link GetCommand} command.
105+
*/
106+
public static GetCommand get(String releaseName) {
107+
return new GetCommand(HelmLibHolder.INSTANCE, releaseName);
108+
}
109+
99110
/**
100111
* This command packages a chart into a versioned chart archive file.
101112
* If a path is given, this will look at that path for a chart (which must contain a Chart.yaml file) and then package that directory.

helm-java/src/test/java/com/marcnuri/helm/HelmKubernetesTest.java

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,4 +780,89 @@ void withInstallAndInvalidKubeVersion() {
780780
}
781781
}
782782
}
783+
784+
@Nested
785+
class Get {
786+
787+
@Nested
788+
class Values {
789+
790+
@Test
791+
void returnsUserSuppliedValues() {
792+
helm.install()
793+
.withKubeConfig(kubeConfigFile)
794+
.withName("get-values-user-supplied")
795+
.set("replicaCount", "3")
796+
.call();
797+
final String result = Helm.get("get-values-user-supplied").values()
798+
.withKubeConfig(kubeConfigFile)
799+
.call();
800+
assertThat(result)
801+
.contains("replicaCount: 3");
802+
}
803+
804+
@Test
805+
void allValuesIncludesDefaultValues() {
806+
helm.install()
807+
.withKubeConfig(kubeConfigFile)
808+
.withName("get-values-all")
809+
.set("replicaCount", "2")
810+
.call();
811+
final String result = Helm.get("get-values-all").values()
812+
.withKubeConfig(kubeConfigFile)
813+
.allValues()
814+
.call();
815+
assertThat(result)
816+
.contains("replicaCount: 2")
817+
.contains("serviceAccount:");
818+
}
819+
820+
@Test
821+
void withRevision() {
822+
helm.install()
823+
.withKubeConfig(kubeConfigFile)
824+
.withName("get-values-revision")
825+
.set("replicaCount", "1")
826+
.call();
827+
helm.upgrade()
828+
.withKubeConfig(kubeConfigFile)
829+
.withName("get-values-revision")
830+
.set("replicaCount", "5")
831+
.call();
832+
final String result = Helm.get("get-values-revision").values()
833+
.withKubeConfig(kubeConfigFile)
834+
.withRevision(1)
835+
.call();
836+
assertThat(result)
837+
.contains("replicaCount: 1");
838+
}
839+
840+
@Test
841+
void withNamespace() {
842+
helm.install()
843+
.withKubeConfig(kubeConfigFile)
844+
.withName("get-values-namespace")
845+
.withNamespace("default")
846+
.call();
847+
final String result = Helm.get("get-values-namespace").values()
848+
.withKubeConfig(kubeConfigFile)
849+
.withNamespace("default")
850+
.call();
851+
assertThat(result).isNotNull();
852+
}
853+
}
854+
855+
@Nested
856+
class Invalid {
857+
858+
@Test
859+
void missingRelease() {
860+
final GetCommand.GetValuesSubcommand getValues = Helm.get("non-existent-release").values()
861+
.withKubeConfig(kubeConfigFile);
862+
assertThatThrownBy(getValues::call)
863+
.message()
864+
.contains("not found");
865+
}
866+
}
867+
}
783868
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2026 Marc Nuri
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.marcnuri.helm.jni;
18+
19+
import com.sun.jna.Structure;
20+
21+
/**
22+
* @author Antonio Fernandez Alhambra
23+
*/
24+
@Structure.FieldOrder({
25+
"releaseName",
26+
"allValues",
27+
"revision",
28+
"namespace",
29+
"kubeConfig",
30+
"kubeConfigContents"
31+
})
32+
public class GetValuesOptions extends Structure {
33+
public String releaseName;
34+
public int allValues;
35+
public int revision;
36+
public String namespace;
37+
public String kubeConfig;
38+
public String kubeConfigContents;
39+
40+
public GetValuesOptions(String releaseName, int allValues, int revision, String namespace, String kubeConfig, String kubeConfigContents) {
41+
this.releaseName = releaseName;
42+
this.allValues = allValues;
43+
this.revision = revision;
44+
this.namespace = namespace;
45+
this.kubeConfig = kubeConfig;
46+
this.kubeConfigContents = kubeConfigContents;
47+
}
48+
}

lib/api/src/main/java/com/marcnuri/helm/jni/HelmLib.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
/**
2222
* @author Marc Nuri
2323
* @author Andres F. Vallecilla
24+
* @author Antonio Fernandez Alhambra
2425
*/
2526
public interface HelmLib extends Library {
2627

@@ -38,6 +39,8 @@ public interface HelmLib extends Library {
3839

3940
Result List(ListOptions options);
4041

42+
Result GetValues(GetValuesOptions options);
43+
4144
Result Package(PackageOptions options);
4245

4346
Result Push(PushOptions options);

native/internal/helm/get.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright 2026 Marc Nuri
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package helm
18+
19+
import (
20+
"encoding/json"
21+
22+
"helm.sh/helm/v3/pkg/action"
23+
"sigs.k8s.io/yaml"
24+
)
25+
26+
type GetValuesOptions struct {
27+
ReleaseName string
28+
AllValues bool
29+
Revision int
30+
Namespace string
31+
KubeConfig string
32+
KubeConfigContents string
33+
}
34+
35+
func GetValues(options *GetValuesOptions) (string, error) {
36+
cfg, err := NewCfg(&CfgOptions{
37+
KubeConfig: options.KubeConfig,
38+
KubeConfigContents: options.KubeConfigContents,
39+
Namespace: options.Namespace,
40+
})
41+
if err != nil {
42+
return "", err
43+
}
44+
client := action.NewGetValues(cfg)
45+
client.AllValues = options.AllValues
46+
if options.Revision > 0 {
47+
client.Version = options.Revision
48+
}
49+
50+
values, err := client.Run(options.ReleaseName)
51+
if err != nil {
52+
return "", err
53+
}
54+
55+
// Convert values to YAML format (default Helm output format)
56+
jsonBytes, err := json.Marshal(values)
57+
if err != nil {
58+
return "", err
59+
}
60+
yamlBytes, err := yaml.JSONToYAML(jsonBytes)
61+
if err != nil {
62+
return "", err
63+
}
64+
return string(yamlBytes), nil
65+
}

0 commit comments

Comments
 (0)