From c5d9f69c9c0400946a397190d38aa42862a09dce Mon Sep 17 00:00:00 2001 From: shivin Date: Wed, 19 Mar 2025 05:05:06 +0530 Subject: [PATCH] Fix: removing detached clusters from resource trackers (#6728) * removing detached clusters from resource trackers Signed-off-by: Pushparaj Shetty KS Signed-off-by: Pushparaj Shetty K S * resolve merge conflicts Signed-off-by: Pushparaj Shetty K S * resolved code conflicts Signed-off-by: Chaitanya Reddy Onteddu Signed-off-by: Pushparaj Shetty K S * update TestGetAddonStatus test case Signed-off-by: Chaitanya Reddy Onteddu --------- Signed-off-by: Pushparaj Shetty KS Signed-off-by: Pushparaj Shetty K S Signed-off-by: Chaitanya Reddy Onteddu Co-authored-by: Shivin Gopalani Co-authored-by: Pushparaj Shetty K S --- pkg/addon/addon_test.go | 7 ++++++- pkg/addon/helper.go | 14 ++++++++++++- pkg/multicluster/cluster_management.go | 28 ++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/pkg/addon/addon_test.go b/pkg/addon/addon_test.go index 42cf74604..6d66ef4f4 100644 --- a/pkg/addon/addon_test.go +++ b/pkg/addon/addon_test.go @@ -378,7 +378,8 @@ func TestGetAddonStatus(t *testing.T) { }) cli := test.MockClient{ - MockGet: getFunc, + MockGet: getFunc, + MockList: listFunc, } cases := []struct { @@ -410,6 +411,10 @@ func TestGetAddonStatus(t *testing.T) { } } +func listFunc(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error { + return nil +} + func TestGetAddonVersionMeetSystemRequirement(t *testing.T) { server := httptest.NewServer(helmHandler) defer server.Close() diff --git a/pkg/addon/helper.go b/pkg/addon/helper.go index 34705d7e0..d58f96104 100644 --- a/pkg/addon/helper.go +++ b/pkg/addon/helper.go @@ -123,6 +123,14 @@ func EnableAddonByLocalDir(ctx context.Context, name string, dir string, cli cli // GetAddonStatus is general func for cli and apiServer get addon status func GetAddonStatus(ctx context.Context, cli client.Client, name string) (Status, error) { var addonStatus Status + joinedClusters, err := multicluster.NewClusterClient(cli).List(ctx) + if err != nil { + return addonStatus, errors.Wrap(err, "failed to list registered clusters") + } + var joinedClusterMap = make(map[string]bool) + for _, joinedCluster := range joinedClusters.Items { + joinedClusterMap[joinedCluster.Name] = true + } app, err := FetchAddonRelatedApp(ctx, cli, name) if err != nil { @@ -143,8 +151,12 @@ func GetAddonStatus(ctx context.Context, cli client.Client, name string) (Status r.Cluster = multicluster.ClusterLocalName } // TODO(wonderflow): we should collect all the necessary information as observability, currently we only collect cluster name - clusters[r.Cluster] = make(map[string]interface{}) + // If cluster is not registered in KubeVela then skip it. + if joinedClusterMap[r.Cluster] { + clusters[r.Cluster] = make(map[string]interface{}) + } } + addonStatus.Clusters = clusters if app.Status.Workflow != nil && app.Status.Workflow.Suspend { diff --git a/pkg/multicluster/cluster_management.go b/pkg/multicluster/cluster_management.go index 9dfc00959..1cf93ab33 100644 --- a/pkg/multicluster/cluster_management.go +++ b/pkg/multicluster/cluster_management.go @@ -44,6 +44,7 @@ import ( ocmclusterv1 "open-cluster-management.io/api/cluster/v1" "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/pkg/utils" cmdutil "github.com/oam-dev/kubevela/pkg/utils/util" ) @@ -486,6 +487,9 @@ func (op DetachClusterManagedClusterKubeConfigPathOption) ApplyToArgs(args *Deta // DetachCluster detach cluster by name, if cluster is using by application, it will return error func DetachCluster(ctx context.Context, cli client.Client, clusterName string, options ...DetachClusterOption) error { + if err := removeClusterFromResourceTrackers(ctx, cli, clusterName); err != nil { + return fmt.Errorf("error in removing cluster references from resourcetrackers: %w", err) + } args := newDetachClusterArgs(options...) if clusterName == ClusterLocalName { return ErrReservedLocalClusterName @@ -612,6 +616,30 @@ func getMutableClusterSecret(ctx context.Context, c client.Client, clusterName s return clusterSecret, nil } +// removeClusterFromResourceTrackers removes cluster references from all resource trackers. +func removeClusterFromResourceTrackers(ctx context.Context, cli client.Client, clusterName string) error { + rts := v1beta1.ResourceTrackerList{} + if err := cli.List(ctx, &rts); err != nil { + return fmt.Errorf("unable to list resourcetrackers due to error: %w", err) + } + for i := range rts.Items { + managedResources := rts.Items[i].Spec.ManagedResources + var result []v1beta1.ManagedResource + for _, mr := range managedResources { + if mr.ClusterObjectReference.Cluster != clusterName { + result = append(result, mr) + } + } + if len(rts.Items[i].Spec.ManagedResources) != len(result) { + rts.Items[i].Spec.ManagedResources = result + if err := cli.Update(ctx, &rts.Items[i]); err != nil { + return fmt.Errorf("error in updating resourcetracker %s: %w", rts.Items[i].Name, err) + } + } + } + return nil +} + func getTokenFromExec(execConfig *clientcmdapi.ExecConfig) (string, error) { // #nosec G204 -- This is intentionally running an exec command with user-provided input // The execConfig comes from the kubeconfig which should be trusted in this context