Skip to content

Commit 19c972d

Browse files
committed
Move generation check from change_processor to controller
Problem: When processing updates to cluster resources, for some resources, we check their generation, so that we don't trigger state change (graph rebuild) if the generation didn't change. This is a performance optimization so that we don't rebuild the graph and as a result do not regenerate NGINX config and reload it. This is not a K8s-native solution, and may introduce complexity for the codebase. Solution: Use `GenerationChangedPredicate` in controller-runtime to filter out the resource events at the controller level.
1 parent 9f4248e commit 19c972d

File tree

4 files changed

+17
-101
lines changed

4 files changed

+17
-101
lines changed

internal/mode/static/manager.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -281,22 +281,28 @@ func registerControllers(
281281
{
282282
objectType: &gatewayv1.GatewayClass{},
283283
options: []controller.Option{
284+
controller.WithK8sPredicate(k8spredicate.GenerationChangedPredicate{}),
284285
controller.WithK8sPredicate(predicate.GatewayClassPredicate{ControllerName: cfg.GatewayCtlrName}),
285286
},
286287
},
287288
{
288289
objectType: &gatewayv1.Gateway{},
289290
options: func() []controller.Option {
291+
options := []controller.Option{
292+
controller.WithK8sPredicate(k8spredicate.GenerationChangedPredicate{}),
293+
}
290294
if cfg.GatewayNsName != nil {
291-
return []controller.Option{
292-
controller.WithNamespacedNameFilter(filter.CreateSingleResourceFilter(*cfg.GatewayNsName)),
293-
}
295+
options = append(options,
296+
controller.WithNamespacedNameFilter(filter.CreateSingleResourceFilter(*cfg.GatewayNsName)))
294297
}
295-
return nil
298+
return options
296299
}(),
297300
},
298301
{
299302
objectType: &gatewayv1.HTTPRoute{},
303+
options: []controller.Option{
304+
controller.WithK8sPredicate(k8spredicate.GenerationChangedPredicate{}),
305+
},
300306
},
301307
{
302308
objectType: &apiv1.Service{},
@@ -334,6 +340,9 @@ func registerControllers(
334340
},
335341
{
336342
objectType: &gatewayv1beta1.ReferenceGrant{},
343+
options: []controller.Option{
344+
controller.WithK8sPredicate(k8spredicate.GenerationChangedPredicate{}),
345+
},
337346
},
338347
{
339348
objectType: &crdWithGVK,

internal/mode/static/state/change_processor.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,22 +126,22 @@ func NewChangeProcessorImpl(cfg ChangeProcessorConfig) *ChangeProcessorImpl {
126126
{
127127
gvk: extractGVK(&v1.GatewayClass{}),
128128
store: newObjectStoreMapAdapter(clusterStore.GatewayClasses),
129-
predicate: generationChangedPredicate{},
129+
predicate: nil,
130130
},
131131
{
132132
gvk: extractGVK(&v1.Gateway{}),
133133
store: newObjectStoreMapAdapter(clusterStore.Gateways),
134-
predicate: generationChangedPredicate{},
134+
predicate: nil,
135135
},
136136
{
137137
gvk: extractGVK(&v1.HTTPRoute{}),
138138
store: newObjectStoreMapAdapter(clusterStore.HTTPRoutes),
139-
predicate: generationChangedPredicate{},
139+
predicate: nil,
140140
},
141141
{
142142
gvk: extractGVK(&v1beta1.ReferenceGrant{}),
143143
store: newObjectStoreMapAdapter(clusterStore.ReferenceGrants),
144-
predicate: generationChangedPredicate{},
144+
predicate: nil,
145145
},
146146
{
147147
gvk: extractGVK(&apiv1.Namespace{}),

internal/mode/static/state/changed_predicate.go

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,6 @@ func (f funcPredicate) delete(object client.Object) bool {
2424
return f.stateChanged(object)
2525
}
2626

27-
// generationChangedPredicate implements stateChangedPredicate based on the generation of the object.
28-
// This predicate will return true on upsert if the object's generation has changed.
29-
// It always returns true on delete.
30-
type generationChangedPredicate struct{}
31-
32-
func (generationChangedPredicate) delete(_ client.Object) bool { return true }
33-
34-
func (generationChangedPredicate) upsert(oldObject, newObject client.Object) bool {
35-
if oldObject == nil {
36-
return true
37-
}
38-
39-
if newObject == nil {
40-
panic("Cannot determine if generation has changed on upsert because new object is nil")
41-
}
42-
43-
return newObject.GetGeneration() != oldObject.GetGeneration()
44-
}
45-
4627
// annotationChangedPredicate implements stateChangedPredicate based on the value of the annotation provided.
4728
// This predicate will return true on upsert if the annotation's value has changed.
4829
// It always returns true on delete.

internal/mode/static/state/changed_predicate_test.go

Lines changed: 0 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -20,80 +20,6 @@ func TestFuncPredicate(t *testing.T) {
2020
g.Expect(p.upsert(nil, nil)).To(BeTrue())
2121
}
2222

23-
func TestGenerationChangedPredicate_Delete(t *testing.T) {
24-
p := generationChangedPredicate{}
25-
26-
g := NewWithT(t)
27-
g.Expect(p.delete(nil)).To(BeTrue())
28-
}
29-
30-
func TestGenerationChangedPredicate_Update(t *testing.T) {
31-
tests := []struct {
32-
oldObj client.Object
33-
newObj client.Object
34-
name string
35-
stateChanged bool
36-
expPanic bool
37-
}{
38-
{
39-
name: "generation has changed",
40-
oldObj: &v1.Pod{
41-
ObjectMeta: metav1.ObjectMeta{
42-
Generation: 1,
43-
},
44-
},
45-
newObj: &v1.Pod{
46-
ObjectMeta: metav1.ObjectMeta{
47-
Generation: 2,
48-
},
49-
},
50-
stateChanged: true,
51-
},
52-
{
53-
name: "generation has not changed",
54-
oldObj: &v1.Pod{
55-
ObjectMeta: metav1.ObjectMeta{
56-
Generation: 1,
57-
},
58-
},
59-
newObj: &v1.Pod{
60-
ObjectMeta: metav1.ObjectMeta{
61-
Generation: 1,
62-
},
63-
},
64-
stateChanged: false,
65-
},
66-
{
67-
name: "old object is nil",
68-
oldObj: nil,
69-
newObj: &v1.Pod{},
70-
stateChanged: true,
71-
},
72-
{
73-
name: "new object is nil",
74-
oldObj: &v1.Pod{},
75-
newObj: nil,
76-
expPanic: true,
77-
},
78-
}
79-
80-
p := generationChangedPredicate{}
81-
82-
for _, test := range tests {
83-
t.Run(test.name, func(t *testing.T) {
84-
g := NewWithT(t)
85-
if test.expPanic {
86-
upsert := func() {
87-
p.upsert(test.oldObj, test.newObj)
88-
}
89-
g.Expect(upsert).Should(Panic())
90-
} else {
91-
g.Expect(p.upsert(test.oldObj, test.newObj)).To(Equal(test.stateChanged))
92-
}
93-
})
94-
}
95-
}
96-
9723
func TestAnnotationChangedPredicate_Delete(t *testing.T) {
9824
p := annotationChangedPredicate{}
9925

0 commit comments

Comments
 (0)