From d9c708114b398cbe58cf822234dc41f61b82ccd8 Mon Sep 17 00:00:00 2001 From: Abhisek Dwivedi Date: Wed, 10 Jul 2024 18:32:51 +0530 Subject: [PATCH] Added Backup Service test-suite --- api/v1beta1/aerospikebackup_webhook.go | 5 +- api/v1beta1/aerospikebackupservice_webhook.go | 3 +- api/v1beta1/aerospikerestore_webhook.go | 3 +- .../asdb_v1beta1_aerospikebackupservice.yaml | 4 +- controllers/backup-service/reconciler.go | 18 +- controllers/restore/reconciler.go | 5 + go.mod | 2 +- go.sum | 4 +- .../backup_service_suite_test.go | 106 +++++++ test/backup_service/backup_service_test.go | 172 +++++++++++ test/backup_service/helper_test.go | 267 ++++++++++++++++++ 11 files changed, 572 insertions(+), 17 deletions(-) create mode 100644 test/backup_service/backup_service_suite_test.go create mode 100644 test/backup_service/backup_service_test.go create mode 100644 test/backup_service/helper_test.go diff --git a/api/v1beta1/aerospikebackup_webhook.go b/api/v1beta1/aerospikebackup_webhook.go index 1d8836ba5..92d0a374a 100644 --- a/api/v1beta1/aerospikebackup_webhook.go +++ b/api/v1beta1/aerospikebackup_webhook.go @@ -21,13 +21,12 @@ import ( "fmt" "reflect" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" utilRuntime "k8s.io/apimachinery/pkg/util/runtime" clientGoScheme "k8s.io/client-go/kubernetes/scheme" - "sigs.k8s.io/controller-runtime/pkg/client" - - "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" diff --git a/api/v1beta1/aerospikebackupservice_webhook.go b/api/v1beta1/aerospikebackupservice_webhook.go index 2b09e9485..08806f4af 100644 --- a/api/v1beta1/aerospikebackupservice_webhook.go +++ b/api/v1beta1/aerospikebackupservice_webhook.go @@ -17,13 +17,14 @@ limitations under the License. package v1beta1 import ( - "github.com/abhishekdwivedi3060/aerospike-backup-service/pkg/model" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" "sigs.k8s.io/yaml" + + "github.com/abhishekdwivedi3060/aerospike-backup-service/pkg/model" ) // log is for logging in this package. diff --git a/api/v1beta1/aerospikerestore_webhook.go b/api/v1beta1/aerospikerestore_webhook.go index 867a35b48..e0e39e6a3 100644 --- a/api/v1beta1/aerospikerestore_webhook.go +++ b/api/v1beta1/aerospikerestore_webhook.go @@ -21,13 +21,14 @@ import ( "reflect" "time" - "github.com/abhishekdwivedi3060/aerospike-backup-service/pkg/model" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" "sigs.k8s.io/yaml" + + "github.com/abhishekdwivedi3060/aerospike-backup-service/pkg/model" ) // log is for logging in this package. diff --git a/config/samples/asdb_v1beta1_aerospikebackupservice.yaml b/config/samples/asdb_v1beta1_aerospikebackupservice.yaml index 149f56022..3e4b86243 100644 --- a/config/samples/asdb_v1beta1_aerospikebackupservice.yaml +++ b/config/samples/asdb_v1beta1_aerospikebackupservice.yaml @@ -10,7 +10,7 @@ metadata: name: aerospikebackupservice-sample namespace: aerospike spec: - image: aerospike.jfrog.io/ecosystem-container-prod-local/aerospike-backup-service:0.3.0 + image: aerospike.jfrog.io/ecosystem-container-prod-local/aerospike-backup-service:1.0.0 config: service: http: @@ -27,7 +27,7 @@ spec: storage: local: path: /localStorage - type: 0 + type: local secrets: - secretName: auth-secret volumeMount: diff --git a/controllers/backup-service/reconciler.go b/controllers/backup-service/reconciler.go index fcde6ff62..503013940 100644 --- a/controllers/backup-service/reconciler.go +++ b/controllers/backup-service/reconciler.go @@ -64,6 +64,11 @@ func (r *SingleBackupServiceReconciler) Reconcile() (result ctrl.Result, recErr } }() + if !r.aeroBackupService.ObjectMeta.DeletionTimestamp.IsZero() { + // Stop reconciliation as the Aerospike Backup service is being deleted + return reconcile.Result{}, nil + } + // Set the status to AerospikeClusterInProgress before starting any operations if err := r.setStatusPhase(asdbv1beta1.AerospikeBackupServiceInProgress); err != nil { return reconcile.Result{}, err @@ -273,11 +278,9 @@ func (r *SingleBackupServiceReconciler) reconcileDeployment() error { return err } } - - return r.waitForDeploymentToBeReady() } - return nil + return r.waitForDeploymentToBeReady() } func getBackupServiceName(aeroBackupService *asdbv1beta1.AerospikeBackupService) types.NamespacedName { @@ -568,7 +571,7 @@ func (r *SingleBackupServiceReconciler) getBackupServiceConfig() (*serviceConfig func (r *SingleBackupServiceReconciler) waitForDeploymentToBeReady() error { const ( podStatusTimeout = 2 * time.Minute - podStatusRetryInterval = time.Second * 5 + podStatusRetryInterval = 5 * time.Second ) r.Log.Info( @@ -583,7 +586,8 @@ func (r *SingleBackupServiceReconciler) waitForDeploymentToBeReady() error { } if len(podList.Items) == 0 { - return false, fmt.Errorf("no pod found for deployment") + r.Log.Info("No pod found for deployment") + return false, nil } for idx := range podList.Items { @@ -609,7 +613,7 @@ func (r *SingleBackupServiceReconciler) waitForDeploymentToBeReady() error { } if deploy.Status.Replicas != *deploy.Spec.Replicas { - return false, fmt.Errorf("deployment status is not updated") + return false, nil } return true, nil @@ -628,7 +632,7 @@ func (r *SingleBackupServiceReconciler) setStatusPhase(phase asdbv1beta1.Aerospi r.aeroBackupService.Status.Phase = phase if err := r.Client.Status().Update(context.Background(), r.aeroBackupService); err != nil { - r.Log.Error(err, fmt.Sprintf("Failed to set restore status to %s", phase)) + r.Log.Error(err, fmt.Sprintf("Failed to set backup service status to %s", phase)) return err } } diff --git a/controllers/restore/reconciler.go b/controllers/restore/reconciler.go index 80f367244..bd123edfc 100644 --- a/controllers/restore/reconciler.go +++ b/controllers/restore/reconciler.go @@ -30,6 +30,11 @@ type SingleRestoreReconciler struct { } func (r *SingleRestoreReconciler) Reconcile() (result ctrl.Result, recErr error) { + if !r.aeroRestore.ObjectMeta.DeletionTimestamp.IsZero() { + // Stop reconciliation as the Aerospike restore is being deleted + return reconcile.Result{}, nil + } + if err := r.setStatusPhase(asdbv1beta1.AerospikeRestoreInProgress); err != nil { return ctrl.Result{}, err } diff --git a/go.mod b/go.mod index 272fd40b2..e8752f31a 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( ) require ( - github.com/abhishekdwivedi3060/aerospike-backup-service v0.0.0-20240604175608-042db47ee091 + github.com/abhishekdwivedi3060/aerospike-backup-service v0.0.0-20240709182036-38038c5c38c7 github.com/aerospike/aerospike-client-go/v7 v7.4.0 github.com/deckarep/golang-set/v2 v2.3.1 github.com/sirupsen/logrus v1.9.0 diff --git a/go.sum b/go.sum index 300994a4f..1c1019664 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/abhishekdwivedi3060/aerospike-backup-service v0.0.0-20240604175608-042db47ee091 h1:eY5MT18Ocf5cCHohbZ1qcdophb/aOqr066lwSM3zGPk= -github.com/abhishekdwivedi3060/aerospike-backup-service v0.0.0-20240604175608-042db47ee091/go.mod h1:CMA+bHRLvL/Kj/aLlbu95iNnlPnvP67q62X81b5e2G4= +github.com/abhishekdwivedi3060/aerospike-backup-service v0.0.0-20240709182036-38038c5c38c7 h1:BP+LMehEXEsUE2HGT/Wn1ib0ZarBLHjjzg+x6XGIJ1s= +github.com/abhishekdwivedi3060/aerospike-backup-service v0.0.0-20240709182036-38038c5c38c7/go.mod h1:CMA+bHRLvL/Kj/aLlbu95iNnlPnvP67q62X81b5e2G4= github.com/aerospike/aerospike-client-go/v7 v7.4.0 h1:g8/7v8RHhQhTArhW3C7Au7o+u8j8x5eySZL6MXfpHKU= github.com/aerospike/aerospike-client-go/v7 v7.4.0/go.mod h1:pPKnWiS8VDJcH4IeB1b8SA2TWnkjcVLHwAAJ+BHfGK8= github.com/aerospike/aerospike-management-lib v1.4.0 h1:wT0l3kwzXv5DV5Cd+hD0BQq3hjSIyaPX1HaUb1304TI= diff --git a/test/backup_service/backup_service_suite_test.go b/test/backup_service/backup_service_suite_test.go new file mode 100644 index 000000000..e6b9771cb --- /dev/null +++ b/test/backup_service/backup_service_suite_test.go @@ -0,0 +1,106 @@ +package backupservice + +import ( + "context" + "testing" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/onsi/gomega/gexec" + admissionv1 "k8s.io/api/admission/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + k8Runtime "k8s.io/apimachinery/pkg/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + ctrl "sigs.k8s.io/controller-runtime" + "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" + + asdbv1 "github.com/aerospike/aerospike-kubernetes-operator/api/v1" + asdbv1beta1 "github.com/aerospike/aerospike-kubernetes-operator/api/v1beta1" + "github.com/aerospike/aerospike-kubernetes-operator/controllers/common" +) + +var cfg *rest.Config + +var testEnv *envtest.Environment + +var k8sClient client.Client + +var scheme = k8Runtime.NewScheme() + +var testCtx = context.TODO() + +var pkgLog = ctrl.Log.WithName("test") + +const ( + name = "backup-service" + namespace = "test" +) + +func TestBackupService(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "BackupService Suite") +} + +var _ = BeforeSuite( + func() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + By("Bootstrapping test environment") + t := true + testEnv = &envtest.Environment{ + UseExistingCluster: &t, + } + var err error + + cfg, err = testEnv.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).NotTo(BeNil()) + + err = clientgoscheme.AddToScheme(scheme) + Expect(err).NotTo(HaveOccurred()) + + err = asdbv1.AddToScheme(scheme) + Expect(err).NotTo(HaveOccurred()) + + err = asdbv1beta1.AddToScheme(scheme) + Expect(err).NotTo(HaveOccurred()) + + err = admissionv1.AddToScheme(scheme) + Expect(err).NotTo(HaveOccurred()) + + // +kubebuilder:scaffold:scheme + + k8sClient, err = client.New( + cfg, client.Options{Scheme: scheme}, + ) + Expect(err).NotTo(HaveOccurred()) + Expect(k8sClient).NotTo(BeNil()) + + sa := corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: common.AerospikeBackupService, + Namespace: namespace, + }, + } + + err = k8sClient.Create(testCtx, &sa) + if err != nil && !errors.IsAlreadyExists(err) { + Fail(err.Error()) + } + }) + +var _ = AfterSuite( + func() { + By("tearing down the test environment") + gexec.KillAndWait(5 * time.Second) + err := testEnv.Stop() + Expect(err).ToNot(HaveOccurred()) + }, +) diff --git a/test/backup_service/backup_service_test.go b/test/backup_service/backup_service_test.go new file mode 100644 index 000000000..ed36799fa --- /dev/null +++ b/test/backup_service/backup_service_test.go @@ -0,0 +1,172 @@ +package backupservice + +import ( + "net/http" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + + asdbv1beta1 "github.com/aerospike/aerospike-kubernetes-operator/api/v1beta1" +) + +var _ = Describe( + "Backup Service Test", func() { + var ( + backupService *asdbv1beta1.AerospikeBackupService + err error + ) + + AfterEach(func() { + Expect(deleteBackupService(k8sClient, backupService)).ToNot(HaveOccurred()) + }) + + Context( + "When doing Invalid operations", func() { + It("Should fail when wrong format backup config is given", func() { + backupService, err = newBackupService() + Expect(err).ToNot(HaveOccurred()) + + badConfig, gErr := getWrongBackupServiceConfBytes() + Expect(gErr).ToNot(HaveOccurred()) + backupService.Spec.Config.Raw = badConfig + + err = deployBackupService(k8sClient, backupService) + Expect(err).To(HaveOccurred()) + }, + ) + + It("Should fail when wrong image is given", func() { + backupService, err = newBackupService() + Expect(err).ToNot(HaveOccurred()) + + backupService.Spec.Image = "wrong-image" + + err = deployBackupServiceWithTO(k8sClient, backupService, 1*time.Minute) + Expect(err).To(HaveOccurred()) + }, + ) + }, + ) + + Context("When doing Valid operations", func() { + It("Should deploy backup service components when correct backup config is given", func() { + backupService, err = newBackupService() + Expect(err).ToNot(HaveOccurred()) + err = deployBackupService(k8sClient, backupService) + Expect(err).ToNot(HaveOccurred()) + }) + + It("Should restart backup service deployment pod when config is changed", func() { + backupService, err = newBackupService() + Expect(err).ToNot(HaveOccurred()) + err = deployBackupService(k8sClient, backupService) + Expect(err).ToNot(HaveOccurred()) + + podList, gErr := getBackupServicePodList(k8sClient, backupService) + Expect(gErr).ToNot(HaveOccurred()) + Expect(len(podList.Items)).To(Equal(1)) + + PodUID := podList.Items[0].ObjectMeta.UID + + // Get backup service object + backupService, err = getBackupServiceObj(k8sClient, name, namespace) + Expect(err).ToNot(HaveOccurred()) + + // Change config + backupService.Spec.Config.Raw = []byte(`{"service":{"http":{"port":8080}}}`) + err = updateBackupService(k8sClient, backupService) + Expect(err).ToNot(HaveOccurred()) + + podList, err = getBackupServicePodList(k8sClient, backupService) + Expect(err).ToNot(HaveOccurred()) + Expect(len(podList.Items)).To(Equal(1)) + + Expect(podList.Items[0].ObjectMeta.UID).ToNot(Equal(PodUID)) + }) + + It("Should restart backup service deployment pod when pod spec is changed", func() { + backupService, err = newBackupService() + Expect(err).ToNot(HaveOccurred()) + err = deployBackupService(k8sClient, backupService) + Expect(err).ToNot(HaveOccurred()) + + podList, gErr := getBackupServicePodList(k8sClient, backupService) + Expect(gErr).ToNot(HaveOccurred()) + Expect(len(podList.Items)).To(Equal(1)) + + PodUID := podList.Items[0].ObjectMeta.UID + + // Get backup service object + backupService, err = getBackupServiceObj(k8sClient, name, namespace) + Expect(err).ToNot(HaveOccurred()) + + // Change Pod spec + backupService.Spec.Resources = corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("0.5"), + }, + } + + err = updateBackupService(k8sClient, backupService) + Expect(err).ToNot(HaveOccurred()) + + podList, err = getBackupServicePodList(k8sClient, backupService) + Expect(err).ToNot(HaveOccurred()) + Expect(len(podList.Items)).To(Equal(1)) + + Expect(podList.Items[0].ObjectMeta.UID).ToNot(Equal(PodUID)) + }) + + It("Should change K8s service type when pod service type is changed in CR", func() { + backupService, err = newBackupService() + Expect(err).ToNot(HaveOccurred()) + err := deployBackupService(k8sClient, backupService) + Expect(err).ToNot(HaveOccurred()) + + svc, err := getBackupK8sServiceObj(k8sClient, name, namespace) + Expect(err).ToNot(HaveOccurred()) + Expect(svc.Spec.Type).To(Equal(corev1.ServiceTypeClusterIP)) + + // Get backup service object + backupService, err = getBackupServiceObj(k8sClient, name, namespace) + Expect(err).ToNot(HaveOccurred()) + + // Change service type + backupService.Spec.Service = &asdbv1beta1.Service{Type: corev1.ServiceTypeLoadBalancer} + + err = updateBackupService(k8sClient, backupService) + Expect(err).ToNot(HaveOccurred()) + + svc, err = getBackupK8sServiceObj(k8sClient, name, namespace) + Expect(err).ToNot(HaveOccurred()) + Expect(svc.Spec.Type).To(Equal(corev1.ServiceTypeLoadBalancer)) + + Eventually(func() bool { + svc, err = getBackupK8sServiceObj(k8sClient, name, namespace) + if err != nil { + return false + } + return svc.Status.LoadBalancer.Ingress != nil + }, timeout, interval).Should(BeTrue()) + + // Check backup service health using LB IP + Eventually(func() bool { + resp, err := http.Get("http://" + svc.Status.LoadBalancer.Ingress[0].IP + ":8081/health") + if err != nil { + pkgLog.Error(err, "Failed to get health") + return false + } + + defer resp.Body.Close() + + return resp.StatusCode == http.StatusOK + }, timeout, interval).Should(BeTrue()) + + }) + + }) + }, +) diff --git a/test/backup_service/helper_test.go b/test/backup_service/helper_test.go new file mode 100644 index 000000000..fe709c863 --- /dev/null +++ b/test/backup_service/helper_test.go @@ -0,0 +1,267 @@ +package backupservice + +import ( + "context" + "encoding/json" + "fmt" + "time" + + app "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/wait" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/yaml" + + asdbv1beta1 "github.com/aerospike/aerospike-kubernetes-operator/api/v1beta1" + "github.com/aerospike/aerospike-kubernetes-operator/pkg/utils" +) + +const BackupServiceImage = "aerospike.jfrog.io/ecosystem-container-prod-local/aerospike-backup-service:1.0.0" + +const ( + timeout = 2 * time.Minute + interval = 2 * time.Second +) + +func newBackupService() (*asdbv1beta1.AerospikeBackupService, error) { + configBytes, err := getBackupServiceConfBytes() + if err != nil { + return nil, err + } + + return &asdbv1beta1.AerospikeBackupService{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Spec: asdbv1beta1.AerospikeBackupServiceSpec{ + Image: BackupServiceImage, + Config: runtime.RawExtension{ + Raw: configBytes, + }, + }, + }, nil +} + +func getBackupServiceObj(cl client.Client, name, namespace string) (*asdbv1beta1.AerospikeBackupService, + error) { + var backupService asdbv1beta1.AerospikeBackupService + + if err := cl.Get(testCtx, types.NamespacedName{Name: name, Namespace: namespace}, &backupService); err != nil { + return nil, err + } + + return &backupService, nil +} + +func getBackupK8sServiceObj(cl client.Client, name, namespace string) (*corev1.Service, error) { + var svc corev1.Service + + if err := cl.Get(testCtx, types.NamespacedName{Name: name, Namespace: namespace}, &svc); err != nil { + return nil, err + } + + return &svc, nil +} +func deployBackupService(cl client.Client, backupService *asdbv1beta1.AerospikeBackupService) error { + if err := cl.Create(testCtx, backupService); err != nil { + return err + } + + return waitForBackupService(cl, backupService, timeout) +} + +func deployBackupServiceWithTO(cl client.Client, backupService *asdbv1beta1.AerospikeBackupService, + timeout time.Duration) error { + if err := cl.Create(testCtx, backupService); err != nil { + return err + } + + return waitForBackupService(cl, backupService, timeout) +} + +func updateBackupService(cl client.Client, backupService *asdbv1beta1.AerospikeBackupService) error { + if err := cl.Update(testCtx, backupService); err != nil { + return err + } + + return waitForBackupService(cl, backupService, timeout) +} + +func waitForBackupService(cl client.Client, backupService *asdbv1beta1.AerospikeBackupService, + timeout time.Duration) error { + namespaceName := types.NamespacedName{ + Name: backupService.Name, Namespace: backupService.Namespace, + } + + if err := wait.PollUntilContextTimeout( + testCtx, 1*time.Second, + timeout, true, func(ctx context.Context) (bool, error) { + if err := cl.Get(ctx, namespaceName, backupService); err != nil { + return false, nil + } + + if backupService.Status.Phase != asdbv1beta1.AerospikeBackupServiceCompleted { + pkgLog.Info(fmt.Sprintf("BackupService is in %s phase", backupService.Status.Phase)) + return false, nil + } + + podList, err := getBackupServicePodList(cl, backupService) + if err != nil { + return false, nil + } + + if len(podList.Items) != 1 { + return false, nil + } + + return true, nil + }); err != nil { + return err + } + + var cm corev1.ConfigMap + + if err := cl.Get(testCtx, namespaceName, &cm); err != nil { + return err + } + + pkgLog.Info("ConfigMap is present") + + var deploy app.Deployment + + if err := cl.Get(testCtx, namespaceName, &deploy); err != nil { + return err + } + + pkgLog.Info("Deployment is present") + + var svc corev1.Service + + if err := cl.Get(testCtx, namespaceName, &svc); err != nil { + return err + } + + pkgLog.Info("Service is present") + + return nil +} + +func getBackupServiceConfBytes() ([]byte, error) { + config := `service: + http: + port: 8081 +backup-policies: + test-policy: + parallel: 3 + remove-files: KeepAll + type: 1 + test-policy1: + parallel: 3 + remove-files: KeepAll + type: 1 +storage: + local: + path: /localStorage + type: local` + + configMap := make(map[string]interface{}) + + if err := yaml.Unmarshal([]byte(config), &configMap); err != nil { + return nil, err + } + + configBytes, err := json.Marshal(configMap) + if err != nil { + return nil, err + } + + pkgLog.Info(string(configBytes)) + + return configBytes, nil +} + +func getBackupServicePodList(cl client.Client, backupService *asdbv1beta1.AerospikeBackupService) (*corev1.PodList, + error) { + var podList corev1.PodList + + labelSelector := labels.SelectorFromSet(utils.LabelsForAerospikeBackupService(backupService.Name)) + listOps := &client.ListOptions{ + Namespace: backupService.Namespace, LabelSelector: labelSelector, + } + + if err := cl.List(context.TODO(), &podList, listOps); err != nil { + return nil, err + } + + return &podList, nil +} + +func getWrongBackupServiceConfBytes() ([]byte, error) { + config := `service: + http: + port: 8081 +backup-policies: + - test-policy: + parallel: 3 + remove-files: KeepAll + type: 1 + - test-policy1: + parallel: 3 + remove-files: KeepAll + type: 1 +storage: + local: + path: /localStorage + type: local` + + configMap := make(map[string]interface{}) + + if err := yaml.Unmarshal([]byte(config), &configMap); err != nil { + return nil, err + } + + configBytes, err := json.Marshal(configMap) + if err != nil { + return nil, err + } + + pkgLog.Info(string(configBytes)) + + return configBytes, nil +} + +func deleteBackupService( + k8sClient client.Client, + backService *asdbv1beta1.AerospikeBackupService, +) error { + deletePolicy := metav1.DeletePropagationForeground + + // Add Delete propagation policy to delete the dependent resources first + if err := k8sClient.Delete(testCtx, backService, + &client.DeleteOptions{PropagationPolicy: &deletePolicy}); err != nil && !k8serrors.IsNotFound(err) { + return err + } + + // Wait for all the dependent resources to be garbage collected by k8s + for { + _, err := getBackupServiceObj(k8sClient, backService.Name, backService.Namespace) + + if err != nil { + if k8serrors.IsNotFound(err) { + break + } + + return err + } + + time.Sleep(1 * time.Second) + } + + return nil +}