如何在kubebuilder中监视外部自定义资源的更改,而无需导入外部类型

huangapple go评论91阅读模式
英文:

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.RESTClientYourNativeResource 调谐器中操作 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:   &quot;some.group.io&quot;,
	Version: &quot;v1&quot;,
	Kind:    &quot;External&quot;,
}

restClient, err := apiutil.RESTClientForGVK(gvkExternal, false, mgr.GetConfig(), serializer.NewCodecFactory(mgr.GetScheme()))
if err != nil {
	setupLog.Error(err, &quot;unable to create REST client&quot;)
}

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 = (&amp;controllers.YourNativeResourceReconciler{
	Client:        mgr.GetClient(),
	Scheme:        mgr.GetScheme(),
	RESTClient:    restClient,
}).SetupWithManager(mgr); err != nil {
	setupLog.Error(err, &quot;unable to create controller&quot;, &quot;controller&quot;, &quot;YourNativeResource&quot;)
	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, &quot;unable to create dynamic client&quot;)
}

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:    &quot;some.group.io&quot;,
	Version:  &quot;&quot;,
	Resource: &quot;externals&quot;,
})
externalWatcher, err := resourceInterface.Watch(ctx, metav1.ListOptions{})
if err != nil {
	return err
}

defer externalWatcher.Stop()

select {
case event := &lt;-externalWatcher.ResultChan():
	if event.Type == watch.Deleted {
		logger.Info(&quot;FINALIZER: An external resource is deleted.&quot;)
	}
}

huangapple
  • 本文由 发表于 2023年2月1日 00:57:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/75300521.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定