mirror of
https://github.com/vmware-tanzu/velero.git
synced 2026-04-25 10:10:33 +00:00
Merge pull request #9743 from Joeavaikath/cherrypick-9684
Fix wildcard expansion when includes is empty and excludes has wildca…
This commit is contained in:
1
changelogs/unreleased/9743-Joeavaikath
Normal file
1
changelogs/unreleased/9743-Joeavaikath
Normal file
@@ -0,0 +1 @@
|
||||
Fix wildcard expansion when includes is empty and excludes has wildcards
|
||||
@@ -570,6 +570,13 @@ func (b *backupReconciler) prepareBackupRequest(ctx context.Context, backup *vel
|
||||
}
|
||||
}
|
||||
|
||||
// Empty IncludedNamespaces means "include all namespaces". Normalize
|
||||
// to ["*"] so that downstream wildcard expansion does not collapse
|
||||
// an empty-includes + wildcard-excludes combination into "back up nothing".
|
||||
if len(request.Spec.IncludedNamespaces) == 0 {
|
||||
request.Spec.IncludedNamespaces = []string{"*"}
|
||||
}
|
||||
|
||||
// validate the included/excluded namespaces
|
||||
for _, err := range collections.ValidateNamespaceIncludesExcludes(request.Spec.IncludedNamespaces, request.Spec.ExcludedNamespaces) {
|
||||
request.Status.ValidationErrors = append(request.Status.ValidationErrors, fmt.Sprintf("Invalid included/excluded namespace lists: %v", err))
|
||||
|
||||
@@ -320,6 +320,34 @@ func TestBackupLocationLabel(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrepareBackupRequest_EmptyIncludedNamespacesNormalizedToWildcard(t *testing.T) {
|
||||
formatFlag := logging.FormatText
|
||||
logger := logging.DefaultLogger(logrus.DebugLevel, formatFlag)
|
||||
|
||||
apiServer := velerotest.NewAPIServer(t)
|
||||
discoveryHelper, err := discovery.NewHelper(apiServer.DiscoveryClient, logger)
|
||||
require.NoError(t, err)
|
||||
|
||||
backupLocation := builder.ForBackupStorageLocation("velero", "loc-1").Result()
|
||||
fakeClient := velerotest.NewFakeControllerRuntimeClient(t, backupLocation)
|
||||
|
||||
c := &backupReconciler{
|
||||
discoveryHelper: discoveryHelper,
|
||||
kbClient: fakeClient,
|
||||
defaultBackupLocation: backupLocation.Name,
|
||||
clock: &clock.RealClock{},
|
||||
formatFlag: formatFlag,
|
||||
}
|
||||
|
||||
backup := defaultBackup().Result()
|
||||
backup.Spec.IncludedNamespaces = nil
|
||||
|
||||
res := c.prepareBackupRequest(ctx, backup, logger)
|
||||
defer res.WorkerPool.Stop()
|
||||
|
||||
assert.Equal(t, []string{"*"}, res.Spec.IncludedNamespaces)
|
||||
}
|
||||
|
||||
func Test_prepareBackupRequest_BackupStorageLocation(t *testing.T) {
|
||||
var (
|
||||
defaultBackupTTL = metav1.Duration{Duration: 24 * 30 * time.Hour}
|
||||
@@ -709,11 +737,11 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
},
|
||||
Spec: velerov1api.BackupSpec{
|
||||
StorageLocation: defaultBackupLocation.Name,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
DefaultVolumesToFsBackup: boolptr.True(),
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -749,11 +777,11 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
},
|
||||
Spec: velerov1api.BackupSpec{
|
||||
StorageLocation: "alt-loc",
|
||||
IncludedNamespaces: []string{"*"},
|
||||
DefaultVolumesToFsBackup: boolptr.False(),
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -793,11 +821,11 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
},
|
||||
Spec: velerov1api.BackupSpec{
|
||||
StorageLocation: "read-write",
|
||||
IncludedNamespaces: []string{"*"},
|
||||
DefaultVolumesToFsBackup: boolptr.True(),
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -834,11 +862,11 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
Spec: velerov1api.BackupSpec{
|
||||
TTL: metav1.Duration{Duration: 10 * time.Minute},
|
||||
StorageLocation: defaultBackupLocation.Name,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
DefaultVolumesToFsBackup: boolptr.False(),
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -875,11 +903,11 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
},
|
||||
Spec: velerov1api.BackupSpec{
|
||||
StorageLocation: defaultBackupLocation.Name,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
DefaultVolumesToFsBackup: boolptr.True(),
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -917,11 +945,11 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
},
|
||||
Spec: velerov1api.BackupSpec{
|
||||
StorageLocation: defaultBackupLocation.Name,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
DefaultVolumesToFsBackup: boolptr.False(),
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -959,11 +987,11 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
},
|
||||
Spec: velerov1api.BackupSpec{
|
||||
StorageLocation: defaultBackupLocation.Name,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
DefaultVolumesToFsBackup: boolptr.True(),
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1001,11 +1029,11 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
},
|
||||
Spec: velerov1api.BackupSpec{
|
||||
StorageLocation: defaultBackupLocation.Name,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
DefaultVolumesToFsBackup: boolptr.True(),
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1043,11 +1071,11 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
},
|
||||
Spec: velerov1api.BackupSpec{
|
||||
StorageLocation: defaultBackupLocation.Name,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
DefaultVolumesToFsBackup: boolptr.False(),
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1086,11 +1114,11 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
},
|
||||
Spec: velerov1api.BackupSpec{
|
||||
StorageLocation: defaultBackupLocation.Name,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
DefaultVolumesToFsBackup: boolptr.True(),
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFailed,
|
||||
@@ -1129,11 +1157,11 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
},
|
||||
Spec: velerov1api.BackupSpec{
|
||||
StorageLocation: defaultBackupLocation.Name,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
DefaultVolumesToFsBackup: boolptr.True(),
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFailed,
|
||||
@@ -1172,11 +1200,11 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
},
|
||||
Spec: velerov1api.BackupSpec{
|
||||
StorageLocation: defaultBackupLocation.Name,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
DefaultVolumesToFsBackup: boolptr.False(),
|
||||
SnapshotMoveData: boolptr.True(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1216,11 +1244,11 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
},
|
||||
Spec: velerov1api.BackupSpec{
|
||||
StorageLocation: defaultBackupLocation.Name,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
DefaultVolumesToFsBackup: boolptr.False(),
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1260,11 +1288,11 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
},
|
||||
Spec: velerov1api.BackupSpec{
|
||||
StorageLocation: defaultBackupLocation.Name,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
DefaultVolumesToFsBackup: boolptr.False(),
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1304,11 +1332,11 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
},
|
||||
Spec: velerov1api.BackupSpec{
|
||||
StorageLocation: defaultBackupLocation.Name,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
DefaultVolumesToFsBackup: boolptr.False(),
|
||||
SnapshotMoveData: boolptr.True(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1349,11 +1377,11 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
},
|
||||
Spec: velerov1api.BackupSpec{
|
||||
StorageLocation: defaultBackupLocation.Name,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
DefaultVolumesToFsBackup: boolptr.False(),
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1393,11 +1421,11 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
},
|
||||
Spec: velerov1api.BackupSpec{
|
||||
StorageLocation: defaultBackupLocation.Name,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
DefaultVolumesToFsBackup: boolptr.False(),
|
||||
SnapshotMoveData: boolptr.True(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1441,13 +1469,13 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
},
|
||||
Spec: velerov1api.BackupSpec{
|
||||
StorageLocation: defaultBackupLocation.Name,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
DefaultVolumesToFsBackup: boolptr.False(),
|
||||
SnapshotMoveData: boolptr.True(),
|
||||
IncludedClusterScopedResources: []string{"storageclasses"},
|
||||
ExcludedClusterScopedResources: append([]string{"clusterroles"}, autoExcludeClusterScopedResources...),
|
||||
IncludedNamespaceScopedResources: []string{"pods"},
|
||||
ExcludedNamespaceScopedResources: append([]string{"secrets"}, autoExcludeNamespaceScopedResources...),
|
||||
IncludedNamespaces: []string{"*"},
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1491,13 +1519,13 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
},
|
||||
Spec: velerov1api.BackupSpec{
|
||||
StorageLocation: defaultBackupLocation.Name,
|
||||
IncludedNamespaces: []string{"*"},
|
||||
DefaultVolumesToFsBackup: boolptr.False(),
|
||||
SnapshotMoveData: boolptr.True(),
|
||||
IncludedClusterScopedResources: []string{"storageclasses"},
|
||||
ExcludedClusterScopedResources: append([]string{"clusterroles"}, autoExcludeClusterScopedResources...),
|
||||
IncludedNamespaceScopedResources: []string{"pods"},
|
||||
ExcludedNamespaceScopedResources: append([]string{"secrets"}, autoExcludeNamespaceScopedResources...),
|
||||
IncludedNamespaces: []string{"*"},
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
|
||||
@@ -19,6 +19,11 @@ func ShouldExpandWildcards(includes []string, excludes []string, fromBackup bool
|
||||
return false
|
||||
}
|
||||
|
||||
// Empty includes is equivalent to * (match all) - don't expand
|
||||
if len(includes) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
wildcardFound := false
|
||||
for _, include := range includes {
|
||||
if containsWildcardPattern(include) {
|
||||
|
||||
@@ -90,6 +90,12 @@ func TestShouldExpandWildcards(t *testing.T) {
|
||||
fromBackup: true,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "empty includes with wildcard excludes - should not expand",
|
||||
includes: []string{},
|
||||
excludes: []string{"ns*"},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "complex wildcard patterns",
|
||||
includes: []string{"*-prod"},
|
||||
|
||||
Reference in New Issue
Block a user