Skip to content

Backup.status.artifact.sizeBytes is only ever set by the etcd strategy #4316

Closed

Description

@mattia-eleuteri

Summary

Backup.status.artifact.sizeBytes is part of the backups.cozystack.io/v1alpha1 contract and documented as "the size of the artifact in bytes, if known", but on v1.6.3 only the etcd strategy ever sets it. The cnpg, velero and mariadb strategies build an artifact carrying the URI and nothing else, so every Backup produced for a Postgres, MariaDB, VM instance or VM disk application arrives without a size.

Consumers that surface backups — the console track in #2609, and our own API on top of the same CRs — therefore have a field that is always empty for the kinds tenants actually use, with no way to tell "not measured" from "empty backup" unless they model the absence explicitly.

Evidence

At v1.6.3, sizeBytes is written in exactly one place:

internal/backupcontroller/etcdstrategy_controller.go:553
    status.Artifact = &backupsv1alpha1.BackupArtifact{
        URI:       s.URI,
        SizeBytes: s.SizeBytes,
        Checksum:  s.Checksum,
    }

The other strategies:

strategy file:line artifact built
cnpg cnpgstrategy_controller.go:577 BackupArtifact{URI: "cnpg://…"}
velero velerostrategy_controller.go:529 BackupArtifact{URI: "velero://…"} — commented "Create a basic artifact"
mariadb mariadbstrategy_controller.go:390 BackupArtifact{URI: uri}
foundationdb foundationdbstrategy_controller.go:760 BackupArtifact{URI: uri}

On a cluster running v1.6.3, 27 of 27 Backup objects across all four application kinds carry status.artifact with uri only.

The etcd strategy shows the field is wired end to end — it propagates a size the agent measured at write time. This is a parity gap, not a missing design.

Why it is not a one-line propagation

Worth stating up front, because the obvious fix does not exist for three of the four:

  • MariaDB — the cheapest. The strategy already resolves k8s.mariadb.com/storage-uri to a single object (s3://<bucket>/<ns>/mariadb/<name>). A HEAD at completion gives an exact, durable size. Note that backups.k8s.mariadb.com status carries only conditions, so there is nothing to copy from the operator — it has to be measured.
  • CNPG — backups.postgresql.cnpg.io status has no size field either (checked against the v1 CRD schema). The size lives in barman's own metadata under destination-path, so this means reading object-store metadata, not forwarding a field.
  • Velero — there may be no meaningful per-backup number at all. The data lands in a content-addressed kopia repository, so the stored size is not a per-backup quantity. DataUpload.status.progress.totalBytes is the volume read, which is a different figure and would be misleading under the name "artifact size". Leaving it absent here looks correct, and is what "if known" already allows.
  • etcd — already done.

So the realistic scope is MariaDB first, CNPG second, and an explicit decision to leave Velero absent.

Why absence matters, not just the value

Whatever gets filled, consumers need "unmeasured" to stay distinguishable from "zero bytes". sizeBytes is omitempty, so absence is already expressible on the wire — the ask is that it stays absent rather than being set to 0 when a driver cannot measure.

This is the same reasoning the MariaDB strategy already applies to the neighbouring field:

internal/backupcontroller/mariadbstrategy_controller.go:385
    // Status.Artifact carries a "this backup has an artefact at URI X"
    // signal. PVC/Volume storage has no stable URI […] so an
    // Artifact{URI: ""} is a worse signal than no Artifact at all -
    // leave it nil instead.

Proposal

  1. Populate sizeBytes in the MariaDB strategy from the object it already names.
  2. Populate it in the CNPG strategy from barman's metadata under the destination path.
  3. Decide explicitly for Velero — most likely: leave absent, and document why, so consumers stop waiting for it.
  4. Keep absence meaningful in all cases: never write 0 to mean "unknown".

Happy to send a PR for (1), which looks self-contained, if that is useful.

Related: #2609 (surfacing backup state), epic #1713.

Checked against v1.6.3 and a cluster running backup-controller:v1.6.3.

Activity

  1. added
    kind/featureCategorizes issue or PR as related to a new feature
    area/storageIssues or PRs related to storage (linstor, seaweedfs, bucket, velero, harbor)
    triage/acceptedIndicates an issue is ready to be actively worked on
    priority/important-longtermImportant over the long term, but may not be staffed and/or may need multiple releases to complete
    and removed
    triage/needs-triageIndicates an issue needs triage by a maintainer
    on Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/storageIssues or PRs related to storage (linstor, seaweedfs, bucket, velero, harbor)kind/featureCategorizes issue or PR as related to a new featurepriority/important-longtermImportant over the long term, but may not be staffed and/or may need multiple releases to completetriage/acceptedIndicates an issue is ready to be actively worked on

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions