Skip to content

Commit

Permalink
Merge pull request #6081 from zhzhuang-zju/unjoin
Browse files Browse the repository at this point in the history
Restrict the cluster sync mode for the unjoin and unregister command
  • Loading branch information
karmada-bot authored Feb 14, 2025
2 parents e75306d + f751f9f commit 80d3d9e
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 4 deletions.
18 changes: 17 additions & 1 deletion pkg/karmadactl/unjoin/unjoin.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,21 @@ limitations under the License.
package unjoin

import (
"context"
"errors"
"fmt"
"time"

"github.com/spf13/cobra"
"github.com/spf13/pflag"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kubeclient "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/klog/v2"
"k8s.io/kubectl/pkg/util/templates"

clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
"github.com/karmada-io/karmada/pkg/karmadactl/options"
cmdutil "github.com/karmada-io/karmada/pkg/karmadactl/util"
Expand Down Expand Up @@ -194,8 +198,20 @@ func (j *CommandUnjoinOption) RunUnJoinCluster(controlPlaneRestConfig, clusterCo
controlPlaneKarmadaClient := controlPlaneKarmadaClientBuilder(controlPlaneRestConfig)
controlPlaneKubeClient := controlPlaneKubeClientBuilder(controlPlaneRestConfig)

target, err := controlPlaneKarmadaClient.ClusterV1alpha1().Clusters().Get(context.TODO(), j.ClusterName, metav1.GetOptions{})
if apierrors.IsNotFound(err) {
return fmt.Errorf("no cluster object %s found in karmada control Plane", j.ClusterName)
}
if err != nil {
klog.Errorf("Failed to get cluster object. cluster name: %s, error: %v", j.ClusterName, err)
return err
}
if target.Spec.SyncMode == clusterv1alpha1.Pull {
return fmt.Errorf("cluster %s is a %s mode member cluster, please use command `unregister` if you want to continue unregistering the cluster", j.ClusterName, target.Spec.SyncMode)
}

// delete the cluster object in host cluster that associates the unjoining cluster
err := cmdutil.DeleteClusterObject(controlPlaneKubeClient, controlPlaneKarmadaClient, j.ClusterName, j.Wait, j.DryRun, j.forceDeletion)
err = cmdutil.DeleteClusterObject(controlPlaneKubeClient, controlPlaneKarmadaClient, j.ClusterName, j.Wait, j.DryRun, j.forceDeletion)
if err != nil {
klog.Errorf("Failed to delete cluster object. cluster name: %s, error: %v", j.ClusterName, err)
return err
Expand Down
38 changes: 38 additions & 0 deletions pkg/karmadactl/unjoin/unjoin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,51 @@ func TestRunUnJoinCluster(t *testing.T) {
wantErr bool
errMsg string
}{
{
name: "RunUnJoinCluster_DeleteClusterObject_PullModeMemberCluster",
unjoinOpts: &CommandUnjoinOption{ClusterName: "member1"},
controlPlaneRestConfig: &rest.Config{},
clusterConfig: &rest.Config{},
karmadaClient: fakekarmadaclient.NewSimpleClientset(),
prep: func(_ kubeclient.Interface, _ kubeclient.Interface, karmadaClient karmadaclientset.Interface, _ *CommandUnjoinOption) error {
karmadaClient.(*fakekarmadaclient.Clientset).Fake.PrependReactor("get", "clusters", func(coretesting.Action) (bool, runtime.Object, error) {
return true, &clusterv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{
Name: "member1",
},
Spec: clusterv1alpha1.ClusterSpec{
SyncMode: clusterv1alpha1.Pull,
},
}, nil
})
controlPlaneKarmadaClientBuilder = func(*rest.Config) karmadaclientset.Interface {
return karmadaClient
}
return nil
},
verify: func(kubeclient.Interface, kubeclient.Interface, karmadaclientset.Interface, *CommandUnjoinOption) error {
return nil
},
wantErr: true,
errMsg: "cluster member1 is a Pull mode member cluster, please use command `unregister` if you want to continue unregistering the cluster",
},
{
name: "RunUnJoinCluster_DeleteClusterObject_FailedToDeleteClusterObject",
unjoinOpts: &CommandUnjoinOption{ClusterName: "member1"},
controlPlaneRestConfig: &rest.Config{},
clusterConfig: &rest.Config{},
karmadaClient: fakekarmadaclient.NewSimpleClientset(),
prep: func(_ kubeclient.Interface, _ kubeclient.Interface, karmadaClient karmadaclientset.Interface, _ *CommandUnjoinOption) error {
karmadaClient.(*fakekarmadaclient.Clientset).Fake.PrependReactor("get", "clusters", func(coretesting.Action) (bool, runtime.Object, error) {
return true, &clusterv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{
Name: "member1",
},
Spec: clusterv1alpha1.ClusterSpec{
SyncMode: clusterv1alpha1.Push,
},
}, nil
})
karmadaClient.(*fakekarmadaclient.Clientset).Fake.PrependReactor("delete", "clusters", func(coretesting.Action) (bool, runtime.Object, error) {
return true, nil, errors.New("unexpected error: encountered a network issue while deleting the clusters")
})
Expand Down
15 changes: 14 additions & 1 deletion pkg/karmadactl/unregister/unregister.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"k8s.io/klog/v2"
"k8s.io/kubectl/pkg/util/templates"

clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
"github.com/karmada-io/karmada/pkg/apis/cluster/validation"
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
"github.com/karmada-io/karmada/pkg/karmadactl/options"
Expand Down Expand Up @@ -310,6 +311,18 @@ func (j *CommandUnregisterOption) getKarmadaAgentConfig(agent *appsv1.Deployment

// RunUnregisterCluster unregister the pull mode cluster from karmada.
func (j *CommandUnregisterOption) RunUnregisterCluster() error {
target, err := j.ControlPlaneClient.ClusterV1alpha1().Clusters().Get(context.TODO(), j.ClusterName, metav1.GetOptions{})
if apierrors.IsNotFound(err) {
return fmt.Errorf("no cluster object %s found in karmada control Plane", j.ClusterName)
}
if err != nil {
klog.Errorf("Failed to get cluster object. cluster name: %s, error: %v", j.ClusterName, err)
return err
}
if target.Spec.SyncMode == clusterv1alpha1.Push {
return fmt.Errorf("cluster %s is a %s mode member cluster, please use command `unjoin` if you want to continue unjoining the cluster", j.ClusterName, target.Spec.SyncMode)
}

if j.DryRun {
return nil
}
Expand All @@ -318,7 +331,7 @@ func (j *CommandUnregisterOption) RunUnregisterCluster() error {
// 1. delete the work object from the Karmada control plane
// When deleting a cluster, the deletion triggers the removal of executionSpace, which can lead to the deletion of RBAC roles related to work.
// Therefore, the deletion of work should be performed before deleting the cluster.
err := cmdutil.EnsureWorksDeleted(j.ControlPlaneClient, names.GenerateExecutionSpaceName(j.ClusterName), j.Wait)
err = cmdutil.EnsureWorksDeleted(j.ControlPlaneClient, names.GenerateExecutionSpaceName(j.ClusterName), j.Wait)
if err != nil {
klog.Errorf("Failed to delete works object. cluster name: %s, error: %v", j.ClusterName, err)
return err
Expand Down
16 changes: 14 additions & 2 deletions pkg/karmadactl/unregister/unregister_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,23 @@ func TestCommandUnregisterOption_RunUnregisterCluster(t *testing.T) {
wantErr: true,
},
{
name: "cluster exist, but cluster resources not found",
clusterObject: []runtime.Object{&clusterv1alpha1.Cluster{ObjectMeta: metav1.ObjectMeta{Name: clusterName}}},
name: "cluster exist, but cluster resources not found",
clusterObject: []runtime.Object{&clusterv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{Name: clusterName},
Spec: clusterv1alpha1.ClusterSpec{SyncMode: clusterv1alpha1.Pull}},
},
clusterResources: []runtime.Object{},
wantErr: false,
},
{
name: "push mode member cluster",
clusterObject: []runtime.Object{&clusterv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{Name: clusterName},
Spec: clusterv1alpha1.ClusterSpec{SyncMode: clusterv1alpha1.Push}},
},
clusterResources: []runtime.Object{},
wantErr: true,
},
}

for _, tt := range tests {
Expand Down

0 comments on commit 80d3d9e

Please sign in to comment.