Summary
Implement a reusable Go package that derives per-item backup outcomes from Velero backup metadata and rolls them up to a logical grouping target (e.g. owning VirtualMachine).
Parent: #269 (OADP-8697)
Design: oadp-operator/docs/design/backup_resource_rollup-design.md (local; pending upstream PR — see parent #269)
Why
Velero does not publish a structured per-item outcome index. Integrators must join:
<backup>-resource-list.json.gz (inventory)
<backup>-results.gz (unstructured error strings)
<backup>-volumeinfo.json.gz (PVC-scoped volume results)
<backup>-itemoperations.json.gz (async PVC ops; may disagree with results — see velero#9377)
<backup>.tar.gz manifests (for ownerReferences when cluster objects are gone)
This package centralizes that logic so the CLI and future consumers do not duplicate fragile parsing.
Scope
1. Error/warning structurer
Parse results.gz Velero error strings into {groupResource, namespace, name, message}:
- Shape A:
error executing custom action (groupResource=..., namespace=..., name=...): ...
- Shape B:
name: /X message: /... → resolve kind via resource-list cross-reference (do not assume name is always the same resource type)
Unrecognized patterns → Unstructured bucket (never drop).
2. Metadata fetch + merge
Use existing Velero client/persistence APIs (same patterns as backup describe/logs — avoid direct S3 access unless already used elsewhere in oadp-cli).
Merge resource-list, structured errors, volumeinfo, and itemoperations into a unified per-item view.
3. Ownership graph
Build ownerReferences graph from:
- Live cluster (preferred when namespace still exists)
- Backup tarball manifests (fallback for deleted namespaces)
Walk controller: true refs upward per grouping strategy:
owner:<Kind> (e.g. VirtualMachine)
owner (topmost)
label:<key> (flat grouping, no graph walk)
4. Rollup semantics
Per group: Succeeded | Failed | Skipped + deduplicated reasons/messages.
Optional reason-code classifier: MissingPVC, MissingDataSource, MissingDataVolume, DataUploadFailed, Unknown.
Suggested package location
pkg/backuprollup/ (or follow existing oadp-cli package conventions)
Tests
Unit tests with recorded fixtures (no live cluster required):
oadp-8697-multi-vm-backup — 5 VMs, 2 failures (PartiallyFailed)
vmfr-test-backup-202608070835 — PVC-level error (name: is PVC, not VM)
vmfr-test-backup — Completed success path
Fixtures can be copied from oadp-operator repro artifacts or regenerated from a test cluster.
Non-goals
- CLI formatting / cobra commands (separate issue)
- Velero upstream changes
- KubeVirt-specific
spec.template.spec.volumes[] parsing (use ownerReferences instead)
Acceptance criteria
Summary
Implement a reusable Go package that derives per-item backup outcomes from Velero backup metadata and rolls them up to a logical grouping target (e.g. owning
VirtualMachine).Parent: #269 (OADP-8697)
Design:
oadp-operator/docs/design/backup_resource_rollup-design.md(local; pending upstream PR — see parent #269)Why
Velero does not publish a structured per-item outcome index. Integrators must join:
<backup>-resource-list.json.gz(inventory)<backup>-results.gz(unstructured error strings)<backup>-volumeinfo.json.gz(PVC-scoped volume results)<backup>-itemoperations.json.gz(async PVC ops; may disagree with results — see velero#9377)<backup>.tar.gzmanifests (forownerReferenceswhen cluster objects are gone)This package centralizes that logic so the CLI and future consumers do not duplicate fragile parsing.
Scope
1. Error/warning structurer
Parse
results.gzVelero error strings into{groupResource, namespace, name, message}:error executing custom action (groupResource=..., namespace=..., name=...): ...name: /X message: /...→ resolvekindvia resource-list cross-reference (do not assumenameis always the same resource type)Unrecognized patterns →
Unstructuredbucket (never drop).2. Metadata fetch + merge
Use existing Velero client/persistence APIs (same patterns as
backup describe/logs— avoid direct S3 access unless already used elsewhere in oadp-cli).Merge resource-list, structured errors, volumeinfo, and itemoperations into a unified per-item view.
3. Ownership graph
Build
ownerReferencesgraph from:Walk
controller: truerefs upward per grouping strategy:owner:<Kind>(e.g.VirtualMachine)owner(topmost)label:<key>(flat grouping, no graph walk)4. Rollup semantics
Per group:
Succeeded|Failed|Skipped+ deduplicated reasons/messages.Optional reason-code classifier:
MissingPVC,MissingDataSource,MissingDataVolume,DataUploadFailed,Unknown.Suggested package location
pkg/backuprollup/(or follow existing oadp-cli package conventions)Tests
Unit tests with recorded fixtures (no live cluster required):
oadp-8697-multi-vm-backup— 5 VMs, 2 failures (PartiallyFailed)vmfr-test-backup-202608070835— PVC-level error (name:is PVC, not VM)vmfr-test-backup— Completed success pathFixtures can be copied from oadp-operator repro artifacts or regenerated from a test cluster.
Non-goals
spec.template.spec.volumes[]parsing (useownerReferencesinstead)Acceptance criteria