Skip to content

Commit 416cd03

Browse files
authored
chore(test): add tests to vcluster controller (#49)
1 parent 16d8438 commit 416cd03

File tree

513 files changed

+231001
-17
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

513 files changed

+231001
-17
lines changed

controllers/vcluster_controller.go

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,49 @@ import (
5454
"github.com/loft-sh/cluster-api-provider-vcluster/pkg/util/vclustervalues"
5555
)
5656

57+
type ClientConfigGetter interface {
58+
NewForConfig(restConfig *rest.Config) (kubernetes.Interface, error)
59+
}
60+
61+
type clientConfigGetter struct {
62+
}
63+
64+
func (c *clientConfigGetter) NewForConfig(restConfig *rest.Config) (kubernetes.Interface, error) {
65+
return kubernetes.NewForConfig(restConfig)
66+
}
67+
68+
func NewClientConfigGetter() ClientConfigGetter {
69+
return &clientConfigGetter{}
70+
}
71+
72+
type HTTPClientGetter interface {
73+
ClientFor(r http.RoundTripper, timeout time.Duration) *http.Client
74+
}
75+
76+
type httpClientGetter struct {
77+
}
78+
79+
func (h *httpClientGetter) ClientFor(r http.RoundTripper, timeout time.Duration) *http.Client {
80+
return &http.Client{
81+
Timeout: timeout,
82+
Transport: r,
83+
}
84+
}
85+
86+
func NewHTTPClientGetter() HTTPClientGetter {
87+
return &httpClientGetter{}
88+
}
89+
5790
// VClusterReconciler reconciles a VCluster object
5891
type VClusterReconciler struct {
5992
client.Client
60-
HelmClient helm.Client
61-
HelmSecrets *helm.Secrets
62-
Log logr.Logger
63-
Scheme *runtime.Scheme
64-
clusterKindExists bool
93+
HelmClient helm.Client
94+
HelmSecrets *helm.Secrets
95+
Log logr.Logger
96+
Scheme *runtime.Scheme
97+
ClientConfigGetter ClientConfigGetter
98+
HTTPClientGetter HTTPClientGetter
99+
clusterKindExists bool
65100
}
66101

67102
type Credentials struct {
@@ -347,7 +382,7 @@ func (r *VClusterReconciler) syncVClusterKubeconfig(ctx context.Context, vCluste
347382
return nil, err
348383
}
349384

350-
kubeClient, err := kubernetes.NewForConfig(restConfig)
385+
kubeClient, err := r.ClientConfigGetter.NewForConfig(restConfig)
351386
if err != nil {
352387
return nil, err
353388
}
@@ -433,10 +468,7 @@ func (r *VClusterReconciler) checkReadyz(vCluster *v1alpha1.VCluster, restConfig
433468
if err != nil {
434469
return false, err
435470
}
436-
client := http.Client{
437-
Timeout: 10 * time.Second,
438-
Transport: transport,
439-
}
471+
client := r.HTTPClientGetter.ClientFor(transport, 10*time.Second)
440472
resp, err := client.Get(fmt.Sprintf("https://%s:%d/readyz", vCluster.Spec.ControlPlaneEndpoint.Host, vCluster.Spec.ControlPlaneEndpoint.Port))
441473
r.Log.V(1).Info("ready check done", "namespace", vCluster.Namespace, "name", vCluster.Name, "duration", time.Since(t))
442474
if err != nil {

go.mod

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ require (
66
github.com/golangci/golangci-lint v1.56.2
77
github.com/loft-sh/log v0.0.0-20240219160058-26d83ffb46ac
88
github.com/loft-sh/utils v0.0.29
9+
github.com/onsi/ginkgo/v2 v2.15.0
10+
github.com/onsi/gomega v1.31.1
11+
github.com/stretchr/testify v1.8.4
912
k8s.io/apimachinery v0.26.1
1013
k8s.io/apiserver v0.26.1
1114
k8s.io/client-go v0.26.1
@@ -84,6 +87,7 @@ require (
8487
github.com/go-openapi/jsonpointer v0.19.5 // indirect
8588
github.com/go-openapi/jsonreference v0.20.0 // indirect
8689
github.com/go-openapi/swag v0.22.3 // indirect
90+
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
8791
github.com/go-toolsmith/astcast v1.1.0 // indirect
8892
github.com/go-toolsmith/astcopy v1.1.0 // indirect
8993
github.com/go-toolsmith/astequal v1.2.0 // indirect
@@ -105,6 +109,7 @@ require (
105109
github.com/golangci/revgrep v0.5.2 // indirect
106110
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect
107111
github.com/google/gnostic v0.6.9 // indirect
112+
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
108113
github.com/gordonklaus/ineffassign v0.1.0 // indirect
109114
github.com/gostaticanalysis/analysisutil v0.7.1 // indirect
110115
github.com/gostaticanalysis/comment v1.4.2 // indirect
@@ -183,7 +188,6 @@ require (
183188
github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect
184189
github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect
185190
github.com/stretchr/objx v0.5.0 // indirect
186-
github.com/stretchr/testify v1.8.4 // indirect
187191
github.com/subosito/gotenv v1.4.2 // indirect
188192
github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c // indirect
189193
github.com/tdakkota/asciicheck v0.2.0 // indirect

go.sum

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
371371
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
372372
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
373373
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
374+
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
374375
github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
375376
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
376377
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@@ -506,7 +507,6 @@ github.com/nunnatsa/ginkgolinter v0.15.2 h1:N2ORxUxPU56R9gsfLIlVVvCv/V/VVou5qVI1
506507
github.com/nunnatsa/ginkgolinter v0.15.2/go.mod h1:oYxE7dt1vZI8cK2rZOs3RgTaBN2vggkqnENmoJ8kVvc=
507508
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
508509
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
509-
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
510510
github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
511511
github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
512512
github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo=
@@ -633,6 +633,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
633633
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
634634
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
635635
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
636+
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
636637
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
637638
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
638639
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=

main.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,13 @@ func main() {
101101
}
102102

103103
if err = (&controllers.VClusterReconciler{
104-
Client: mgr.GetClient(),
105-
HelmClient: helm.NewClient(rawConfig),
106-
HelmSecrets: helm.NewSecrets(mgr.GetClient()),
107-
Log: log,
108-
Scheme: mgr.GetScheme(),
104+
Client: mgr.GetClient(),
105+
HelmClient: helm.NewClient(rawConfig),
106+
HelmSecrets: helm.NewSecrets(mgr.GetClient()),
107+
Log: log,
108+
Scheme: mgr.GetScheme(),
109+
ClientConfigGetter: controllers.NewClientConfigGetter(),
110+
HTTPClientGetter: controllers.NewHTTPClientGetter(),
109111
}).SetupWithManager(mgr); err != nil {
110112
setupLog.Error(err, "unable to create controller", "controller", "VCluster")
111113
os.Exit(1)
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package controllerstest
2+
3+
import (
4+
"context"
5+
"testing"
6+
"time"
7+
8+
"github.com/loft-sh/cluster-api-provider-vcluster/api/v1alpha1"
9+
"github.com/loft-sh/cluster-api-provider-vcluster/controllers"
10+
"github.com/onsi/ginkgo/v2"
11+
"github.com/onsi/gomega"
12+
corev1 "k8s.io/api/core/v1"
13+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14+
"k8s.io/apimachinery/pkg/runtime"
15+
"k8s.io/apimachinery/pkg/types"
16+
17+
fakeclientset "k8s.io/client-go/kubernetes/fake"
18+
ctrl "sigs.k8s.io/controller-runtime"
19+
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
20+
)
21+
22+
var (
23+
kubeconfigBytes = []byte(`
24+
kind: Config
25+
apiVersion: v1
26+
clusters:
27+
- cluster:
28+
api-version: v1
29+
server: https://test:443
30+
certificate-authority: test.crt
31+
name: kubeconfig-cluster
32+
users:
33+
- name: kubeconfig-user
34+
user:
35+
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrakNDQVRlZ0F3SUJBZ0lJT2FQRzhMc21MNWd3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOekE0TURBNE1qRXpNQjRYRFRJME1ESXhOVEUwTkRNek0xb1hEVEkxTURJeApOREUwTkRNek0xb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJDbysyRzRzQ0pjaTVZTlMKMkp6VTd5ZnEzSUR0dE1tcnU2bGtGV2NMR2FJSVRTVDZPbFdzaDdaYkJRb3FrTkk5c3dTOStCWHptV2FOQ1FzRgp1Q0ZaL0F1alNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCUyt0MG1hMFR2ZHN5d2RuVGpYd0ExWis0eFZJakFLQmdncWhrak9QUVFEQWdOSkFEQkcKQWlFQThjZXNlcWhjOFpGU0Z3TERzdDJYUS9lU0xiVWFuNnNYenhFeHFtSlNEbXNDSVFEcDdJWmRJd3FaVmY2WQpQMWRaOWwzeE9JTDFRL2Y5VXdNVC9aOFRaZEZJa2c9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQpNSUlCZGpDQ0FSMmdBd0lCQWdJQkFEQUtCZ2dxaGtqT1BRUURBakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwClpXNTBMV05oUURFM01EZ3dNRGd5TVRNd0hoY05NalF3TWpFMU1UUTBNek16V2hjTk16UXdNakV5TVRRME16TXoKV2pBak1TRXdId1lEVlFRRERCaHJNM010WTJ4cFpXNTBMV05oUURFM01EZ3dNRGd5TVRNd1dUQVRCZ2NxaGtqTwpQUUlCQmdncWhrak9QUU1CQndOQ0FBVCtZbTVnL0o4TzIwQ0llSFB4Z2hRWTBXajl3QVZzc0QxdHRzS0VnMFFRCjA3UDNLZEttV3AzS3BvV3FkdkN4dTNFMkp4ZDBGVDh5eG1IOVJiamVXRW90bzBJd1FEQU9CZ05WSFE4QkFmOEUKQkFNQ0FxUXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QWRCZ05WSFE0RUZnUVV2cmRKbXRFNzNiTXNIWjA0MThBTgpXZnVNVlNJd0NnWUlLb1pJemowRUF3SURSd0F3UkFJZ1VldS9yVnBmc1NoUUZmSjIyb05CMVhwY1djUWFPY2FBCnF4ZGg0dzhGdHBRQ0lIdmVTRE00clN2V3ZGZktROXRWTDRFZkpUdDc2cWliMFMyY2FBdDQwUHNGCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
36+
client-key-data: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSVBWS2JlQzJua2JaZ1UxZUNaS2NxUHpnSXd0MWxtOGcxZFNRaENoaHRURWVvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFS2o3WWJpd0lseUxsZzFMWW5OVHZKK3JjZ08yMHlhdTdxV1FWWndzWm9naE5KUG82VmF5SAp0bHNGQ2lxUTBqMnpCTDM0RmZPWlpvMEpDd1c0SVZuOEN3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
37+
`)
38+
)
39+
40+
func TestRunControllersTests(t *testing.T) {
41+
gomega.RegisterFailHandler(ginkgo.Fail)
42+
ginkgo.RunSpecs(t, "controllers suite")
43+
}
44+
45+
var _ = ginkgo.Describe("Vcluster Controller test", func() {
46+
ginkgo.Context("Reconcile", func() {
47+
var (
48+
reconciler *controllers.VClusterReconciler
49+
ctx context.Context
50+
scheme *runtime.Scheme
51+
hemlClient *MockHelmClient
52+
)
53+
54+
ginkgo.BeforeEach(func() {
55+
scheme = runtime.NewScheme()
56+
err := v1alpha1.AddToScheme(scheme)
57+
gomega.Expect(err).NotTo(gomega.HaveOccurred())
58+
59+
err = corev1.AddToScheme(scheme)
60+
gomega.Expect(err).NotTo(gomega.HaveOccurred())
61+
62+
ctx = context.Background()
63+
hemlClient = &MockHelmClient{}
64+
})
65+
66+
ginkgo.It("reconcile successfully", func() {
67+
vCluster := &v1alpha1.VCluster{
68+
ObjectMeta: metav1.ObjectMeta{
69+
Name: "test-vcluster",
70+
Namespace: "default",
71+
},
72+
Spec: v1alpha1.VClusterSpec{},
73+
}
74+
secret := &corev1.Secret{
75+
ObjectMeta: metav1.ObjectMeta{
76+
Namespace: vCluster.Namespace,
77+
Name: "vc-test-vcluster",
78+
},
79+
Data: map[string][]byte{
80+
"config": kubeconfigBytes,
81+
},
82+
}
83+
hemlClient.On("Upgrade").Return(nil)
84+
f := fakeclientset.NewSimpleClientset()
85+
86+
_, err := f.CoreV1().ServiceAccounts("default").Create(context.Background(), &corev1.ServiceAccount{
87+
ObjectMeta: metav1.ObjectMeta{
88+
Name: "default",
89+
Namespace: "default",
90+
},
91+
}, metav1.CreateOptions{})
92+
gomega.Expect(err).NotTo(gomega.HaveOccurred())
93+
94+
reconciler = &controllers.VClusterReconciler{
95+
Client: fakeclient.NewClientBuilder().WithScheme(scheme).WithObjects(vCluster, secret).Build(),
96+
HelmClient: hemlClient,
97+
Scheme: scheme,
98+
ClientConfigGetter: &fakeConfigGetter{
99+
fake: f,
100+
},
101+
HTTPClientGetter: &fakeHTTPClientGetter{},
102+
}
103+
req := ctrl.Request{
104+
NamespacedName: types.NamespacedName{
105+
Name: vCluster.Name,
106+
Namespace: vCluster.Namespace,
107+
},
108+
}
109+
result, err := reconciler.Reconcile(ctx, req)
110+
gomega.Expect(err).NotTo(gomega.HaveOccurred())
111+
gomega.Expect(result.RequeueAfter).Should(gomega.Equal(time.Minute))
112+
})
113+
})
114+
115+
})

test/controllerstest/fake.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package controllerstest
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"time"
7+
8+
"net/http/httptest"
9+
10+
"k8s.io/client-go/kubernetes"
11+
fakeclientset "k8s.io/client-go/kubernetes/fake"
12+
"k8s.io/client-go/rest"
13+
restfake "k8s.io/client-go/rest/fake"
14+
)
15+
16+
type fakeConfigGetter struct {
17+
fake *fakeclientset.Clientset
18+
}
19+
20+
func (f *fakeConfigGetter) NewForConfig(_ *rest.Config) (kubernetes.Interface, error) {
21+
return f.fake, nil
22+
}
23+
24+
type fakeHTTPClientGetter struct {
25+
}
26+
27+
func (f *fakeHTTPClientGetter) ClientFor(_ http.RoundTripper, _ time.Duration) *http.Client {
28+
return restfake.CreateHTTPClient(func(*http.Request) (*http.Response, error) {
29+
recorder := httptest.NewRecorder()
30+
fmt.Fprint(recorder, "ok")
31+
return recorder.Result(), nil
32+
})
33+
}

test/controllerstest/mock.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package controllerstest
2+
3+
import (
4+
"github.com/loft-sh/cluster-api-provider-vcluster/pkg/helm"
5+
"github.com/stretchr/testify/mock"
6+
)
7+
8+
type MockHelmClient struct {
9+
mock.Mock
10+
}
11+
12+
func (m *MockHelmClient) Install(_, _ string, _ helm.UpgradeOptions) error {
13+
args := m.Called()
14+
return args.Error(0)
15+
}
16+
17+
func (m *MockHelmClient) Upgrade(_, _ string, _ helm.UpgradeOptions) error {
18+
args := m.Called()
19+
return args.Error(0)
20+
}
21+
22+
func (m *MockHelmClient) Rollback(_, _ string, _ string) error {
23+
args := m.Called()
24+
return args.Error(0)
25+
}
26+
27+
func (m *MockHelmClient) Delete(_, _ string) error {
28+
args := m.Called()
29+
return args.Error(0)
30+
}
31+
32+
func (m *MockHelmClient) Exists(_, _ string) (bool, error) {
33+
args := m.Called()
34+
return args.Bool(0), args.Error(1)
35+
}

0 commit comments

Comments
 (0)