Restrict the cluster sync mode for the unjoin and unregister command

Signed-off-by: zhzhuang-zju <m17799853869@163.com>
This commit is contained in:
zhzhuang-zju 2025-02-06 10:27:49 +08:00
parent d80b7d4864
commit f751f9fe0d
4 changed files with 83 additions and 4 deletions

View File

@ -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"
@ -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

View File

@ -111,6 +111,34 @@ 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"},
@ -118,6 +146,16 @@ func TestRunUnJoinCluster(t *testing.T) {
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")
})

View File

@ -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"
@ -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
}
@ -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

View File

@ -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 {