257 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			257 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Go
		
	
	
	
package util
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"reflect"
 | 
						|
	"testing"
 | 
						|
	"time"
 | 
						|
 | 
						|
	corev1 "k8s.io/api/core/v1"
 | 
						|
	apierrors "k8s.io/apimachinery/pkg/api/errors"
 | 
						|
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						|
	"k8s.io/apimachinery/pkg/util/wait"
 | 
						|
	"k8s.io/client-go/kubernetes"
 | 
						|
	"k8s.io/client-go/kubernetes/fake"
 | 
						|
	"k8s.io/client-go/rest"
 | 
						|
 | 
						|
	clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
 | 
						|
	"github.com/karmada-io/karmada/pkg/util/names"
 | 
						|
)
 | 
						|
 | 
						|
func TestObtainCredentialsFromMemberCluster(t *testing.T) {
 | 
						|
	type args struct {
 | 
						|
		clusterKubeClient kubernetes.Interface
 | 
						|
		opts              ClusterRegisterOption
 | 
						|
		aop               func(t *testing.T, clusterKubeClient kubernetes.Interface) func()
 | 
						|
	}
 | 
						|
	tests := []struct {
 | 
						|
		name    string
 | 
						|
		args    args
 | 
						|
		want    *corev1.Secret
 | 
						|
		want1   *corev1.Secret
 | 
						|
		wantErr bool
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			name: "disable report secret",
 | 
						|
			args: args{
 | 
						|
				opts: ClusterRegisterOption{
 | 
						|
					ClusterNamespace: "karmada-cluster",
 | 
						|
					ClusterName:      "member1",
 | 
						|
					ReportSecrets:    []string{KubeImpersonator},
 | 
						|
					DryRun:           false,
 | 
						|
				},
 | 
						|
				aop: func(t *testing.T, clusterKubeClient kubernetes.Interface) func() {
 | 
						|
					stopChan := make(chan struct{})
 | 
						|
					go func(clusterKubeClient kubernetes.Interface) {
 | 
						|
						_ = wait.PollUntil(1*time.Second, func() (done bool, err error) {
 | 
						|
							impersonationSA, err := clusterKubeClient.CoreV1().ServiceAccounts("karmada-cluster").Get(context.TODO(), names.GenerateServiceAccountName("impersonator"), metav1.GetOptions{})
 | 
						|
							if err != nil {
 | 
						|
								t.Logf("get sa failed, err: %v", err)
 | 
						|
								return false, nil
 | 
						|
							}
 | 
						|
							impersonatorSecret := &corev1.Secret{
 | 
						|
								ObjectMeta: metav1.ObjectMeta{Namespace: "karmada-cluster", Name: impersonationSA.Name},
 | 
						|
								Type:       corev1.SecretTypeServiceAccountToken,
 | 
						|
								Data: map[string][]byte{
 | 
						|
									"token": []byte(`impersonatorSecret-token-value`),
 | 
						|
								},
 | 
						|
							}
 | 
						|
							impersonationSA.Secrets = []corev1.ObjectReference{{Kind: "Secret", Namespace: impersonatorSecret.Namespace, Name: impersonatorSecret.Name}}
 | 
						|
							_, _ = clusterKubeClient.CoreV1().ServiceAccounts(impersonationSA.Namespace).Update(context.TODO(), impersonationSA, metav1.UpdateOptions{})
 | 
						|
							_, err = clusterKubeClient.CoreV1().Secrets(impersonatorSecret.Namespace).Create(context.TODO(), impersonatorSecret, metav1.CreateOptions{})
 | 
						|
							if err != nil && apierrors.IsAlreadyExists(err) {
 | 
						|
								_, _ = clusterKubeClient.CoreV1().Secrets(impersonatorSecret.Namespace).Update(context.TODO(), impersonatorSecret, metav1.UpdateOptions{})
 | 
						|
								t.Logf("secret exists and update it")
 | 
						|
							}
 | 
						|
							t.Log("create secret successfully")
 | 
						|
							return true, nil
 | 
						|
						}, stopChan)
 | 
						|
					}(clusterKubeClient)
 | 
						|
					return func() {
 | 
						|
						close(stopChan)
 | 
						|
					}
 | 
						|
				},
 | 
						|
			},
 | 
						|
			want:  nil,
 | 
						|
			want1: &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Namespace: "karmada-cluster", Name: names.GenerateServiceAccountName("impersonator")}, Type: corev1.SecretTypeServiceAccountToken, Data: map[string][]byte{"token": []byte(`impersonatorSecret-token-value`)}},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "report secret enabled",
 | 
						|
			args: args{
 | 
						|
				opts: ClusterRegisterOption{
 | 
						|
					ClusterNamespace: "karmada-cluster",
 | 
						|
					ClusterName:      "member1",
 | 
						|
					ReportSecrets:    []string{KubeImpersonator, KubeCredentials},
 | 
						|
					DryRun:           false,
 | 
						|
				},
 | 
						|
				aop: func(t *testing.T, clusterKubeClient kubernetes.Interface) func() {
 | 
						|
					stopChan := make(chan struct{})
 | 
						|
					go func(clusterKubeClient kubernetes.Interface) {
 | 
						|
						_ = wait.PollUntil(1*time.Second, func() (done bool, err error) {
 | 
						|
							impersonationSA, err := clusterKubeClient.CoreV1().ServiceAccounts("karmada-cluster").Get(context.TODO(), names.GenerateServiceAccountName("impersonator"), metav1.GetOptions{})
 | 
						|
							if err != nil {
 | 
						|
								t.Logf("create impersonationSA failed, err:%v", err)
 | 
						|
								return false, nil
 | 
						|
							}
 | 
						|
							impersonatorSecret := &corev1.Secret{
 | 
						|
								ObjectMeta: metav1.ObjectMeta{Namespace: "karmada-cluster", Name: impersonationSA.Name},
 | 
						|
								Type:       corev1.SecretTypeServiceAccountToken,
 | 
						|
								Data: map[string][]byte{
 | 
						|
									"token": []byte(`impersonatorSecret-token-value`),
 | 
						|
								},
 | 
						|
							}
 | 
						|
							impersonationSA.Secrets = []corev1.ObjectReference{{Kind: "Secret", Namespace: impersonatorSecret.Namespace, Name: impersonatorSecret.Name}}
 | 
						|
							_, _ = clusterKubeClient.CoreV1().ServiceAccounts(impersonationSA.Namespace).Update(context.TODO(), impersonationSA, metav1.UpdateOptions{})
 | 
						|
							_, err = clusterKubeClient.CoreV1().Secrets(impersonatorSecret.Namespace).Create(context.TODO(), impersonatorSecret, metav1.CreateOptions{})
 | 
						|
							if err != nil && apierrors.IsAlreadyExists(err) {
 | 
						|
								_, _ = clusterKubeClient.CoreV1().Secrets(impersonatorSecret.Namespace).Update(context.TODO(), impersonatorSecret, metav1.UpdateOptions{})
 | 
						|
								t.Log("impersonatorSecret exists and update it")
 | 
						|
							}
 | 
						|
							t.Log("create impersonatorSecret successfully")
 | 
						|
 | 
						|
							serviceAccountObj, err := clusterKubeClient.CoreV1().ServiceAccounts("karmada-cluster").Get(context.TODO(), names.GenerateServiceAccountName("member1"), metav1.GetOptions{})
 | 
						|
							if err != nil {
 | 
						|
								t.Logf("get sa failed, err:%v", err)
 | 
						|
								return false, nil
 | 
						|
							}
 | 
						|
							clusterSecret := &corev1.Secret{
 | 
						|
								ObjectMeta: metav1.ObjectMeta{Namespace: "karmada-cluster", Name: serviceAccountObj.Name},
 | 
						|
								Type:       corev1.SecretTypeServiceAccountToken,
 | 
						|
								Data: map[string][]byte{
 | 
						|
									"token": []byte(`clusterSecret-token-value`),
 | 
						|
								},
 | 
						|
							}
 | 
						|
							serviceAccountObj.Secrets = []corev1.ObjectReference{{Kind: "Secret", Namespace: clusterSecret.Namespace, Name: clusterSecret.Name}}
 | 
						|
							_, _ = clusterKubeClient.CoreV1().ServiceAccounts(serviceAccountObj.Namespace).Update(context.TODO(), serviceAccountObj, metav1.UpdateOptions{})
 | 
						|
							_, err = clusterKubeClient.CoreV1().Secrets(clusterSecret.Namespace).Create(context.TODO(), clusterSecret, metav1.CreateOptions{})
 | 
						|
							if err != nil && apierrors.IsAlreadyExists(err) {
 | 
						|
								_, _ = clusterKubeClient.CoreV1().Secrets(clusterSecret.Namespace).Update(context.TODO(), clusterSecret, metav1.UpdateOptions{})
 | 
						|
								t.Log("secret exist and update it")
 | 
						|
							}
 | 
						|
							t.Log("create clusterSecret successfully")
 | 
						|
							return true, nil
 | 
						|
						}, stopChan)
 | 
						|
					}(clusterKubeClient)
 | 
						|
					return func() {
 | 
						|
						close(stopChan)
 | 
						|
					}
 | 
						|
				},
 | 
						|
			},
 | 
						|
			want: &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Namespace: "karmada-cluster", Name: names.GenerateServiceAccountName("member1")}, Type: corev1.SecretTypeServiceAccountToken, Data: map[string][]byte{
 | 
						|
				"token": []byte(`clusterSecret-token-value`),
 | 
						|
			}},
 | 
						|
			want1: &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Namespace: "karmada-cluster", Name: names.GenerateServiceAccountName("impersonator")}, Type: corev1.SecretTypeServiceAccountToken, Data: map[string][]byte{
 | 
						|
				"token": []byte(`impersonatorSecret-token-value`),
 | 
						|
			}},
 | 
						|
		},
 | 
						|
	}
 | 
						|
	for _, tt := range tests {
 | 
						|
		t.Run(tt.name, func(t *testing.T) {
 | 
						|
			tt.args.clusterKubeClient = fake.NewSimpleClientset()
 | 
						|
			if tt.args.aop != nil {
 | 
						|
				cancel := tt.args.aop(t, tt.args.clusterKubeClient)
 | 
						|
				defer cancel()
 | 
						|
			}
 | 
						|
			got, got1, err := ObtainCredentialsFromMemberCluster(tt.args.clusterKubeClient, tt.args.opts)
 | 
						|
			if (err != nil) != tt.wantErr {
 | 
						|
				t.Errorf("ObtainCredentialsFromMemberCluster() error = %v, wantErr %v", err, tt.wantErr)
 | 
						|
				return
 | 
						|
			}
 | 
						|
			if !reflect.DeepEqual(got, tt.want) {
 | 
						|
				t.Errorf("ObtainCredentialsFromMemberCluster() got = %v, want %v", got, tt.want)
 | 
						|
			}
 | 
						|
			if !reflect.DeepEqual(got1, tt.want1) {
 | 
						|
				t.Errorf("ObtainCredentialsFromMemberCluster() got1 = %v, want %v", got1, tt.want1)
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestRegisterClusterInControllerPlane(t *testing.T) {
 | 
						|
	fakeClient := fake.NewSimpleClientset()
 | 
						|
	type args struct {
 | 
						|
		opts                             ClusterRegisterOption
 | 
						|
		controlPlaneKubeClient           kubernetes.Interface
 | 
						|
		generateClusterInControllerPlane generateClusterInControllerPlaneFunc
 | 
						|
	}
 | 
						|
	tests := []struct {
 | 
						|
		name    string
 | 
						|
		args    args
 | 
						|
		wantErr bool
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			name: "report secret not enabled",
 | 
						|
			args: args{
 | 
						|
				opts: ClusterRegisterOption{
 | 
						|
					ClusterNamespace:   "karmada-cluster",
 | 
						|
					ClusterName:        "member1",
 | 
						|
					ReportSecrets:      []string{"KubeImpersonator"},
 | 
						|
					DryRun:             false,
 | 
						|
					ControlPlaneConfig: &rest.Config{},
 | 
						|
					ClusterConfig:      &rest.Config{},
 | 
						|
					ImpersonatorSecret: corev1.Secret{
 | 
						|
						ObjectMeta: metav1.ObjectMeta{Namespace: "karmada-cluster", Name: names.GenerateImpersonationSecretName("member1")},
 | 
						|
						Data:       map[string][]byte{clusterv1alpha1.SecretTokenKey: []byte("impersonator-secret-token-value")},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				controlPlaneKubeClient: fakeClient,
 | 
						|
				generateClusterInControllerPlane: func(opts ClusterRegisterOption) (*clusterv1alpha1.Cluster, error) {
 | 
						|
					clusterObj := &clusterv1alpha1.Cluster{ObjectMeta: metav1.ObjectMeta{Name: opts.ClusterName}}
 | 
						|
					clusterObj.Spec.SyncMode = clusterv1alpha1.Pull
 | 
						|
					clusterObj.Spec.APIEndpoint = opts.ClusterAPIEndpoint
 | 
						|
					clusterObj.Spec.ProxyURL = opts.ProxyServerAddress
 | 
						|
					clusterObj.Spec.ImpersonatorSecretRef = &clusterv1alpha1.LocalSecretReference{
 | 
						|
						Namespace: opts.ImpersonatorSecret.Namespace,
 | 
						|
						Name:      opts.ImpersonatorSecret.Name,
 | 
						|
					}
 | 
						|
					return clusterObj, nil
 | 
						|
				},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "enable report secret",
 | 
						|
			args: args{
 | 
						|
				opts: ClusterRegisterOption{
 | 
						|
					ClusterNamespace:   "karmada-cluster",
 | 
						|
					ClusterName:        "member1",
 | 
						|
					ReportSecrets:      []string{"KubeImpersonator", "KubeCredentials"},
 | 
						|
					DryRun:             false,
 | 
						|
					ControlPlaneConfig: &rest.Config{},
 | 
						|
					ClusterConfig:      &rest.Config{},
 | 
						|
					Secret: corev1.Secret{
 | 
						|
						ObjectMeta: metav1.ObjectMeta{Namespace: "karmada-cluster", Name: "member1"},
 | 
						|
						Data:       map[string][]byte{"ca.crt": []byte("ca.crt-values"), clusterv1alpha1.SecretTokenKey: []byte(`secret-token-value`)},
 | 
						|
					},
 | 
						|
					ImpersonatorSecret: corev1.Secret{
 | 
						|
						ObjectMeta: metav1.ObjectMeta{Namespace: "karmada-cluster", Name: names.GenerateImpersonationSecretName("member1")},
 | 
						|
						Data:       map[string][]byte{clusterv1alpha1.SecretTokenKey: []byte(`impersonator-secret-token-value`)},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				controlPlaneKubeClient: fakeClient,
 | 
						|
				generateClusterInControllerPlane: func(opts ClusterRegisterOption) (*clusterv1alpha1.Cluster, error) {
 | 
						|
					clusterObj := &clusterv1alpha1.Cluster{ObjectMeta: metav1.ObjectMeta{Name: opts.ClusterName}}
 | 
						|
					clusterObj.Spec.SyncMode = clusterv1alpha1.Push
 | 
						|
					clusterObj.Spec.APIEndpoint = opts.ClusterAPIEndpoint
 | 
						|
					clusterObj.Spec.ProxyURL = opts.ProxyServerAddress
 | 
						|
					clusterObj.Spec.ImpersonatorSecretRef = &clusterv1alpha1.LocalSecretReference{
 | 
						|
						Namespace: opts.ImpersonatorSecret.Namespace,
 | 
						|
						Name:      opts.ImpersonatorSecret.Name,
 | 
						|
					}
 | 
						|
					clusterObj.Spec.SecretRef = &clusterv1alpha1.LocalSecretReference{
 | 
						|
						Namespace: opts.Secret.Namespace,
 | 
						|
						Name:      opts.Secret.Name,
 | 
						|
					}
 | 
						|
					return clusterObj, nil
 | 
						|
				},
 | 
						|
			},
 | 
						|
		},
 | 
						|
	}
 | 
						|
	for _, tt := range tests {
 | 
						|
		t.Run(tt.name, func(t *testing.T) {
 | 
						|
			if err := RegisterClusterInControllerPlane(tt.args.opts, tt.args.controlPlaneKubeClient, tt.args.generateClusterInControllerPlane); (err != nil) != tt.wantErr {
 | 
						|
				t.Errorf("RegisterClusterInControllerPlane() error = %v, wantErr %v", err, tt.wantErr)
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 |