karmada/pkg/util/membercluster_client_test.go

501 lines
16 KiB
Go

package util
import (
"context"
"io"
"net/http"
"net/http/httptest"
"reflect"
"testing"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"sigs.k8s.io/controller-runtime/pkg/client"
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
"github.com/karmada-io/karmada/pkg/util/gclient"
)
// copy from go/src/net/http/internal/testcert/testcert.go
var testCA = []byte(`-----BEGIN CERTIFICATE-----
MIIDOTCCAiGgAwIBAgIQSRJrEpBGFc7tNb1fb5pKFzANBgkqhkiG9w0BAQsFADAS
MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEA6Gba5tHV1dAKouAaXO3/ebDUU4rvwCUg/CNaJ2PT5xLD4N1Vcb8r
bFSW2HXKq+MPfVdwIKR/1DczEoAGf/JWQTW7EgzlXrCd3rlajEX2D73faWJekD0U
aUgz5vtrTXZ90BQL7WvRICd7FlEZ6FPOcPlumiyNmzUqtwGhO+9ad1W5BqJaRI6P
YfouNkwR6Na4TzSj5BrqUfP0FwDizKSJ0XXmh8g8G9mtwxOSN3Ru1QFc61Xyeluk
POGKBV/q6RBNklTNe0gI8usUMlYyoC7ytppNMW7X2vodAelSu25jgx2anj9fDVZu
h7AXF5+4nJS4AAt0n1lNY7nGSsdZas8PbQIDAQABo4GIMIGFMA4GA1UdDwEB/wQE
AwICpDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
DgQWBBStsdjh3/JCXXYlQryOrL4Sh7BW5TAuBgNVHREEJzAlggtleGFtcGxlLmNv
bYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAxWGI
5NhpF3nwwy/4yB4i/CwwSpLrWUa70NyhvprUBC50PxiXav1TeDzwzLx/o5HyNwsv
cxv3HdkLW59i/0SlJSrNnWdfZ19oTcS+6PtLoVyISgtyN6DpkKpdG1cOkW3Cy2P2
+tK/tKHRP1Y/Ra0RiDpOAmqn0gCOFGz8+lqDIor/T7MTpibL3IxqWfPrvfVRHL3B
grw/ZQTTIVjjh4JBSW3WyWgNo/ikC1lrVxzl4iPUGptxT36Cr7Zk2Bsg0XqwbOvK
5d+NTDREkSnUbie4GeutujmX3Dsx88UiV6UY/4lHJa6I5leHUNOHahRbpbWeOfs/
WkBKOclmOV2xlTVuPw==
-----END CERTIFICATE-----`)
func TestNewClusterClientSet(t *testing.T) {
type args struct {
clusterName string
client client.Client
clientOption *ClientOption
}
tests := []struct {
name string
args args
wantErr bool
}{
{
name: "cluster not found",
args: args{
clusterName: "test",
client: fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).Build(),
clientOption: nil,
},
wantErr: true,
},
{
name: "APIEndpoint is empty",
args: args{
clusterName: "test",
client: fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).
WithObjects(newCluster("test")).Build(),
clientOption: nil,
},
wantErr: true,
},
{
name: "SecretRef is empty",
args: args{
clusterName: "test",
client: fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).
WithObjects(withAPIEndPoint(newCluster("test"), "https://127.0.0.1")).Build(),
clientOption: nil,
},
wantErr: true,
},
{
name: "Secret not found",
args: args{
clusterName: "test",
client: fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(
&clusterv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{Name: "test"},
Spec: clusterv1alpha1.ClusterSpec{
APIEndpoint: "https://127.0.0.1",
SecretRef: &clusterv1alpha1.LocalSecretReference{Namespace: "default", Name: "secret1"},
},
}).Build(),
clientOption: nil,
},
wantErr: true,
},
{
name: "token not found",
args: args{
clusterName: "test",
client: fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(
&clusterv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{Name: "test"},
Spec: clusterv1alpha1.ClusterSpec{
APIEndpoint: "https://127.0.0.1",
SecretRef: &clusterv1alpha1.LocalSecretReference{Namespace: "ns1", Name: "secret1"},
},
},
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{Namespace: "ns1", Name: "secret1"},
}).Build(),
clientOption: nil,
},
wantErr: true,
},
{
name: "CA data is set",
args: args{
clusterName: "test",
client: fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(
&clusterv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{Name: "test"},
Spec: clusterv1alpha1.ClusterSpec{
APIEndpoint: "https://127.0.0.1",
SecretRef: &clusterv1alpha1.LocalSecretReference{Namespace: "ns1", Name: "secret1"},
},
},
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{Namespace: "ns1", Name: "secret1"},
Data: map[string][]byte{clusterv1alpha1.SecretTokenKey: []byte("token"), clusterv1alpha1.SecretCADataKey: testCA},
}).Build(),
clientOption: &ClientOption{QPS: 100, Burst: 200},
},
wantErr: false,
},
{
name: "skip TLS verification",
args: args{
clusterName: "test",
client: fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(
&clusterv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{Name: "test"},
Spec: clusterv1alpha1.ClusterSpec{
APIEndpoint: "https://127.0.0.1",
SecretRef: &clusterv1alpha1.LocalSecretReference{Namespace: "ns1", Name: "secret1"},
InsecureSkipTLSVerification: true,
},
},
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{Namespace: "ns1", Name: "secret1"},
Data: map[string][]byte{clusterv1alpha1.SecretTokenKey: []byte("token")},
}).Build(),
clientOption: &ClientOption{QPS: 100, Burst: 200},
},
wantErr: false,
},
{
name: "ProxyURL is error",
args: args{
clusterName: "test",
client: fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(
&clusterv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{Name: "test"},
Spec: clusterv1alpha1.ClusterSpec{
APIEndpoint: "https://127.0.0.1",
SecretRef: &clusterv1alpha1.LocalSecretReference{Namespace: "ns1", Name: "secret1"},
ProxyURL: "://",
},
},
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{Namespace: "ns1", Name: "secret1"},
Data: map[string][]byte{clusterv1alpha1.SecretTokenKey: []byte("token"), clusterv1alpha1.SecretCADataKey: testCA}}).Build(),
clientOption: &ClientOption{QPS: 100, Burst: 200},
},
wantErr: true,
},
{
name: "ProxyURL is set",
args: args{
clusterName: "test",
client: fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(
&clusterv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{Name: "test"},
Spec: clusterv1alpha1.ClusterSpec{
APIEndpoint: "https://127.0.0.1",
SecretRef: &clusterv1alpha1.LocalSecretReference{Namespace: "ns1", Name: "secret1"},
ProxyURL: "http://1.1.1.1",
},
},
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{Namespace: "ns1", Name: "secret1"},
Data: map[string][]byte{clusterv1alpha1.SecretTokenKey: []byte("token"), clusterv1alpha1.SecretCADataKey: testCA},
}).Build(),
clientOption: &ClientOption{QPS: 100, Burst: 200},
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := NewClusterClientSet(tt.args.clusterName, tt.args.client, tt.args.clientOption)
if (err != nil) != tt.wantErr {
t.Errorf("NewClusterClientSet() error = %v, wantErr %v", err, tt.wantErr)
return
}
if err != nil {
return
}
if got == nil {
t.Error("NewClusterClientSet() got nil")
return
}
if got.ClusterName != tt.args.clusterName {
t.Errorf("NewClusterClientSet() got.ClusterName = %v, want %v", got.ClusterName, tt.args.clusterName)
return
}
if got.KubeClient == nil {
t.Error("NewClusterClientSet() got.KubeClient got nil")
return
}
})
}
}
func TestNewClusterClientSet_ClientWorks(t *testing.T) {
s := httptest.NewTLSServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.Header().Add("Content-Type", "application/json")
_, _ = io.WriteString(rw, `
{
"apiVersion": "v1",
"kind": "Node",
"metadata": {
"name": "foo"
}
}`)
}))
defer s.Close()
const clusterName = "test"
hostClient := fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(
&clusterv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{Name: clusterName},
Spec: clusterv1alpha1.ClusterSpec{
APIEndpoint: s.URL,
SecretRef: &clusterv1alpha1.LocalSecretReference{Namespace: "ns1", Name: "secret1"},
},
},
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{Namespace: "ns1", Name: "secret1"},
Data: map[string][]byte{clusterv1alpha1.SecretTokenKey: []byte("token"), clusterv1alpha1.SecretCADataKey: testCA},
}).Build()
clusterClient, err := NewClusterClientSet(clusterName, hostClient, nil)
if err != nil {
t.Error(err)
return
}
got, err := clusterClient.KubeClient.CoreV1().Nodes().Get(context.TODO(), "foo", metav1.GetOptions{})
if err != nil {
t.Error(err)
return
}
want := &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
},
}
if !reflect.DeepEqual(got, want) {
t.Errorf("got = %#v, want %#v", got, want)
}
}
func TestNewClusterDynamicClientSet(t *testing.T) {
type args struct {
clusterName string
client client.Client
}
tests := []struct {
name string
args args
wantErr bool
}{
{
name: "cluster not found",
args: args{
clusterName: "test",
client: fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).Build(),
},
wantErr: true,
},
{
name: "APIEndpoint is empty",
args: args{
clusterName: "test",
client: fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).
WithObjects(newCluster("test")).Build(),
},
wantErr: true,
},
{
name: "SecretRef is empty",
args: args{
clusterName: "test",
client: fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).
WithObjects(withAPIEndPoint(newCluster("test"), "https://127.0.0.1")).Build(),
},
wantErr: true,
},
{
name: "Secret not found",
args: args{
clusterName: "test",
client: fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(
&clusterv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{Name: "test"},
Spec: clusterv1alpha1.ClusterSpec{
APIEndpoint: "https://127.0.0.1",
SecretRef: &clusterv1alpha1.LocalSecretReference{Namespace: "default", Name: "secret1"},
},
}).Build(),
},
wantErr: true,
},
{
name: "token not found",
args: args{
clusterName: "test",
client: fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(
&clusterv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{Name: "test"},
Spec: clusterv1alpha1.ClusterSpec{
APIEndpoint: "https://127.0.0.1",
SecretRef: &clusterv1alpha1.LocalSecretReference{Namespace: "ns1", Name: "secret1"},
},
},
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{Namespace: "ns1", Name: "secret1"},
}).Build(),
},
wantErr: true,
},
{
name: "CA data is set",
args: args{
clusterName: "test",
client: fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(
&clusterv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{Name: "test"},
Spec: clusterv1alpha1.ClusterSpec{
APIEndpoint: "https://127.0.0.1",
SecretRef: &clusterv1alpha1.LocalSecretReference{Namespace: "ns1", Name: "secret1"},
},
},
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{Namespace: "ns1", Name: "secret1"},
Data: map[string][]byte{clusterv1alpha1.SecretTokenKey: []byte("token"), clusterv1alpha1.SecretCADataKey: testCA},
}).Build(),
},
wantErr: false,
},
{
name: "skip TLS verification",
args: args{
clusterName: "test",
client: fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(
&clusterv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{Name: "test"},
Spec: clusterv1alpha1.ClusterSpec{
APIEndpoint: "https://127.0.0.1",
SecretRef: &clusterv1alpha1.LocalSecretReference{Namespace: "ns1", Name: "secret1"},
},
},
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{Namespace: "ns1", Name: "secret1"},
Data: map[string][]byte{clusterv1alpha1.SecretTokenKey: []byte("token"), clusterv1alpha1.SecretCADataKey: testCA},
}).Build(),
},
wantErr: false,
},
{
name: "ProxyURL is error",
args: args{
clusterName: "test",
client: fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(
&clusterv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{Name: "test"},
Spec: clusterv1alpha1.ClusterSpec{
APIEndpoint: "https://127.0.0.1",
SecretRef: &clusterv1alpha1.LocalSecretReference{Namespace: "ns1", Name: "secret1"},
ProxyURL: "://",
},
},
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{Namespace: "ns1", Name: "secret1"},
Data: map[string][]byte{clusterv1alpha1.SecretTokenKey: []byte("token"), clusterv1alpha1.SecretCADataKey: testCA},
}).Build(),
},
wantErr: true,
},
{
name: "ProxyURL is set",
args: args{
clusterName: "test",
client: fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(
&clusterv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{Name: "test"},
Spec: clusterv1alpha1.ClusterSpec{
APIEndpoint: "https://127.0.0.1",
SecretRef: &clusterv1alpha1.LocalSecretReference{Namespace: "ns1", Name: "secret1"},
ProxyURL: "http://1.1.1.1",
},
},
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{Namespace: "ns1", Name: "secret1"},
Data: map[string][]byte{clusterv1alpha1.SecretTokenKey: []byte("token"), clusterv1alpha1.SecretCADataKey: testCA},
}).Build(),
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := NewClusterDynamicClientSet(tt.args.clusterName, tt.args.client)
if (err != nil) != tt.wantErr {
t.Errorf("NewClusterClientSet() error = %v, wantErr %v", err, tt.wantErr)
return
}
if err != nil {
return
}
if got == nil {
t.Error("NewClusterClientSet() got nil")
return
}
if got.ClusterName != tt.args.clusterName {
t.Errorf("NewClusterClientSet() got ClusterName = %v, want %v", got.ClusterName, tt.args.clusterName)
return
}
if got.DynamicClientSet == nil {
t.Error("NewClusterClientSet() got DynamicClientSet nil")
return
}
})
}
}
func TestNewClusterDynamicClientSet_ClientWorks(t *testing.T) {
s := httptest.NewTLSServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.Header().Add("Content-Type", "application/json")
_, _ = io.WriteString(rw, `
{
"apiVersion": "v1",
"kind": "Node",
"metadata": {
"name": "foo"
}
}`)
}))
defer s.Close()
const clusterName = "test"
hostClient := fakeclient.NewClientBuilder().WithScheme(gclient.NewSchema()).WithObjects(
&clusterv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{Name: clusterName},
Spec: clusterv1alpha1.ClusterSpec{
APIEndpoint: s.URL,
SecretRef: &clusterv1alpha1.LocalSecretReference{Namespace: "ns1", Name: "secret1"},
},
},
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{Namespace: "ns1", Name: "secret1"},
Data: map[string][]byte{clusterv1alpha1.SecretTokenKey: []byte("token"), clusterv1alpha1.SecretCADataKey: testCA},
}).Build()
clusterClient, err := NewClusterDynamicClientSet(clusterName, hostClient)
if err != nil {
t.Error(err)
return
}
nodeGVR := corev1.SchemeGroupVersion.WithResource("nodes")
got, err := clusterClient.DynamicClientSet.Resource(nodeGVR).Get(context.TODO(), "foo", metav1.GetOptions{})
if err != nil {
t.Error(err)
return
}
want := &unstructured.Unstructured{}
want.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("Node"))
want.SetName("foo")
if !reflect.DeepEqual(got, want) {
t.Errorf("got = %#v, want %#v", got, want)
}
}