From 62a24ece5027c9eb67f7fc8dc5a173bf0e9ad6a4 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Mon, 9 Feb 2026 16:10:00 +0800 Subject: [PATCH 1/2] If BIA return updateObj with SkipFromBackupAnnotation, treat it as skip the resource from backup. Signed-off-by: Xun Jiang --- changelogs/unreleased/9547-blackpiglet | 1 + pkg/apis/velero/v1/labels_annotations.go | 9 +++++++++ pkg/backup/item_backupper.go | 13 +++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 changelogs/unreleased/9547-blackpiglet diff --git a/changelogs/unreleased/9547-blackpiglet b/changelogs/unreleased/9547-blackpiglet new file mode 100644 index 000000000..f1e546be6 --- /dev/null +++ b/changelogs/unreleased/9547-blackpiglet @@ -0,0 +1 @@ +If BIA return updateObj with SkipFromBackupAnnotation, treat it as skip the resource from backup. \ No newline at end of file diff --git a/pkg/apis/velero/v1/labels_annotations.go b/pkg/apis/velero/v1/labels_annotations.go index c1431d3cc..85d8b05aa 100644 --- a/pkg/apis/velero/v1/labels_annotations.go +++ b/pkg/apis/velero/v1/labels_annotations.go @@ -102,6 +102,15 @@ const ( // even if the resource contains a matching selector label. ExcludeFromBackupLabel = "velero.io/exclude-from-backup" + // SkipFromBackupAnnotation is the annotation used by internal BackupItemActions + // to indicate that a resource should be skipped from backup, + // even if it doesn't have the ExcludeFromBackupLabel. + // This is used in cases where we want to skip backup of a resource based on some logic in a plugin. + // + // Notice: SkipFromBackupAnnotation's priority is higher than MustIncludeAdditionalItemAnnotation. + // If SkipFromBackupAnnotation is set, the resource will be skipped even if MustIncludeAdditionalItemAnnotation is set. + SkipFromBackupAnnotation = "velero.io/skip-from-backup" + // defaultVGSLabelKey is the default label key used to group PVCs under a VolumeGroupSnapshot DefaultVGSLabelKey = "velero.io/volume-group" diff --git a/pkg/backup/item_backupper.go b/pkg/backup/item_backupper.go index feae0e01c..770b1ed41 100644 --- a/pkg/backup/item_backupper.go +++ b/pkg/backup/item_backupper.go @@ -244,6 +244,12 @@ func (ib *itemBackupper) backupItemInternal(logger logrus.FieldLogger, obj runti return false, itemFiles, kubeerrs.NewAggregate(backupErrs) } + // If err is nil and updatedObj is nil, it means the item is skipped by plugin action, + // we should return here to avoid backing up the item, and avoid potential NPE in the following code. + if updatedObj == nil { + return false, itemFiles, nil + } + itemFiles = append(itemFiles, additionalItemFiles...) obj = updatedObj if metadata, err = meta.Accessor(obj); err != nil { @@ -398,6 +404,13 @@ func (ib *itemBackupper) executeActions( } u := &unstructured.Unstructured{Object: updatedItem.UnstructuredContent()} + + if _, ok := u.GetAnnotations()[velerov1api.SkipFromBackupAnnotation]; ok { + log.Infof("Resource (groupResource=%s, namespace=%s, name=%s) is skipped from backup by action %s.", + groupResource.String(), namespace, name, actionName) + return nil, itemFiles, nil + } + if actionName == csiBIAPluginName { if additionalItemIdentifiers == nil && u.GetAnnotations()[velerov1api.SkippedNoCSIPVAnnotation] == "true" { // snapshot was skipped by CSI plugin From 9a39cbfbf57220ce3eaa4f5a19825a901570c2e8 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 27 Feb 2026 00:28:49 +0800 Subject: [PATCH 2/2] Remove the skipped item from the resource list when it's skipped by BIA. Signed-off-by: Xun Jiang --- .../unreleased/{9547-blackpiglet => 9597-blackpiglet} | 0 pkg/backup/backed_up_items_map.go | 8 ++++++++ pkg/backup/item_backupper.go | 2 ++ 3 files changed, 10 insertions(+) rename changelogs/unreleased/{9547-blackpiglet => 9597-blackpiglet} (100%) diff --git a/changelogs/unreleased/9547-blackpiglet b/changelogs/unreleased/9597-blackpiglet similarity index 100% rename from changelogs/unreleased/9547-blackpiglet rename to changelogs/unreleased/9597-blackpiglet diff --git a/pkg/backup/backed_up_items_map.go b/pkg/backup/backed_up_items_map.go index f5764cd8e..174a50e1e 100644 --- a/pkg/backup/backed_up_items_map.go +++ b/pkg/backup/backed_up_items_map.go @@ -98,6 +98,14 @@ func (m *backedUpItemsMap) AddItem(key itemKey) { m.totalItems[key] = struct{}{} } +func (m *backedUpItemsMap) DeleteItem(key itemKey) { + m.Lock() + defer m.Unlock() + + delete(m.backedUpItems, key) + delete(m.totalItems, key) +} + func (m *backedUpItemsMap) AddItemToTotal(key itemKey) { m.Lock() defer m.Unlock() diff --git a/pkg/backup/item_backupper.go b/pkg/backup/item_backupper.go index 770b1ed41..b50f4e119 100644 --- a/pkg/backup/item_backupper.go +++ b/pkg/backup/item_backupper.go @@ -247,6 +247,8 @@ func (ib *itemBackupper) backupItemInternal(logger logrus.FieldLogger, obj runti // If err is nil and updatedObj is nil, it means the item is skipped by plugin action, // we should return here to avoid backing up the item, and avoid potential NPE in the following code. if updatedObj == nil { + log.Infof("Remove item from the backup's backupItems list and totalItems list because it's skipped by plugin action.") + ib.backupRequest.BackedUpItems.DeleteItem(key) return false, itemFiles, nil }