Ctrl K
ComunidadGuías…

patches/vitess-backup-schedule-test.go.txt

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package vitessbackupschedule

import (
	"context"
	"testing"
	"time"

	kbatch "k8s.io/api/batch/v1"
	corev1 "k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	planetscalev2 "planetscale.dev/vitess-operator/pkg/apis/planetscale/v2"
	"planetscale.dev/vitess-operator/pkg/operator/vttablet"
	ctrl "sigs.k8s.io/controller-runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/client/fake"
)

func TestHakopodScheduledBackupRetention(t *testing.T) {
	schedule := planetscalev2.VitessBackupSchedule{}
	schedule.Spec.JobTimeoutMinutes = 60
	strategy := planetscalev2.VitessBackupScheduleStrategy{ExtraFlags: map[string]string{"min_retention_time": "72h", "min_retention_count": "2", "min_backup_interval": "30m"}}
	spec := &vttablet.BackupSpec{}
	if err := configureScheduledBackup(spec, schedule, strategy); err != nil {
		t.Fatal(err)
	}
	if spec.MinRetentionTime != 72*time.Hour || spec.MinRetentionCount != 2 || spec.MinBackupInterval != 30*time.Minute {
		t.Fatal("retention flags were ignored")
	}
	for name, flags := range map[string]map[string]string{
		"missing":   {},
		"unbounded": {"min_retention_time": "0", "min_retention_count": "2"},
		"one-copy":  {"min_retention_time": "72h", "min_retention_count": "1"},
		"unknown":   {"database-password": "secret"},
	} {
		t.Run(name, func(t *testing.T) {
			strategy.ExtraFlags = flags
			if configureScheduledBackup(&vttablet.BackupSpec{}, schedule, strategy) == nil {
				t.Fatal("unsafe configuration accepted")
			}
		})
	}
}

func TestHakopodScheduledBackupStorageRetryAndBounds(t *testing.T) {
	scheme := runtime.NewScheme()
	for _, add := range []func(*runtime.Scheme) error{corev1.AddToScheme, kbatch.AddToScheme, planetscalev2.SchemeBuilder.AddToScheme} {
		if err := add(scheme); err != nil {
			t.Fatal(err)
		}
	}
	schedule := &planetscalev2.VitessBackupSchedule{ObjectMeta: metav1.ObjectMeta{Name: "member-recovery", Namespace: "database", UID: "schedule-one"}}
	labels := map[string]string{planetscalev2.ClusterLabel: "database", planetscalev2.KeyspaceLabel: "app", planetscalev2.ShardLabel: "x-x", planetscalev2.ComponentLabel: planetscalev2.VtbackupComponentName}
	job := &kbatch.Job{ObjectMeta: metav1.ObjectMeta{Name: "backup-current", Namespace: "database", Labels: labels}}
	spec := &vttablet.Spec{Labels: labels, DataVolumePVCSpec: &corev1.PersistentVolumeClaimSpec{AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, Resources: corev1.VolumeResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceStorage: resource.MustParse("1Gi")}}}}
	claim := func(name string) *corev1.PersistentVolumeClaim {
		pvc := vttablet.NewPVC(client.ObjectKey{Namespace: "database", Name: name}, spec)
		if err := ctrl.SetControllerReference(schedule, pvc, scheme); err != nil {
			t.Fatal(err)
		}
		return pvc
	}
	t.Run("retry-owned-claim", func(t *testing.T) {
		c := fake.NewClientBuilder().WithScheme(scheme).Build()
		r := &ReconcileVitessBackupsSchedule{client: c, scheme: scheme}
		for range 2 {
			if err := r.ensureScheduledBackupStorage(context.Background(), schedule, job, spec); err != nil {
				t.Fatal(err)
			}
		}
		var claims corev1.PersistentVolumeClaimList
		if err := c.List(context.Background(), &claims); err != nil || len(claims.Items) != 1 {
			t.Fatal("retry allocated another claim", err)
		}
	})
	t.Run("foreign-claim", func(t *testing.T) {
		pvc := claim(job.Name)
		pvc.OwnerReferences[0].UID = "foreign-schedule"
		c := fake.NewClientBuilder().WithScheme(scheme).WithObjects(pvc).Build()
		r := &ReconcileVitessBackupsSchedule{client: c, scheme: scheme}
		if r.ensureScheduledBackupStorage(context.Background(), schedule, job, spec) == nil {
			t.Fatal("accepted foreign claim")
		}
	})
	t.Run("full-storage", func(t *testing.T) {
		c := fake.NewClientBuilder().WithScheme(scheme).WithObjects(claim("first"), claim("second")).Build()
		r := &ReconcileVitessBackupsSchedule{client: c, scheme: scheme}
		if r.ensureScheduledBackupStorage(context.Background(), schedule, job, spec) == nil {
			t.Fatal("allocated a third claim")
		}
	})
	t.Run("full-pods", func(t *testing.T) {
		one := &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "one", Namespace: "database", Labels: labels}}
		two := one.DeepCopy()
		two.Name = "two"
		c := fake.NewClientBuilder().WithScheme(scheme).WithObjects(one, two).Build()
		r := &ReconcileVitessBackupsSchedule{client: c, scheme: scheme}
		if r.ensureScheduledBackupStorage(context.Background(), schedule, job, spec) == nil {
			t.Fatal("allocated storage for a third pod")
		}
	})
	t.Run("recover-crashed-job-creation", func(t *testing.T) {
		pvc := claim("old-abandoned")
		pvc.UID = "claim-one"
		pvc.CreationTimestamp = metav1.NewTime(time.Now().Add(-3 * time.Hour))
		c := fake.NewClientBuilder().WithScheme(scheme).WithObjects(pvc).Build()
		r := &ReconcileVitessBackupsSchedule{client: c, scheme: scheme}
		if r.ensureScheduledBackupStorage(context.Background(), schedule, job, spec) == nil {
			t.Fatal("did not wait for orphan cleanup")
		}
		if err := c.Get(context.Background(), client.ObjectKeyFromObject(pvc), &corev1.PersistentVolumeClaim{}); !apierrors.IsNotFound(err) {
			t.Fatal("owned orphan claim remains", err)
		}
		if err := r.ensureScheduledBackupStorage(context.Background(), schedule, job, spec); err != nil {
			t.Fatal(err)
		}
	})
}