diff --git a/pkg/predicate/predicate.go b/pkg/predicate/predicate.go index 4077300cf0..ae9b93c80e 100644 --- a/pkg/predicate/predicate.go +++ b/pkg/predicate/predicate.go @@ -41,6 +41,8 @@ type Predicate interface { var _ Predicate = Funcs{} var _ Predicate = ResourceVersionChangedPredicate{} var _ Predicate = GenerationChangedPredicate{} +var _ Predicate = or{} +var _ Predicate = and{} // Funcs is a function that implements Predicate. type Funcs struct { @@ -155,3 +157,93 @@ func (GenerationChangedPredicate) Update(e event.UpdateEvent) bool { } return e.MetaNew.GetGeneration() != e.MetaOld.GetGeneration() } + +// And returns a composite predicate that implements a logical AND of the predicates passed to it. +func And(predicates ...Predicate) Predicate { + return and{predicates} +} + +type and struct { + predicates []Predicate +} + +func (a and) Create(e event.CreateEvent) bool { + for _, p := range a.predicates { + if !p.Create(e) { + return false + } + } + return true +} + +func (a and) Update(e event.UpdateEvent) bool { + for _, p := range a.predicates { + if !p.Update(e) { + return false + } + } + return true +} + +func (a and) Delete(e event.DeleteEvent) bool { + for _, p := range a.predicates { + if !p.Delete(e) { + return false + } + } + return true +} + +func (a and) Generic(e event.GenericEvent) bool { + for _, p := range a.predicates { + if !p.Generic(e) { + return false + } + } + return true +} + +// Or returns a composite predicate that implements a logical OR of the predicates passed to it. +func Or(predicates ...Predicate) Predicate { + return or{predicates} +} + +type or struct { + predicates []Predicate +} + +func (o or) Create(e event.CreateEvent) bool { + for _, p := range o.predicates { + if p.Create(e) { + return true + } + } + return false +} + +func (o or) Update(e event.UpdateEvent) bool { + for _, p := range o.predicates { + if p.Update(e) { + return true + } + } + return false +} + +func (o or) Delete(e event.DeleteEvent) bool { + for _, p := range o.predicates { + if p.Delete(e) { + return true + } + } + return false +} + +func (o or) Generic(e event.GenericEvent) bool { + for _, p := range o.predicates { + if p.Generic(e) { + return true + } + } + return false +} diff --git a/pkg/predicate/predicate_test.go b/pkg/predicate/predicate_test.go index c43c88e9b1..242a7a687e 100644 --- a/pkg/predicate/predicate_test.go +++ b/pkg/predicate/predicate_test.go @@ -438,4 +438,57 @@ var _ = Describe("Predicate", func() { }) }) + + Context("With a boolean predicate", func() { + funcs := func(pass bool) predicate.Funcs { + return predicate.Funcs{ + CreateFunc: func(event.CreateEvent) bool { + return pass + }, + DeleteFunc: func(event.DeleteEvent) bool { + return pass + }, + UpdateFunc: func(event.UpdateEvent) bool { + return pass + }, + GenericFunc: func(event.GenericEvent) bool { + return pass + }, + } + } + passFuncs := funcs(true) + failFuncs := funcs(false) + Describe("When checking an And predicate", func() { + It("should return false when one of its predicates returns false", func() { + a := predicate.And(passFuncs, failFuncs) + Expect(a.Create(event.CreateEvent{})).To(BeFalse()) + Expect(a.Update(event.UpdateEvent{})).To(BeFalse()) + Expect(a.Delete(event.DeleteEvent{})).To(BeFalse()) + Expect(a.Generic(event.GenericEvent{})).To(BeFalse()) + }) + It("should return true when all of its predicates return true", func() { + a := predicate.And(passFuncs, passFuncs) + Expect(a.Create(event.CreateEvent{})).To(BeTrue()) + Expect(a.Update(event.UpdateEvent{})).To(BeTrue()) + Expect(a.Delete(event.DeleteEvent{})).To(BeTrue()) + Expect(a.Generic(event.GenericEvent{})).To(BeTrue()) + }) + }) + Describe("When checking an Or predicate", func() { + It("should return true when one of its predicates returns true", func() { + o := predicate.Or(passFuncs, failFuncs) + Expect(o.Create(event.CreateEvent{})).To(BeTrue()) + Expect(o.Update(event.UpdateEvent{})).To(BeTrue()) + Expect(o.Delete(event.DeleteEvent{})).To(BeTrue()) + Expect(o.Generic(event.GenericEvent{})).To(BeTrue()) + }) + It("should return false when all of its predicates return false", func() { + o := predicate.Or(failFuncs, failFuncs) + Expect(o.Create(event.CreateEvent{})).To(BeFalse()) + Expect(o.Update(event.UpdateEvent{})).To(BeFalse()) + Expect(o.Delete(event.DeleteEvent{})).To(BeFalse()) + Expect(o.Generic(event.GenericEvent{})).To(BeFalse()) + }) + }) + }) })