Skip to content

Commit 361e12e

Browse files
authored
feat: [ISSUE-1401]: Added helm get values option in Helm collector (#1402)
* feat: [ISSUE-1401]: Added helm get values option in Helm collector Signed-off-by: Akash Shrivastava <[email protected]> * Made changes in error handling Signed-off-by: Akash Shrivastava <[email protected]> * feat: [ISSUE-1401]: Added test cases and fixes Signed-off-by: Akash Shrivastava <[email protected]> * fixed test case Signed-off-by: Akash Shrivastava <[email protected]> --------- Signed-off-by: Akash Shrivastava <[email protected]>
1 parent e542f4f commit 361e12e

File tree

11 files changed

+94
-26
lines changed

11 files changed

+94
-26
lines changed

config/crds/troubleshoot.sh_collectors.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,8 @@ spec:
349349
type: object
350350
helm:
351351
properties:
352+
collectValues:
353+
type: boolean
352354
collectorName:
353355
type: string
354356
exclude:

config/crds/troubleshoot.sh_preflights.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1910,6 +1910,8 @@ spec:
19101910
type: object
19111911
helm:
19121912
properties:
1913+
collectValues:
1914+
type: boolean
19131915
collectorName:
19141916
type: string
19151917
exclude:

config/crds/troubleshoot.sh_supportbundles.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1941,6 +1941,8 @@ spec:
19411941
type: object
19421942
helm:
19431943
properties:
1944+
collectValues:
1945+
type: boolean
19441946
collectorName:
19451947
type: string
19461948
exclude:

pkg/apis/troubleshoot/v1beta2/collector_shared.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ type Helm struct {
257257
CollectorMeta `json:",inline" yaml:",inline"`
258258
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
259259
ReleaseName string `json:"releaseName,omitempty" yaml:"releaseName,omitempty"`
260+
CollectValues bool `json:"collectValues,omitempty" yaml:"collectValues,omitempty"`
260261
}
261262

262263
type Goldpinger struct {

pkg/collect/helm.go

Lines changed: 68 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ import (
55
"context"
66
"encoding/json"
77
"fmt"
8-
"log"
98
"strconv"
9+
"strings"
1010

1111
"github.com/pkg/errors"
1212
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
13-
1413
"helm.sh/helm/v3/pkg/action"
1514
"k8s.io/client-go/kubernetes"
1615
"k8s.io/client-go/rest"
@@ -39,10 +38,11 @@ type ReleaseInfo struct {
3938

4039
// Helm release version information struct
4140
type VersionInfo struct {
42-
Revision string `json:"revision"`
43-
Date string `json:"date"`
44-
Status string `json:"status"`
45-
IsPending bool `json:"isPending,omitempty"`
41+
Revision string `json:"revision"`
42+
Date string `json:"date"`
43+
Status string `json:"status"`
44+
IsPending bool `json:"isPending,omitempty"`
45+
Values map[string]interface{} `json:"values,omitempty"`
4646
}
4747

4848
func (c *CollectHelm) Title() string {
@@ -57,9 +57,15 @@ func (c *CollectHelm) Collect(progressChan chan<- interface{}) (CollectorResult,
5757

5858
output := NewResult()
5959

60-
releaseInfos, err := helmReleaseHistoryCollector(c.Collector.ReleaseName, c.Collector.Namespace)
60+
releaseInfos, err := helmReleaseHistoryCollector(c.Collector.ReleaseName, c.Collector.Namespace, c.Collector.CollectValues)
6161
if err != nil {
62-
return nil, errors.Wrap(err, "failed to get Helm release history")
62+
errsToMarhsal := []string{}
63+
for _, e := range err {
64+
errsToMarhsal = append(errsToMarhsal, e.Error())
65+
}
66+
output.SaveResult(c.BundlePath, "helm/errors.json", marshalErrors(errsToMarhsal))
67+
klog.Errorf("error collecting helm release info: %v", err)
68+
return output, nil
6369
}
6470

6571
releaseInfoByNamespace := helmReleaseInfoByNamespaces(releaseInfos)
@@ -72,40 +78,42 @@ func (c *CollectHelm) Collect(progressChan chan<- interface{}) (CollectorResult,
7278
}
7379

7480
filePath := fmt.Sprintf("helm/%s.json", namespace)
75-
76-
err := output.SaveResult(c.BundlePath, filePath, bytes.NewBuffer(helmHistoryJson))
77-
if err != nil {
78-
return nil, err
81+
if c.Collector.ReleaseName != "" {
82+
filePath = fmt.Sprintf("helm/%s/%s.json", namespace, c.Collector.ReleaseName)
7983
}
84+
85+
output.SaveResult(c.BundlePath, filePath, bytes.NewBuffer(helmHistoryJson))
8086
}
8187

8288
return output, nil
8389
}
8490

85-
func helmReleaseHistoryCollector(releaseName string, namespace string) ([]ReleaseInfo, error) {
91+
func helmReleaseHistoryCollector(releaseName string, namespace string, collectValues bool) ([]ReleaseInfo, []error) {
8692
var results []ReleaseInfo
93+
error_list := []error{}
8794

8895
actionConfig := new(action.Configuration)
8996
if err := actionConfig.Init(nil, namespace, "", klog.V(2).Infof); err != nil {
90-
return nil, errors.Wrap(err, "failed to initialize Helm action config")
97+
return nil, []error{err}
9198
}
9299

93100
// If releaseName is specified, get the history of that release
94101
if releaseName != "" {
95102
getAction := action.NewGet(actionConfig)
96103
r, err := getAction.Run(releaseName)
97104
if err != nil {
98-
return nil, errors.Wrapf(err, "failed to get Helm release %s", releaseName)
105+
return nil, []error{err}
99106
}
107+
versionInfo, err := getVersionInfo(actionConfig, r.Name, r.Namespace, collectValues)
100108
results = append(results, ReleaseInfo{
101109
ReleaseName: r.Name,
102110
Chart: r.Chart.Metadata.Name,
103111
ChartVersion: r.Chart.Metadata.Version,
104112
AppVersion: r.Chart.Metadata.AppVersion,
105113
Namespace: r.Namespace,
106-
VersionInfo: getVersionInfo(actionConfig, releaseName),
114+
VersionInfo: versionInfo,
107115
})
108-
return results, nil
116+
return results, []error{err}
109117
}
110118

111119
// If releaseName is not specified, get the history of all releases
@@ -114,39 +122,64 @@ func helmReleaseHistoryCollector(releaseName string, namespace string) ([]Releas
114122
listAction := action.NewList(actionConfig)
115123
releases, err := listAction.Run()
116124
if err != nil {
117-
log.Fatalf("Failed to list Helm releases: %v", err)
125+
return nil, []error{err}
118126
}
119127

120128
for _, r := range releases {
129+
versionInfo, err := getVersionInfo(actionConfig, r.Name, r.Namespace, collectValues)
130+
if err != nil {
131+
error_list = append(error_list, err)
132+
}
121133
results = append(results, ReleaseInfo{
122134
ReleaseName: r.Name,
123135
Chart: r.Chart.Metadata.Name,
124136
ChartVersion: r.Chart.Metadata.Version,
125137
AppVersion: r.Chart.Metadata.AppVersion,
126138
Namespace: r.Namespace,
127-
VersionInfo: getVersionInfo(actionConfig, r.Name),
139+
VersionInfo: versionInfo,
128140
})
129141
}
130-
142+
if len(error_list) > 0 {
143+
return nil, error_list
144+
}
131145
return results, nil
132146
}
133147

134-
func getVersionInfo(actionConfig *action.Configuration, releaseName string) []VersionInfo {
148+
func getVersionInfo(actionConfig *action.Configuration, releaseName, namespace string, collectValues bool) ([]VersionInfo, error) {
135149

136150
versionCollect := []VersionInfo{}
151+
error_list := []error{}
137152

138-
history, _ := action.NewHistory(actionConfig).Run(releaseName)
153+
history, err := action.NewHistory(actionConfig).Run(releaseName)
154+
if err != nil {
155+
return nil, err
156+
}
139157

140158
for _, release := range history {
159+
values := map[string]interface{}{}
160+
if collectValues {
161+
values, err = getHelmValues(releaseName, namespace, release.Version)
162+
if err != nil {
163+
error_list = append(error_list, err)
164+
}
165+
}
141166

142167
versionCollect = append(versionCollect, VersionInfo{
143168
Revision: strconv.Itoa(release.Version),
144169
Date: release.Info.LastDeployed.String(),
145170
Status: release.Info.Status.String(),
146171
IsPending: release.Info.Status.IsPending(),
172+
Values: values,
147173
})
148174
}
149-
return versionCollect
175+
if len(error_list) > 0 {
176+
errs := []string{}
177+
for _, e := range error_list {
178+
errs = append(errs, e.Error())
179+
}
180+
return nil, errors.New(strings.Join(errs, "\n"))
181+
}
182+
return versionCollect, nil
150183
}
151184

152185
func helmReleaseInfoByNamespaces(releaseInfo []ReleaseInfo) map[string][]ReleaseInfo {
@@ -158,3 +191,15 @@ func helmReleaseInfoByNamespaces(releaseInfo []ReleaseInfo) map[string][]Release
158191

159192
return releaseInfoByNamespace
160193
}
194+
195+
func getHelmValues(releaseName, namespace string, revision int) (map[string]interface{}, error) {
196+
actionConfig := new(action.Configuration)
197+
if err := actionConfig.Init(nil, namespace, "", klog.V(2).Infof); err != nil {
198+
return nil, err
199+
}
200+
getAction := action.NewGetValues(actionConfig)
201+
getAction.AllValues = true
202+
getAction.Version = revision
203+
helmValues, err := getAction.Run(releaseName)
204+
return helmValues, err
205+
}

schemas/collector-troubleshoot-v1beta2.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,9 @@
483483
"helm": {
484484
"type": "object",
485485
"properties": {
486+
"collectValues": {
487+
"type": "boolean"
488+
},
486489
"collectorName": {
487490
"type": "string"
488491
},

schemas/preflight-troubleshoot-v1beta2.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2888,6 +2888,9 @@
28882888
"helm": {
28892889
"type": "object",
28902890
"properties": {
2891+
"collectValues": {
2892+
"type": "boolean"
2893+
},
28912894
"collectorName": {
28922895
"type": "string"
28932896
},

schemas/supportbundle-troubleshoot-v1beta2.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2934,6 +2934,9 @@
29342934
"helm": {
29352935
"type": "object",
29362936
"properties": {
2937+
"collectValues": {
2938+
"type": "boolean"
2939+
},
29372940
"collectorName": {
29382941
"type": "string"
29392942
},

test/e2e/support-bundle/helm_collector_e2e_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func Test_HelmCollector(t *testing.T) {
2727
Setup(func(ctx context.Context, t *testing.T, c *envconf.Config) context.Context {
2828
cluster := getClusterFromContext(t, ctx, ClusterName)
2929
manager := helm.New(cluster.GetKubeconfig())
30-
manager.RunInstall(helm.WithName(releaseName), helm.WithNamespace(c.Namespace()), helm.WithChart(filepath.Join(curDir, "testdata/charts/nginx-15.2.0.tgz")), helm.WithWait(), helm.WithTimeout("1m"))
30+
manager.RunInstall(helm.WithName(releaseName), helm.WithNamespace(c.Namespace()), helm.WithChart(filepath.Join(curDir, "testdata/charts/nginx-15.2.0.tgz")), helm.WithArgs("-f "+filepath.Join(curDir, "testdata/helm-values.yaml")), helm.WithWait(), helm.WithTimeout("1m"))
3131
//ignore error to allow test to speed up, helm collector will catch the pending or deployed helm release status
3232
return ctx
3333
}).
@@ -62,10 +62,11 @@ func Test_HelmCollector(t *testing.T) {
6262
if err != nil {
6363
t.Fatal(err)
6464
}
65-
6665
assert.Equal(t, 1, len(results))
6766
assert.Equal(t, releaseName, results[0].ReleaseName)
6867
assert.Equal(t, "nginx", results[0].Chart)
68+
assert.Equal(t, map[string]interface{}{"name": "TEST_ENV_VAR", "value": "test-value"}, results[0].VersionInfo[0].Values["extraEnvVars"].([]interface{})[0])
69+
assert.Equal(t, "1.25.2-debian-11-r3", results[0].VersionInfo[0].Values["image"].(map[string]interface{})["tag"])
6970
return ctx
7071
}).
7172
Teardown(func(ctx context.Context, t *testing.T, c *envconf.Config) context.Context {
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
---
12
apiVersion: troubleshoot.sh/v1beta2
23
kind: SupportBundle
34
metadata:
45
name: default
56
spec:
67
collectors:
7-
- helm: {}
8+
- helm:
9+
collectValues: true

0 commit comments

Comments
 (0)