Skip to content

Commit d912d7d

Browse files
authored
chore: install new 1.0 addon failed when existing 0.9 addon chart (#594)
1 parent 02962c4 commit d912d7d

2 files changed

Lines changed: 116 additions & 120 deletions

File tree

pkg/cmd/addon/install.go

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,13 @@ import (
2727
"strings"
2828

2929
"github.com/Masterminds/semver/v3"
30+
kbappsv1 "github.com/apecloud/kubeblocks/apis/apps/v1"
31+
"github.com/apecloud/kubeblocks/pkg/constant"
3032
"github.com/spf13/cobra"
33+
helmaction "helm.sh/helm/v3/pkg/action"
34+
"helm.sh/helm/v3/pkg/chart/loader"
35+
"helm.sh/helm/v3/pkg/releaseutil"
36+
apierrors "k8s.io/apimachinery/pkg/api/errors"
3137
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3238
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
3339
"k8s.io/apimachinery/pkg/runtime"
@@ -37,13 +43,16 @@ import (
3743
"k8s.io/client-go/kubernetes"
3844
cmdutil "k8s.io/kubectl/pkg/cmd/util"
3945
"k8s.io/kubectl/pkg/util/templates"
46+
"sigs.k8s.io/yaml"
4047

4148
extensionsv1alpha1 "github.com/apecloud/kubeblocks/apis/extensions/v1alpha1"
4249

50+
"github.com/apecloud/kbcli/pkg/cluster"
4351
clusterCmd "github.com/apecloud/kbcli/pkg/cmd/cluster"
4452
"github.com/apecloud/kbcli/pkg/printer"
4553
"github.com/apecloud/kbcli/pkg/types"
4654
"github.com/apecloud/kbcli/pkg/util"
55+
"github.com/apecloud/kbcli/pkg/util/helm"
4756
)
4857

4958
var addonInstallExample = templates.Examples(`
@@ -136,6 +145,7 @@ func newInstallCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra
136145
o.name = args[0]
137146
util.CheckErr(o.Complete())
138147
util.CheckErr(o.Validate())
148+
util.CheckErr(o.process09ClusterDefAndComponentVersions())
139149
util.CheckErr(o.Run(f, streams))
140150
// avoid unnecessary messages for upgrade
141151
fmt.Fprintf(o.Out, "addon %s installed successfully\n", o.name)
@@ -304,3 +314,106 @@ func validateVersion(annotations, kbVersion string) (bool, error) {
304314
validate, _ := constraint.Validate(v)
305315
return validate, nil
306316
}
317+
318+
func (o *installOption) process09ClusterDefAndComponentVersions() error {
319+
kbDeploys, err := util.GetKBDeploys(o.Client, util.KubeblocksAppComponent, metav1.NamespaceAll)
320+
if err != nil || len(kbDeploys) < 2 {
321+
return err
322+
}
323+
var newKBNamespace string
324+
for _, v := range kbDeploys {
325+
if strings.HasPrefix(v.Labels[constant.AppVersionLabelKey], "1.0") {
326+
newKBNamespace = v.Namespace
327+
break
328+
}
329+
}
330+
// 1. get manifests from the helm repo
331+
chartsDownloader, err := helm.NewDownloader(helm.NewConfig(newKBNamespace, "", "", false))
332+
if err != nil {
333+
return err
334+
}
335+
// DownloadTo can't specify the saved name, so download it to TempDir and rename it when copy
336+
chartPath, _, err := chartsDownloader.DownloadTo(o.addon.Spec.Helm.ChartLocationURL, "", cluster.CliChartsCacheDir)
337+
if err != nil {
338+
return err
339+
}
340+
// 2. overwrite the spec of ClusterDefinition and ComponentVersion with the new version
341+
actionCfg, err := helm.NewActionConfig(helm.NewConfig(newKBNamespace, "", "", false))
342+
if err != nil {
343+
return err
344+
}
345+
chart, err := loader.Load(chartPath)
346+
if err != nil {
347+
return err
348+
}
349+
renderer := helmaction.NewInstall(actionCfg)
350+
renderer.ReleaseName = o.addon.Name + "for-upgrade"
351+
renderer.Namespace = newKBNamespace
352+
renderer.DryRun = true
353+
renderer.Replace = true
354+
renderer.ClientOnly = true
355+
valuesMap := map[string]interface{}{}
356+
if o.addon.Spec.Helm != nil {
357+
for _, v := range o.addon.Spec.Helm.InstallValues.SetValues {
358+
keyValues := strings.Split(v, "=")
359+
if len(keyValues) != 2 {
360+
return fmt.Errorf("invalid install value: %s", v)
361+
}
362+
valuesMap[keyValues[0]] = keyValues[1]
363+
}
364+
}
365+
release, err := renderer.Run(chart, valuesMap)
366+
if err != nil {
367+
return err
368+
}
369+
370+
updateObject := func(obj runtime.Object, gvr schema.GroupVersionResource) error {
371+
unstructuredObj := obj.(*unstructured.Unstructured)
372+
targetObj, err := o.Dynamic.Resource(gvr).Namespace("").Get(context.TODO(), unstructuredObj.GetName(), metav1.GetOptions{})
373+
if err != nil {
374+
if apierrors.IsNotFound(err) {
375+
return nil
376+
}
377+
return err
378+
}
379+
annotations := targetObj.GetAnnotations()
380+
annotations[constant.CRDAPIVersionAnnotationKey] = kbappsv1.GroupVersion.String()
381+
annotations["meta.helm.sh/release-name"] = "kb-addon-" + o.addon.Name
382+
annotations["meta.helm.sh/release-namespace"] = newKBNamespace
383+
targetObj.SetAnnotations(annotations)
384+
targetObj.Object["spec"] = unstructuredObj.Object["spec"]
385+
if _, err = o.Dynamic.Resource(gvr).Namespace("").Update(context.TODO(), targetObj, metav1.UpdateOptions{}); err != nil {
386+
return err
387+
}
388+
return nil
389+
}
390+
manifests := releaseutil.SplitManifests(release.Manifest)
391+
for _, manifest := range manifests {
392+
393+
// convert yaml to json
394+
jsonData, err := yaml.YAMLToJSON([]byte(manifest))
395+
if err != nil {
396+
return err
397+
}
398+
// check if jsonData is empty or null
399+
if len(jsonData) == 0 || string(jsonData) == "null" {
400+
continue
401+
}
402+
// get resource gvk
403+
obj, gvk, err := unstructured.UnstructuredJSONScheme.Decode(jsonData, nil, nil)
404+
if err != nil {
405+
return err
406+
}
407+
switch gvk.Kind {
408+
case types.KindClusterDef:
409+
if err = updateObject(obj, types.ClusterDefGVR()); err != nil {
410+
return err
411+
}
412+
case types.KindComponentVersion:
413+
if err = updateObject(obj, types.ComponentVersionsGVR()); err != nil {
414+
return err
415+
}
416+
}
417+
}
418+
return nil
419+
}

pkg/cmd/addon/upgrade.go

Lines changed: 3 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -26,28 +26,15 @@ import (
2626
"strings"
2727

2828
"github.com/Masterminds/semver/v3"
29-
kbappsv1 "github.com/apecloud/kubeblocks/apis/apps/v1"
3029
extensionsv1alpha1 "github.com/apecloud/kubeblocks/apis/extensions/v1alpha1"
31-
"github.com/apecloud/kubeblocks/pkg/constant"
3230
"github.com/spf13/cobra"
33-
helmaction "helm.sh/helm/v3/pkg/action"
34-
"helm.sh/helm/v3/pkg/chart/loader"
35-
"helm.sh/helm/v3/pkg/releaseutil"
36-
apierrors "k8s.io/apimachinery/pkg/api/errors"
3731
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
38-
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
39-
"k8s.io/apimachinery/pkg/runtime"
40-
"k8s.io/apimachinery/pkg/runtime/schema"
4132
ktypes "k8s.io/apimachinery/pkg/types"
4233
"k8s.io/cli-runtime/pkg/genericiooptions"
4334
cmdutil "k8s.io/kubectl/pkg/cmd/util"
4435
"k8s.io/kubectl/pkg/util/templates"
45-
"sigs.k8s.io/yaml"
4636

47-
"github.com/apecloud/kbcli/pkg/cluster"
4837
"github.com/apecloud/kbcli/pkg/printer"
49-
"github.com/apecloud/kbcli/pkg/util/helm"
50-
5138
"github.com/apecloud/kbcli/pkg/types"
5239
"github.com/apecloud/kbcli/pkg/util"
5340
)
@@ -110,7 +97,9 @@ func newUpgradeCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra
11097
o.name = args[0]
11198
util.CheckErr(o.Complete())
11299
util.CheckErr(o.Validate())
113-
util.CheckErr(o.process09ClusterDefAndComponentVersions())
100+
if strings.HasPrefix(o.currentVersion, "0.9") {
101+
util.CheckErr(o.process09ClusterDefAndComponentVersions())
102+
}
114103
util.CheckErr(o.Run(f, streams))
115104
},
116105
}
@@ -185,109 +174,3 @@ func (o *upgradeOption) Run(f cmdutil.Factory, streams genericiooptions.IOStream
185174
}
186175
return err
187176
}
188-
189-
func (o *upgradeOption) process09ClusterDefAndComponentVersions() error {
190-
kbDeploys, err := util.GetKBDeploys(o.Client, util.KubeblocksAppComponent, metav1.NamespaceAll)
191-
if err != nil || len(kbDeploys) < 2 {
192-
return err
193-
}
194-
if !strings.HasPrefix(o.currentVersion, "0.9") {
195-
return nil
196-
}
197-
var newKBNamespace string
198-
for _, v := range kbDeploys {
199-
if strings.HasPrefix(v.Labels[constant.AppVersionLabelKey], "1.0") {
200-
newKBNamespace = v.Namespace
201-
break
202-
}
203-
}
204-
// 1. get manifests from the helm repo
205-
chartsDownloader, err := helm.NewDownloader(helm.NewConfig(newKBNamespace, "", "", false))
206-
if err != nil {
207-
return err
208-
}
209-
// DownloadTo can't specify the saved name, so download it to TempDir and rename it when copy
210-
chartPath, _, err := chartsDownloader.DownloadTo(o.addon.Spec.Helm.ChartLocationURL, "", cluster.CliChartsCacheDir)
211-
if err != nil {
212-
return err
213-
}
214-
// 2. overwrite the spec of ClusterDefinition and ComponentVersion with the new version
215-
actionCfg, err := helm.NewActionConfig(helm.NewConfig(newKBNamespace, "", "", false))
216-
if err != nil {
217-
return err
218-
}
219-
chart, err := loader.Load(chartPath)
220-
if err != nil {
221-
return err
222-
}
223-
renderer := helmaction.NewInstall(actionCfg)
224-
renderer.ReleaseName = o.addon.Name + "for-upgrade"
225-
renderer.Namespace = newKBNamespace
226-
renderer.DryRun = true
227-
renderer.Replace = true
228-
renderer.ClientOnly = true
229-
valuesMap := map[string]interface{}{}
230-
if o.addon.Spec.Helm != nil {
231-
for _, v := range o.addon.Spec.Helm.InstallValues.SetValues {
232-
keyValues := strings.Split(v, "=")
233-
if len(keyValues) != 2 {
234-
return fmt.Errorf("invalid install value: %s", v)
235-
}
236-
valuesMap[keyValues[0]] = keyValues[1]
237-
}
238-
}
239-
release, err := renderer.Run(chart, valuesMap)
240-
if err != nil {
241-
return err
242-
}
243-
244-
updateObject := func(obj runtime.Object, gvr schema.GroupVersionResource) error {
245-
unstructuredObj := obj.(*unstructured.Unstructured)
246-
targetObj, err := o.Dynamic.Resource(gvr).Namespace("").Get(context.TODO(), unstructuredObj.GetName(), metav1.GetOptions{})
247-
if err != nil {
248-
if apierrors.IsNotFound(err) {
249-
return nil
250-
}
251-
return err
252-
}
253-
annotations := targetObj.GetAnnotations()
254-
annotations[constant.CRDAPIVersionAnnotationKey] = kbappsv1.GroupVersion.String()
255-
annotations["meta.helm.sh/release-name"] = "kb-addon-" + o.addon.Name
256-
annotations["meta.helm.sh/release-namespace"] = newKBNamespace
257-
targetObj.SetAnnotations(annotations)
258-
targetObj.Object["spec"] = unstructuredObj.Object["spec"]
259-
if _, err = o.Dynamic.Resource(gvr).Namespace("").Update(context.TODO(), targetObj, metav1.UpdateOptions{}); err != nil {
260-
return err
261-
}
262-
return nil
263-
}
264-
manifests := releaseutil.SplitManifests(release.Manifest)
265-
for _, manifest := range manifests {
266-
267-
// convert yaml to json
268-
jsonData, err := yaml.YAMLToJSON([]byte(manifest))
269-
if err != nil {
270-
return err
271-
}
272-
// check if jsonData is empty or null
273-
if len(jsonData) == 0 || string(jsonData) == "null" {
274-
continue
275-
}
276-
// get resource gvk
277-
obj, gvk, err := unstructured.UnstructuredJSONScheme.Decode(jsonData, nil, nil)
278-
if err != nil {
279-
return err
280-
}
281-
switch gvk.Kind {
282-
case types.KindClusterDef:
283-
if err = updateObject(obj, types.ClusterDefGVR()); err != nil {
284-
return err
285-
}
286-
case types.KindComponentVersion:
287-
if err = updateObject(obj, types.ComponentVersionsGVR()); err != nil {
288-
return err
289-
}
290-
}
291-
}
292-
return nil
293-
}

0 commit comments

Comments
 (0)