Skip to content

Commit b356036

Browse files
committed
fix : Add Groups filter to CustomResourceDefinition reconciler
- Introduced Groups field in Options to specify API groups for CRDs. - Implemented GroupPredicate to filter CRDs based on specified groups. - Updated Setup function to apply the Groups filter during reconciliation.
1 parent 8fa945b commit b356036

File tree

3 files changed

+116
-4
lines changed

3 files changed

+116
-4
lines changed

pkg/controller/options.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ type Options struct {
7777

7878
// EventFilterFunctions used to filter events emitted by the controllers.
7979
EventFilterFunctions []event.FilterFn
80+
81+
// Groups is the list of API groups managed by this provider.
82+
// If specified, the CRD gate will only watch CRDs belonging to these groups,
83+
// reducing unnecessary reconciles from unrelated CRDs in the cluster.
84+
Groups []string
8085
}
8186

8287
// ForControllerRuntime extracts options for controller-runtime.

pkg/reconciler/customresourcesgate/reconciler_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,13 @@ import (
2323
"testing"
2424

2525
"github.com/google/go-cmp/cmp"
26+
corev1 "k8s.io/api/core/v1"
2627
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2728
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2829
"k8s.io/apimachinery/pkg/runtime/schema"
2930
ctrl "sigs.k8s.io/controller-runtime"
31+
"sigs.k8s.io/controller-runtime/pkg/client"
32+
"sigs.k8s.io/controller-runtime/pkg/event"
3033

3134
"github.com/crossplane/crossplane-runtime/v2/pkg/logging"
3235
"github.com/crossplane/crossplane-runtime/v2/pkg/test"
@@ -560,3 +563,85 @@ func TestReconcile(t *testing.T) {
560563
})
561564
}
562565
}
566+
567+
func TestGroupPredicate(t *testing.T) {
568+
type args struct {
569+
groups []string
570+
obj client.Object
571+
}
572+
type want struct {
573+
match bool
574+
}
575+
576+
cases := map[string]struct {
577+
reason string
578+
args args
579+
want want
580+
}{
581+
"CRDGroupPresent": {
582+
reason: "CRD is present in the specified groups, predicate should return true",
583+
args: args{
584+
groups: []string{"example.com"},
585+
obj: &apiextensionsv1.CustomResourceDefinition{
586+
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
587+
Group: "example.com",
588+
},
589+
},
590+
},
591+
want: want{
592+
match: true,
593+
},
594+
},
595+
"CRDGroupAbsent": {
596+
reason: "CRD is not present in the specified groups, predicate should return false",
597+
args: args{
598+
groups: []string{"example.com"},
599+
obj: &apiextensionsv1.CustomResourceDefinition{
600+
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
601+
Group: "other.com",
602+
},
603+
},
604+
},
605+
want: want{
606+
match: false,
607+
},
608+
},
609+
"EmptyGroups": {
610+
reason: "No groups specified, predicate should return false for any CRD",
611+
args: args{
612+
groups: []string{},
613+
obj: &apiextensionsv1.CustomResourceDefinition{
614+
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
615+
Group: "example.com",
616+
},
617+
},
618+
},
619+
want: want{
620+
match: false,
621+
},
622+
},
623+
"NonCRDObject": {
624+
reason: "Object is not a CRD, predicate should return false",
625+
args: args{
626+
groups: []string{"example.com"},
627+
obj: &corev1.ConfigMap{},
628+
},
629+
want: want{
630+
match: false,
631+
},
632+
},
633+
}
634+
635+
for name, tc := range cases {
636+
t.Run(name, func(t *testing.T) {
637+
got := GroupPredicate(tc.args.groups...)
638+
ev := event.GenericEvent{
639+
Object: tc.args.obj,
640+
}
641+
match := got.Generic(ev)
642+
if match != tc.want.match {
643+
t.Errorf("\n%s\nGroupPredicate(...): -want match, +got match:\n%s", tc.reason, cmp.Diff(tc.want.match, match))
644+
}
645+
})
646+
}
647+
}

pkg/reconciler/customresourcesgate/setup.go

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222

2323
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2424
ctrl "sigs.k8s.io/controller-runtime"
25+
"sigs.k8s.io/controller-runtime/pkg/client"
26+
"sigs.k8s.io/controller-runtime/pkg/predicate"
2527
"sigs.k8s.io/controller-runtime/pkg/reconcile"
2628

2729
"github.com/crossplane/crossplane-runtime/v2/pkg/controller"
@@ -38,9 +40,29 @@ func Setup(mgr ctrl.Manager, o controller.Options) error {
3840
log: o.Logger,
3941
gate: o.Gate,
4042
}
41-
42-
return ctrl.NewControllerManagedBy(mgr).
43+
b := ctrl.NewControllerManagedBy(mgr).
4344
For(&apiextensionsv1.CustomResourceDefinition{}).
44-
Named("crd-gate").
45-
Complete(reconcile.AsReconciler[*apiextensionsv1.CustomResourceDefinition](mgr.GetClient(), r))
45+
Named("crd-gate")
46+
47+
if len(o.Groups) > 0 {
48+
b = b.WithEventFilter(GroupPredicate(o.Groups...))
49+
}
50+
51+
return b.Complete(reconcile.AsReconciler[*apiextensionsv1.CustomResourceDefinition](mgr.GetClient(), r))
52+
}
53+
54+
// GroupPredicate returns a predicate that filters CustomResourceDefinitions by group.
55+
func GroupPredicate(groups ...string) predicate.Predicate {
56+
groupSet := make(map[string]struct{})
57+
for _, g := range groups {
58+
groupSet[g] = struct{}{}
59+
}
60+
return predicate.NewPredicateFuncs(func(obj client.Object) bool {
61+
crd, ok := obj.(*apiextensionsv1.CustomResourceDefinition)
62+
if !ok {
63+
return false
64+
}
65+
_, ok = groupSet[crd.Spec.Group]
66+
return ok
67+
})
4668
}

0 commit comments

Comments
 (0)