best practices
What did you do?
I'm trying to figure out ways of sharing resources between controllers under the same manager.
What did you expect to see?
I'd like to have some resource SharedObj shared between controllers. Ideally it should be initialized before the manager starts and Reconcile() code in controllers operate on the SharedObj.
What did you see instead? Under which circumstances?
I think it's hard to inject shared objects inside the current generated code by operator-sdk without replacing the manager and controller with my own structs like
import "sigs.k8s.io/controller-runtime/pkg/manager"
type MyManager struct {
manager.Manager
obj SharedObj
}
And change how it is created in cmd/manager/main.go. Also, controllers need to be changed in the similar way.
I do think of some alternative ways like storing the shared object as global variables in some packages, so I don't need to change the generated code. But I think this way makes it harder to perform dependency injection and write tests.
Did anyone faced a similar situation and how did you work around it? Thanks
Environment
Hi @danielsig727,
An object/structure will have its attributes according to its domain. So, IMO we do not add an attribute to an object because we would like to use it in more than one place. We add an attribute to an object because it is part of this domain. E.g: Saving Account has the attributed amount. However, would not make sense say that amount is part of the Client domain when a client would have a name, an address, an age end etc. Since I understand that you are looking for good practices, I'd like to recommend the book which is one of the best ones that I already read.
Regards your problem, wdyt about try to tell us what you would like to achieve with? I mean, what exactly would you like to have in more than one controller and why? What is the problem that you are trying to solve? Could you provide this info? It might help us understand your problem and try to help you to solve it.
thanks for the reply and book recommendation @camilamacedo86 !
I agree that I should share more about my use case. Currently, I'm trying to implement an operator that scales up and down deployments periodically. Ideally, it should take configuration by watching and parse annotations form Deployment, and maybe some Custom Resources in the future. And I'm also planning to extend it to handle more complex house-keeping logic that also runs periodically.
I was planning to implement an extra loop for executing the cronjobs. And Reconcile() updates the list of cronjobs upon create/update/delete events from Deployment and CRs. So the extra loop needs to be initiated in main() along with the manager. Also, to let Reconcile() update the cronjobs, it needs to access a handle to the cronjob loop. As far as I can think of, putting the handles in ReconcileCR struct in pkg/controller/cr/cr_controller.go might look cleaner, and easier to inject dependency when writing tests. But it requires many modifications to several parts of generated code due to the way the object is created. So that's why I need some way to pass objects top-down.
I hope this explains my original question. Or are there other designs to bypass this issue? Thank you!
HI @danielsig727,
From the controller.Reconcile you can GET/UPDATE/DELETE/LIST any resource in the cluster. So, I still not see any need for we add an attribute that is not part of the Manager domain on it or what actually information you would need to share between both controllers.
See my comment in https://github.com/operator-framework/operator-sdk/issues/3086#issuecomment-633753732 to understand how the reconcile works and the options to re-trigger the reconcile and the blog post Getting started with Golang Operators by using Operator SDK which I think can really help and the things more clear about how to work with it since it has an example to illustrate the idea.
I believe that the above contents suggested provided will help you know how to achieve your goal and answered your question. So, I am closing this one. However, feel free to ping me here to re-open if you still looking for help with and/or raise new issues.
Ah I definitely missed the part that it can be retriggered using Result.RequeueAfter, which makes it a lot easier. Thanks for the links! :D
Most helpful comment
Ah I definitely missed the part that it can be retriggered using
Result.RequeueAfter, which makes it a lot easier. Thanks for the links! :D