/
helm.go
180 lines (154 loc) · 5.11 KB
/
helm.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
package tool
import (
"context"
"errors"
"fmt"
"os"
"time"
"github.com/mgoerens/my-chart-verifier/internal/chartverifier/utils"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/cli"
"helm.sh/helm/v3/pkg/cli/values"
"helm.sh/helm/v3/pkg/getter"
"k8s.io/helm/pkg/strvals"
)
type Helm struct {
config *action.Configuration
envSettings *cli.EnvSettings
timeout time.Duration
args map[string]interface{}
}
func NewHelm(envSettings *cli.EnvSettings, args map[string]interface{}, timeout time.Duration) (*Helm, error) {
helm := &Helm{envSettings: envSettings, args: args, timeout: timeout}
if timeout < 5*time.Minute {
helm.timeout = 5 * time.Minute
}
config := new(action.Configuration)
if err := config.Init(envSettings.RESTClientGetter(), envSettings.Namespace(), os.Getenv("HELM_DRIVER"), func(format string, v ...interface{}) {
utils.LogInfo(fmt.Sprintf(format, v))
}); err != nil {
return nil, err
}
helm.config = config
return helm, nil
}
func (h Helm) Install(ctx context.Context, namespace, chart, release, valuesFile string) error {
utils.LogInfo(fmt.Sprintf("Execute helm install. namespace: %s, release: %s chart: %s", namespace, release, chart))
client := action.NewInstall(h.config)
client.Namespace = namespace
client.ReleaseName = release
client.Wait = true
// default timeout duration
// ref: https://helm.sh/docs/helm/helm_install
client.Timeout = h.timeout
cp, err := client.ChartPathOptions.LocateChart(chart, h.envSettings)
if err != nil {
utils.LogError(fmt.Sprintf("Error LocateChart: %v", err))
return err
}
p := getter.All(h.envSettings)
valueOpts := &values.Options{}
if valuesFile != "" {
valueOpts.ValueFiles = append(valueOpts.ValueFiles, valuesFile)
}
vals, err := valueOpts.MergeValues(p)
if err != nil {
utils.LogError(fmt.Sprintf("Error MergeValues: %v", err))
return err
}
if val, ok := h.args["set"]; ok {
if err := strvals.ParseInto(fmt.Sprintf("%v", val), vals); err != nil {
utils.LogError(fmt.Sprintf("Error parsing --set values: %v", err))
return err
}
}
if val, ok := h.args["set-file"]; ok {
if err := strvals.ParseInto(fmt.Sprintf("%v", val), vals); err != nil {
utils.LogError(fmt.Sprintf("Error parsing --set-file values: %v", err))
return err
}
}
if val, ok := h.args["set-string"]; ok {
if err := strvals.ParseInto(fmt.Sprintf("%v", val), vals); err != nil {
utils.LogError(fmt.Sprintf("Error parsing --set-string values: %v", err))
return err
}
}
c, err := loader.Load(cp)
if err != nil {
utils.LogError(fmt.Sprintf("Error loading chart path: %v", err))
return err
}
utils.LogInfo(fmt.Sprintf("Start install with timeout %s", client.Timeout.String()))
// TODO: support other options if required
_, err = client.RunWithContext(ctx, c, vals)
if err != nil {
utils.LogError(fmt.Sprintf("Error running chart install: %v", err))
return err
}
utils.LogInfo("Helm install complete")
return nil
}
func (h Helm) Test(ctx context.Context, namespace, release string) error {
utils.LogInfo(fmt.Sprintf("Execute helm test. namespace: %s, release: %s, args: %+v", namespace, release, h.args))
deadline, _ := ctx.Deadline()
client := action.NewReleaseTesting(h.config)
client.Namespace = namespace
client.Timeout = time.Until(deadline)
if client.Timeout <= 0 {
return errors.New("Helm test error : timeout has expired, please consider increasing the timeout using the my-chart-verifier timeout flag")
}
// TODO: support filter
_, err := client.Run(release)
if err != nil {
utils.LogError(fmt.Sprintf("Execute helm test. error %v", err))
return err
}
utils.LogInfo("Helm test complete")
return nil
}
func (h Helm) Uninstall(namespace, release string) error {
utils.LogInfo(fmt.Sprintf("Execute helm uninstall. namespace: %s, release: %s", namespace, release))
client := action.NewUninstall(h.config)
// TODO: support other options if required
_, err := client.Run(release)
if err != nil {
utils.LogError(fmt.Sprintf("Error from helm uninstall : %v", err))
return err
}
utils.LogInfo("Delete release complete")
return nil
}
func (h Helm) Upgrade(ctx context.Context, namespace, chart, release string) error {
utils.LogInfo(fmt.Sprintf("Execute helm upgrade. namespace: %s, release: %s chart: %s", namespace, release, chart))
client := action.NewUpgrade(h.config)
client.Namespace = namespace
client.ReuseValues = true
client.Wait = true
cp, err := client.ChartPathOptions.LocateChart(chart, h.envSettings)
if err != nil {
utils.LogError(fmt.Sprintf("Error LocateChart: %v", err))
return err
}
p := getter.All(h.envSettings)
valueOpts := &values.Options{}
vals, err := valueOpts.MergeValues(p)
if err != nil {
utils.LogError(fmt.Sprintf("Error MergeValues: %v", err))
return err
}
c, err := loader.Load(cp)
if err != nil {
utils.LogError(fmt.Sprintf("Error loading chart path: %v", err))
return err
}
// TODO: support other options if required
_, err = client.RunWithContext(ctx, release, c, vals)
if err != nil {
utils.LogError(fmt.Sprintf("Error running chart upgrade: %v", err))
return err
}
utils.LogInfo("Helm upgrade complete")
return nil
}