501 lines
16 KiB
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)
|
|
}
|
|
}
|