1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package helm
17
18 import (
19 "fmt"
20
21 "github.com/go-logr/logr"
22 "github.com/pkg/errors"
23 "helm.sh/helm/v3/pkg/action"
24 "helm.sh/helm/v3/pkg/chart"
25 "helm.sh/helm/v3/pkg/chartutil"
26 "helm.sh/helm/v3/pkg/kube"
27 "helm.sh/helm/v3/pkg/registry"
28 "helm.sh/helm/v3/pkg/release"
29 "helm.sh/helm/v3/pkg/storage"
30 "helm.sh/helm/v3/pkg/storage/driver"
31 "k8s.io/cli-runtime/pkg/genericclioptions"
32 )
33
34 type HelmClient struct {
35 restClientGetter genericclioptions.RESTClientGetter
36 logger logr.Logger
37 }
38
39 func NewHelmClient(restClientGetter genericclioptions.RESTClientGetter, logger logr.Logger) (*HelmClient, error) {
40 return &HelmClient{restClientGetter: restClientGetter, logger: logger}, nil
41 }
42
43 func (h HelmClient) spawnConfigurationWithNamespace(namespace string) (*action.Configuration, error) {
44 registryClient, err := registry.NewClient()
45 if err != nil {
46 return nil, errors.Wrap(err, "create helm registry client")
47 }
48 kubeclient := kube.New(h.restClientGetter)
49 if err != nil {
50 return nil, errors.Wrap(err, "create kubernetes client set")
51 }
52 clientset, err := kubeclient.Factory.KubernetesClientSet()
53 if err != nil {
54 return nil, errors.Wrap(err, "create kubernetes client set")
55 }
56 secretInterface := clientset.CoreV1().Secrets(namespace)
57 helmConfiguration := action.Configuration{
58 Releases: storage.Init(driver.NewSecrets(secretInterface)),
59 KubeClient: kubeclient,
60 Capabilities: chartutil.DefaultCapabilities,
61 RegistryClient: registryClient,
62 RESTClientGetter: h.restClientGetter,
63 Log: func(format string, v ...interface{}) {
64 h.logger.Info(fmt.Sprintf(format, v...))
65 },
66 }
67 return &helmConfiguration, nil
68 }
69
70 func (h *HelmClient) GetRelease(namespace string, releaseName string) (*release.Release, error) {
71 configurationWithNamespace, err := h.spawnConfigurationWithNamespace(namespace)
72 if err != nil {
73 return nil, errors.Wrap(err, "create helm configuration")
74 }
75 getAction := action.NewGet(configurationWithNamespace)
76 result, err := getAction.Run(releaseName)
77 if err != nil {
78 return nil, errors.Wrapf(err, "get release %s, in namespace %s", releaseName, namespace)
79 }
80 return result, nil
81 }
82
83 func (h *HelmClient) InstallRelease(namespace string, releaseName string, chart *chart.Chart, values map[string]interface{}) (*release.Release, error) {
84 configurationWithNamespace, err := h.spawnConfigurationWithNamespace(namespace)
85 if err != nil {
86 return nil, errors.Wrap(err, "create helm configuration")
87 }
88 actionInstall := action.NewInstall(configurationWithNamespace)
89 actionInstall.ReleaseName = releaseName
90 actionInstall.Namespace = namespace
91 actionInstall.CreateNamespace = true
92 result, err := actionInstall.Run(chart, values)
93 if err != nil {
94 return nil, errors.Wrapf(err, "install release %s, with chart %s, with values %v", releaseName, chart.Metadata.Name, values)
95 }
96 return result, nil
97 }
98
99 func (h *HelmClient) UpgradeRelease(namespace string, releaseName string, chart *chart.Chart, values map[string]interface{}) (*release.Release, error) {
100 configurationWithNamespace, err := h.spawnConfigurationWithNamespace(namespace)
101 if err != nil {
102 return nil, errors.Wrap(err, "create helm configuration")
103 }
104 actionUpgrade := action.NewUpgrade(configurationWithNamespace)
105 actionUpgrade.Namespace = namespace
106 result, err := actionUpgrade.Run(releaseName, chart, values)
107 if err != nil {
108 return nil, errors.Wrapf(err, "upgrade release %s, with chart %s, with values %v", releaseName, chart.Metadata.Name, values)
109 }
110 return result, nil
111 }
112
113 func (h *HelmClient) UninstallRelease(namespace string, releaseName string) (*release.UninstallReleaseResponse, error) {
114 configurationWithNamespace, err := h.spawnConfigurationWithNamespace(namespace)
115 if err != nil {
116 return nil, errors.Wrap(err, "create helm configuration")
117 }
118 uninstallAction := action.NewUninstall(configurationWithNamespace)
119 response, err := uninstallAction.Run(releaseName)
120 if err != nil {
121 return nil, errors.Wrapf(err, "uninstall release %s, in namespace %s", releaseName, namespace)
122 }
123 return response, nil
124 }
125