Skip to content

Commit

Permalink
chore(test): add tests to vcluster controller (#49)
Browse files Browse the repository at this point in the history
  • Loading branch information
narcis96 authored Mar 5, 2024
1 parent 16d8438 commit 416cd03
Show file tree
Hide file tree
Showing 513 changed files with 231,001 additions and 17 deletions.
52 changes: 42 additions & 10 deletions controllers/vcluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,49 @@ import (
"github.com/loft-sh/cluster-api-provider-vcluster/pkg/util/vclustervalues"
)

type ClientConfigGetter interface {
NewForConfig(restConfig *rest.Config) (kubernetes.Interface, error)
}

type clientConfigGetter struct {
}

func (c *clientConfigGetter) NewForConfig(restConfig *rest.Config) (kubernetes.Interface, error) {
return kubernetes.NewForConfig(restConfig)
}

func NewClientConfigGetter() ClientConfigGetter {
return &clientConfigGetter{}
}

type HTTPClientGetter interface {
ClientFor(r http.RoundTripper, timeout time.Duration) *http.Client
}

type httpClientGetter struct {
}

func (h *httpClientGetter) ClientFor(r http.RoundTripper, timeout time.Duration) *http.Client {
return &http.Client{
Timeout: timeout,
Transport: r,
}
}

func NewHTTPClientGetter() HTTPClientGetter {
return &httpClientGetter{}
}

// VClusterReconciler reconciles a VCluster object
type VClusterReconciler struct {
client.Client
HelmClient helm.Client
HelmSecrets *helm.Secrets
Log logr.Logger
Scheme *runtime.Scheme
clusterKindExists bool
HelmClient helm.Client
HelmSecrets *helm.Secrets
Log logr.Logger
Scheme *runtime.Scheme
ClientConfigGetter ClientConfigGetter
HTTPClientGetter HTTPClientGetter
clusterKindExists bool
}

type Credentials struct {
Expand Down Expand Up @@ -347,7 +382,7 @@ func (r *VClusterReconciler) syncVClusterKubeconfig(ctx context.Context, vCluste
return nil, err
}

kubeClient, err := kubernetes.NewForConfig(restConfig)
kubeClient, err := r.ClientConfigGetter.NewForConfig(restConfig)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -433,10 +468,7 @@ func (r *VClusterReconciler) checkReadyz(vCluster *v1alpha1.VCluster, restConfig
if err != nil {
return false, err
}
client := http.Client{
Timeout: 10 * time.Second,
Transport: transport,
}
client := r.HTTPClientGetter.ClientFor(transport, 10*time.Second)
resp, err := client.Get(fmt.Sprintf("https://%s:%d/readyz", vCluster.Spec.ControlPlaneEndpoint.Host, vCluster.Spec.ControlPlaneEndpoint.Port))
r.Log.V(1).Info("ready check done", "namespace", vCluster.Namespace, "name", vCluster.Name, "duration", time.Since(t))
if err != nil {
Expand Down
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ require (
github.com/golangci/golangci-lint v1.56.2
github.com/loft-sh/log v0.0.0-20240219160058-26d83ffb46ac
github.com/loft-sh/utils v0.0.29
github.com/onsi/ginkgo/v2 v2.15.0
github.com/onsi/gomega v1.31.1
github.com/stretchr/testify v1.8.4
k8s.io/apimachinery v0.26.1
k8s.io/apiserver v0.26.1
k8s.io/client-go v0.26.1
Expand Down Expand Up @@ -84,6 +87,7 @@ require (
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/go-toolsmith/astcast v1.1.0 // indirect
github.com/go-toolsmith/astcopy v1.1.0 // indirect
github.com/go-toolsmith/astequal v1.2.0 // indirect
Expand All @@ -105,6 +109,7 @@ require (
github.com/golangci/revgrep v0.5.2 // indirect
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect
github.com/google/gnostic v0.6.9 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
github.com/gordonklaus/ineffassign v0.1.0 // indirect
github.com/gostaticanalysis/analysisutil v0.7.1 // indirect
github.com/gostaticanalysis/comment v1.4.2 // indirect
Expand Down Expand Up @@ -183,7 +188,6 @@ require (
github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect
github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/stretchr/testify v1.8.4 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c // indirect
github.com/tdakkota/asciicheck v0.2.0 // indirect
Expand Down
3 changes: 2 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
Expand Down Expand Up @@ -506,7 +507,6 @@ github.com/nunnatsa/ginkgolinter v0.15.2 h1:N2ORxUxPU56R9gsfLIlVVvCv/V/VVou5qVI1
github.com/nunnatsa/ginkgolinter v0.15.2/go.mod h1:oYxE7dt1vZI8cK2rZOs3RgTaBN2vggkqnENmoJ8kVvc=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo=
Expand Down Expand Up @@ -633,6 +633,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
Expand Down
12 changes: 7 additions & 5 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,13 @@ func main() {
}

if err = (&controllers.VClusterReconciler{
Client: mgr.GetClient(),
HelmClient: helm.NewClient(rawConfig),
HelmSecrets: helm.NewSecrets(mgr.GetClient()),
Log: log,
Scheme: mgr.GetScheme(),
Client: mgr.GetClient(),
HelmClient: helm.NewClient(rawConfig),
HelmSecrets: helm.NewSecrets(mgr.GetClient()),
Log: log,
Scheme: mgr.GetScheme(),
ClientConfigGetter: controllers.NewClientConfigGetter(),
HTTPClientGetter: controllers.NewHTTPClientGetter(),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "VCluster")
os.Exit(1)
Expand Down
115 changes: 115 additions & 0 deletions test/controllerstest/controllers_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package controllerstest

import (
"context"
"testing"
"time"

"github.com/loft-sh/cluster-api-provider-vcluster/api/v1alpha1"
"github.com/loft-sh/cluster-api-provider-vcluster/controllers"
"github.com/onsi/ginkgo/v2"
"github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"

fakeclientset "k8s.io/client-go/kubernetes/fake"
ctrl "sigs.k8s.io/controller-runtime"
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
)

var (
kubeconfigBytes = []byte(`
kind: Config
apiVersion: v1
clusters:
- cluster:
api-version: v1
server: https://test:443
certificate-authority: test.crt
name: kubeconfig-cluster
users:
- name: kubeconfig-user
user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrakNDQVRlZ0F3SUJBZ0lJT2FQRzhMc21MNWd3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOekE0TURBNE1qRXpNQjRYRFRJME1ESXhOVEUwTkRNek0xb1hEVEkxTURJeApOREUwTkRNek0xb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJDbysyRzRzQ0pjaTVZTlMKMkp6VTd5ZnEzSUR0dE1tcnU2bGtGV2NMR2FJSVRTVDZPbFdzaDdaYkJRb3FrTkk5c3dTOStCWHptV2FOQ1FzRgp1Q0ZaL0F1alNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCUyt0MG1hMFR2ZHN5d2RuVGpYd0ExWis0eFZJakFLQmdncWhrak9QUVFEQWdOSkFEQkcKQWlFQThjZXNlcWhjOFpGU0Z3TERzdDJYUS9lU0xiVWFuNnNYenhFeHFtSlNEbXNDSVFEcDdJWmRJd3FaVmY2WQpQMWRaOWwzeE9JTDFRL2Y5VXdNVC9aOFRaZEZJa2c9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQpNSUlCZGpDQ0FSMmdBd0lCQWdJQkFEQUtCZ2dxaGtqT1BRUURBakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwClpXNTBMV05oUURFM01EZ3dNRGd5TVRNd0hoY05NalF3TWpFMU1UUTBNek16V2hjTk16UXdNakV5TVRRME16TXoKV2pBak1TRXdId1lEVlFRRERCaHJNM010WTJ4cFpXNTBMV05oUURFM01EZ3dNRGd5TVRNd1dUQVRCZ2NxaGtqTwpQUUlCQmdncWhrak9QUU1CQndOQ0FBVCtZbTVnL0o4TzIwQ0llSFB4Z2hRWTBXajl3QVZzc0QxdHRzS0VnMFFRCjA3UDNLZEttV3AzS3BvV3FkdkN4dTNFMkp4ZDBGVDh5eG1IOVJiamVXRW90bzBJd1FEQU9CZ05WSFE4QkFmOEUKQkFNQ0FxUXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QWRCZ05WSFE0RUZnUVV2cmRKbXRFNzNiTXNIWjA0MThBTgpXZnVNVlNJd0NnWUlLb1pJemowRUF3SURSd0F3UkFJZ1VldS9yVnBmc1NoUUZmSjIyb05CMVhwY1djUWFPY2FBCnF4ZGg0dzhGdHBRQ0lIdmVTRE00clN2V3ZGZktROXRWTDRFZkpUdDc2cWliMFMyY2FBdDQwUHNGCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
client-key-data: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSVBWS2JlQzJua2JaZ1UxZUNaS2NxUHpnSXd0MWxtOGcxZFNRaENoaHRURWVvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFS2o3WWJpd0lseUxsZzFMWW5OVHZKK3JjZ08yMHlhdTdxV1FWWndzWm9naE5KUG82VmF5SAp0bHNGQ2lxUTBqMnpCTDM0RmZPWlpvMEpDd1c0SVZuOEN3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
`)
)

func TestRunControllersTests(t *testing.T) {
gomega.RegisterFailHandler(ginkgo.Fail)
ginkgo.RunSpecs(t, "controllers suite")
}

var _ = ginkgo.Describe("Vcluster Controller test", func() {
ginkgo.Context("Reconcile", func() {
var (
reconciler *controllers.VClusterReconciler
ctx context.Context
scheme *runtime.Scheme
hemlClient *MockHelmClient
)

ginkgo.BeforeEach(func() {
scheme = runtime.NewScheme()
err := v1alpha1.AddToScheme(scheme)
gomega.Expect(err).NotTo(gomega.HaveOccurred())

err = corev1.AddToScheme(scheme)
gomega.Expect(err).NotTo(gomega.HaveOccurred())

ctx = context.Background()
hemlClient = &MockHelmClient{}
})

ginkgo.It("reconcile successfully", func() {
vCluster := &v1alpha1.VCluster{
ObjectMeta: metav1.ObjectMeta{
Name: "test-vcluster",
Namespace: "default",
},
Spec: v1alpha1.VClusterSpec{},
}
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: vCluster.Namespace,
Name: "vc-test-vcluster",
},
Data: map[string][]byte{
"config": kubeconfigBytes,
},
}
hemlClient.On("Upgrade").Return(nil)
f := fakeclientset.NewSimpleClientset()

_, err := f.CoreV1().ServiceAccounts("default").Create(context.Background(), &corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
Namespace: "default",
},
}, metav1.CreateOptions{})
gomega.Expect(err).NotTo(gomega.HaveOccurred())

reconciler = &controllers.VClusterReconciler{
Client: fakeclient.NewClientBuilder().WithScheme(scheme).WithObjects(vCluster, secret).Build(),
HelmClient: hemlClient,
Scheme: scheme,
ClientConfigGetter: &fakeConfigGetter{
fake: f,
},
HTTPClientGetter: &fakeHTTPClientGetter{},
}
req := ctrl.Request{
NamespacedName: types.NamespacedName{
Name: vCluster.Name,
Namespace: vCluster.Namespace,
},
}
result, err := reconciler.Reconcile(ctx, req)
gomega.Expect(err).NotTo(gomega.HaveOccurred())
gomega.Expect(result.RequeueAfter).Should(gomega.Equal(time.Minute))
})
})

})
33 changes: 33 additions & 0 deletions test/controllerstest/fake.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package controllerstest

import (
"fmt"
"net/http"
"time"

"net/http/httptest"

"k8s.io/client-go/kubernetes"
fakeclientset "k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/rest"
restfake "k8s.io/client-go/rest/fake"
)

type fakeConfigGetter struct {
fake *fakeclientset.Clientset
}

func (f *fakeConfigGetter) NewForConfig(_ *rest.Config) (kubernetes.Interface, error) {
return f.fake, nil
}

type fakeHTTPClientGetter struct {
}

func (f *fakeHTTPClientGetter) ClientFor(_ http.RoundTripper, _ time.Duration) *http.Client {
return restfake.CreateHTTPClient(func(*http.Request) (*http.Response, error) {
recorder := httptest.NewRecorder()
fmt.Fprint(recorder, "ok")
return recorder.Result(), nil
})
}
35 changes: 35 additions & 0 deletions test/controllerstest/mock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package controllerstest

import (
"github.com/loft-sh/cluster-api-provider-vcluster/pkg/helm"
"github.com/stretchr/testify/mock"
)

type MockHelmClient struct {
mock.Mock
}

func (m *MockHelmClient) Install(_, _ string, _ helm.UpgradeOptions) error {
args := m.Called()
return args.Error(0)
}

func (m *MockHelmClient) Upgrade(_, _ string, _ helm.UpgradeOptions) error {
args := m.Called()
return args.Error(0)
}

func (m *MockHelmClient) Rollback(_, _ string, _ string) error {
args := m.Called()
return args.Error(0)
}

func (m *MockHelmClient) Delete(_, _ string) error {
args := m.Called()
return args.Error(0)
}

func (m *MockHelmClient) Exists(_, _ string) (bool, error) {
args := m.Called()
return args.Bool(0), args.Error(1)
}
Loading

0 comments on commit 416cd03

Please sign in to comment.