karmada/pkg/util/credential_test.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)
}
})
}
}