* Add block data mover support for Velero backup/restore describe CLI.
Update output tests to accommodate RestoreType in VolumeInfo
This commit addresses the compilation and assertion errors caused by the introduction of `RestoreType` in `VolumeInfo` and the separation of `SnapshotDataMovementInfo` / `PodVolumeInfo` into their backup and restore counterparts. It fixes references across the test fixtures and the print guard conditions in `restore_describer.go`.
* Modify according to comments
* Add missing JSON tag in the VolumeInfo structures.
* Get uploaderType from the DU and DD's dataMover for the data mover volume info.
* Add IncrementalSize in the data mover volume info.
* Add existingVolumeDataPolicy and restoreType in the restore describe CLI output
* Add more UTs.
* Add some fields value setting that were previously missed.
* Fix the timestamp compare error only found in the GitHub action.
Signed-off-by: Xun Jiang <xun.jiang@broadcom.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* test: Unify duplicate test harness structs in restore and delete tests
Extract the duplicated test harness (fakeRestorer, Harness struct, and
AddResource/AddItems helpers) from restore_test.go and
delete_item_action_handler_test.go into a shared pkg/test.Harness.
Backup tests are intentionally excluded: the shared AddResource strips
metadata.creationTimestamp and status (restore semantics), which would
change what the backup tests tar up and assert on.
Signed-off-by: opbot_xd <awasthikrishna23052005@gmail.com>
* ci: retry
Signed-off-by: opbot_xd <awasthikrishna23052005@gmail.com>
* ci: retry
Signed-off-by: opbot_xd <awasthikrishna23052005@gmail.com>
---------
Signed-off-by: opbot_xd <awasthikrishna23052005@gmail.com>
* Report a measured zero incremental instead of erasing it
A CBT incremental with an exactly zero delta -- nothing changed since
the parent -- was reported identically to a backup that moved the whole
device. `velero backup describe --details` printed only
"Moved data Size (bytes): 3221225472" with no incremental line, and
status.incrementalBytes was absent, for a run that transferred nothing.
The best possible CBT outcome displayed as the worst, and was
indistinguishable from a genuine full, a whole-device fallback, or a
backup predating incremental accounting.
The zero was being erased twice. Besides the API status fields,
datapath.BackupResult also carried omitempty, and that struct crosses a
JSON boundary from the data mover pod to the controller (see
micro_service_watcher.go), so the value was destroyed before the
controller could persist it. Every uploader always reports a figure
there, so 0 internally always means "transferred nothing" -- dropping
omitempty is sufficient and correct for that hop.
The API fields move to *int64 rather than just dropping omitempty. The
field shipped in v1.18.0-v1.18.2, so backups exist whose stored volume
info has no incrementalSize at all; with a plain int64 those unmarshal
to 0 and would render "Incremental data Size (bytes): 0", a false claim
of a perfect incremental on a run that never measured one. nil means not
measured, a pointer to 0 means measured zero. Both fields already carry
+optional, so the generated CRD schema is unchanged and no regeneration
is required.
Display gates relax from > 0 to != nil in all three places, including
volumesByPod.Add, whose signature takes *int64 now; the restore describer
passes nil, which is correct since restores measure no incremental.
Verified live: the same zero-delta scenario that reported <none> now
reports 0 and renders "Incremental data Size (bytes): 0", while an older
backup described with the new client still correctly prints no
incremental line at all.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com>
(cherry picked from commit 6c7aa9d588f6d5eab134d4ce19c92b838f45557c)
Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com>
* gofmt: fix import ordering in backup_test.go
Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com>
* Regenerate CRDs for IncrementalBytes pointer type
make update-crd was missed in the original commit. Regenerated with
the pinned controller-gen v0.16.5 to avoid unrelated version-annotation
churn across other CRDs.
Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com>
* Add changelog for #10309
Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com>
* Address review: make IncrementalBytes a pointer to preserve backward compat
Per Lyndon-Li's review on #10309: dropping omitempty on the plain int64
field breaks compatibility with a data mover from release-1.17 or
earlier that predates IncrementalBytes and never writes the key -- the
new controller would unmarshal a zero value ("nothing transferred")
instead of recognizing the field is simply absent ("not measured").
Switch to *int64 with omitempty restored:
- an old mover's omitted key unmarshals to nil ("not measured")
- a current mover's genuine zero still serializes the key, unmarshaling
to a non-nil pointer to 0 ("measured zero")
- nonzero values work exactly as before
- an old controller can still unmarshal a numeric value from a new mover
pkg/controller/data_upload_controller.go and pod_volume_backup_controller.go
assign the wire-struct field directly to their already-*int64,omitempty
CRD status field instead of re-wrapping it with ptr.To, since both are
now the same pointer type.
Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com>
* Fix CI: update marshal-fail test assertions for IncrementalBytes pointer
Both backup_micro_service_test.go files hardcoded the %v-formatted
zero-value BackupResult struct in an error-message assertion. Now that
IncrementalBytes is *int64, its zero value prints as <nil> instead of 0.
Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com>
---------
Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit double checks the label of the VSC on the cluster before
deleting it to avoid mis-deletion.
Signed-off-by: Daniel Jiang <daniel.jiang@broadcom.com>
Refactor function ShouldPerformCustomAction and GetActionParameters:
extract shared code to a new function getPVAndMatchAction.
Signed-off-by: Xun Jiang <xun.jiang@broadcom.com>
* Add SnapshotClassParameter constant and GetSnapshotClass getter
Add a new snapshotClass action parameter to volume policies, allowing
users to specify which VolumeSnapshotClass to use for CSI snapshots.
This follows the existing dataMover parameter pattern with a typed
constant and getter method on the Action struct.
Ref: #8807
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Add snapshotClass parameter validation
Validate the snapshotClass parameter in Action.validate(): it must only
appear on snapshot actions, must be a string, and must not be empty.
Follows the same validation pattern as the dataMover parameter.
Ref: #8807
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Add volume policy tier to VolumeSnapshotClass selection
Add GetVolumeSnapshotClassFromVolumePolicy helper and extend
GetVolumeSnapshotClass with a policySnapshotClass parameter. The new
tier sits between PVC annotation and backup annotation in the priority
chain: PVC annotation > volume policy > backup annotation > VSC label.
Ref: #8807
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Wire snapshotClass from volume policy through CSI plugin
In pvcBackupItemAction.Execute, call GetActionParameters to extract the
snapshotClass from the matched volume policy and pass it through
getVolumeSnapshotReference and createVolumeSnapshot to
GetVolumeSnapshotClass. This connects the volume policy parameter to
the CSI snapshot creation path.
Fixes#8807
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Add changelog for PR #10070
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Document snapshotClass volume policy parameter
Add documentation for the new snapshotClass parameter in the volume
policy snapshot action. Update the CSI docs to include volume policy
as a tier in the VolumeSnapshotClass selection priority, and add
Example 6 to resource-filtering.md showing multi-array usage.
Ref: #8807
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Fix import ordering in pvc_action.go
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Add end-to-end test for snapshotClass volume policy parameter
Verify that when a volume policy specifies snapshotClass, the CSI
plugin creates a VolumeSnapshot using that VolumeSnapshotClass. The
test uses a VSC without the velero label to confirm selection comes
from the volume policy parameter, not the label-based fallback.
Ref: #8807
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Fix gofmt struct field alignment in pvc_action_test.go
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Add GetSnapshotClass to VolumeHelper interface
Add a GetSnapshotClass method to VolumeHelper that encapsulates the
extraction of the snapshotClass parameter from volume policy actions.
This avoids requiring callers to parse raw parameters from
GetActionParameters. Simplify the CSI plugin to use the new method.
Ref: #8807
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Fix gofmt formatting in resource_policies.go
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
---------
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
Modify the logs.
Modify the CRD's data mover's comment.
Modify the resource policy's GetDataMover for default data mover case.
Signed-off-by: Xun Jiang <xun.jiang@broadcom.com>
archive.GetItemFilePath/GetVersionedItemFilePath joined the group resource,
namespace and name into a path without checking the result against rootDir.
Those components can come from backup contents - the additional items a
RestoreItemAction returns are built from annotations on a backed up object -
so a component containing ".." resolved to an arbitrary file on the Velero
pod, which was then Stat'd, unmarshalled and restored as a Kubernetes object.
Both helpers now return an error when the joined path escapes rootDir, and all
callers handle it. rootDir is empty when building an entry path inside the
backup tarball, so "." is used as the containment base for that relative form.
Signed-off-by: chlins <chlins.zhang@gmail.com>
Add a GetSnapshotClass method to VolumeHelper that encapsulates the
extraction of the snapshotClass parameter from volume policy actions.
This avoids requiring callers to parse raw parameters from
GetActionParameters. Simplify the CSI plugin to use the new method.
Ref: #8807
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
Validate the snapshotClass parameter in Action.validate(): it must only
appear on snapshot actions, must be a string, and must not be empty.
Follows the same validation pattern as the dataMover parameter.
Ref: #8807
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
Add a new snapshotClass action parameter to volume policies, allowing
users to specify which VolumeSnapshotClass to use for CSI snapshots.
This follows the existing dataMover parameter pattern with a typed
constant and getter method on the Action struct.
Ref: #8807
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Support set-based filter label selectors
Use matchLabels/matchExpressions in fine-grained filters.
Signed-off-by: Adam Zhang <adam.zhang@broadcom.com>
* omit the details of resource policy for cli
The reason to not resolve and display CLI is because it may go
out of sync, we want to avoid display it to mislead users.
We may consider to cpature those information and display it
in later release.
Signed-off-by: Adam Zhang <adam.zhang@broadcom.com>
---------
Signed-off-by: Adam Zhang <adam.zhang@broadcom.com>
Co-authored-by: Scott Seago <sseago@redhat.com>
The Kubernetes image volume type (GA in k8s 1.31) was not recognized by
Velero's volume type detection logic, causing volume policies with
volumeTypes condition set to "image" to be silently ignored. This led
to failed fs-backups when defaultVolumesToFsBackup was enabled, since
image volumes have no host path for the node agent to back up.
Add the "image" SupportedVolume constant and detection in
getVolumeTypeFromVolume() so that volume policies can properly match
and skip image volumes.
Fixesvelero-io/velero#9977
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
For resource policy in restore, it will reject invalid sections
such as volumePolicies or includeExcludePolicy, to prevent user
from misuse backup side resource policy configmap.
Signed-off-by: Adam Zhang <adam.zhang@broadcom.com>
Add resourcePolicy field for restore CRD which is backed by
a configmap that holds ClusterScopedFilterPolicy and
NamespacedFilterPolicies for restore side filtering.
Signed-off-by: Adam Zhang <adam.zhang@broadcom.com>
Fixes a flaky test in TestWaitExecHandleHooks:
"should return no error with 2 spec hooks in 2 different containers,
1st container starts running after 10ms, 2nd container after 20ms,
both succeed"
Observed failure (CI run https://github.com/velero-io/velero/actions/runs/28119573625/job/83267758421):
mock: Unexpected Method Call
ExecutePodCommand called with resourceVersion:"3" (both containers running),
but mock was registered expecting resourceVersion:"2" (container1 running,
container2 still waiting).
Root cause: the two source.Modify calls were 10ms apart. The informer's
DeltaFIFO queue can coalesce rapid updates, delivering only the latest pod
state (resourceVersion:3) to the handler before the hook for container1 fires.
The comment "each of these states will be seen by the UpdateFunc handler" was
incorrect — intermediate states can be silently skipped under load.
Fix: add waitForSignal chan struct{} to the change struct and onCalled func()
to the expectedExecution struct. The goroutine now blocks after sending the
first change until the mock signals that the hook has fired (via close), then
sends the second change. This guarantees the handler observes the intermediate
pod state (resourceVersion:2) when executing container1's hook.
Signed-off-by: Lubron Zhan <lubronzhan@gmail.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Change errors.Cause to errors.Is, because github.com/cockroachdb/errors
New() function create a error with error stack with depth 1, but
github.com/pkg/errors's New() function create error with no depth.
Signed-off-by: Xun Jiang <xun.jiang@broadcom.com>
Merge validateNoDuplicateNamespacePatterns and validateGlobPatterns
into validateNamespacedFilterPolicies to avoid iterate the policies
multiple times.
Signed-off-by: Adam Zhang <adam.zhang@broadcom.com>
Add validation rules for NamespacedFilterPolicies to fail fast
for invalid NamespacedFilterPolicies.
Signed-off-by: Adam Zhang <adam.zhang@broadcom.com>
- added ClusterScopedFilterPolicy/NamespacedFilterPolicy
- added run time data structure, ResolvedResourceFilter and ResolvedNamespaceFilter
Signed-off-by: Adam Zhang <adam.zhang@broadcom.com>
* Fix UT failures caused by client-go version bump.
* Some modifications to enhance the UT stability.
* Fix UT errors: non-constant format string in call to ...
* Fix linter issues.
Signed-off-by: Xun Jiang <xun.jiang@broadcom.com>
* Fix VolumeGroupSnapshot restore on Ceph RBD
This PR fixes two related issues affecting CSI snapshot restore on Ceph RBD:
1. VolumeGroupSnapshot restore fails because Ceph RBD populates
volumeGroupSnapshotHandle on pre-provisioned VSCs, but Velero doesn't
create the required VGSC during restore.
2. CSI snapshot restore fails because VolumeSnapshotClassName is removed
from restored VSCs, preventing the CSI controller from getting
credentials for snapshot verification.
Changes:
- Capture volumeGroupSnapshotHandle during backup as VS annotation
- Create stub VGSC during restore with matching handle in status
- Look up VolumeSnapshotClass by driver and set on restored VSC
Fixes#9512Fixes#9515
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Add changelog for VGS restore fix
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Fix gofmt import order
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Add changelog for VGS restore fix
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Fix import alias corev1 to corev1api per lint config
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Fix: Add snapshot handles to existing stub VGSC and add unit tests
When multiple VolumeSnapshots from the same VolumeGroupSnapshot are
restored, they share the same VolumeGroupSnapshotHandle but have
different individual snapshot handles. This commit:
1. Fixes incomplete logic where existing VGSC wasn't updated with
new snapshot handles (addresses review feedback)
2. Fixes race condition where Create returning AlreadyExists would
skip adding the snapshot handle
3. Adds comprehensive unit tests for ensureStubVGSCExists (5 cases)
and addSnapshotHandleToVGSC (4 cases) functions
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Clean up stub VolumeGroupSnapshotContents during restore finalization
Add cleanup logic for stub VGSCs created during VolumeGroupSnapshot restore.
The stub VGSCs are temporary objects needed to satisfy CSI controller
validation during VSC reconciliation. Once all related VSCs become
ReadyToUse, the stub VGSCs are no longer needed and should be removed.
The cleanup runs in the restore finalizer controller's execute() phase.
Before deleting each VGSC, it polls until all related VolumeSnapshotContents
(correlated by snapshot handle) are ReadyToUse, with a timeout fallback.
Deletion failures and CRD-not-installed scenarios are treated as warnings
rather than errors to avoid failing the restore.
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Fix lint: remove unused nolint directive and simplify cleanupStubVGSC return
The cleanupStubVGSC function only produces warnings (not errors), so
simplify its return signature. Also remove the now-unused nolint:unparam
directive on execute() since warnings are no longer always nil.
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
---------
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Fix DBR stuck when CSI snapshot no longer exists in cloud provider
During backup deletion, VolumeSnapshotContentDeleteItemAction creates a
new VSC with the snapshot handle from the backup and polls for readiness.
If the underlying snapshot no longer exists (e.g., deleted externally),
the CSI driver reports Status.Error but checkVSCReadiness() only checks
ReadyToUse, causing it to poll for the full 10-minute timeout instead of
failing fast. Additionally, the newly created VSC is never cleaned up on
failure, leaving orphaned resources in the cluster.
This commit:
- Adds Status.Error detection in checkVSCReadiness() to fail immediately
on permanent CSI driver errors (e.g., InvalidSnapshot.NotFound)
- Cleans up the dangling VSC when readiness polling fails
Fixes#9579
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Add changelog for PR #9581
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
* Fix typo in pod_volume_test.go: colume -> volume
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
---------
Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
Use typed error approach: Make GetPVForPVC return ErrPVNotFoundForPVC
when PV is not expected to be found (unbound PVC), then use errors.Is
to check for this error type. When a matching policy exists (e.g.,
pvcPhase: [Pending, Lost] with action: skip), apply the action without
error. When no policy matches, return the original error to preserve
default behavior.
Changes:
- Add ErrPVNotFoundForPVC sentinel error to pvc_pv.go
- Update ShouldPerformSnapshot to handle unbound PVCs with policies
- Update ShouldPerformFSBackup to handle unbound PVCs with policies
- Update item_backupper.go to handle Lost PVCs in tracking functions
- Remove checkPVCOnlySkip helper (no longer needed)
- Update tests to reflect new behavior
Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit implements VolumePolicy support for PVC Phase conditions, resolving
vmware-tanzu/velero#7233 where backups fail with ''PVC has no volume backing this claim''
for Pending PVCs.
Changes made:
- Extended VolumePolicy API to support PVC phase conditions
- Added pvcPhaseCondition struct with matching logic
- Modified getMatchAction() to evaluate policies for unbound PVCs before returning errors
- Added case to GetMatchAction() to handle PVC-only scenarios (nil PV)
- Added comprehensive unit tests for PVC phase parsing and matching
Users can now skip Pending PVCs through volume policy configuration:
apiVersion: v1
kind: ConfigMap
metadata:
name: volume-policy
namespace: velero
data:
policy.yaml: |
version: v1
volumePolicies:
- conditions:
pvcPhase: [Pending]
action:
type: skip
chore: rename changelog file to match PR #9166
Renamed changelogs/unreleased/7233-claude to changelogs/unreleased/9166-claude
to match the opened PR at https://github.com/vmware-tanzu/velero/pull/9166
docs: Add PVC phase condition support to VolumePolicy documentation
- Added pvcPhase field to YAML template example
- Documented pvcPhase as a supported condition in the list
- Added comprehensive examples for using PVC phase conditions
- Included examples for Pending, Bound, and Lost phases
- Demonstrated combining PVC phase with other conditions
Co-Authored-By: Tiger Kaovilai <kaovilai@users.noreply.github.com>