Skip to content

Commit 582b82e

Browse files
authored
Merge pull request kubernetes-sigs#1242 from vincepri/only-metadata-watches
✨ Allow to use builder.OnlyMetadata option with Watches
2 parents 9975e29 + df54dc5 commit 582b82e

File tree

3 files changed

+71
-8
lines changed

3 files changed

+71
-8
lines changed

pkg/builder/controller.go

+14-4
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,10 @@ func (blder *Builder) Owns(object client.Object, opts ...OwnsOption) *Builder {
116116

117117
// WatchesInput represents the information set by Watches method.
118118
type WatchesInput struct {
119-
src source.Source
120-
eventhandler handler.EventHandler
121-
predicates []predicate.Predicate
119+
src source.Source
120+
eventhandler handler.EventHandler
121+
predicates []predicate.Predicate
122+
objectProjection objectProjection
122123
}
123124

124125
// Watches exposes the lower-level ControllerManagedBy Watches functions through the builder. Consider using
@@ -255,10 +256,19 @@ func (blder *Builder) doWatch() error {
255256
for _, w := range blder.watchesInput {
256257
allPredicates := append([]predicate.Predicate(nil), blder.globalPredicates...)
257258
allPredicates = append(allPredicates, w.predicates...)
259+
260+
// If the source of this watch is of type *source.Kind, project it.
261+
if srckind, ok := w.src.(*source.Kind); ok {
262+
typeForSrc, err := blder.project(srckind.Type, w.objectProjection)
263+
if err != nil {
264+
return err
265+
}
266+
srckind.Type = typeForSrc
267+
}
268+
258269
if err := blder.ctrl.Watch(w.src, w.eventhandler, allPredicates...); err != nil {
259270
return err
260271
}
261-
262272
}
263273
return nil
264274
}

pkg/builder/controller_test.go

+49-2
Original file line numberDiff line numberDiff line change
@@ -371,14 +371,61 @@ var _ = Describe("application", func() {
371371
Expect(err).NotTo(HaveOccurred())
372372
})
373373

374-
It("should support watching For & Owns as metadata", func() {
374+
It("should support watching For, Owns, and Watch as metadata", func() {
375+
statefulSetMaps := make(chan *metav1.PartialObjectMetadata)
376+
375377
bldr := ControllerManagedBy(mgr).
376378
For(&appsv1.Deployment{}, OnlyMetadata).
377-
Owns(&appsv1.ReplicaSet{}, OnlyMetadata)
379+
Owns(&appsv1.ReplicaSet{}, OnlyMetadata).
380+
Watches(&source.Kind{Type: &appsv1.StatefulSet{}},
381+
handler.EnqueueRequestsFromMapFunc(func(o client.Object) []reconcile.Request {
382+
ometa := o.(*metav1.PartialObjectMetadata)
383+
statefulSetMaps <- ometa
384+
return nil
385+
}),
386+
OnlyMetadata)
378387

379388
ctx, cancel := context.WithCancel(context.Background())
380389
defer cancel()
381390
doReconcileTest(ctx, "8", bldr, mgr, true)
391+
392+
By("Creating a new stateful set")
393+
set := &appsv1.StatefulSet{
394+
ObjectMeta: metav1.ObjectMeta{
395+
Namespace: "default",
396+
Name: "test1",
397+
Labels: map[string]string{
398+
"foo": "bar",
399+
},
400+
},
401+
Spec: appsv1.StatefulSetSpec{
402+
Selector: &metav1.LabelSelector{
403+
MatchLabels: map[string]string{"foo": "bar"},
404+
},
405+
Template: corev1.PodTemplateSpec{
406+
ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"foo": "bar"}},
407+
Spec: corev1.PodSpec{
408+
Containers: []corev1.Container{
409+
{
410+
Name: "nginx",
411+
Image: "nginx",
412+
},
413+
},
414+
},
415+
},
416+
},
417+
}
418+
err := mgr.GetClient().Create(context.TODO(), set)
419+
Expect(err).NotTo(HaveOccurred())
420+
421+
By("Checking that the mapping function has been called")
422+
Eventually(func() bool {
423+
metaSet := <-statefulSetMaps
424+
Expect(metaSet.Name).To(Equal(set.Name))
425+
Expect(metaSet.Namespace).To(Equal(set.Namespace))
426+
Expect(metaSet.Labels).To(Equal(set.Labels))
427+
return true
428+
}).Should(BeTrue())
382429
})
383430
})
384431
})

pkg/builder/options.go

+8-2
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)