Address review feedback: remove deprecated functions

Remove deprecated functions that were marked for removal per review:
- Remove GetPodsUsingPVC (replaced by GetPodsUsingPVCWithCache)
- Remove IsPVCDefaultToFSBackup (replaced by IsPVCDefaultToFSBackupWithCache)
- Remove associated tests for deprecated functions
- Add deprecation marker to NewVolumeHelperImpl
- Add deprecation marker to ShouldPerformSnapshotWithBackup

Signed-off-by: Shubham Pampattiwar <spampatt@redhat.com>
This commit is contained in:
Shubham Pampattiwar
2025-12-17 10:44:15 -08:00
parent 10ef43e147
commit f592a264a6
5 changed files with 50 additions and 566 deletions
@@ -17,10 +17,7 @@ limitations under the License.
package volumehelper
import (
"context"
"github.com/sirupsen/logrus"
corev1api "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
crclient "sigs.k8s.io/controller-runtime/pkg/client"
@@ -36,6 +33,11 @@ import (
// up on demand. On the other hand, the volumeHelperImpl assume there
// is a VolumeHelper instance initialized before calling the
// ShouldPerformXXX functions.
//
// Deprecated: Use ShouldPerformSnapshotWithVolumeHelper instead for better performance.
// ShouldPerformSnapshotWithVolumeHelper allows passing a pre-created VolumeHelper with
// an internal PVC-to-Pod cache, which avoids O(N*M) complexity when there are many PVCs and pods.
// See issue #9179 for details.
func ShouldPerformSnapshotWithBackup(
unstructured runtime.Unstructured,
groupResource schema.GroupResource,
@@ -92,92 +94,3 @@ func ShouldPerformSnapshotWithVolumeHelper(
return volumeHelperImpl.ShouldPerformSnapshot(unstructured, groupResource)
}
// NewVolumeHelperForBackup creates a VolumeHelper for the given backup with a PVC-to-Pod cache.
// The cache is built for the provided namespaces list to avoid O(N*M) complexity when there
// are many PVCs and pods. See issue #9179 for details.
//
// This function is intended for BIA plugins to create a VolumeHelper once and reuse it
// across multiple Execute() calls for the same backup.
//
// If namespaces is nil or empty, the function will resolve the namespace list from the backup spec.
// If backup.Spec.IncludedNamespaces is empty (meaning all namespaces), it will list all namespaces
// from the cluster.
func NewVolumeHelperForBackup(
backup velerov1api.Backup,
crClient crclient.Client,
logger logrus.FieldLogger,
namespaces []string,
) (volumehelper.VolumeHelper, error) {
// If no namespaces provided, resolve from backup spec
if len(namespaces) == 0 {
var err error
namespaces, err = resolveNamespacesForBackup(backup, crClient)
if err != nil {
logger.WithError(err).Warn("Failed to resolve namespaces for cache, proceeding without cache")
namespaces = nil
}
}
resourcePolicies, err := resourcepolicies.GetResourcePoliciesFromBackup(
backup,
crClient,
logger,
)
if err != nil {
return nil, err
}
return volumehelper.NewVolumeHelperImplWithNamespaces(
resourcePolicies,
backup.Spec.SnapshotVolumes,
logger,
crClient,
boolptr.IsSetToTrue(backup.Spec.DefaultVolumesToFsBackup),
true,
namespaces,
)
}
// resolveNamespacesForBackup determines which namespaces will be backed up.
// If IncludedNamespaces is specified, it returns those (excluding any in ExcludedNamespaces).
// If IncludedNamespaces is empty (meaning all namespaces), it lists all namespaces from the cluster.
func resolveNamespacesForBackup(backup velerov1api.Backup, crClient crclient.Client) ([]string, error) {
// If specific namespaces are included, use those
if len(backup.Spec.IncludedNamespaces) > 0 {
// Filter out excluded namespaces
excludeSet := make(map[string]bool)
for _, ns := range backup.Spec.ExcludedNamespaces {
excludeSet[ns] = true
}
var namespaces []string
for _, ns := range backup.Spec.IncludedNamespaces {
if !excludeSet[ns] {
namespaces = append(namespaces, ns)
}
}
return namespaces, nil
}
// IncludedNamespaces is empty, meaning all namespaces - list from cluster
nsList := &corev1api.NamespaceList{}
if err := crClient.List(context.Background(), nsList); err != nil {
return nil, err
}
// Filter out excluded namespaces
excludeSet := make(map[string]bool)
for _, ns := range backup.Spec.ExcludedNamespaces {
excludeSet[ns] = true
}
var namespaces []string
for _, ns := range nsList.Items {
if !excludeSet[ns.Name] {
namespaces = append(namespaces, ns.Name)
}
}
return namespaces, nil
}
@@ -26,6 +26,7 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"github.com/vmware-tanzu/velero/internal/volumehelper"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/kuberesource"
velerotest "github.com/vmware-tanzu/velero/pkg/test"
@@ -290,8 +291,16 @@ func TestShouldPerformSnapshotWithNonNilVolumeHelper(t *testing.T) {
logger := logrus.New()
// Create VolumeHelper using the factory function
vh, err := NewVolumeHelperForBackup(*backup, client, logger, []string{"default"})
// Create VolumeHelper using the internal function with namespace caching
vh, err := volumehelper.NewVolumeHelperImplWithNamespaces(
nil, // no resource policies for this test
nil, // snapshotVolumes not set
logger,
client,
false, // defaultVolumesToFSBackup
true, // backupExcludePVC
[]string{"default"},
)
require.NoError(t, err)
require.NotNil(t, vh)
@@ -313,128 +322,3 @@ func TestShouldPerformSnapshotWithNonNilVolumeHelper(t *testing.T) {
require.NoError(t, err)
require.True(t, result, "Should return true for snapshot when snapshotVolumes not set")
}
func TestNewVolumeHelperForBackup(t *testing.T) {
tests := []struct {
name string
backup *velerov1api.Backup
namespaces []string
wantError bool
}{
{
name: "Creates VolumeHelper with explicit namespaces",
backup: &velerov1api.Backup{
ObjectMeta: metav1.ObjectMeta{
Name: "test-backup",
Namespace: "velero",
},
Spec: velerov1api.BackupSpec{
IncludedNamespaces: []string{"ns1", "ns2"},
},
},
namespaces: []string{"ns1", "ns2"},
wantError: false,
},
{
name: "Creates VolumeHelper with namespaces from backup spec",
backup: &velerov1api.Backup{
ObjectMeta: metav1.ObjectMeta{
Name: "test-backup",
Namespace: "velero",
},
Spec: velerov1api.BackupSpec{
IncludedNamespaces: []string{"ns1", "ns2"},
},
},
namespaces: nil, // Will be resolved from backup spec
wantError: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
client := velerotest.NewFakeControllerRuntimeClient(t)
logger := logrus.New()
vh, err := NewVolumeHelperForBackup(*tt.backup, client, logger, tt.namespaces)
if tt.wantError {
require.Error(t, err)
require.Nil(t, vh)
} else {
require.NoError(t, err)
require.NotNil(t, vh)
}
})
}
}
func TestResolveNamespacesForBackup(t *testing.T) {
tests := []struct {
name string
backup *velerov1api.Backup
existingNS []string
expectedResult []string
}{
{
name: "Returns included namespaces",
backup: &velerov1api.Backup{
ObjectMeta: metav1.ObjectMeta{
Name: "test-backup",
Namespace: "velero",
},
Spec: velerov1api.BackupSpec{
IncludedNamespaces: []string{"ns1", "ns2", "ns3"},
},
},
existingNS: []string{"ns1", "ns2", "ns3", "ns4"},
expectedResult: []string{"ns1", "ns2", "ns3"},
},
{
name: "Excludes specified namespaces from included list",
backup: &velerov1api.Backup{
ObjectMeta: metav1.ObjectMeta{
Name: "test-backup",
Namespace: "velero",
},
Spec: velerov1api.BackupSpec{
IncludedNamespaces: []string{"ns1", "ns2", "ns3"},
ExcludedNamespaces: []string{"ns2"},
},
},
existingNS: []string{"ns1", "ns2", "ns3", "ns4"},
expectedResult: []string{"ns1", "ns3"},
},
{
name: "Returns all namespaces when IncludedNamespaces is empty",
backup: &velerov1api.Backup{
ObjectMeta: metav1.ObjectMeta{
Name: "test-backup",
Namespace: "velero",
},
Spec: velerov1api.BackupSpec{},
},
existingNS: []string{"default", "kube-system", "app-ns"},
expectedResult: []string{"default", "kube-system", "app-ns"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Create fake client with namespaces
var objects []runtime.Object
for _, ns := range tt.existingNS {
objects = append(objects, &corev1api.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: ns,
},
})
}
client := velerotest.NewFakeControllerRuntimeClient(t, objects...)
result, err := resolveNamespacesForBackup(*tt.backup, client)
require.NoError(t, err)
require.ElementsMatch(t, tt.expectedResult, result)
})
}
}