Repository navigation
bug(backups): RestoreJob targetApplicationRef rename is silently ignored for Velero-backed non-VM apps #3537
Description
Summary
A RestoreJob (backups.cozystack.io/v1alpha1) that requests a rename via
spec.targetApplicationRef.name into a different namespace reports
phase: Succeeded, but the application is restored under the original
name. The requested target name is silently ignored. This affects every
non-VM application backed by the Velero strategy (Postgres, MariaDB,
ClickHouse, MongoDB).
For the same-namespace case the rename is instead hard-rejected, so there is
no working path to restore such an application under a new name via the
Velero strategy.
Observed on backup-controller v1.6.0-rc.4; the same code is present on
main (internal/backupcontroller/velerostrategy_controller.go).
Steps to reproduce
-
Use a
BackupClassthat mapsPostgresto theVelerostrategy. -
Create a
BackupJobfor a Postgres appsrcand let it complete. -
Apply a
RestoreJob:apiVersion: backups.cozystack.io/v1alpha1 kind: RestoreJob metadata: generateName: src-restore- namespace: <tenant-namespace> spec: backupRef: name: src-sb targetApplicationRef: apiGroup: apps.cozystack.io kind: Postgres name: dst options: targetNamespace: <other-namespace>
Expected
Either the application is restored as dst, or the RestoreJob fails with a
clear message stating that rename is not supported for this application kind
via the Velero strategy.
Actual
RestoreJob reports phase: Succeeded, but the restored application keeps
the original name src. targetApplicationRef.name has no effect.
For options.targetNamespace equal to the source namespace (or omitted) with
a different targetApplicationRef.name, the RestoreJob fails with:
restoring to the same namespace with a different application name is not
supported due to Velero DataUpload limitations: data is always uploaded to
PVCs with the original name. Use options.targetNamespace to restore into a
different namespace
Root cause
postRestoreRename (velerostrategy_controller.go:1014) is the only place
that applies the rename, and it hardcodes the VMInstance HelmRelease prefix:
sourceHRName := vmNamePrefix + sourceAppName // "vm-instance-src"
targetHRName := vmNamePrefix + target.AppName // "vm-instance-dst"
oldHR, err := hrClient.Get(ctx, sourceHRName, metav1.GetOptions{})
if errors.IsNotFound(err) {
return nil // silent no-op
}A Postgres application's HelmRelease is named after the app itself (no
vm-instance- prefix), so the Get returns NotFound, the function returns
nil, and the reconcile proceeds to mark the RestoreJob Succeeded
(velerostrategy_controller.go:719). The rename never happens and no error
is surfaced.
Why this cannot be fixed by just generalizing the HelmRelease name
The VM rename path relies on CDI claim adoption: renamePVC rebinds the
old PV, the DataVolume is deleted with Orphan propagation, and the restored
PVC carries cdi.kubevirt.io/allowClaimAdoption: true so the freshly
rendered DataVolume adopts the existing PVC.
CNPG has no equivalent adoption mechanism. A freshly reconciled
Cluster dst bootstraps a new empty database into new PVCs (dst-1, ...)
instead of adopting the restored volumes, which Velero DataUpload always
writes under the original name. Renaming the HelmRelease (and even the PVCs)
therefore yields an empty dst plus orphaned src volumes.
The correct way to restore a Postgres under a new name is engine-native
recovery (CNPG bootstrap.recovery into a new cluster), i.e. the CNPG
strategy, not the Velero strategy.
Proposed fix
Short term (correctness): make the rename path kind-aware and fail the
RestoreJob explicitly when a rename is requested for a Velero-backed
application kind that does not support it, mirroring the existing
same-namespace guard (velerostrategy_controller.go:604). A silent
Succeeded under the wrong name is worse than an explicit failure.
Longer term (feature): support rename-on-restore for non-VM apps through
engine-native recovery (e.g. CNPG bootstrap.recovery) rather than the
Velero DataUpload path.
Activity
fix(backups): fail Velero RestoreJob rename for non-VMInstance kinds
fix(backups): fail Velero RestoreJob rename for non-VMInstance kinds (c…