Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: support to upgrade addon to 1.0 version #494

Merged
merged 3 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions pkg/cmd/addon/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,15 +241,18 @@ func (o *installOption) Validate() error {
fmt.Fprint(o.Out, printer.BoldYellow("Warning: --force flag will skip version checks, which may result in the cluster not running correctly.\n"))
return nil
}

if o.addon.Annotations == nil || len(o.addon.Annotations[types.KBVersionValidateAnnotationKey]) == 0 {
fmt.Fprint(o.Out, printer.BoldYellow(fmt.Sprintf(`Warning: The addon %s is missing annotations to validate KubeBlocks versions.
It will automatically skip version checks, which may result in the cluster not running correctly.
`, o.name)))
} else if ok, err = validateVersion(o.addon.Annotations[types.KBVersionValidateAnnotationKey], v.KubeBlocks); err == nil && !ok {
return fmt.Errorf("KubeBlocks version %s does not meet the requirements \"%s\" for addon installation\nUse --force option to skip this check", v.KubeBlocks, o.addon.Annotations[types.KBVersionValidateAnnotationKey])
} else {
kbVersions := strings.Split(v.KubeBlocks, ",")
for _, kbVersion := range kbVersions {
if ok, err = validateVersion(o.addon.Annotations[types.KBVersionValidateAnnotationKey], kbVersion); err == nil && !ok {
return fmt.Errorf("KubeBlocks version %s does not meet the requirements \"%s\" for addon installation\nUse --force option to skip this check", v.KubeBlocks, o.addon.Annotations[types.KBVersionValidateAnnotationKey])
}
}
}

return err
}

Expand Down
39 changes: 39 additions & 0 deletions pkg/cmd/addon/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@ import (
"context"
"encoding/json"
"fmt"
"strings"

"github.com/Masterminds/semver/v3"
"github.com/apecloud/dbctl/constant"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
ktypes "k8s.io/apimachinery/pkg/types"
"k8s.io/cli-runtime/pkg/genericiooptions"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
Expand Down Expand Up @@ -98,6 +101,7 @@ func newUpgradeCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra
o.name = args[0]
util.CheckErr(o.Complete())
util.CheckErr(o.Validate())
util.CheckErr(o.takeOver09AddonGlobalResources())
util.CheckErr(o.Run(f, streams))
},
}
Expand All @@ -111,6 +115,41 @@ func newUpgradeCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra
cmd.Flags().StringVar(&o.path, "path", "", "specify the local path contains addon CRs and needs to be specified when operating offline")
return cmd
}
func (o *upgradeOption) takeOver09AddonGlobalResources() error {
kbDeploys, err := util.GetKBDeploys(o.Client, util.KubeblocksAppComponent, metav1.NamespaceAll)
if err != nil || len(kbDeploys) < 2 {
return err
}
if !strings.HasPrefix(o.version, "1.0") {
return nil
}
var newKBNamespace string
for _, v := range kbDeploys {
if strings.HasPrefix(v.Labels[constant.AppVersionLabelKey], "1.0") {
newKBNamespace = v.Namespace
break
}
}
selector := metav1.ListOptions{
LabelSelector: fmt.Sprintf("%s=%s", constant.AppNameLabelKey, o.name),
}
takeOverRelease := func(gvr schema.GroupVersionResource) error {
cdList, err := o.Dynamic.Resource(gvr).Namespace("").List(context.TODO(), selector)
if err != nil {
return err
}
for _, v := range cdList.Items {
if err = util.SetHelmOwner(o.Dynamic, gvr, newKBNamespace, []string{v.GetName()}); err != nil {
return err
}
}
return nil
}
if err := takeOverRelease(types.ClusterDefGVR()); err != nil {
return err
}
return takeOverRelease(types.ComponentVersionsGVR())
}

