Files
autobackup-operator/internal/controller/destinations_test.go
T
unkin-agent 9da206dc7c Implement autobackup-operator controllers, tests, CI and packaging
PVCs and CloudNativePG Clusters need S3 buckets and backup schedules
provisioned consistently. This operator watches the
backups.unkin.net/{schedule,destination} annotations on those objects and
provisions everything needed to back them up, with no new CRDs.

- Add a PVC controller that provisions cephrgw ObjectStoreUser/Bucket/BucketAccess,
  auto-generates a restic repo-password Secret and creates a k8up Schedule scoped
  to the PVC via spec.backup.volumes[].persistentVolumeClaim.claimName.
- Add a CNPG Cluster controller that provisions the same bucket stack, idempotently
  patches spec.backup.barmanObjectStore (leaving a user-set destinationPath alone
  with a Warning event) and creates a ScheduledBackup.
- Resolve destinations through a ConfigMap lookup table; requeue until the
  BucketAccess is Ready before creating schedule resources; own-reference created
  resources and retain bucket data by default.
- Add schedule-mapping helpers (k8up 5-field/shortcut pass-through, CNPG 6-field
  seconds-first) and deterministic, length-bounded name derivation.
- Add unit tests (schedule mapping, name derivation, destination resolution) and
  envtest controller tests for both paths, wiring the external CRDs into envtest.
- Add kubebuilder-generated RBAC, a Dockerfile (distroless/nonroot), Woodpecker
  lint/test/build pipelines and a tag-triggered image push to the artifactapi
  docker-internal registry, plus a version-bump Makefile and deploy manifests.
2026-08-14 00:08:37 +10:00

71 lines
2.6 KiB
Go

package controller
import (
"context"
"errors"
"testing"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
)
func destClient(t *testing.T, objs ...runtime.Object) *fake.ClientBuilder {
t.Helper()
return fake.NewClientBuilder().WithScheme(clientgoscheme.Scheme).WithRuntimeObjects(objs...)
}
func TestResolveDestinationHit(t *testing.T) {
cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "autobackup-destinations", Namespace: "autobackup-operator"},
Data: map[string]string{
"cephs3_ec4_1": "placementTarget: cephs3_ec4_1\nzonegroup: au\nendpoint: https://s3.ceph.unkin.net\nendpointCASecret: vault-ca-cert\nendpointCAKey: ca.crt\n",
},
}
c := destClient(t, cm).Build()
d, err := resolveDestination(context.Background(), c, "autobackup-operator", "autobackup-destinations", "cephs3_ec4_1")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if d.PlacementTarget != "cephs3_ec4_1" || d.Zonegroup != "au" || d.Endpoint != "https://s3.ceph.unkin.net" {
t.Errorf("unexpected destination: %+v", d)
}
if d.EndpointCASecret != "vault-ca-cert" || d.EndpointCAKey != "ca.crt" {
t.Errorf("unexpected CA fields: %+v", d)
}
}
func TestResolveDestinationMissEntry(t *testing.T) {
cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "autobackup-destinations", Namespace: "autobackup-operator"},
Data: map[string]string{"other": "endpoint: https://x\n"},
}
c := destClient(t, cm).Build()
_, err := resolveDestination(context.Background(), c, "autobackup-operator", "autobackup-destinations", "cephs3_ec4_1")
if !errors.Is(err, errDestinationNotFound) {
t.Errorf("expected errDestinationNotFound, got %v", err)
}
}
func TestResolveDestinationMissConfigMap(t *testing.T) {
c := destClient(t).Build()
_, err := resolveDestination(context.Background(), c, "autobackup-operator", "autobackup-destinations", "cephs3_ec4_1")
if !errors.Is(err, errDestinationNotFound) {
t.Errorf("expected errDestinationNotFound, got %v", err)
}
}
func TestResolveDestinationMissingEndpoint(t *testing.T) {
cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "autobackup-destinations", Namespace: "autobackup-operator"},
Data: map[string]string{"noendpoint": "placementTarget: x\n"},
}
c := destClient(t, cm).Build()
_, err := resolveDestination(context.Background(), c, "autobackup-operator", "autobackup-destinations", "noendpoint")
if err == nil {
t.Errorf("expected error for missing endpoint")
}
}