forked from knechtionscoding/keel
/
implementer.go
131 lines (111 loc) · 3.65 KB
/
implementer.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
package helm3
import (
"os"
"strings"
"time"
"helm.sh/helm/v3/pkg/chart"
log "github.com/sirupsen/logrus"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/release"
// "helm.sh/helm/v3/pkg/cli"
"k8s.io/cli-runtime/pkg/genericclioptions"
)
// to do:
// * update to latest chart package
// * udpate the paramateres for the function
// #595 - DefaultUpdateTimeout is in ns
// Per https://pkg.go.dev/helm.sh/helm/v3/pkg/action#Upgrade
const DefaultUpdateTimeout = 5 * time.Minute
// Implementer - generic helm implementer used to abstract actual implementation
type Implementer interface {
// ListReleases(opts ...helm.ReleaseListOption) ([]*release.Release, error)
ListReleases() ([]*release.Release, error)
UpdateReleaseFromChart(rlsName string, chart *chart.Chart, vals map[string]string, namespace string, opts ...bool) (*release.Release, error)
}
// Helm3Implementer - actual helm3 implementer
type Helm3Implementer struct {
// actionConfig *action.Configuration
HelmDriver string
KubeContext string
KubeToken string
KubeAPIServer string
}
// NewHelm3Implementer - get new helm implementer
func NewHelm3Implementer() *Helm3Implementer {
return &Helm3Implementer{
HelmDriver: os.Getenv("HELM_DRIVER"),
KubeContext: os.Getenv("HELM_KUBECONTEXT"),
KubeToken: os.Getenv("HELM_KUBETOKEN"),
KubeAPIServer: os.Getenv("HELM_KUBEAPISERVER"),
}
}
// ListReleases - list available releases
func (i *Helm3Implementer) ListReleases() ([]*release.Release, error) {
actionConfig := i.generateConfig("")
client := action.NewList(actionConfig)
results, err := client.Run()
if err != nil {
log.WithFields(log.Fields{
"error": err,
}).Fatal("helm3: failed to list release")
return []*release.Release{}, err
}
return results, nil
}
// UpdateReleaseFromChart - update release from chart
func (i *Helm3Implementer) UpdateReleaseFromChart(rlsName string, chart *chart.Chart, vals map[string]string, namespace string, opts ...bool) (*release.Release, error) {
actionConfig := i.generateConfig(namespace)
client := action.NewUpgrade(actionConfig)
client.Namespace = namespace
client.Force = true
client.Timeout = DefaultUpdateTimeout
client.ReuseValues = true
// set reuse values to false if currentRelease.config is nil (temp fix for bug in chartutil.coalesce v3.1.2)
if len(opts) == 1 && opts[0] {
client.ReuseValues = false
}
convertedVals := convertToInterface(vals)
// returns the new release
results, err := client.Run(rlsName, chart, convertedVals)
if err != nil {
log.WithFields(log.Fields{
"error": err,
}).Fatal("helm3: failed to update release from chart")
return nil, err
}
return results, err
}
func (i *Helm3Implementer) generateConfig(namespace string) *action.Configuration {
// settings := cli.New()
config := &genericclioptions.ConfigFlags{
Namespace: &namespace,
Context: &i.KubeContext,
BearerToken: &i.KubeToken,
APIServer: &i.KubeAPIServer,
}
actionConfig := &action.Configuration{}
if err := actionConfig.Init(config, namespace, i.HelmDriver, log.Printf); err != nil {
log.Printf("%+v", err)
os.Exit(1)
}
return actionConfig
}
// convert map[string]string to map[string]interface
// converts:
// map[string]string{"image.tag": "0.1.0"}
// to:
// map[string]interface{"image": map[string]interface{"tag": "0.1.0"}}
func convertToInterface(values map[string]string) map[string]interface{} {
converted := make(map[string]interface{})
for key, value := range values {
keys := strings.SplitN(key, ".", 2)
if len(keys) == 1 {
converted[key] = value
} else if len(keys) == 2 {
converted[keys[0]] = convertToInterface(map[string]string{
keys[1]: value,
})
}
}
return converted
}