-
Notifications
You must be signed in to change notification settings - Fork 1.2k
⚠️ Refactor source/handler/predicate packages to remove dep injection #2120
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
d6a053f
c6fbc02
ad96c14
1c3b223
36ef9e1
b324b0b
ea1fcf3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
Signed-off-by: Vince Prignano <[email protected]>
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,7 +22,6 @@ import ( | |
| "strings" | ||
|
|
||
| "github.com/go-logr/logr" | ||
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
| "k8s.io/apimachinery/pkg/runtime/schema" | ||
| "k8s.io/klog/v2" | ||
|
|
||
|
|
@@ -197,18 +196,16 @@ func (blder *Builder) Build(r reconcile.Reconciler) (controller.Controller, erro | |
| return blder.ctrl, nil | ||
| } | ||
|
|
||
| func (blder *Builder) project(obj client.Object, proj objectProjection) (client.Object, error) { | ||
| func (blder *Builder) project(obj client.Object, proj objectProjection) (source.Source, error) { | ||
| src := source.Kind(blder.mgr.GetCache(), obj) | ||
| switch proj { | ||
| case projectAsNormal: | ||
| return obj, nil | ||
| return src, nil | ||
| case projectAsMetadata: | ||
| metaObj := &metav1.PartialObjectMetadata{} | ||
| gvk, err := getGvk(obj, blder.mgr.GetScheme()) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("unable to determine GVK of %T for a metadata-only watch: %w", obj, err) | ||
| if err := source.KindAsPartialMetadata(src, blder.mgr.GetScheme()); err != nil { | ||
|
||
| return nil, err | ||
| } | ||
| metaObj.SetGroupVersionKind(gvk) | ||
| return metaObj, nil | ||
| return src, nil | ||
| default: | ||
| panic(fmt.Sprintf("unexpected projection type %v on type %T, should not be possible since this is an internal field", proj, obj)) | ||
| } | ||
|
|
@@ -217,11 +214,10 @@ func (blder *Builder) project(obj client.Object, proj objectProjection) (client. | |
| func (blder *Builder) doWatch() error { | ||
| // Reconcile type | ||
| if blder.forInput.object != nil { | ||
| typeForSrc, err := blder.project(blder.forInput.object, blder.forInput.objectProjection) | ||
| src, err := blder.project(blder.forInput.object, blder.forInput.objectProjection) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| src := &source.Kind{Type: typeForSrc} | ||
| hdler := &handler.EnqueueRequestForObject{} | ||
| allPredicates := append(blder.globalPredicates, blder.forInput.predicates...) | ||
| if err := blder.ctrl.Watch(src, hdler, allPredicates...); err != nil { | ||
|
|
@@ -234,15 +230,15 @@ func (blder *Builder) doWatch() error { | |
| return errors.New("Owns() can only be used together with For()") | ||
| } | ||
| for _, own := range blder.ownsInput { | ||
| typeForSrc, err := blder.project(own.object, own.objectProjection) | ||
| src, err := blder.project(own.object, own.objectProjection) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| src := &source.Kind{Type: typeForSrc} | ||
| hdler := &handler.EnqueueRequestForOwner{ | ||
| OwnerType: blder.forInput.object, | ||
| IsController: true, | ||
| } | ||
| hdler := handler.EnqueueRequestForOwner( | ||
| blder.mgr.GetScheme(), blder.mgr.GetRESTMapper(), | ||
| blder.forInput.object, | ||
| handler.OnlyControllerOwner(), | ||
| ) | ||
| allPredicates := append([]predicate.Predicate(nil), blder.globalPredicates...) | ||
| allPredicates = append(allPredicates, own.predicates...) | ||
| if err := blder.ctrl.Watch(src, hdler, allPredicates...); err != nil { | ||
|
|
@@ -259,12 +255,12 @@ func (blder *Builder) doWatch() error { | |
| allPredicates = append(allPredicates, w.predicates...) | ||
|
|
||
| // If the source of this watch is of type *source.Kind, project it. | ||
|
||
| if srckind, ok := w.src.(*source.Kind); ok { | ||
| typeForSrc, err := blder.project(srckind.Type, w.objectProjection) | ||
| if err != nil { | ||
| return err | ||
| if srckind, ok := w.src.(source.SyncingSource); ok { | ||
| if w.objectProjection == projectAsMetadata { | ||
| if err := source.KindAsPartialMetadata(srckind, blder.mgr.GetScheme()); err != nil { | ||
| return err | ||
| } | ||
| } | ||
| srckind.Type = typeForSrc | ||
| } | ||
|
|
||
| if err := blder.ctrl.Watch(w.src, w.eventhandler, allPredicates...); err != nil { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -118,7 +118,7 @@ var _ = Describe("application", func() { | |
| Expect(err).NotTo(HaveOccurred()) | ||
|
|
||
| instance, err := ControllerManagedBy(m). | ||
| Watches(&source.Kind{Type: &appsv1.ReplicaSet{}}, &handler.EnqueueRequestForObject{}). | ||
| Watches(source.Kind(m.GetCache(), &appsv1.ReplicaSet{}), &handler.EnqueueRequestForObject{}). | ||
| Build(noop) | ||
| Expect(err).To(MatchError(ContainSubstring("one of For() or Named() must be called"))) | ||
| Expect(instance).To(BeNil()) | ||
|
|
@@ -157,7 +157,7 @@ var _ = Describe("application", func() { | |
|
|
||
| instance, err := ControllerManagedBy(m). | ||
| Named("my_controller"). | ||
| Watches(&source.Kind{Type: &appsv1.ReplicaSet{}}, &handler.EnqueueRequestForObject{}). | ||
| Watches(source.Kind(m.GetCache(), &appsv1.ReplicaSet{}), &handler.EnqueueRequestForObject{}). | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is now the new experience on how to create a controller in a manager. Over time, the builder has increased the options we're passing in, which is ok, but we've also had to deal with all of the dependency injection stuff which isn't pretty at all. This UX might be a stopgap, but it's actually nicer to be explicit where a source is getting its cache or any other function. In a follow-up PR we might want to explore easier ways to plow through this information when we're clearly building a controller in a Manager, and make the source aware that it can access whatever it needs through the manager. For now, we can keep this as a first step breaking change and iterate on it as we see fit. The clarity might come handy in the future when we reason through the codebase. |
||
| Build(noop) | ||
| Expect(err).NotTo(HaveOccurred()) | ||
| Expect(instance).NotTo(BeNil()) | ||
|
|
@@ -369,8 +369,9 @@ var _ = Describe("application", func() { | |
| bldr := ControllerManagedBy(m). | ||
| For(&appsv1.Deployment{}). | ||
| Watches( // Equivalent of Owns | ||
| &source.Kind{Type: &appsv1.ReplicaSet{}}, | ||
| &handler.EnqueueRequestForOwner{OwnerType: &appsv1.Deployment{}, IsController: true}) | ||
| source.Kind(m.GetCache(), &appsv1.ReplicaSet{}), | ||
| handler.EnqueueRequestForOwner(m.GetScheme(), m.GetRESTMapper(), &appsv1.Deployment{}, handler.OnlyControllerOwner()), | ||
| ) | ||
|
|
||
| ctx, cancel := context.WithCancel(context.Background()) | ||
| defer cancel() | ||
|
|
@@ -384,10 +385,11 @@ var _ = Describe("application", func() { | |
| bldr := ControllerManagedBy(m). | ||
| Named("Deployment"). | ||
| Watches( // Equivalent of For | ||
| &source.Kind{Type: &appsv1.Deployment{}}, &handler.EnqueueRequestForObject{}). | ||
| source.Kind(m.GetCache(), &appsv1.Deployment{}), &handler.EnqueueRequestForObject{}). | ||
| Watches( // Equivalent of Owns | ||
| &source.Kind{Type: &appsv1.ReplicaSet{}}, | ||
| &handler.EnqueueRequestForOwner{OwnerType: &appsv1.Deployment{}, IsController: true}) | ||
| source.Kind(m.GetCache(), &appsv1.ReplicaSet{}), | ||
| handler.EnqueueRequestForOwner(m.GetScheme(), m.GetRESTMapper(), &appsv1.Deployment{}, handler.OnlyControllerOwner()), | ||
| ) | ||
|
|
||
| ctx, cancel := context.WithCancel(context.Background()) | ||
| defer cancel() | ||
|
|
@@ -481,7 +483,7 @@ var _ = Describe("application", func() { | |
| bldr := ControllerManagedBy(mgr). | ||
| For(&appsv1.Deployment{}, OnlyMetadata). | ||
| Owns(&appsv1.ReplicaSet{}, OnlyMetadata). | ||
| Watches(&source.Kind{Type: &appsv1.StatefulSet{}}, | ||
| Watches(source.Kind(mgr.GetCache(), &appsv1.StatefulSet{}), | ||
| handler.EnqueueRequestsFromMapFunc(func(o client.Object) []reconcile.Request { | ||
| defer GinkgoRecover() | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These were actually useful to catch errors right away, and have a bit more verbosity when tests are running, we should probably keep them