Skip to content

Commit 37a7265

Browse files
Implementation + Tests
1 parent cea989b commit 37a7265

File tree

2 files changed

+73
-1
lines changed

2 files changed

+73
-1
lines changed

pkg/predicate/predicate.go

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ package predicate
1818

1919
import (
2020
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
"k8s.io/apimachinery/pkg/labels"
2122
"k8s.io/apimachinery/pkg/runtime"
22-
2323
"sigs.k8s.io/controller-runtime/pkg/event"
2424
logf "sigs.k8s.io/controller-runtime/pkg/internal/log"
2525
)
@@ -270,3 +270,48 @@ func (o or) Generic(e event.GenericEvent) bool {
270270
}
271271
return false
272272
}
273+
274+
// LabelSelectorPredicate implements predicate functions and requires a selector that will filter an event by its labels.
275+
//
276+
// This predicate will skip reconciliation on all events that have labels that do not match the selector of the predicate.
277+
// A metav1.LabelSelector is passed as an input parameter while instantiating an LabelSelectorPredicate, and this is (explicitly)
278+
// converted to a labels.Selector object, and stored within the struct. When a predicate function is evoked, the event labels are checked
279+
// for a match with the predicate's selector to decide whether an event undergoes reconciliation or not.
280+
// If the labels match, the event will undergo reconciliation. If the labels do not match, it will skip reconciliation for that particular event.
281+
282+
type LabelSelectorPredicate struct {
283+
Funcs
284+
Selector labels.Selector
285+
}
286+
287+
// eventFilter skips reconciliation of events that have labels matching selectors
288+
func (r LabelSelectorPredicate) eventFilter(eventLabels map[string]string) bool {
289+
return r.Selector.Matches(labels.Set(eventLabels))
290+
}
291+
292+
// NewLabelSelectorPredicate instantiates a new LabelSelectorPredicate with the LabelSelector specified through parameters.
293+
func NewLabelSelectorPredicate(s metav1.LabelSelector) (Predicate, error) {
294+
selectorSpecs, err := metav1.LabelSelectorAsSelector(&s)
295+
requirements := LabelSelectorPredicate{Selector: selectorSpecs}
296+
return requirements, err
297+
}
298+
299+
// Update implements default UpdateEvent filter for validating event labels against the predicate selector
300+
func (r LabelSelectorPredicate) Update(e event.UpdateEvent) bool {
301+
return r.eventFilter(e.MetaNew.GetLabels())
302+
}
303+
304+
// Create implements default CreateEvent filter for validating event labels against the predicate selector
305+
func (r LabelSelectorPredicate) Create(e event.CreateEvent) bool {
306+
return r.eventFilter(e.Meta.GetLabels())
307+
}
308+
309+
// Delete implements default DeleteEvent filter for validating event labels against the predicate selector
310+
func (r LabelSelectorPredicate) Delete(e event.DeleteEvent) bool {
311+
return r.eventFilter(e.Meta.GetLabels())
312+
}
313+
314+
// Generic implements default GenericEvent filter for validating event labels against the predicate selector
315+
func (r LabelSelectorPredicate) Generic(e event.GenericEvent) bool {
316+
return r.eventFilter(e.Meta.GetLabels())
317+
}

pkg/predicate/predicate_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,4 +543,31 @@ var _ = Describe("Predicate", func() {
543543
})
544544
})
545545
})
546+
547+
Describe("When checking a LabelSelectorPredicate", func() {
548+
instance, err := predicate.NewLabelSelectorPredicate(*(&metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}))
549+
successLabels := map[string]string{"foo": "bar"}
550+
failureLabels := map[string]string{"bar": "foo"}
551+
if err != nil {
552+
Fail("Improper Label Selector passed during predicate instantiation.")
553+
}
554+
555+
Context("When the Selector does not match the event labels", func() {
556+
It("should return false", func() {
557+
Expect(instance.Create(event.CreateEvent{Meta: &metav1.ObjectMeta{Labels: failureLabels}})).To(BeFalse())
558+
Expect(instance.Delete(event.DeleteEvent{Meta: &metav1.ObjectMeta{Labels: failureLabels}})).To(BeFalse())
559+
Expect(instance.Generic(event.GenericEvent{Meta: &metav1.ObjectMeta{Labels: failureLabels}})).To(BeFalse())
560+
Expect(instance.Update(event.UpdateEvent{MetaNew: &metav1.ObjectMeta{Labels: failureLabels}})).To(BeFalse())
561+
})
562+
})
563+
564+
Context("When the Selector matches the event labels", func() {
565+
It("should return true", func() {
566+
Expect(instance.Create(event.CreateEvent{Meta: &metav1.ObjectMeta{Labels: successLabels}})).To(BeTrue())
567+
Expect(instance.Delete(event.DeleteEvent{Meta: &metav1.ObjectMeta{Labels: successLabels}})).To(BeTrue())
568+
Expect(instance.Generic(event.GenericEvent{Meta: &metav1.ObjectMeta{Labels: successLabels}})).To(BeTrue())
569+
Expect(instance.Update(event.UpdateEvent{MetaNew: &metav1.ObjectMeta{Labels: successLabels}})).To(BeTrue())
570+
})
571+
})
572+
})
546573
})

0 commit comments

Comments
 (0)