-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
K8s client as reusable cell #21026
K8s client as reusable cell #21026
Conversation
bde7662
to
7e8c3af
Compare
/test |
Here is how
From the above we see that the We can use for example
|
7e8c3af
to
21a444e
Compare
Closing and reopening to rerun CI. |
85e3b93
to
a7ff5e3
Compare
/test |
f1f23dc
to
22ac15f
Compare
/test |
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.
Great! 🎉
A couple of things left inline (one naming preference and a possible missing initialization).
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.
LGTM besides a few minor comments. Awesome PR! 🚀
22ac15f
to
e1d96a8
Compare
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.
Nice PR! LGTM 💯
daemon/cmd/root.go
Outdated
func init() { | ||
cobra.OnInitialize(option.InitConfig(RootCmd, "cilium-agent", "cilium", Vp)) | ||
setupSleepBeforeFatal() | ||
registerBootstrapMetrics() | ||
initializeFlags() | ||
|
||
flags := pflag.NewFlagSet("hive", pflag.ContinueOnError) |
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.
This all is a bit confusing. there's initializeFlags()
which takes no arguments, then there's the flags
var, then there's RootCmd.Flags()
? And commands
Is there any way to make this simpler? I would expect that creating the Hive would make the flags Just Work.
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.
The reason for this is that the root, "dot-graph" and "objects" commands in cilium-agent want all the same flags, but then we have "cmdref" which shouldn't. But now that you pointed this out I realized I can just made cmdref
a hidden command and then we don't have Documentation/cmdref/cilium-agenc_cmdref.md
and it doesn't matter what flags are there (unless we start adding mandatory flags at some point etc.). Will push the fix in a sec...
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.
I get it now. I realized as I was walking for coffee that a Cell is different from a subcommand. Nevertheless, any way you can make flags simpler would be good; I've personally had poor experiences with other "do-it-all" cmd frameworks making it unergonomic to set flags the way you want.
@@ -53,6 +54,33 @@ func Invoke(fn any) *Cell { | |||
return NewCell("", fx.Invoke(fn)) | |||
} | |||
|
|||
// OnStart registers a function to run on start up. | |||
func OnStart(fn any) *Cell { |
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.
Hey look, it's generics (not really) :-p.
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.
Okay but really, this is a bit too much black magic for me. So, this is basically a decorator -- by doing evil reflection magic to ensure args are passed through. Cute... but...
For the sake of simplicity, what if this just took a func()
and left it at that? Yes, it means a closure, but that is certainly more idiomatic.
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.
And if there's a reason I'm missing that a closure wouldn't work, can you at least document the magic?
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.
Yeah I got annoyed by having to do fx.Invoke(func(lc fx.Lifecycle) { lc.Append(fx.Hook{OnStart: func(context.Context) error { thisOneThing() } } ) })
:)
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.
Ah the reason why this can’t just take “func()” is that the input arguments actually matter. E.g. if you give this a “func(a A)” then fx will go and construct “A” and pass it in. The trade-off here is between having to do this start hook the long way via fx.Invoke etc. or this magic. I’m fine either way, but though that for the command-line utility use-cases where we just want to construct and start few things and then run a function that uses them it makes sense to provide a simple helper.
I’ll document this better though!
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.
Documented and changed it to take a function that returns an error so it's more general. Does this seem reasonable now? What we could also do, if you think it'd be preferred, is to write this as func OnStart[T any](func(T) error) *Cell
. It'd constrain the function to a single input argument, but one could then use fx.In: type Inputs struct { fx.In; Foo Foo; ...}
.
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.
Documenting the magic is fine for now. If it winds up needing changes later, we can do that.
It is cute :-)
e1d96a8
to
20752a7
Compare
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.
Reviewed test changes, LGTM, thanks!
80add65
to
ae81615
Compare
/test |
One minor question, then lgtm. |
/test-1.16-4.9 Job 'Cilium-PR-K8s-1.16-kernel-4.9' failed: Click to show.Test Name
Failure Output
If it is a flake and a GitHub issue doesn't already exist to track it, comment Doh, moving the option.Config.Populate() before SetMapElementSizes screwed up the dynamic map size calculation. Fixed. |
Signed-off-by: Jussi Maki <jussi@isovalent.com>
This test was used to benchmark json versus protobuf for the k8s client and has served its purpose. To simplify refactoring of the k8s client, remove this test ahead of time. Signed-off-by: Jussi Maki <jussi@isovalent.com>
This adds a cell for the kubernetes client that provides a Clientset for the application for accessing Kubernetes resources. The integration of the new clientset to the codebase is done gradually. In this commit the APIs provided by pkg/k8s are kept mostly as is, with Configure and Init still functioning. Daemon is modified to take in the clientset as parameter which is then used to populate the existing global client variables via k8s.SetClients. Minimal changes were made to cilium command and the operator. New command-line flag, --skip-daemon, was added to allow experimenting with new cells without having the daemon start up. Signed-off-by: Jussi Maki <jussi@isovalent.com>
This switches the operator to use the k8-client provided via the k8s-client cell instead of going via the global variables in pkg/k8s. Code is refactored to pass around the clientset. Signed-off-by: Jussi Maki <jussi@isovalent.com>
This refactors clustermesh-apiserver to use the k8s-client provided clientset. The health API server was refactored as a hive cell as it was a low-hanging fruit. Signed-off-by: Jussi Maki <jussi@isovalent.com>
This switches the two uses of k8s client in the cilium (agent) cli utility to use the k8s-client. Signed-off-by: Jussi Maki <jussi@isovalent.com>
Drop the now unused k8s.Init and k8s.Configure methods, and configuration types and methods related to them. Drop unused call to k8s.Configure in informer benchmark. The benchmark setup called k8s.Configure if INTEGRATION environment variable was set, but none of the code in the benchmark made any use of it. Signed-off-by: Jussi Maki <jussi@isovalent.com>
ae81615
to
e34e1cb
Compare
/test |
ci-l4lb failure fixed by just merged #21302. Earlier run of ci-l4lb passed. Marking ready-to-merge. |
First commit drops the cnp_test.go test that was used to benchmark protobuf vs json serialization for K8s objects. It is no longer needed and would have complicated implementation of the k8s client cell.
Second commit implements K8s client as a reusable cell that provides the
Clientset
interface to the application, which is a composition of the different client interfaces used by Cilium (Kubernetes, APIExt, Cilium and Slim version of Kubernetes).The configuration needed by the client is moved from DaemonConfig into
client.Config
inpkg/k8s/client/config.go
and it implementsCellFlags
to register the command-line flags. This allows easy embedding of the client cell into other applications besides cilium-agent.Rest of the commits convert uses of the k8s client over to this new abstraction out from k8s.Configure/k8s.Init. There are still some holdouts that use the global accessors (k8s.Client() etc.) that will be addressed in a follow-up.
To make this more concrete, here is an abbreviated example application using the client cell:
The application now has the k8s configuration options included, so to run it with kubeconfig file:
$ ./example --k8s-kubeconfig-path=$HOME/.kube/config