From 2e0a7b0f78e1d05bc9f027e056ea5aac48bc0670 Mon Sep 17 00:00:00 2001 From: Lukasz Zajaczkowski Date: Tue, 22 Oct 2024 13:26:25 +0200 Subject: [PATCH] add unit tests --- .../pipelinegates/reconciler_test.go | 69 ++++++++++ pkg/controller/pipelinegates/suite_test.go | 74 +++++++++++ pkg/controller/service/reconciler_test.go | 118 ++++++++++++++++++ pkg/controller/service/suite_test.go | 75 +++++++++++ test/tarball/test.tar.gz | Bin 0 -> 244 bytes 5 files changed, 336 insertions(+) create mode 100644 pkg/controller/pipelinegates/reconciler_test.go create mode 100644 pkg/controller/pipelinegates/suite_test.go create mode 100644 pkg/controller/service/reconciler_test.go create mode 100644 pkg/controller/service/suite_test.go create mode 100644 test/tarball/test.tar.gz diff --git a/pkg/controller/pipelinegates/reconciler_test.go b/pkg/controller/pipelinegates/reconciler_test.go new file mode 100644 index 00000000..26ac485f --- /dev/null +++ b/pkg/controller/pipelinegates/reconciler_test.go @@ -0,0 +1,69 @@ +package pipelinegates_test + +import ( + "context" + "os" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + console "github.com/pluralsh/console/go/client" + "github.com/pluralsh/deployment-operator/api/v1alpha1" + "github.com/pluralsh/deployment-operator/cmd/agent/args" + "github.com/pluralsh/deployment-operator/pkg/cache" + "github.com/pluralsh/deployment-operator/pkg/controller/pipelinegates" + "github.com/pluralsh/deployment-operator/pkg/test/mocks" + "github.com/stretchr/testify/mock" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +var _ = Describe("Reconciler", Ordered, func() { + Context("When reconciling a resource", func() { + const ( + namespace = "default" + gateId = "1" + pipelinegateName = "test" + ) + gateFragment := &console.PipelineGateFragment{ + ID: gateId, + Type: console.GateTypeJob, + } + pipelinegate := &v1alpha1.PipelineGate{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: pipelinegateName, + }, + Spec: v1alpha1.PipelineGateSpec{ + Name: pipelinegateName, + Type: v1alpha1.GateType(console.GateTypeApproval), + }, + } + + ctx := context.Background() + + BeforeEach(func() { + os.Setenv("OPERATOR_NAMESPACE", "default") + }) + AfterEach(func() { + os.Unsetenv("OPERATOR_NAMESPACE") + }) + + It("should create Gate object", func() { + fakeConsoleClient := mocks.NewClientMock(mocks.TestingT) + fakeConsoleClient.On("GetClusterGate", mock.Anything).Return(gateFragment, nil) + fakeConsoleClient.On("ParsePipelineGateCR", mock.Anything, mock.Anything).Return(pipelinegate, nil) + + cache.InitGateCache(args.ControllerCacheTTL(), fakeConsoleClient) + + reconciler, err := pipelinegates.NewGateReconciler(fakeConsoleClient, kClient, cfg, time.Minute) + Expect(err).NotTo(HaveOccurred()) + _, err = reconciler.Reconcile(ctx, gateId) + Expect(err).NotTo(HaveOccurred()) + + Expect(kClient.Get(ctx, types.NamespacedName{Name: pipelinegateName, Namespace: namespace}, &v1alpha1.PipelineGate{})).NotTo(HaveOccurred()) + + }) + + }) +}) diff --git a/pkg/controller/pipelinegates/suite_test.go b/pkg/controller/pipelinegates/suite_test.go new file mode 100644 index 00000000..3a0fcd86 --- /dev/null +++ b/pkg/controller/pipelinegates/suite_test.go @@ -0,0 +1,74 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package pipelinegates_test + +import ( + "fmt" + "path/filepath" + "runtime" + "testing" + + "k8s.io/client-go/rest" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/pluralsh/deployment-operator/api/v1alpha1" + "k8s.io/client-go/kubernetes/scheme" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" +) + +// These tests use Ginkgo (BDD-style Go testing framework). Refer to +// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. +var testEnv *envtest.Environment +var kClient client.Client +var cfg *rest.Config + +func TestStacks(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Stack Suite") +} + +var _ = BeforeSuite(func() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crd", "bases")}, + ErrorIfCRDPathMissing: true, + BinaryAssetsDirectory: filepath.Join("..", "..", "bin", "k8s", fmt.Sprintf("1.28.3-%s-%s", runtime.GOOS, runtime.GOARCH)), + } + var err error + cfg, err = testEnv.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).NotTo(BeNil()) + + err = v1alpha1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + kClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + Expect(err).NotTo(HaveOccurred()) + Expect(kClient).NotTo(BeNil()) +}) + +var _ = AfterSuite(func() { + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).NotTo(HaveOccurred()) +}) diff --git a/pkg/controller/service/reconciler_test.go b/pkg/controller/service/reconciler_test.go new file mode 100644 index 00000000..e8db3071 --- /dev/null +++ b/pkg/controller/service/reconciler_test.go @@ -0,0 +1,118 @@ +package service_test + +import ( + "context" + "log" + "net/http" + "os" + "path/filepath" + "time" + + "github.com/gin-gonic/gin" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + console "github.com/pluralsh/console/go/client" + "github.com/pluralsh/deployment-operator/pkg/controller/service" + "github.com/pluralsh/deployment-operator/pkg/test/mocks" + "github.com/samber/lo" + "github.com/stretchr/testify/mock" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +var _ = Describe("Reconciler", Ordered, func() { + Context("When reconciling a resource", func() { + const ( + namespace = "default" + serviceId = "1" + serviceName = "test" + clusterId = "1" + clusterName = "cluster-test" + operatorNamespace = "plrl-deploy-operator" + ) + consoleService := &console.GetServiceDeploymentForAgent_ServiceDeployment{ + ID: serviceId, + Name: serviceName, + Namespace: namespace, + Tarball: lo.ToPtr("http://localhost:8080/ext/v1/digests"), + Configuration: []*console.GetServiceDeploymentForAgent_ServiceDeployment_Configuration{ + { + Name: "name", + Value: serviceName, + }, + }, + Cluster: &console.GetServiceDeploymentForAgent_ServiceDeployment_Cluster{ + ID: clusterId, + Name: clusterName, + }, + Revision: &console.GetServiceDeploymentForAgent_ServiceDeployment_Revision{ + ID: serviceId, + }, + } + ctx := context.Background() + tarPath := filepath.Join("..", "..", "..", "test", "tarball", "test.tar.gz") + + r := gin.Default() + r.GET("/ext/v1/digests", func(c *gin.Context) { + res, err := os.ReadFile(tarPath) + Expect(err).NotTo(HaveOccurred()) + c.String(http.StatusOK, string(res)) + }) + + srv := &http.Server{ + Addr: ":8080", + Handler: r, + } + dir := "" + BeforeEach(func() { + var err error + dir, err = os.MkdirTemp("", "test") + Expect(err).NotTo(HaveOccurred()) + Expect(kClient.Create(ctx, &v1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: operatorNamespace, + }, + })).NotTo(HaveOccurred()) + // Initializing the server in a goroutine so that + // it won't block the graceful shutdown handling below + go func() { + if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { + Expect(err).NotTo(HaveOccurred()) + } + }() + }) + AfterEach(func() { + os.RemoveAll(dir) + Expect(kClient.Delete(ctx, &v1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: operatorNamespace, + }, + })).NotTo(HaveOccurred()) + // The context is used to inform the server it has 5 seconds to finish + // the request it is currently handling + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + if err := srv.Shutdown(ctx); err != nil { + log.Fatal("Server forced to shutdown: ", err) + } + + log.Println("Server exiting") + }) + + It("should create NewServiceReconciler and apply service", func() { + fakeConsoleClient := mocks.NewClientMock(mocks.TestingT) + fakeConsoleClient.On("GetCredentials").Return("", "") + fakeConsoleClient.On("GetService", mock.Anything).Return(consoleService, nil) + fakeConsoleClient.On("UpdateComponents", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) + + reconciler, err := service.NewServiceReconciler(fakeConsoleClient, cfg, time.Minute, time.Minute, namespace, "http://localhost:8080") + Expect(err).NotTo(HaveOccurred()) + _, err = reconciler.Reconcile(ctx, serviceId) + Expect(err).NotTo(HaveOccurred()) + + Expect(kClient.Get(ctx, types.NamespacedName{Name: serviceName, Namespace: namespace}, &v1.Pod{})).NotTo(HaveOccurred()) + }) + + }) +}) diff --git a/pkg/controller/service/suite_test.go b/pkg/controller/service/suite_test.go new file mode 100644 index 00000000..7b014d54 --- /dev/null +++ b/pkg/controller/service/suite_test.go @@ -0,0 +1,75 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package service_test + +import ( + "fmt" + "path/filepath" + "runtime" + "testing" + + "k8s.io/client-go/rest" + + velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "k8s.io/client-go/kubernetes/scheme" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" +) + +// These tests use Ginkgo (BDD-style Go testing framework). Refer to +// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. +var testEnv *envtest.Environment +var kClient client.Client +var cfg *rest.Config + +func TestStacks(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Stack Suite") +} + +var _ = BeforeSuite(func() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "test", "crd")}, + ErrorIfCRDPathMissing: true, + BinaryAssetsDirectory: filepath.Join("..", "..", "bin", "k8s", fmt.Sprintf("1.28.3-%s-%s", runtime.GOOS, runtime.GOARCH)), + } + var err error + cfg, err = testEnv.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).NotTo(BeNil()) + + err = velerov1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + kClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + Expect(err).NotTo(HaveOccurred()) + Expect(kClient).NotTo(BeNil()) +}) + +var _ = AfterSuite(func() { + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).NotTo(HaveOccurred()) +}) diff --git a/test/tarball/test.tar.gz b/test/tarball/test.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..9f15930ab77b1ef8a5cc3d8200c14f1fc86ad2c1 GIT binary patch literal 244 zcmb2|=3oE==C>Cd{SF%lum-Fz?%K&P?X89GC(T_+_N$yzOgB0|QdscnuBVs7ilC#b zn3nuEQ$GK_N9X&=)8X%;ZniDgtSIEp+P1N5WmWXb_g~M1OubMR{OZ(n+a literal 0 HcmV?d00001