Files
autobackup-operator/internal/controller/suite_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

88 lines
2.4 KiB
Go

package controller
import (
"context"
"fmt"
"os"
"path/filepath"
"testing"
cephv1 "git.unkin.net/unkin/cephrgw-operator/api/v1alpha1"
k8upv1 "github.com/k8up-io/k8up/v2/api/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest"
)
var (
testEnv *envtest.Environment
k8sClient client.Client
envtestReady bool
)
func TestMain(m *testing.M) {
utilruntime.Must(cephv1.AddToScheme(clientgoscheme.Scheme))
utilruntime.Must(k8upv1.AddToScheme(clientgoscheme.Scheme))
testEnv = &envtest.Environment{
CRDDirectoryPaths: []string{filepath.Join("..", "..", "test", "crds")},
ErrorIfCRDPathMissing: true,
}
cfg, err := testEnv.Start()
if err != nil {
// envtest binaries (KUBEBUILDER_ASSETS) may be unavailable; run the
// pure-unit tests and skip the controller tests.
fmt.Fprintf(os.Stderr, "envtest unavailable, skipping controller tests: %v\n", err)
os.Exit(m.Run())
}
k8sClient, err = client.New(cfg, client.Options{Scheme: clientgoscheme.Scheme})
if err != nil {
fmt.Fprintf(os.Stderr, "failed to build client: %v\n", err)
os.Exit(1)
}
envtestReady = true
code := m.Run()
_ = testEnv.Stop()
os.Exit(code)
}
func requireEnvtest(t *testing.T) {
t.Helper()
if !envtestReady {
t.Skip("envtest not available (KUBEBUILDER_ASSETS unset)")
}
}
func newNamespace(t *testing.T, ctx context.Context) string {
t.Helper()
name := fmt.Sprintf("test-%s", randSuffix())
ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: name}}
if err := k8sClient.Create(ctx, ns); err != nil {
t.Fatalf("create namespace: %v", err)
}
return name
}
func createDestinations(t *testing.T, ctx context.Context, ns string) {
t.Helper()
cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "autobackup-destinations", Namespace: ns},
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",
},
}
if err := k8sClient.Create(ctx, cm); err != nil {
t.Fatalf("create destinations configmap: %v", err)
}
}
var suffixCounter int
func randSuffix() string {
suffixCounter++
return fmt.Sprintf("%d", suffixCounter)
}