Skip to content

Commit ef0f2df

Browse files
committed
🐛 PartialMetadataObject should preserve GVK information
Currently we have a bug that GVK information is not passed into mapping functions when using the OnlyMetadata option in the builder. This patch adds a wrapper that preserves the GVK information when events come in. Signed-off-by: Vince Prignano <vincepri@vmware.com>
1 parent 4aecab5 commit ef0f2df

File tree

3 files changed

+96
-16
lines changed

3 files changed

+96
-16
lines changed

pkg/builder/controller.go

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -199,47 +199,45 @@ func (blder *Builder) Build(r reconcile.Reconciler) (controller.Controller, erro
199199
return blder.ctrl, nil
200200
}
201201

202-
func (blder *Builder) project(obj client.Object, proj objectProjection) (client.Object, error) {
202+
func (blder *Builder) project(obj client.Object, hdl handler.EventHandler, proj objectProjection) (client.Object, handler.EventHandler, error) {
203203
switch proj {
204204
case projectAsNormal:
205-
return obj, nil
205+
return obj, hdl, nil
206206
case projectAsMetadata:
207207
metaObj := &metav1.PartialObjectMetadata{}
208208
gvk, err := getGvk(obj, blder.mgr.GetScheme())
209209
if err != nil {
210-
return nil, fmt.Errorf("unable to determine GVK of %T for a metadata-only watch: %w", obj, err)
210+
return nil, nil, fmt.Errorf("unable to determine GVK of %T for a metadata-only watch: %w", obj, err)
211211
}
212212
metaObj.SetGroupVersionKind(gvk)
213-
return metaObj, nil
213+
return metaObj, handler.WrapPartialObjectMetadataHandler(metaObj, hdl), err
214214
default:
215215
panic(fmt.Sprintf("unexpected projection type %v on type %T, should not be possible since this is an internal field", proj, obj))
216216
}
217217
}
218218

219219
func (blder *Builder) doWatch() error {
220220
// Reconcile type
221-
typeForSrc, err := blder.project(blder.forInput.object, blder.forInput.objectProjection)
221+
typeForSrc, hdler, err := blder.project(blder.forInput.object, &handler.EnqueueRequestForObject{}, blder.forInput.objectProjection)
222222
if err != nil {
223223
return err
224224
}
225225
src := &source.Kind{Type: typeForSrc}
226-
hdler := &handler.EnqueueRequestForObject{}
227226
allPredicates := append(blder.globalPredicates, blder.forInput.predicates...)
228227
if err := blder.ctrl.Watch(src, hdler, allPredicates...); err != nil {
229228
return err
230229
}
231230

232231
// Watches the managed types
233232
for _, own := range blder.ownsInput {
234-
typeForSrc, err := blder.project(own.object, own.objectProjection)
233+
typeForSrc, hdler, err := blder.project(own.object, &handler.EnqueueRequestForOwner{
234+
OwnerType: blder.forInput.object,
235+
IsController: true,
236+
}, own.objectProjection)
235237
if err != nil {
236238
return err
237239
}
238240
src := &source.Kind{Type: typeForSrc}
239-
hdler := &handler.EnqueueRequestForOwner{
240-
OwnerType: blder.forInput.object,
241-
IsController: true,
242-
}
243241
allPredicates := append([]predicate.Predicate(nil), blder.globalPredicates...)
244242
allPredicates = append(allPredicates, own.predicates...)
245243
if err := blder.ctrl.Watch(src, hdler, allPredicates...); err != nil {
@@ -252,16 +250,19 @@ func (blder *Builder) doWatch() error {
252250
allPredicates := append([]predicate.Predicate(nil), blder.globalPredicates...)
253251
allPredicates = append(allPredicates, w.predicates...)
254252

253+
watchHandler := w.eventhandler
254+
255255
// If the source of this watch is of type *source.Kind, project it.
256256
if srckind, ok := w.src.(*source.Kind); ok {
257-
typeForSrc, err := blder.project(srckind.Type, w.objectProjection)
257+
typeForSrc, hdl, err := blder.project(srckind.Type, w.eventhandler, w.objectProjection)
258258
if err != nil {
259259
return err
260260
}
261261
srckind.Type = typeForSrc
262+
watchHandler = hdl
262263
}
263264

264-
if err := blder.ctrl.Watch(w.src, w.eventhandler, allPredicates...); err != nil {
265+
if err := blder.ctrl.Watch(w.src, watchHandler, allPredicates...); err != nil {
265266
return err
266267
}
267268
}

pkg/builder/controller_test.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636

3737
"sigs.k8s.io/controller-runtime/pkg/cache"
3838
"sigs.k8s.io/controller-runtime/pkg/client"
39+
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
3940
"sigs.k8s.io/controller-runtime/pkg/config/v1alpha1"
4041
"sigs.k8s.io/controller-runtime/pkg/controller"
4142
"sigs.k8s.io/controller-runtime/pkg/event"
@@ -409,6 +410,9 @@ var _ = Describe("application", func() {
409410
Watches(&source.Kind{Type: &appsv1.StatefulSet{}},
410411
handler.EnqueueRequestsFromMapFunc(func(o client.Object) []reconcile.Request {
411412
ometa := o.(*metav1.PartialObjectMetadata)
413+
if _, err := apiutil.GVKForObject(o, mgr.GetScheme()); err != nil {
414+
Expect(err).NotTo(HaveOccurred())
415+
}
412416
statefulSetMaps <- ometa
413417
return nil
414418
}),
@@ -583,9 +587,9 @@ func doReconcileTest(ctx context.Context, nameSuffix string, blder *Builder, mgr
583587
Expect(err).NotTo(HaveOccurred())
584588

585589
By("Waiting for the ReplicaSet Reconcile")
586-
Eventually(ch).Should(Receive(Equal(reconcile.Request{
587-
NamespacedName: types.NamespacedName{Namespace: "default", Name: deployName}})))
588-
590+
rec := reconcile.Request{
591+
NamespacedName: types.NamespacedName{Namespace: "default", Name: deployName}}
592+
Eventually(ch).Should(Receive(Equal(rec)), rec.String())
589593
}
590594

591595
var _ runtime.Object = &fakeType{}

pkg/handler/metadata_wrapper.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package handler
2+
3+
import (
4+
"k8s.io/apimachinery/pkg/api/meta"
5+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
6+
"k8s.io/apimachinery/pkg/runtime"
7+
"k8s.io/apimachinery/pkg/runtime/schema"
8+
"k8s.io/client-go/util/workqueue"
9+
"sigs.k8s.io/controller-runtime/pkg/client"
10+
"sigs.k8s.io/controller-runtime/pkg/event"
11+
"sigs.k8s.io/controller-runtime/pkg/runtime/inject"
12+
)
13+
14+
type metadataOnlyWrapper struct {
15+
gvk schema.GroupVersionKind
16+
handler EventHandler
17+
}
18+
19+
func (e *metadataOnlyWrapper) restoreGVK(o client.Object) {
20+
pom := o.(*metav1.PartialObjectMetadata)
21+
pom.SetGroupVersionKind(e.gvk)
22+
}
23+
24+
// Create implements EventHandler
25+
func (e *metadataOnlyWrapper) Create(evt event.CreateEvent, q workqueue.RateLimitingInterface) {
26+
e.restoreGVK(evt.Object)
27+
e.handler.Create(evt, q)
28+
}
29+
30+
// Update implements EventHandler
31+
func (e *metadataOnlyWrapper) Update(evt event.UpdateEvent, q workqueue.RateLimitingInterface) {
32+
e.restoreGVK(evt.ObjectOld)
33+
e.restoreGVK(evt.ObjectNew)
34+
e.handler.Update(evt, q)
35+
}
36+
37+
// Delete implements EventHandler
38+
func (e *metadataOnlyWrapper) Delete(evt event.DeleteEvent, q workqueue.RateLimitingInterface) {
39+
e.restoreGVK(evt.Object)
40+
e.handler.Delete(evt, q)
41+
}
42+
43+
// Generic implements EventHandler
44+
func (e *metadataOnlyWrapper) Generic(evt event.GenericEvent, q workqueue.RateLimitingInterface) {
45+
e.restoreGVK(evt.Object)
46+
e.handler.Generic(evt, q)
47+
}
48+
49+
var _ inject.Scheme = &metadataOnlyWrapper{}
50+
51+
func (e *metadataOnlyWrapper) InjectScheme(s *runtime.Scheme) error {
52+
if i, ok := e.handler.(inject.Scheme); ok {
53+
return i.InjectScheme(s)
54+
}
55+
return nil
56+
}
57+
58+
var _ inject.Mapper = &metadataOnlyWrapper{}
59+
60+
func (e *metadataOnlyWrapper) InjectMapper(m meta.RESTMapper) error {
61+
if i, ok := e.handler.(inject.Mapper); ok {
62+
return i.InjectMapper(m)
63+
}
64+
return nil
65+
}
66+
67+
// WrapPartialObjectMetadataHandler wraps an event handler for partial metadata objects
68+
// which restores the GVK for PartialObjectMetadata objects which loses this information when
69+
// events come from the informer code.
70+
func WrapPartialObjectMetadataHandler(o *metav1.PartialObjectMetadata, hdl EventHandler) EventHandler {
71+
return &metadataOnlyWrapper{
72+
gvk: o.GroupVersionKind(),
73+
handler: hdl,
74+
}
75+
}

0 commit comments

Comments
 (0)