-
Notifications
You must be signed in to change notification settings - Fork 875
/
helm.go
104 lines (91 loc) · 3.33 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
package helm
import (
"encoding/json"
"fmt"
"time"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"github.com/pkg/errors"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
helmapi "github.com/oam-dev/kubevela/pkg/appfile/helm/flux2apis"
)
var (
// DefaultIntervalDuration is the interval that flux controller reconcile HelmRelease and HelmRepository
DefaultIntervalDuration = &metav1.Duration{Duration: 5 * time.Minute}
)
// RenderHelmReleaseAndHelmRepo constructs HelmRelease and HelmRepository in unstructured format
func RenderHelmReleaseAndHelmRepo(helmSpec *v1alpha2.Helm, compName, appName, ns string, values map[string]interface{}) (*unstructured.Unstructured, *unstructured.Unstructured, error) {
releaseSpec := &helmapi.HelmReleaseSpec{}
if err := json.Unmarshal(helmSpec.Release.Raw, releaseSpec); err != nil {
return nil, nil, err
}
if releaseSpec.Interval == nil {
releaseSpec.Interval = DefaultIntervalDuration
}
repoSpec := &helmapi.HelmRepositorySpec{}
if err := json.Unmarshal(helmSpec.Repository.Raw, repoSpec); err != nil {
return nil, nil, err
}
if repoSpec.Interval == nil {
repoSpec.Interval = DefaultIntervalDuration
}
// construct unstructured HelmRepository object
repoName := fmt.Sprintf("%s-%s", appName, compName)
helmRepo := generateUnstructuredObj(repoName, ns, helmapi.HelmRepositoryGVK)
if err := setSpecObjIntoUnstructuredObj(repoSpec, helmRepo); err != nil {
return nil, nil, errors.Wrap(err, "cannot set spec to HelmRepository")
}
// construct unstructured HelmRelease object
rlsName := fmt.Sprintf("%s-%s", appName, compName)
helmRelease := generateUnstructuredObj(rlsName, ns, helmapi.HelmReleaseGVK)
// construct HelmRelease chart values
chartValues := map[string]interface{}{}
if releaseSpec.Values != nil {
if err := json.Unmarshal(releaseSpec.Values.Raw, &chartValues); err != nil {
return nil, nil, errors.Wrap(err, "cannot get chart values")
}
}
for k, v := range values {
// override values with settings from application
chartValues[k] = v
}
if len(chartValues) > 0 {
// avoid an empty map
vJSON, err := json.Marshal(chartValues)
if err != nil {
return nil, nil, errors.Wrap(err, "cannot get chart values")
}
releaseSpec.Values = &apiextensionsv1.JSON{Raw: vJSON}
}
// reference HelmRepository by HelmRelease
releaseSpec.Chart.Spec.SourceRef = helmapi.CrossNamespaceObjectReference{
Kind: helmapi.HelmRepositoryKind,
Namespace: ns,
Name: repoName,
}
if err := setSpecObjIntoUnstructuredObj(releaseSpec, helmRelease); err != nil {
return nil, nil, errors.Wrap(err, "cannot set spec to HelmRelease")
}
return helmRelease, helmRepo, nil
}
func generateUnstructuredObj(name, ns string, gvk schema.GroupVersionKind) *unstructured.Unstructured {
u := &unstructured.Unstructured{}
u.SetGroupVersionKind(gvk)
u.SetName(name)
u.SetNamespace(ns)
return u
}
func setSpecObjIntoUnstructuredObj(spec interface{}, u *unstructured.Unstructured) error {
bts, err := json.Marshal(spec)
if err != nil {
return err
}
data := make(map[string]interface{})
if err := json.Unmarshal(bts, &data); err != nil {
return err
}
_ = unstructured.SetNestedMap(u.Object, data, "spec")
return nil
}