Suppose I have bellow code snippet which setups a reconciler that watches external resource "External":
// SetupWithManager sets up the controller with the Manager.
func (r *SomethingReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&api.Something{}).
WithOptions(controller.Options{
MaxConcurrentReconciles: stdruntime.NumCPU(),
RecoverPanic: true,
}).
Watches(
&source.Kind{Type: &somev1.External{}},
handler.EnqueueRequestsFromMapFunc(r.findInternalObjectsForExternal),
builder.WithPredicates(predicate.Funcs{
UpdateFunc: func(ue event.UpdateEvent) bool { return true },
DeleteFunc: func(de event.DeleteEvent) bool { return true },
}),
).
Complete(r)
}
My problem is that I can not import somev1.External
type into my project because importing the go module containing this type would break my current project's dependencies.
Is there a way in kubebuilder to watch for external resources without having to explicitly importing their types? like GVK or something?
Yes it's possible.
You can create a REST client for your resource in main.go
as below:
gvkExternal := schema.GroupVersionKind{
Group: "some.group.io",
Version: "v1",
Kind: "External",
}
restClient, err := apiutil.RESTClientForGVK(gvkExternal, false, mgr.GetConfig(), serializer.NewCodecFactory(mgr.GetScheme()))
if err != nil {
setupLog.Error(err, "unable to create REST client")
}
Then add a field for this REST client (rest.Interface
) to your reconciler (yournativeresource_controller.go
) struct such as:
type YourNativeResourceReconciler struct {
client.Client
Scheme *runtime.Scheme
// add this
RESTClient rest.Interface
}
Last, initialize your reconciler with this REST client (main.go
):
if err = (&controllers.YourNativeResourceReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
RESTClient: restClient,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "YourNativeResource")
os.Exit(1)
}
Do not forget to add RBAC marker to your project (reconciler preferably) that will generate RBAC rules allowing you to manipulate External
resource:
//+kubebuilder:rbac:groups=some.group.io,resources=externals,verbs=get;list;watch;create;update;patch;delete
After these steps, you can use REST client for manipulating External
resource over YourNativeResource
reconciler using r.RESTClient
.
EDIT:
If you want to watch resources, dynamic clients may help. Create a dynamic client in main.go
:
dynamicClient, err := dynamic.NewForConfig(mgr.GetConfig())
if err != nil {
setupLog.Error(err, "unable to create dynamic client")
}
Apply above steps, add it to your reconciler etc. Then you will be able to watch External
resource as below:
resourceInterface := r.DynamicClient.Resource(schema.GroupVersionResource{
Group: "some.group.io",
Version: "",
Resource: "externals",
})
externalWatcher, err := resourceInterface.Watch(ctx, metav1.ListOptions{})
if err != nil {
return err
}
defer externalWatcher.Stop()
select {
case event := <-externalWatcher.ResultChan():
if event.Type == watch.Deleted {
logger.Info("FINALIZER: An external resource is deleted.")
}
}