Skip to content
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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

馃尡 Refactor internal cache/informers map impl #2103

Merged
merged 2 commits into from Dec 22, 2022

Conversation

vincepri
Copy link
Member

@vincepri vincepri commented Dec 16, 2022

This is a first of a series of cleanups of our internal libraries, which has been long overdue. There are two commits in here, which we can also separate in different PRs if needed. The first pass simplifies w/ adding options to the implementation, the second refactors the map by removing the delegating map logic, which had lots of repetition and created confusion in the past.

Signed-off-by: Vince Prignano vince@prigna.com

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Dec 16, 2022
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: vincepri

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added approved Indicates a PR has been approved by an approver from all required OWNERS files. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Dec 16, 2022
@vincepri vincepri force-pushed the cleanup-informer-map branch 2 times, most recently from f637164 to 4a1bb11 Compare December 16, 2022 20:33
@vincepri
Copy link
Member Author

/assign @alvaroaleman @sbueringer

@k8s-ci-robot k8s-ci-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Dec 17, 2022
@vincepri vincepri changed the title 馃尡 Cleanup internal cache/informers map impl 馃尡 Refactor internal cache/informers map impl Dec 17, 2022
@vincepri
Copy link
Member Author

/retest

Copy link
Member

@sbueringer sbueringer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some nits, overall lgtm

// in an InformerMap.
type InformersMapOptionsByGVK struct {
Selectors SelectorsByGVK
Transformers TransformFuncByObject
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No strong objection but it seems a bit odd to have "ByGVK" and then have TransformFuncByObject.

Looking at TransformFuncByObject it seems to essentially also use GVK

	Set(runtime.Object, *runtime.Scheme, cache.TransformFunc) error
	Get(schema.GroupVersionKind) cache.TransformFunc

Get directly works with GVK and only Set takes an Object but only uses it to infer the GVK.

Wondering if we could/should rename TransformFuncByObject to TransformFuncByGVK especially as I would say the main functionality is mapping from "something" to TransformFunc in Get and that is done by GVK

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed, it was all internal functions fortunately

@@ -145,7 +152,7 @@ type specificInformersMap struct {

// Start calls Run on each of the informers and sets started to true. Blocks on the context.
// It doesn't return start because it can't return an error, and it's not a runnable directly.
func (ip *specificInformersMap) Start(ctx context.Context) {
func (ip *InformersMap) Start(ctx context.Context) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: Was the error return parameter just added in case we want to return errors in the future? (as of now we only return nil)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was added to satisfy the Runnable interface, the same (nil error returned in any case) was before in the deleg_map file

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, thx for the info!

pkg/cache/internal/informers_map.go Outdated Show resolved Hide resolved
Comment on lines +273 to +284
ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) {
ip.selectors(gvk).ApplyToList(&opts)
return lw.ListFunc(opts)
},
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
ip.selectors(gvk).ApplyToList(&opts)
opts.Watch = true // Watch needs to be set to true separately
return lw.WatchFunc(opts)
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: would it make sense to do this in makeListWatcher so that makeListWatcher alredy creates the final ListWatch vs having "layered" ListWatches?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Originally it was in each list watcher creation function, although the code was duplicate between each watch/listfunc, which was a bit repetitive. Do you see another way to do this that doesn't end up in repetition?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the following options:

  1. write the listFunc and watchFunc in makeListWatcher inside the switch in variables and then build the ListWatch like it is done here at the end of the makeListWatcher func
  2. writing the ListWatch'es in makeListWatcher in a var and then add this code at the end of the makeListWatcher func
  3. defining inline modifyListOptions modifyWatchOptions func in makeListWatcher and calling them in each case

I would probably go with option 1, but also fine to just keep it as is if you want to

pkg/cache/internal/informers_map.go Outdated Show resolved Hide resolved
Signed-off-by: Vince Prignano <vince@prigna.com>
@vincepri vincepri force-pushed the cleanup-informer-map branch 2 times, most recently from ccd3222 to 24812a3 Compare December 21, 2022 15:42
Signed-off-by: Vince Prignano <vince@prigna.com>
return list, err
},
// Setup the watch function
WatchFunc: func(opts metav1.ListOptions) (watcher watch.Interface, err error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
WatchFunc: func(opts metav1.ListOptions) (watcher watch.Interface, err error) {
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {

nit: maybe get rid of the named return parameters if we don't really need them anymore
(fine if you want to keep it)

@@ -145,7 +152,7 @@ type specificInformersMap struct {

// Start calls Run on each of the informers and sets started to true. Blocks on the context.
// It doesn't return start because it can't return an error, and it's not a runnable directly.
func (ip *specificInformersMap) Start(ctx context.Context) {
func (ip *InformersMap) Start(ctx context.Context) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, thx for the info!

Comment on lines +273 to +284
ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) {
ip.selectors(gvk).ApplyToList(&opts)
return lw.ListFunc(opts)
},
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
ip.selectors(gvk).ApplyToList(&opts)
opts.Watch = true // Watch needs to be set to true separately
return lw.WatchFunc(opts)
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the following options:

  1. write the listFunc and watchFunc in makeListWatcher inside the switch in variables and then build the ListWatch like it is done here at the end of the makeListWatcher func
  2. writing the ListWatch'es in makeListWatcher in a var and then add this code at the end of the makeListWatcher func
  3. defining inline modifyListOptions modifyWatchOptions func in makeListWatcher and calling them in each case

I would probably go with option 1, but also fine to just keep it as is if you want to

@vincepri
Copy link
Member Author

/retest

@sbueringer
Copy link
Member

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Dec 22, 2022
@k8s-ci-robot k8s-ci-robot merged commit 3c4deba into kubernetes-sigs:master Dec 22, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants