# autobackup-operator A Kubernetes operator that watches for `backups.unkin.net/*` annotations on **PersistentVolumeClaims** and **CloudNativePG Clusters** and provisions the S3 bucket + backup-schedule resources needed to back them up. No new CRDs — it is purely annotation-driven on existing objects. ## Annotations | Annotation | Meaning | |---|---| | `backups.unkin.net/schedule` | `@hourly` / `@daily` / `@weekly` (plus `@monthly`/`@yearly`) or a raw cron expression. Absence means "not managed". | | `backups.unkin.net/destination` | A logical destination name resolved via the destinations ConfigMap. | | `backups.unkin.net/purge-on-delete` | `"true"` opts into deleting the bucket stack when the schedule annotation is removed (default: retain bucket data). | ## What it does For every annotated object the operator, in the object's own namespace and owner-referenced to it: 1. Provisions a cephrgw (`ceph.unkin.net/v1alpha1`) `ObjectStoreUser`, `Bucket` (`versioning: true`, `retainOnDelete: true`) and read-write `BucketAccess`. 2. Waits for the `BucketAccess` to become `Ready` (requeues until then). 3. Then wires up the backup schedule: - **PVC → k8up** (`k8up.io/v1` `Schedule`): S3 backend from the cephrgw credential Secret, an auto-generated restic repo-password Secret, and the backup scoped to exactly this PVC via `spec.backup.volumes[].persistentVolumeClaim.claimName`. Sane prune retention (keepDaily 7, keepWeekly 4). - **CNPG Cluster** (`postgresql.cnpg.io/v1`): patches `spec.backup.barmanObjectStore` (idempotently; a user-set different `destinationPath` is left untouched with a Warning event) and creates a `ScheduledBackup` with a 6-field (seconds-first) cron. ## Destinations ConfigMap The operator resolves `destination` names against a ConfigMap in its own namespace (`autobackup-operator/autobackup-destinations` by default). See `config/samples/destinations.yaml`. ## Deploy ```sh kubectl apply -k config ``` The `config/kustomization.yaml` orders the `Namespace` first so the ServiceAccount, RBAC and Deployment land in an existing namespace. RBAC covers both the controllers' resources (`config/rbac/role.yaml`) and the leader-election lease/events the manager needs when run with `--leader-elect` (`config/rbac/leader_election_role.yaml`). Then create the destinations ConfigMap (see `config/samples/destinations.yaml`). ## Schedule mapping - **k8up** accepts cron nicknames natively and 5-field cron expressions; the value is validated and passed through. - **CNPG** requires a 6-field (seconds-first) cron: nicknames are expanded and a 5-field cron gains a leading `0` seconds field. Invalid schedules surface as Warning events on the annotated object. ## Development ```sh make build # build the operator binary make test # unit + envtest controller tests (fetches envtest binaries) make lint # go vet make generate # regenerate config/rbac/role.yaml from kubebuilder markers ``` Dependencies are vendored so the container build and CI need no access to the private `cephrgw-operator` module. ## Release `make patch|minor|major` tags and pushes `vX.Y.Z`. A `v*` tag triggers the Woodpecker `docker` pipeline, which builds and pushes `artifactapi.k8s.syd1.au.unkin.net/docker-internal/autobackup-operator:`.