Merge pull request #6081 from zhzhuang-zju/unjoin
Restrict the cluster sync mode for the unjoin and unregister command
This commit is contained in:
commit
80d3d9e007
|
@ -17,17 +17,21 @@ limitations under the License.
|
||||||
package unjoin
|
package unjoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/pflag"
|
"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"
|
kubeclient "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
"k8s.io/kubectl/pkg/util/templates"
|
"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"
|
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
cmdutil "github.com/karmada-io/karmada/pkg/karmadactl/util"
|
cmdutil "github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
@ -194,8 +198,20 @@ func (j *CommandUnjoinOption) RunUnJoinCluster(controlPlaneRestConfig, clusterCo
|
||||||
controlPlaneKarmadaClient := controlPlaneKarmadaClientBuilder(controlPlaneRestConfig)
|
controlPlaneKarmadaClient := controlPlaneKarmadaClientBuilder(controlPlaneRestConfig)
|
||||||
controlPlaneKubeClient := controlPlaneKubeClientBuilder(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
|
// 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 {
|
if err != nil {
|
||||||
klog.Errorf("Failed to delete cluster object. cluster name: %s, error: %v", j.ClusterName, err)
|
klog.Errorf("Failed to delete cluster object. cluster name: %s, error: %v", j.ClusterName, err)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -111,6 +111,34 @@ func TestRunUnJoinCluster(t *testing.T) {
|
||||||
wantErr bool
|
wantErr bool
|
||||||
errMsg string
|
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",
|
name: "RunUnJoinCluster_DeleteClusterObject_FailedToDeleteClusterObject",
|
||||||
unjoinOpts: &CommandUnjoinOption{ClusterName: "member1"},
|
unjoinOpts: &CommandUnjoinOption{ClusterName: "member1"},
|
||||||
|
@ -118,6 +146,16 @@ func TestRunUnJoinCluster(t *testing.T) {
|
||||||
clusterConfig: &rest.Config{},
|
clusterConfig: &rest.Config{},
|
||||||
karmadaClient: fakekarmadaclient.NewSimpleClientset(),
|
karmadaClient: fakekarmadaclient.NewSimpleClientset(),
|
||||||
prep: func(_ kubeclient.Interface, _ kubeclient.Interface, karmadaClient karmadaclientset.Interface, _ *CommandUnjoinOption) error {
|
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) {
|
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")
|
return true, nil, errors.New("unexpected error: encountered a network issue while deleting the clusters")
|
||||||
})
|
})
|
||||||
|
|
|
@ -35,6 +35,7 @@ import (
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
"k8s.io/kubectl/pkg/util/templates"
|
"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"
|
"github.com/karmada-io/karmada/pkg/apis/cluster/validation"
|
||||||
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
|
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"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.
|
// RunUnregisterCluster unregister the pull mode cluster from karmada.
|
||||||
func (j *CommandUnregisterOption) RunUnregisterCluster() error {
|
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 {
|
if j.DryRun {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -318,7 +331,7 @@ func (j *CommandUnregisterOption) RunUnregisterCluster() error {
|
||||||
// 1. delete the work object from the Karmada control plane
|
// 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.
|
// 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.
|
// 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 {
|
if err != nil {
|
||||||
klog.Errorf("Failed to delete works object. cluster name: %s, error: %v", j.ClusterName, err)
|
klog.Errorf("Failed to delete works object. cluster name: %s, error: %v", j.ClusterName, err)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -201,10 +201,22 @@ func TestCommandUnregisterOption_RunUnregisterCluster(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "cluster exist, but cluster resources not found",
|
name: "cluster exist, but cluster resources not found",
|
||||||
clusterObject: []runtime.Object{&clusterv1alpha1.Cluster{ObjectMeta: metav1.ObjectMeta{Name: clusterName}}},
|
clusterObject: []runtime.Object{&clusterv1alpha1.Cluster{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: clusterName},
|
||||||
|
Spec: clusterv1alpha1.ClusterSpec{SyncMode: clusterv1alpha1.Pull}},
|
||||||
|
},
|
||||||
clusterResources: []runtime.Object{},
|
clusterResources: []runtime.Object{},
|
||||||
wantErr: false,
|
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 {
|
for _, tt := range tests {
|
||||||
|
|
Loading…
Reference in New Issue