diff --git a/changelogs/unreleased/8890-blackpiglet b/changelogs/unreleased/8890-blackpiglet new file mode 100644 index 000000000..e670b9635 --- /dev/null +++ b/changelogs/unreleased/8890-blackpiglet @@ -0,0 +1 @@ +Skip namespace in terminating state in backup resource collection. diff --git a/changelogs/unreleased/8946-blackpiglet b/changelogs/unreleased/8946-blackpiglet new file mode 100644 index 000000000..a83ab9290 --- /dev/null +++ b/changelogs/unreleased/8946-blackpiglet @@ -0,0 +1 @@ +Remove CSI VS and VSC metadata from backup. diff --git a/changelogs/unreleased/8975-ywk253100 b/changelogs/unreleased/8975-ywk253100 new file mode 100644 index 000000000..bd21417b7 --- /dev/null +++ b/changelogs/unreleased/8975-ywk253100 @@ -0,0 +1 @@ +Mark BackupRepository not ready when BSL changed \ No newline at end of file diff --git a/pkg/backup/backup_test.go b/pkg/backup/backup_test.go index e2926d471..184b05310 100644 --- a/pkg/backup/backup_test.go +++ b/pkg/backup/backup_test.go @@ -5341,9 +5341,9 @@ func TestBackupNamespaces(t *testing.T) { Result(), apiResources: []*test.APIResource{ test.Namespaces( - builder.ForNamespace("ns-1").Result(), - builder.ForNamespace("ns-2").Result(), - builder.ForNamespace("ns-3").Result(), + builder.ForNamespace("ns-1").Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns-2").Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns-3").Phase(corev1api.NamespaceActive).Result(), ), test.Deployments( builder.ForDeployment("ns-1", "deploy-1").ObjectMeta(builder.WithLabels("a", "b")).Result(), @@ -5364,9 +5364,9 @@ func TestBackupNamespaces(t *testing.T) { }).Result(), apiResources: []*test.APIResource{ test.Namespaces( - builder.ForNamespace("ns-1").Result(), - builder.ForNamespace("ns-2").Result(), - builder.ForNamespace("ns-3").Result(), + builder.ForNamespace("ns-1").Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns-2").Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns-3").Phase(corev1api.NamespaceActive).Result(), ), test.Deployments( builder.ForDeployment("ns-1", "deploy-1").ObjectMeta(builder.WithLabels("a", "b")).Result(), @@ -5390,9 +5390,9 @@ func TestBackupNamespaces(t *testing.T) { Result(), apiResources: []*test.APIResource{ test.Namespaces( - builder.ForNamespace("ns-1").Result(), - builder.ForNamespace("ns-2").Result(), - builder.ForNamespace("ns-3").Result(), + builder.ForNamespace("ns-1").Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns-2").Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns-3").Phase(corev1api.NamespaceActive).Result(), ), test.Deployments( builder.ForDeployment("ns-1", "deploy-1").ObjectMeta(builder.WithLabels("a", "b")).Result(), @@ -5411,9 +5411,9 @@ func TestBackupNamespaces(t *testing.T) { Result(), apiResources: []*test.APIResource{ test.Namespaces( - builder.ForNamespace("ns-1").ObjectMeta(builder.WithLabels("a", "b")).Result(), - builder.ForNamespace("ns-2").Result(), - builder.ForNamespace("ns-3").Result(), + builder.ForNamespace("ns-1").ObjectMeta(builder.WithLabels("a", "b")).Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns-2").Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns-3").Phase(corev1api.NamespaceActive).Result(), ), test.Deployments( builder.ForDeployment("ns-1", "deploy-1").ObjectMeta(builder.WithLabels("a", "b")).Result(), @@ -5431,9 +5431,9 @@ func TestBackupNamespaces(t *testing.T) { backup: defaultBackup().IncludedNamespaces("invalid*").Result(), apiResources: []*test.APIResource{ test.Namespaces( - builder.ForNamespace("ns-1").Result(), - builder.ForNamespace("ns-2").Result(), - builder.ForNamespace("ns-3").Result(), + builder.ForNamespace("ns-1").Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns-2").Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns-3").Phase(corev1api.NamespaceActive).Result(), ), test.Deployments( builder.ForDeployment("ns-1", "deploy-1").ObjectMeta(builder.WithLabels("a", "b")).Result(), @@ -5446,9 +5446,9 @@ func TestBackupNamespaces(t *testing.T) { backup: defaultBackup().Result(), apiResources: []*test.APIResource{ test.Namespaces( - builder.ForNamespace("ns-1").Result(), - builder.ForNamespace("ns-2").Result(), - builder.ForNamespace("ns-3").Result(), + builder.ForNamespace("ns-1").Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns-2").Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns-3").Phase(corev1api.NamespaceActive).Result(), ), test.Deployments( builder.ForDeployment("ns-1", "deploy-1").ObjectMeta(builder.WithLabels("a", "b")).Result(), diff --git a/pkg/backup/item_collector.go b/pkg/backup/item_collector.go index 2eb9079f5..2338dd77b 100644 --- a/pkg/backup/item_collector.go +++ b/pkg/backup/item_collector.go @@ -26,6 +26,7 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" + corev1api "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -114,6 +115,16 @@ func (nt *nsTracker) init( nt.logger = logger for _, namespace := range unstructuredNSs { + ns := new(corev1api.Namespace) + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(namespace.UnstructuredContent(), ns); err != nil { + nt.logger.WithError(err).Errorf("Fail to convert unstructured into namespace %s", namespace.GetName()) + continue + } + if ns.Status.Phase != corev1api.NamespaceActive { + nt.logger.Infof("Skip namespace %s because it's not in Active phase.", namespace.GetName()) + continue + } + if nt.singleLabelSelector != nil && nt.singleLabelSelector.Matches(labels.Set(namespace.GetLabels())) { nt.logger.Debugf("Track namespace %s, because its labels match backup LabelSelector.", diff --git a/pkg/backup/item_collector_test.go b/pkg/backup/item_collector_test.go index 992b5ec7f..bbdad7e43 100644 --- a/pkg/backup/item_collector_test.go +++ b/pkg/backup/item_collector_test.go @@ -158,14 +158,15 @@ func TestItemCollectorBackupNamespaces(t *testing.T) { namespaces []*corev1api.Namespace backup *velerov1api.Backup expectedTrackedNS []string + converter runtime.UnstructuredConverter }{ { name: "ns filter by namespace IE filter", backup: builder.ForBackup("velero", "backup").Result(), ie: collections.NewIncludesExcludes().Includes("ns1"), namespaces: []*corev1api.Namespace{ - builder.ForNamespace("ns1").Result(), - builder.ForNamespace("ns2").Result(), + builder.ForNamespace("ns1").Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns2").Phase(corev1api.NamespaceActive).Result(), }, expectedTrackedNS: []string{"ns1"}, }, @@ -176,8 +177,8 @@ func TestItemCollectorBackupNamespaces(t *testing.T) { }).Result(), ie: collections.NewIncludesExcludes().Includes("*"), namespaces: []*corev1api.Namespace{ - builder.ForNamespace("ns1").ObjectMeta(builder.WithLabels("name", "ns1")).Result(), - builder.ForNamespace("ns2").Result(), + builder.ForNamespace("ns1").ObjectMeta(builder.WithLabels("name", "ns1")).Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns2").Phase(corev1api.NamespaceActive).Result(), }, expectedTrackedNS: []string{"ns1"}, }, @@ -188,8 +189,8 @@ func TestItemCollectorBackupNamespaces(t *testing.T) { }).Result(), ie: collections.NewIncludesExcludes().Includes("*"), namespaces: []*corev1api.Namespace{ - builder.ForNamespace("ns1").ObjectMeta(builder.WithLabels("name", "ns1")).Result(), - builder.ForNamespace("ns2").Result(), + builder.ForNamespace("ns1").ObjectMeta(builder.WithLabels("name", "ns1")).Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns2").Phase(corev1api.NamespaceActive).Result(), }, expectedTrackedNS: []string{"ns1"}, }, @@ -200,8 +201,8 @@ func TestItemCollectorBackupNamespaces(t *testing.T) { }).Result(), ie: collections.NewIncludesExcludes().Excludes("ns1"), namespaces: []*corev1api.Namespace{ - builder.ForNamespace("ns1").ObjectMeta(builder.WithLabels("name", "ns1")).Result(), - builder.ForNamespace("ns2").Result(), + builder.ForNamespace("ns1").ObjectMeta(builder.WithLabels("name", "ns1")).Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns2").Phase(corev1api.NamespaceActive).Result(), }, expectedTrackedNS: []string{"ns1"}, }, @@ -212,9 +213,9 @@ func TestItemCollectorBackupNamespaces(t *testing.T) { }).Result(), ie: collections.NewIncludesExcludes().Excludes("ns1", "ns2"), namespaces: []*corev1api.Namespace{ - builder.ForNamespace("ns1").ObjectMeta(builder.WithLabels("name", "ns1")).Result(), - builder.ForNamespace("ns2").Result(), - builder.ForNamespace("ns3").Result(), + builder.ForNamespace("ns1").ObjectMeta(builder.WithLabels("name", "ns1")).Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns2").Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns3").Phase(corev1api.NamespaceActive).Result(), }, expectedTrackedNS: []string{"ns1", "ns3"}, }, @@ -223,8 +224,8 @@ func TestItemCollectorBackupNamespaces(t *testing.T) { backup: builder.ForBackup("velero", "backup").Result(), ie: collections.NewIncludesExcludes().Includes("*"), namespaces: []*corev1api.Namespace{ - builder.ForNamespace("ns1").ObjectMeta(builder.WithLabels("name", "ns1")).Result(), - builder.ForNamespace("ns2").Result(), + builder.ForNamespace("ns1").ObjectMeta(builder.WithLabels("name", "ns1")).Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns2").Phase(corev1api.NamespaceActive).Result(), }, expectedTrackedNS: []string{"ns1", "ns2"}, }, @@ -233,12 +234,22 @@ func TestItemCollectorBackupNamespaces(t *testing.T) { backup: builder.ForBackup("velero", "backup").IncludedNamespaces("ns1", "invalid", "*").Result(), ie: collections.NewIncludesExcludes().Includes("ns1", "invalid", "*"), namespaces: []*corev1api.Namespace{ - builder.ForNamespace("ns1").ObjectMeta(builder.WithLabels("name", "ns1")).Result(), - builder.ForNamespace("ns2").Result(), - builder.ForNamespace("ns3").Result(), + builder.ForNamespace("ns1").ObjectMeta(builder.WithLabels("name", "ns1")).Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns2").Phase(corev1api.NamespaceActive).Result(), + builder.ForNamespace("ns3").Phase(corev1api.NamespaceActive).Result(), }, expectedTrackedNS: []string{"ns1"}, }, + { + name: "terminating ns should not tracked", + backup: builder.ForBackup("velero", "backup").Result(), + ie: collections.NewIncludesExcludes().Includes("ns1", "ns2"), + namespaces: []*corev1api.Namespace{ + builder.ForNamespace("ns1").Phase(corev1api.NamespaceTerminating).Result(), + builder.ForNamespace("ns2").Phase(corev1api.NamespaceActive).Result(), + }, + expectedTrackedNS: []string{"ns2"}, + }, } for _, tc := range tests { @@ -274,6 +285,10 @@ func TestItemCollectorBackupNamespaces(t *testing.T) { dir: tempDir, } + if tc.converter == nil { + tc.converter = runtime.DefaultUnstructuredConverter + } + r.collectNamespaces( metav1.APIResource{ Name: "Namespace", diff --git a/pkg/controller/backup_controller.go b/pkg/controller/backup_controller.go index 17656d96b..9ae3b3590 100644 --- a/pkg/controller/backup_controller.go +++ b/pkg/controller/backup_controller.go @@ -833,15 +833,6 @@ func persistBackup(backup *pkgbackup.Request, persistErrs = append(persistErrs, errs...) } - csiSnapshotJSON, errs := encode.ToJSONGzip(csiVolumeSnapshots, "csi volume snapshots list") - if errs != nil { - persistErrs = append(persistErrs, errs...) - } - - csiSnapshotContentsJSON, errs := encode.ToJSONGzip(csiVolumeSnapshotContents, "csi volume snapshot contents list") - if errs != nil { - persistErrs = append(persistErrs, errs...) - } csiSnapshotClassesJSON, errs := encode.ToJSONGzip(csiVolumeSnapshotClasses, "csi volume snapshot classes list") if errs != nil { persistErrs = append(persistErrs, errs...) @@ -877,27 +868,23 @@ func persistBackup(backup *pkgbackup.Request, nativeVolumeSnapshots = nil backupItemOperations = nil backupResourceList = nil - csiSnapshotJSON = nil - csiSnapshotContentsJSON = nil csiSnapshotClassesJSON = nil backupResult = nil volumeInfoJSON = nil } backupInfo := persistence.BackupInfo{ - Name: backup.Name, - Metadata: backupJSON, - Contents: backupContents, - Log: backupLog, - BackupResults: backupResult, - PodVolumeBackups: podVolumeBackups, - VolumeSnapshots: nativeVolumeSnapshots, - BackupItemOperations: backupItemOperations, - BackupResourceList: backupResourceList, - CSIVolumeSnapshots: csiSnapshotJSON, - CSIVolumeSnapshotContents: csiSnapshotContentsJSON, - CSIVolumeSnapshotClasses: csiSnapshotClassesJSON, - BackupVolumeInfo: volumeInfoJSON, + Name: backup.Name, + Metadata: backupJSON, + Contents: backupContents, + Log: backupLog, + BackupResults: backupResult, + PodVolumeBackups: podVolumeBackups, + VolumeSnapshots: nativeVolumeSnapshots, + BackupItemOperations: backupItemOperations, + BackupResourceList: backupResourceList, + CSIVolumeSnapshotClasses: csiSnapshotClassesJSON, + BackupVolumeInfo: volumeInfoJSON, } if err := backupStore.PutBackup(backupInfo); err != nil { persistErrs = append(persistErrs, err) diff --git a/pkg/controller/backup_repository_controller.go b/pkg/controller/backup_repository_controller.go index b52282e21..27002c0df 100644 --- a/pkg/controller/backup_repository_controller.go +++ b/pkg/controller/backup_repository_controller.go @@ -31,6 +31,7 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/types" clocks "k8s.io/utils/clock" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" @@ -104,14 +105,11 @@ func (r *BackupRepoReconciler) SetupWithManager(mgr ctrl.Manager) error { For(&velerov1api.BackupRepository{}, builder.WithPredicates(kube.SpecChangePredicate{})). WatchesRawSource(s). Watches( + // mark BackupRepository as invalid when BSL is created, updated or deleted. + // BSL may be recreated after deleting, so also include the create event &velerov1api.BackupStorageLocation{}, kube.EnqueueRequestsFromMapUpdateFunc(r.invalidateBackupReposForBSL), - builder.WithPredicates( - // When BSL updates, check if the backup repositories need to be invalidated - kube.NewUpdateEventPredicate(r.needInvalidBackupRepo), - // When BSL is created, invalidate any backup repositories that reference it - kube.NewCreateEventPredicate(func(client.Object) bool { return true }), - ), + builder.WithPredicates(kube.NewUpdateEventPredicate(r.needInvalidBackupRepo)), ). Complete(r) } @@ -130,14 +128,17 @@ func (r *BackupRepoReconciler) invalidateBackupReposForBSL(ctx context.Context, return []reconcile.Request{} } + requests := []reconcile.Request{} for i := range list.Items { r.logger.WithField("BSL", bsl.Name).Infof("Invalidating Backup Repository %s", list.Items[i].Name) - if err := r.patchBackupRepository(context.Background(), &list.Items[i], repoNotReady("re-establish on BSL change or create")); err != nil { + if err := r.patchBackupRepository(context.Background(), &list.Items[i], repoNotReady("re-establish on BSL change, create or delete")); err != nil { r.logger.WithField("BSL", bsl.Name).WithError(err).Errorf("fail to patch BackupRepository %s", list.Items[i].Name) + continue } + requests = append(requests, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: list.Items[i].Namespace, Name: list.Items[i].Name}}) } - return []reconcile.Request{} + return requests } // needInvalidBackupRepo returns true if the BSL's storage type, bucket, prefix, CACert, or config has changed diff --git a/pkg/persistence/object_store.go b/pkg/persistence/object_store.go index bfdc8fbdc..0fd069d85 100644 --- a/pkg/persistence/object_store.go +++ b/pkg/persistence/object_store.go @@ -49,8 +49,6 @@ type BackupInfo struct { VolumeSnapshots, BackupItemOperations, BackupResourceList, - CSIVolumeSnapshots, - CSIVolumeSnapshotContents, CSIVolumeSnapshotClasses, BackupVolumeInfo io.Reader } @@ -72,7 +70,6 @@ type BackupStore interface { GetPodVolumeBackups(name string) ([]*velerov1api.PodVolumeBackup, error) GetBackupContents(name string) (io.ReadCloser, error) GetCSIVolumeSnapshots(name string) ([]*snapshotv1api.VolumeSnapshot, error) - GetCSIVolumeSnapshotContents(name string) ([]*snapshotv1api.VolumeSnapshotContent, error) GetCSIVolumeSnapshotClasses(name string) ([]*snapshotv1api.VolumeSnapshotClass, error) PutBackupVolumeInfos(name string, volumeInfo io.Reader) error GetBackupVolumeInfos(name string) ([]*volume.BackupVolumeInfo, error) @@ -269,15 +266,13 @@ func (s *objectBackupStore) PutBackup(info BackupInfo) error { // Since the logic for all of these files is the exact same except for the name and the contents, // use a map literal to iterate through them and write them to the bucket. var backupObjs = map[string]io.Reader{ - s.layout.getPodVolumeBackupsKey(info.Name): info.PodVolumeBackups, - s.layout.getBackupVolumeSnapshotsKey(info.Name): info.VolumeSnapshots, - s.layout.getBackupItemOperationsKey(info.Name): info.BackupItemOperations, - s.layout.getBackupResourceListKey(info.Name): info.BackupResourceList, - s.layout.getCSIVolumeSnapshotKey(info.Name): info.CSIVolumeSnapshots, - s.layout.getCSIVolumeSnapshotContentsKey(info.Name): info.CSIVolumeSnapshotContents, - s.layout.getCSIVolumeSnapshotClassesKey(info.Name): info.CSIVolumeSnapshotClasses, - s.layout.getBackupResultsKey(info.Name): info.BackupResults, - s.layout.getBackupVolumeInfoKey(info.Name): info.BackupVolumeInfo, + s.layout.getPodVolumeBackupsKey(info.Name): info.PodVolumeBackups, + s.layout.getBackupVolumeSnapshotsKey(info.Name): info.VolumeSnapshots, + s.layout.getBackupItemOperationsKey(info.Name): info.BackupItemOperations, + s.layout.getBackupResourceListKey(info.Name): info.BackupResourceList, + s.layout.getCSIVolumeSnapshotClassesKey(info.Name): info.CSIVolumeSnapshotClasses, + s.layout.getBackupResultsKey(info.Name): info.BackupResults, + s.layout.getBackupVolumeInfoKey(info.Name): info.BackupVolumeInfo, } for key, reader := range backupObjs { diff --git a/pkg/persistence/object_store_test.go b/pkg/persistence/object_store_test.go index e8eb3b9a0..fab522c53 100644 --- a/pkg/persistence/object_store_test.go +++ b/pkg/persistence/object_store_test.go @@ -863,40 +863,6 @@ func TestGetCSIVolumeSnapshots(t *testing.T) { assert.EqualValues(t, snapshots, res) } -func TestGetCSIVolumeSnapshotContents(t *testing.T) { - harness := newObjectBackupStoreTestHarness("test-bucket", "") - - // file not found should not error - res, err := harness.GetCSIVolumeSnapshotContents("test-backup") - assert.NoError(t, err) - assert.Nil(t, res) - - // file containing invalid data should error - harness.objectStore.PutObject(harness.bucket, "backups/test-backup/test-backup-csi-volumesnapshotcontents.json.gz", newStringReadSeeker("foo")) - _, err = harness.GetCSIVolumeSnapshotContents("test-backup") - assert.Error(t, err) - - // file containing gzipped json data should return correctly - contents := []*snapshotv1api.VolumeSnapshotContent{ - { - Spec: snapshotv1api.VolumeSnapshotContentSpec{ - Driver: "driver", - }, - }, - } - - obj := new(bytes.Buffer) - gzw := gzip.NewWriter(obj) - - require.NoError(t, json.NewEncoder(gzw).Encode(contents)) - require.NoError(t, gzw.Close()) - require.NoError(t, harness.objectStore.PutObject(harness.bucket, "backups/test-backup/test-backup-csi-volumesnapshotcontents.json.gz", obj)) - - res, err = harness.GetCSIVolumeSnapshotContents("test-backup") - assert.NoError(t, err) - assert.EqualValues(t, contents, res) -} - type objectStoreGetter map[string]velero.ObjectStore func (osg objectStoreGetter) GetObjectStore(provider string) (velero.ObjectStore, error) { diff --git a/pkg/util/kube/predicate.go b/pkg/util/kube/predicate.go index 9ac9d9894..2fe985038 100644 --- a/pkg/util/kube/predicate.go +++ b/pkg/util/kube/predicate.go @@ -47,15 +47,6 @@ func (SpecChangePredicate) Update(e event.UpdateEvent) bool { return !reflect.DeepEqual(oldSpec.Interface(), newSpec.Interface()) } -// NewGenericEventPredicate creates a new Predicate that checks the Generic event with the provided func -func NewGenericEventPredicate(f func(object client.Object) bool) predicate.Predicate { - return predicate.Funcs{ - GenericFunc: func(event event.GenericEvent) bool { - return f(event.Object) - }, - } -} - // NewAllEventPredicate creates a new Predicate that checks all the events with the provided func func NewAllEventPredicate(f func(object client.Object) bool) predicate.Predicate { return predicate.Funcs{ @@ -74,25 +65,6 @@ func NewAllEventPredicate(f func(object client.Object) bool) predicate.Predicate } } -// NewUpdateEventPredicate creates a new Predicate that checks the update events with the provided func -// and ignore others -func NewUpdateEventPredicate(f func(client.Object, client.Object) bool) predicate.Predicate { - return predicate.Funcs{ - UpdateFunc: func(event event.UpdateEvent) bool { - return f(event.ObjectOld, event.ObjectNew) - }, - CreateFunc: func(event event.CreateEvent) bool { - return false - }, - DeleteFunc: func(event event.DeleteEvent) bool { - return false - }, - GenericFunc: func(event event.GenericEvent) bool { - return false - }, - } -} - // FalsePredicate always returns false for all kinds of events type FalsePredicate struct{} @@ -116,19 +88,20 @@ func (f FalsePredicate) Generic(event.GenericEvent) bool { return false } -func NewCreateEventPredicate(f func(client.Object) bool) predicate.Predicate { +// NewGenericEventPredicate creates a new Predicate that checks the Generic event with the provided func +func NewGenericEventPredicate(f func(object client.Object) bool) predicate.Predicate { return predicate.Funcs{ - CreateFunc: func(event event.CreateEvent) bool { - return f(event.Object) - }, - DeleteFunc: func(event event.DeleteEvent) bool { - return false - }, GenericFunc: func(event event.GenericEvent) bool { - return false - }, - UpdateFunc: func(event event.UpdateEvent) bool { - return false + return f(event.Object) + }, + } +} + +// NewUpdateEventPredicate creates a new Predicate that checks the Update event with the provided func +func NewUpdateEventPredicate(f func(objectOld client.Object, objectNew client.Object) bool) predicate.Predicate { + return predicate.Funcs{ + UpdateFunc: func(event event.UpdateEvent) bool { + return f(event.ObjectOld, event.ObjectNew) }, } } diff --git a/pkg/util/kube/predicate_test.go b/pkg/util/kube/predicate_test.go index 40d1b8c9c..c9079d029 100644 --- a/pkg/util/kube/predicate_test.go +++ b/pkg/util/kube/predicate_test.go @@ -179,14 +179,6 @@ func TestSpecChangePredicate(t *testing.T) { } } -func TestNewGenericEventPredicate(t *testing.T) { - predicate := NewGenericEventPredicate(func(object client.Object) bool { - return false - }) - - assert.False(t, predicate.Generic(event.GenericEvent{})) -} - func TestNewAllEventPredicate(t *testing.T) { predicate := NewAllEventPredicate(func(object client.Object) bool { return false @@ -197,3 +189,25 @@ func TestNewAllEventPredicate(t *testing.T) { assert.False(t, predicate.Delete(event.DeleteEvent{})) assert.False(t, predicate.Generic(event.GenericEvent{})) } + +func TestNewGenericEventPredicate(t *testing.T) { + predicate := NewGenericEventPredicate(func(object client.Object) bool { + return false + }) + + assert.False(t, predicate.Generic(event.GenericEvent{})) + assert.True(t, predicate.Update(event.UpdateEvent{})) + assert.True(t, predicate.Create(event.CreateEvent{})) + assert.True(t, predicate.Delete(event.DeleteEvent{})) +} + +func TestNewUpdateEventPredicate(t *testing.T) { + predicate := NewUpdateEventPredicate(func(client.Object, client.Object) bool { + return false + }) + + assert.False(t, predicate.Update(event.UpdateEvent{})) + assert.True(t, predicate.Create(event.CreateEvent{})) + assert.True(t, predicate.Delete(event.DeleteEvent{})) + assert.True(t, predicate.Generic(event.GenericEvent{})) +}