Skip to content

Commit fa91e1b

Browse files
vinceprincdc
authored andcommitted
✨ Allow to use builder.OnlyMetadata option with Watches
This change allows builders to use builder.OnlyMetadata when creating extra watches with .Watches(...). The code inspects the passed source.Source, and if it's of type *source.Kind, it calls the internal project method that allows to use metav1.PartialObjectMetadata in mapping functions. Signed-off-by: Vince Prignano <[email protected]> (cherry picked from commit df54dc5)
1 parent dbc25a8 commit fa91e1b

File tree

3 files changed

+73
-8
lines changed

3 files changed

+73
-8
lines changed

pkg/builder/controller.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,10 @@ func (blder *Builder) Owns(object runtime.Object, opts ...OwnsOption) *Builder {
121121

122122
// WatchesInput represents the information set by Watches method.
123123
type WatchesInput struct {
124-
src source.Source
125-
eventhandler handler.EventHandler
126-
predicates []predicate.Predicate
124+
src source.Source
125+
eventhandler handler.EventHandler
126+
predicates []predicate.Predicate
127+
objectProjection objectProjection
127128
}
128129

129130
// Watches exposes the lower-level ControllerManagedBy Watches functions through the builder. Consider using
@@ -261,10 +262,19 @@ func (blder *Builder) doWatch() error {
261262
for _, w := range blder.watchesInput {
262263
allPredicates := append([]predicate.Predicate(nil), blder.globalPredicates...)
263264
allPredicates = append(allPredicates, w.predicates...)
265+
266+
// If the source of this watch is of type *source.Kind, project it.
267+
if srckind, ok := w.src.(*source.Kind); ok {
268+
typeForSrc, err := blder.project(srckind.Type, w.objectProjection)
269+
if err != nil {
270+
return err
271+
}
272+
srckind.Type = typeForSrc
273+
}
274+
264275
if err := blder.ctrl.Watch(w.src, w.eventhandler, allPredicates...); err != nil {
265276
return err
266277
}
267-
268278
}
269279
return nil
270280
}

pkg/builder/controller_test.go

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,12 +306,61 @@ var _ = Describe("application", func() {
306306
Expect(err).NotTo(HaveOccurred())
307307
})
308308

309-
It("should support watching For & Owns as metadata", func() {
309+
It("should support watching For, Owns, and Watch as metadata", func() {
310+
statefulSetMaps := make(chan *metav1.PartialObjectMetadata)
311+
310312
bldr := ControllerManagedBy(mgr).
311313
For(&appsv1.Deployment{}, OnlyMetadata).
312-
Owns(&appsv1.ReplicaSet{}, OnlyMetadata)
314+
Owns(&appsv1.ReplicaSet{}, OnlyMetadata).
315+
Watches(&source.Kind{Type: &appsv1.StatefulSet{}},
316+
&handler.EnqueueRequestsFromMapFunc{
317+
ToRequests: handler.ToRequestsFunc(func(o handler.MapObject) []reconcile.Request {
318+
ometa := o.Object.(*metav1.PartialObjectMetadata)
319+
statefulSetMaps <- ometa
320+
return nil
321+
}),
322+
},
323+
OnlyMetadata)
313324

314325
doReconcileTest("8", stop, bldr, mgr, true)
326+
327+
By("Creating a new stateful set")
328+
set := &appsv1.StatefulSet{
329+
ObjectMeta: metav1.ObjectMeta{
330+
Namespace: "default",
331+
Name: "test1",
332+
Labels: map[string]string{
333+
"foo": "bar",
334+
},
335+
},
336+
Spec: appsv1.StatefulSetSpec{
337+
Selector: &metav1.LabelSelector{
338+
MatchLabels: map[string]string{"foo": "bar"},
339+
},
340+
Template: corev1.PodTemplateSpec{
341+
ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"foo": "bar"}},
342+
Spec: corev1.PodSpec{
343+
Containers: []corev1.Container{
344+
{
345+
Name: "nginx",
346+
Image: "nginx",
347+
},
348+
},
349+
},
350+
},
351+
},
352+
}
353+
err := mgr.GetClient().Create(context.TODO(), set)
354+
Expect(err).NotTo(HaveOccurred())
355+
356+
By("Checking that the mapping function has been called")
357+
Eventually(func() bool {
358+
metaSet := <-statefulSetMaps
359+
Expect(metaSet.Name).To(Equal(set.Name))
360+
Expect(metaSet.Namespace).To(Equal(set.Namespace))
361+
Expect(metaSet.Labels).To(Equal(set.Labels))
362+
return true
363+
}).Should(BeTrue())
315364
})
316365
})
317366
})

pkg/builder/options.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ func (p projectAs) ApplyToOwns(opts *OwnsInput) {
9494
opts.objectProjection = objectProjection(p)
9595
}
9696

97+
// ApplyToWatches applies this configuration to the given WatchesInput options.
98+
func (p projectAs) ApplyToWatches(opts *WatchesInput) {
99+
opts.objectProjection = objectProjection(p)
100+
}
101+
97102
var (
98103
// OnlyMetadata tells the controller to *only* cache metadata, and to watch
99104
// the the API server in metadata-only form. This is useful when watching
@@ -104,8 +109,9 @@ var (
104109
// unstructured cache.
105110
OnlyMetadata = projectAs(projectAsMetadata)
106111

107-
_ ForOption = OnlyMetadata
108-
_ OwnsOption = OnlyMetadata
112+
_ ForOption = OnlyMetadata
113+
_ OwnsOption = OnlyMetadata
114+
_ WatchesOption = OnlyMetadata
109115
)
110116

111117
// }}}

0 commit comments

Comments
 (0)