mirror of
https://github.com/cozystack/cozystack.git
synced 2026-11-12 23:54:01 +09:00
## What this PR does Builds on the shared S3 probe from #5223 (MariaDB and CNPG), which is on `main`. Refs #4316. Backups made by the Redis strategy carry no `Backup.status.artifact` at all: no URI and no size. This covers both the Redis and Valkey apps, which share the driver. The snapshot is a single object per backup, `<namespace>/<app>/<backup>.rdb` (`redisObjectKey`). The driver already records that key in `driverMetadata`. The default strategy uploads the object using the S3 coordinates from the backup credentials Secret, which the controller projects into the application namespace (`endpoint`, `bucketName`, `region` and the access keys). When a backup completes, the driver now: 1. reads that projected Secret (`CredentialsConfig.TargetSecretName`) in the application namespace. The projector stores its `endpoint` without a scheme, and the strategy script reaches it over https; an endpoint with a path prefix is refused by minio-go, which leaves the artifact unset; 2. reads the TLS trust from the pod spec of the completed backup Job, in the order the script applies it: `ca.crt`, then `tls.crt`, from the Secret mounted as the `s3-ca` volume (`backupStorage.endpointCASecretName`). Only when there is no `s3-ca` volume does it honour `S3_INSECURE_SKIP_VERIFY=true`, and only when every container of the pod sets it, since the probe cannot tell which container uploaded. The Secret is read at probe time; the default strategy mounts `s3-ca` only when an endpoint CA is configured, so when the volume yields no CA now (the Secret is gone or lacks both keys, or the volume is not a Secret), the probe leaves the artifact unset rather than trust the system roots or skip verification where the Job may have verified. The CA is trusted on its own, as `curl --cacert` does, not on top of the system roots; 3. runs `StatObject` on the recorded key; a response without `Content-Length`, which minio-go reports as size -1, counts as unmeasured; 4. records `status.artifact.uri = s3://<bucket>/<key>` and `status.artifact.sizeBytes` = the object's size. An empty object is recorded too, but `sizeBytes` is `omitempty`, so on the Backup it reads like an unmeasured size; since a valid RDB snapshot always carries a header, a Warning `EmptySnapshot` Event on the BackupJob flags it as a broken backup. The artifact is set **only when the object is found**. A custom strategy that writes elsewhere would otherwise get a URI pointing at an object that does not exist. On any failure (Secret missing or incomplete, endpoint invalid, CA unreadable, object not found, TLS error) the artifact stays absent and the backup still succeeds. The full error is logged at info, and once the Backup is created a Normal `ArtifactNotMeasured` Event on the BackupJob gives a fixed reason, also when a failed existence check skipped the probe; the Event lives in the application namespace, so it never carries the raw error, which may name the platform's endpoint and bucket. The probe shares the 10s timeout of the MariaDB and CNPG probes. The retry check is shared with those drivers too: a `Backup` that already exists is returned without probing, a failed existence check creates the Backup without probing, a `Create` collision is resolved by reading past the cache, and an existing Backup that cannot be read back is retried with `Ready=False` instead of failing the BackupJob. The size is useful because an RDB snapshot is the compressed dataset. It shows growth, and a snapshot that is suddenly tiny is a broken backup. Kafka is deliberately left out. Its backup is a topic-metadata export of a few kilobytes, so the size would say nothing about the data and might suggest the data itself was backed up. Tests: - the stat uses the projected credentials; - every path that leaves the artifact unset: object missing, Secret missing, bucket, endpoint, access key or secret key missing, no target Secret configured, a size the endpoint did not report; - trust resolution: `ca.crt` wins over `tls.crt` and skip-verify; `items` remapping of the volume, and a key the `items` do not project is never trusted; the Redis CA volume mounted next to `s3-ca` is not taken as the S3 CA; an `s3-ca` volume that yields no CA (Secret gone, Secret without the keys, a ConfigMap source) is refused with and without skip-verify; skip-verify applies only on an exact `true` of that variable in every container, the last entry of a repeated variable winning; - the real minio client against a TLS stub: its certificate is trusted only through the `s3-ca` volume or skip-verify, a CA that did not sign it is refused even with skip-verify set on the Job, and the shared client enforces a configured CA with and without the system roots; the client sends a signed `HEAD` and parses `Content-Length`; - the Events: an unmeasured artifact or a failed existence check raises `ArtifactNotMeasured` without the raw error; an empty snapshot is recorded and raises a Warning `EmptySnapshot`; a measured artifact, a rejected `Create` and a `Create` collision raise none; - a reconcile test pinning that the completed Job's pod spec reaches the probe; a Backup that already exists is returned without a probe or a `Create`; the `Create` collision is read back from the API server past the cache. The suite fails if any guard of the trust lookup (volume name, Secret source, variable name, every-container rule, refusal of an unreadable CA), the CA enforcement in the transport, the negative-size check, the Events, the reason-only message, their place after `Create`, the empty-snapshot warning, the existing-Backup check, the wiring, any term of the Secret check, or the API-server read-back is removed. ### Screenshots N/A — no UI changes. ### Downstream repositories I walked the trigger map against the diff. The change is Go-only in `internal/backupcontroller`, with no API, CRD, chart, value or schema change. Existing `Backup` fields are now filled for one more driver. - [x] No downstream repository is affected by this change - [ ] [cozystack/website](https://github.com/cozystack/website) - follow-up: - [ ] [cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack) - follow-up: - [ ] [cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack) - follow-up: - [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up: - [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up: - [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) - follow-up: - [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) - follow-up: - [ ] [cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server) - follow-up: - [ ] [cozystack/external-apps-example](https://github.com/cozystack/external-apps-example) - follow-up: - [ ] [cozystack/examples](https://github.com/cozystack/examples) - follow-up: - [ ] [cozystack/community](https://github.com/cozystack/community) - follow-up: ### Release note ```release-note feat(backups): Redis and Valkey backups now record `status.artifact` with the `s3://` location and the size of the RDB snapshot. If the snapshot cannot be found with the platform backup credentials, the artifact stays unset and a Normal `ArtifactNotMeasured` Event on the BackupJob says why. An empty snapshot raises a Warning `EmptySnapshot` Event. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> <!-- coderabbit-ai-generated:v1 --> ## Summary by CodeRabbit * **New Features** * Redis backups now include artifact location and size when they can be measured. * Backups are still created when artifact measurement fails, with status reporting that the artifact was not measured. * **Bug Fixes** * Improved handling of existing backups and temporary read-back failures to support reliable reconciliation. * Improved compatibility with S3 endpoints using custom certificate authorities or configured TLS verification settings. * Zero-size snapshots are now reported with a warning. <!-- end of auto-generated comment: release notes by coderabbit.ai -->