func (o *upgradeOption) Complete() error {
if err := o.installOption.Complete(); err != nil {
Expand Down
21 changes: 4 additions & 17 deletions pkg/cmd/kubeblocks/install_1.0.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,9 @@ import (
"helm.sh/helm/v3/pkg/cli/values"
appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
k8stypes "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/apecloud/kbcli/pkg/spinner"
"github.com/apecloud/kbcli/pkg/types"
Expand Down Expand Up @@ -167,20 +165,9 @@ func (o *InstallOptions) stopDeployment(s spinner.Interface, deploy *appsv1.Depl

func (o *InstallOptions) setGlobalResourcesHelmOwner() error {
fmt.Fprintf(o.Out, "Change the release owner for the global resources\n")
setHelmOwner := func(gvr schema.GroupVersionResource, names []string) error {
patchOP := fmt.Sprintf(`[{"op": "replace", "path": "/metadata/annotations/meta.helm.sh~1release-name", "value": "%s"}`+
`,{"op": "replace", "path": "/metadata/annotations/meta.helm.sh~1release-namespace", "value": "%s"}]`, types.KubeBlocksChartName, o.HelmCfg.Namespace())
for _, name := range names {
if _, err := o.Dynamic.Resource(gvr).Namespace("").Patch(context.TODO(), name,
k8stypes.JSONPatchType, []byte(patchOP), metav1.PatchOptions{}); client.IgnoreNotFound(err) != nil {
return err
}
}
return nil
}

// update ClusterRoles
if err := setHelmOwner(types.ClusterRoleGVR(), []string{
if err := util.SetHelmOwner(o.Dynamic, types.ClusterRoleGVR(), o.HelmCfg.Namespace(), []string{
"kubeblocks-cluster-pod-role",
types.KubeBlocksChartName,
fmt.Sprintf("%s-cluster-editor-role", types.KubeBlocksChartName),
Expand All @@ -205,7 +192,7 @@ func (o *InstallOptions) setGlobalResourcesHelmOwner() error {
return err
}
// update Addons
if err := setHelmOwner(types.AddonGVR(), []string{
if err := util.SetHelmOwner(o.Dynamic, types.AddonGVR(), o.HelmCfg.Namespace(), []string{
"apecloud-mysql", "etcd", "kafka", "llm",
"mongodb", "mysql", "postgresql", "pulsar",
"qdrant", "redis", "alertmanager-webhook-adaptor",
Expand All @@ -216,12 +203,12 @@ func (o *InstallOptions) setGlobalResourcesHelmOwner() error {
return err
}
// update StorageProviders
if err := setHelmOwner(types.StorageProviderGVR(), []string{
if err := util.SetHelmOwner(o.Dynamic, types.StorageProviderGVR(), o.HelmCfg.Namespace(), []string{
"cos", "ftp", "gcs-s3comp", "minio", "nfs",
"obs", "oss", "pvc", "s3",
}); err != nil {
return err
}
// update BackupRepo
return setHelmOwner(types.BackupRepoGVR(), []string{fmt.Sprintf("%s-backuprepo", types.KubeBlocksChartName)})
return util.SetHelmOwner(o.Dynamic, types.BackupRepoGVR(), o.HelmCfg.Namespace(), []string{fmt.Sprintf("%s-backuprepo", types.KubeBlocksChartName)})
}
12 changes: 12 additions & 0 deletions pkg/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -1350,3 +1350,15 @@ func GetClusterNameFromArgsOrFlag(cmd *cobra.Command, args []string) string {
}
return ""
}

func SetHelmOwner(dynamicClient dynamic.Interface, gvr schema.GroupVersionResource, namespace string, names []string) error {
patchOP := fmt.Sprintf(`[{"op": "replace", "path": "/metadata/annotations/meta.helm.sh~1release-name", "value": "%s"}`+
`,{"op": "replace", "path": "/metadata/annotations/meta.helm.sh~1release-namespace", "value": "%s"}]`, types.KubeBlocksChartName, namespace)
for _, name := range names {
if _, err := dynamicClient.Resource(gvr).Namespace("").Patch(context.TODO(), name,
k8sapitypes.JSONPatchType, []byte(patchOP), metav1.PatchOptions{}); client.IgnoreNotFound(err) != nil {
return err
}
}
return nil
}
Loading