Skip to content

Commit 7c7672f

Browse files
authored
feat: enqueue instances on rgd update (#474)
* feat: enqueue instance objects after rgd update
1 parent 56ea2e7 commit 7c7672f

File tree

2 files changed

+69
-2
lines changed

2 files changed

+69
-2
lines changed

Diff for: pkg/dynamiccontroller/dynamic_controller.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ import (
6464
"github.com/go-logr/logr"
6565
"golang.org/x/time/rate"
6666
apierrors "k8s.io/apimachinery/pkg/api/errors"
67+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
6768
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
6869
"k8s.io/apimachinery/pkg/runtime/schema"
6970
"k8s.io/apimachinery/pkg/types"
@@ -427,8 +428,16 @@ func (dc *DynamicController) StartServingGVK(ctx context.Context, gvr schema.Gro
427428
_, exists := dc.informers.Load(gvr)
428429
if exists {
429430
// Even thought the informer is already registered, we should still
430-
// still update the handler, as it might have changed.
431+
// update the handler, as it might have changed.
431432
dc.handlers.Store(gvr, handler)
433+
// trigger reconciliation of the corresponding gvr's
434+
objs, err := dc.kubeClient.Resource(gvr).Namespace("").List(ctx, metav1.ListOptions{})
435+
if err != nil {
436+
return fmt.Errorf("failed to list objects for GVR %s: %w", gvr, err)
437+
}
438+
for _, obj := range objs.Items {
439+
dc.enqueueObject(&obj, "update")
440+
}
432441
return nil
433442
}
434443

@@ -441,7 +450,6 @@ func (dc *DynamicController) StartServingGVK(ctx context.Context, gvr schema.Gro
441450
"",
442451
nil,
443452
)
444-
445453
informer := gvkInformer.ForResource(gvr).Informer()
446454

447455
// Set up event handlers

Diff for: pkg/dynamiccontroller/dynamic_controller_test.go

+59
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ package dynamiccontroller
1414

1515
import (
1616
"context"
17+
"fmt"
1718
"io"
19+
"maps"
20+
"slices"
1821
"testing"
1922
"time"
2023

@@ -152,3 +155,59 @@ func TestEnqueueObject(t *testing.T) {
152155

153156
assert.Equal(t, 1, dc.queue.Len())
154157
}
158+
159+
func TestInstanceUpdatePolicy(t *testing.T) {
160+
logger := noopLogger()
161+
162+
scheme := runtime.NewScheme()
163+
gvr := schema.GroupVersionResource{Group: "test", Version: "v1", Resource: "tests"}
164+
gvk := schema.GroupVersionKind{Group: "test", Version: "v1", Kind: "Test"}
165+
166+
objs := make(map[string]runtime.Object)
167+
168+
obj1 := &unstructured.Unstructured{}
169+
obj1.SetGroupVersionKind(gvk)
170+
obj1.SetNamespace("default")
171+
obj1.SetName("test-object-1")
172+
objs[obj1.GetNamespace()+"/"+obj1.GetName()] = obj1
173+
174+
obj2 := &unstructured.Unstructured{}
175+
obj2.SetGroupVersionKind(gvk)
176+
obj2.SetNamespace("test-namespace")
177+
obj2.SetName("test-object-2")
178+
objs[obj2.GetNamespace()+"/"+obj2.GetName()] = obj2
179+
180+
client := fake.NewSimpleDynamicClientWithCustomListKinds(scheme, map[schema.GroupVersionResource]string{
181+
gvr: "TestList",
182+
}, slices.Collect(maps.Values(objs))...)
183+
184+
dc := NewDynamicController(logger, Config{}, client)
185+
186+
handlerFunc := Handler(func(ctx context.Context, req controllerruntime.Request) error {
187+
fmt.Println("reconciling instance", req)
188+
return nil
189+
})
190+
191+
// simulate initial creation of the resource graph
192+
err := dc.StartServingGVK(context.Background(), gvr, handlerFunc)
193+
assert.NoError(t, err)
194+
195+
// simulate reconciling the instances
196+
for dc.queue.Len() > 0 {
197+
item, _ := dc.queue.Get()
198+
dc.queue.Done(item)
199+
dc.queue.Forget(item)
200+
}
201+
202+
// simulate updating the resource graph
203+
err = dc.StartServingGVK(context.Background(), gvr, handlerFunc)
204+
assert.NoError(t, err)
205+
206+
// check if the expected objects are queued
207+
assert.Equal(t, dc.queue.Len(), 2)
208+
for dc.queue.Len() > 0 {
209+
name, _ := dc.queue.Get()
210+
_, ok := objs[name.NamespacedKey]
211+
assert.True(t, ok)
212+
}
213+
}

0 commit comments

Comments
 (0)