英文:
How to watch for external custom resource changes in kubebuilder without importing the external type
问题
假设我有以下代码片段,设置了一个监视外部资源"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)
}
我的问题是,我无法将somev1.External
类型导入到我的项目中,因为导入包含此类型的go模块会破坏我当前项目的依赖关系。是否有一种在kubebuilder中监视外部资源的方法,而无需显式导入其类型?类似于 GVK 或其他方式?
英文:
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. <br>
Is there a way in kubebuilder to watch for external resources without having to explicitly importing their types? like GVK or something?
答案1
得分: 2
是的,这是可能的。
你可以在 main.go
中为你的资源创建一个 REST 客户端,代码如下所示:
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")
}
然后在你的调谐器 (yournativeresource_controller.go
) 结构体中添加一个字段来存储这个 REST 客户端 (rest.Interface
),代码如下所示:
type YourNativeResourceReconciler struct {
client.Client
Scheme *runtime.Scheme
// 添加这个字段
RESTClient rest.Interface
}
最后,在 main.go
中使用这个 REST 客户端来初始化你的调谐器,代码如下所示:
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)
}
不要忘记为你的项目(最好是调谐器)添加 RBAC 标记,以生成允许你操作 External
资源的 RBAC 规则,代码如下所示:
//+kubebuilder:rbac:groups=some.group.io,resources=externals,verbs=get;list;watch;create;update;patch;delete
完成这些步骤后,你可以使用 REST 客户端通过 r.RESTClient
在 YourNativeResource
调谐器中操作 External
资源。
编辑:
如果你想要监视资源,可以使用动态客户端。在 main.go
中创建一个动态客户端,代码如下所示:
dynamicClient, err := dynamic.NewForConfig(mgr.GetConfig())
if err != nil {
setupLog.Error(err, "unable to create dynamic client")
}
应用上述步骤,将其添加到你的调谐器中等等。然后你就可以像下面这样监视 External
资源了:
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.")
}
}
英文:
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.")
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论