You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by zh...@apache.org on 2024/12/24 10:44:59 UTC

(dubbo-kubernetes) branch master updated: [operator] Fix uninstalling panic v3

This is an automated email from the ASF dual-hosted git repository.

zhongxjian pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo-kubernetes.git


The following commit(s) were added to refs/heads/master by this push:
     new a01bbbc5 [operator] Fix uninstalling panic v3
a01bbbc5 is described below

commit a01bbbc5325f3e170f78604240f9082306bc7583
Author: mfordjody <11...@qq.com>
AuthorDate: Tue Dec 24 18:44:50 2024 +0800

    [operator] Fix uninstalling panic v3
---
 dubboctl/pkg/cli/context.go           |  2 +-
 operator/cmd/cluster/uninstall.go     | 13 ++++-----
 operator/pkg/install/installer.go     | 50 +++++++++++++++++++++++++++++++++--
 operator/pkg/manifest/manifest.go     | 11 ++++++++
 operator/pkg/manifest/name.go         |  1 +
 operator/pkg/uninstall/uninstaller.go | 15 ++++++-----
 operator/pkg/util/label.go            | 35 ++++++++++++++++++++++++
 7 files changed, 109 insertions(+), 18 deletions(-)

diff --git a/dubboctl/pkg/cli/context.go b/dubboctl/pkg/cli/context.go
index 4899570c..d12a8958 100644
--- a/dubboctl/pkg/cli/context.go
+++ b/dubboctl/pkg/cli/context.go
@@ -12,8 +12,8 @@ type instance struct {
 }
 
 type Context interface {
-	CLIClientWithRevision(rev string) (kube.CLIClient, error)
 	CLIClient() (kube.CLIClient, error)
+	CLIClientWithRevision(rev string) (kube.CLIClient, error)
 }
 
 func NewCLIContext(rootFlags *RootFlags) Context {
diff --git a/operator/cmd/cluster/uninstall.go b/operator/cmd/cluster/uninstall.go
index f32fb103..e1b5f52d 100644
--- a/operator/cmd/cluster/uninstall.go
+++ b/operator/cmd/cluster/uninstall.go
@@ -37,11 +37,10 @@ func UninstallCmd(ctx cli.Context) *cobra.Command {
 	rootArgs := &RootArgs{}
 	uiArgs := &uninstallArgs{}
 	uicmd := &cobra.Command{
-		Use:           "uninstall",
-		Short:         "Uninstall Dubbo related resources",
-		Long:          "The uninstall command will uninstall the dubbo cluster",
-		SilenceUsage:  true,
-		SilenceErrors: false,
+		Use:          "uninstall",
+		Short:        "Uninstall Dubbo related resources",
+		Long:         "The uninstall command will uninstall the dubbo cluster",
+		SilenceUsage: true,
 		Example: ` # Uninstall a single control plane by dop file
   dubboctl uninstall -f dop.yaml
   
@@ -69,13 +68,11 @@ func Uninstall(cmd *cobra.Command, ctx cli.Context, rootArgs *RootArgs, uiArgs *
 	cl := clog.NewConsoleLogger(cmd.OutOrStdout(), cmd.ErrOrStderr(), installerScope)
 	var kubeClient kube.CLIClient
 	var err error
-
+	kubeClient, err = ctx.CLIClientWithRevision("")
 	if err != nil {
 		return err
 	}
 
-	kubeClient, err = ctx.CLIClientWithRevision("")
-
 	pl := progress.NewInfo()
 	if uiArgs.purge && uiArgs.files != "" {
 		cl.LogAndPrint(PurgeWithRevisionOrOperatorSpecifiedWarning)
diff --git a/operator/pkg/install/installer.go b/operator/pkg/install/installer.go
index b6e542b3..9cadbbd4 100644
--- a/operator/pkg/install/installer.go
+++ b/operator/pkg/install/installer.go
@@ -16,6 +16,8 @@ import (
 	"github.com/apache/dubbo-kubernetes/pkg/util/slices"
 	"github.com/hashicorp/go-multierror"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	klabels "k8s.io/apimachinery/pkg/labels"
+	"k8s.io/apimachinery/pkg/selection"
 	"k8s.io/apimachinery/pkg/types"
 	"sync"
 )
@@ -96,6 +98,10 @@ func (i Installer) applyManifestSet(manifestSet manifest.ManifestSet) error {
 	manifests := manifestSet.Manifests
 	pi := i.ProgressInfo.NewComponent(componentNames)
 	for _, obj := range manifests {
+		obj, err := i.applyLabelsAndAnnotations(obj, componentNames)
+		if err != nil {
+			return err
+		}
 		if err := i.serverSideApply(obj); err != nil {
 			pi.ReportError(err.Error())
 			return err
@@ -126,6 +132,16 @@ func (i Installer) serverSideApply(obj manifest.Manifest) error {
 	return nil
 }
 
+func (i Installer) applyLabelsAndAnnotations(obj manifest.Manifest, cname string) (manifest.Manifest, error) {
+	for k, v := range getOwnerLabels(i.Values, cname) {
+		err := util.SetLabel(obj, k, v)
+		if err != nil {
+			return manifest.Manifest{}, err
+		}
+	}
+	return manifest.FromObject(obj.Unstructured)
+}
+
 func (i Installer) prune(manifests []manifest.ManifestSet) error {
 	if i.DryRun {
 		return nil
@@ -144,6 +160,14 @@ func (i Installer) prune(manifests []manifest.ManifestSet) error {
 		}
 	}
 
+	coreLabels := getOwnerLabels(i.Values, "")
+	selector := klabels.Set(coreLabels).AsSelectorPreValidated()
+	compReq, err := klabels.NewRequirement(manifest.DubboComponentLabel, selection.Exists, nil)
+	if err != nil {
+		return err
+	}
+	selector = selector.Add(*compReq)
+
 	var errs util.Errors
 	resources := uninstall.PrunedResourcesSchemas()
 	for _, gvk := range resources {
@@ -151,15 +175,22 @@ func (i Installer) prune(manifests []manifest.ManifestSet) error {
 		if err != nil {
 			return err
 		}
-		objs, err := dc.List(context.Background(), metav1.ListOptions{})
+		objs, err := dc.List(context.Background(), metav1.ListOptions{LabelSelector: selector.String()})
 		if objs == nil {
 			continue
 		}
-		for _, excluded := range excluded {
+		for comp, excluded := range excluded {
+			compLabels := klabels.SelectorFromSet(getOwnerLabels(i.Values, string(comp)))
 			for _, obj := range objs.Items {
 				if excluded.Contains(manifest.ObjectHash(&obj)) {
 					continue
 				}
+				if obj.GetLabels()[manifest.OwningResourceNotPruned] == "true" {
+					continue
+				}
+				if !compLabels.Matches(klabels.Set(obj.GetLabels())) {
+					continue
+				}
 				if err := uninstall.DeleteResource(i.Kube, i.DryRun, i.Logger, &obj); err != nil {
 					errs = append(errs, err)
 				}
@@ -182,3 +213,18 @@ func dependenciesChs() map[component.Name]chan struct{} {
 	}
 	return r
 }
+
+func getOwnerLabels(dop values.Map, c string) map[string]string {
+	labels := make(map[string]string)
+
+	if n := dop.GetPathString("metadata.name"); n != "" {
+		labels[manifest.OwningResourceName] = n
+	}
+	if n := dop.GetPathString("metadata.namespace"); n != "" {
+		labels[manifest.OwningResourceNamespace] = n
+	}
+	if c != "" {
+		labels[manifest.DubboComponentLabel] = c
+	}
+	return labels
+}
diff --git a/operator/pkg/manifest/manifest.go b/operator/pkg/manifest/manifest.go
index a08c49e9..3e22a4c6 100644
--- a/operator/pkg/manifest/manifest.go
+++ b/operator/pkg/manifest/manifest.go
@@ -41,6 +41,17 @@ func FromYAML(y []byte) (Manifest, error) {
 	return Manifest{Unstructured: us, Content: string(y)}, nil
 }
 
+func FromObject(us *unstructured.Unstructured) (Manifest, error) {
+	c, err := yaml.Marshal(us)
+	if err != nil {
+		return Manifest{}, err
+	}
+	return Manifest{
+		Unstructured: us,
+		Content:      string(c),
+	}, nil
+}
+
 func Parse(output []string) ([]Manifest, error) {
 	result := make([]Manifest, 0, len(output))
 	for _, m := range output {
diff --git a/operator/pkg/manifest/name.go b/operator/pkg/manifest/name.go
index 8d26cc4b..5dc0f7c4 100644
--- a/operator/pkg/manifest/name.go
+++ b/operator/pkg/manifest/name.go
@@ -4,4 +4,5 @@ const (
 	OwningResourceName      = "install.operator.dubbo.io/owning-resource"
 	OwningResourceNamespace = "install.operator.dubbo.io/owning-resource-namespace"
 	DubboComponentLabel     = "operator.dubbo.io/component"
+	OwningResourceNotPruned = "install.operator.dubbo.io/owning-resource-not-pruned"
 )
diff --git a/operator/pkg/uninstall/uninstaller.go b/operator/pkg/uninstall/uninstaller.go
index 54e87e96..00b6f49a 100644
--- a/operator/pkg/uninstall/uninstaller.go
+++ b/operator/pkg/uninstall/uninstaller.go
@@ -24,7 +24,7 @@ var (
 		gvk.CustomResourceDefinition.Kubernetes())
 )
 
-func GetPrunedResources(kcli kube.CLIClient, dopName, dopNamespace string, includeClusterResources bool) ([]*unstructured.UnstructuredList, error) {
+func GetPrunedResources(kc kube.CLIClient, dopName, dopNamespace string, includeClusterResources bool) ([]*unstructured.UnstructuredList, error) {
 	var usList []*unstructured.UnstructuredList
 	labels := make(map[string]string)
 	if dopName != "" {
@@ -44,7 +44,7 @@ func GetPrunedResources(kcli kube.CLIClient, dopName, dopNamespace string, inclu
 		if err != nil {
 			return nil, err
 		}
-		c, err := kcli.DynamicClientFor(g, nil, "")
+		c, err := kc.DynamicClientFor(g, nil, "")
 		if err != nil {
 			return nil, err
 		}
@@ -56,6 +56,7 @@ func GetPrunedResources(kcli kube.CLIClient, dopName, dopNamespace string, inclu
 			continue
 		}
 		usList = append(usList, result)
+
 	}
 	return usList, nil
 }
@@ -71,8 +72,8 @@ func PrunedResourcesSchemas() []schema.GroupVersionKind {
 
 func DeleteObjectsList(c kube.CLIClient, dryRun bool, log clog.Logger, objectsList []*unstructured.UnstructuredList) error {
 	var errs util.Errors
-	for _, ul := range objectsList {
-		for _, o := range ul.Items {
+	for _, ol := range objectsList {
+		for _, o := range ol.Items {
 			if err := DeleteResource(c, dryRun, log, &o); err != nil {
 				errs = append(errs, err)
 			}
@@ -81,14 +82,14 @@ func DeleteObjectsList(c kube.CLIClient, dryRun bool, log clog.Logger, objectsLi
 	return errs.ToErrors()
 }
 
-func DeleteResource(clt kube.CLIClient, dryRun bool, log clog.Logger, obj *unstructured.Unstructured) error {
+func DeleteResource(kc kube.CLIClient, dryRun bool, log clog.Logger, obj *unstructured.Unstructured) error {
 	name := fmt.Sprintf("%v/%s.%s", obj.GroupVersionKind(), obj.GetName(), obj.GetNamespace())
 	if dryRun {
 		log.LogAndPrintf("Not pruning object %s because of dry run.", name)
 		return nil
 	}
 
-	c, err := clt.DynamicClientFor(obj.GroupVersionKind(), obj, "")
+	c, err := kc.DynamicClientFor(obj.GroupVersionKind(), obj, "")
 	if err != nil {
 		return err
 	}
@@ -101,6 +102,6 @@ func DeleteResource(clt kube.CLIClient, dryRun bool, log clog.Logger, obj *unstr
 		return nil
 	}
 
-	log.LogAndPrintf("  Removed %s.", name)
+	log.LogAndPrintf(" ✔︎ Removed %s.", name)
 	return nil
 }
diff --git a/operator/pkg/util/label.go b/operator/pkg/util/label.go
new file mode 100644
index 00000000..307a5dc0
--- /dev/null
+++ b/operator/pkg/util/label.go
@@ -0,0 +1,35 @@
+// Copyright Istio Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package util
+
+import (
+	"k8s.io/apimachinery/pkg/api/meta"
+	"k8s.io/apimachinery/pkg/runtime"
+)
+
+// SetLabel is a helper function which sets the specified label and value on the specified object.
+func SetLabel(resource runtime.Object, label, value string) error {
+	resourceAccessor, err := meta.Accessor(resource)
+	if err != nil {
+		return err
+	}
+	labels := resourceAccessor.GetLabels()
+	if labels == nil {
+		labels = map[string]string{}
+	}
+	labels[label] = value
+	resourceAccessor.SetLabels(labels)
+	return nil
+}