diff --git a/pkg/predicate/predicate.go b/pkg/predicate/predicate.go index ae9b93c80e..66f3e431be 100644 --- a/pkg/predicate/predicate.go +++ b/pkg/predicate/predicate.go @@ -17,6 +17,9 @@ limitations under the License. package predicate import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/event" logf "sigs.k8s.io/controller-runtime/pkg/internal/log" ) @@ -91,6 +94,26 @@ func (p Funcs) Generic(e event.GenericEvent) bool { return true } +// NewPredicateFuncs returns a predicate funcs that applies the given filter function +// on CREATE, UPDATE, DELETE and GENERIC events. For UPDATE events, the filter is applied +// to the new object. +func NewPredicateFuncs(filter func(meta metav1.Object, object runtime.Object) bool) Funcs { + return Funcs{ + CreateFunc: func(e event.CreateEvent) bool { + return filter(e.Meta, e.Object) + }, + UpdateFunc: func(e event.UpdateEvent) bool { + return filter(e.MetaNew, e.ObjectNew) + }, + DeleteFunc: func(e event.DeleteEvent) bool { + return filter(e.Meta, e.Object) + }, + GenericFunc: func(e event.GenericEvent) bool { + return filter(e.Meta, e.Object) + }, + } +} + // ResourceVersionChangedPredicate implements a default update predicate function on resource version change type ResourceVersionChangedPredicate struct { Funcs diff --git a/pkg/predicate/predicate_test.go b/pkg/predicate/predicate_test.go index 242a7a687e..a88afe5b88 100644 --- a/pkg/predicate/predicate_test.go +++ b/pkg/predicate/predicate_test.go @@ -21,6 +21,8 @@ import ( . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" ) @@ -491,4 +493,54 @@ var _ = Describe("Predicate", func() { }) }) }) + + Describe("NewPredicateFuncs with a namespace filter function", func() { + byNamespaceFilter := func(namespace string) func(m metav1.Object, object runtime.Object) bool { + return func(m metav1.Object, object runtime.Object) bool { + return m.GetNamespace() == namespace + } + } + byNamespaceFuncs := predicate.NewPredicateFuncs(byNamespaceFilter("biz")) + Context("Where the namespace is matching", func() { + It("should return true", func() { + new := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "baz", + Namespace: "biz", + }} + + old := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "baz", + Namespace: "biz", + }} + passEvt1 := event.UpdateEvent{MetaOld: old.GetObjectMeta(), ObjectOld: old, MetaNew: new.GetObjectMeta()} + Expect(byNamespaceFuncs.Create(event.CreateEvent{Meta: new.GetObjectMeta(), Object: new})).To(BeTrue()) + Expect(byNamespaceFuncs.Delete(event.DeleteEvent{Meta: old.GetObjectMeta(), Object: old})).To(BeTrue()) + Expect(byNamespaceFuncs.Generic(event.GenericEvent{Meta: new.GetObjectMeta(), Object: new})).To(BeTrue()) + Expect(byNamespaceFuncs.Update(passEvt1)).To(BeTrue()) + }) + }) + + Context("Where the namespace is not matching", func() { + It("should return false", func() { + new := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "baz", + Namespace: "bizz", + }} + + old := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "baz", + Namespace: "biz", + }} + failEvt1 := event.UpdateEvent{MetaOld: old.GetObjectMeta(), ObjectOld: old, MetaNew: new.GetObjectMeta()} + Expect(byNamespaceFuncs.Create(event.CreateEvent{Meta: new.GetObjectMeta(), Object: new})).To(BeFalse()) + Expect(byNamespaceFuncs.Delete(event.DeleteEvent{Meta: new.GetObjectMeta(), Object: new})).To(BeFalse()) + Expect(byNamespaceFuncs.Generic(event.GenericEvent{Meta: new.GetObjectMeta(), Object: new})).To(BeFalse()) + Expect(byNamespaceFuncs.Update(failEvt1)).To(BeFalse()) + }) + }) + }) })