<p>Suppose I have bellow code snippet which setups a reconciler that watches external resource &quot;External&quot;:</p>
<pre><code>// SetupWithManager sets up the controller with the Manager.
func (r *SomethingReconciler) SetupWithManager(mgr ctrl.Manager) error {
    return ctrl.NewControllerManagedBy(mgr).
        For(&amp;api.Something{}).
        WithOptions(controller.Options{
            MaxConcurrentReconciles: stdruntime.NumCPU(),
            RecoverPanic:            true,
        }).
        Watches(
            &amp;source.Kind{Type: &amp;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)
}
</code></pre>
<p>My problem is that I can not import <code>somev1.External</code> 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?</p>

mammad
<p>Yes it's possible.</p>
<p>You can create a REST client for your resource in <code>main.go</code> as below:</p>
<pre class="lang-golang prettyprint-override"><code>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;)
}
</code></pre>
<p>Then add a field for this REST client (<code>rest.Interface</code>) to your reconciler (<code>yournativeresource_controller.go</code>) struct such as:</p>
<pre class="lang-golang prettyprint-override"><code>type YourNativeResourceReconciler struct {
    client.Client
    Scheme        *runtime.Scheme
    // add this
    RESTClient    rest.Interface
}
</code></pre>
<p>Last, initialize your reconciler with this REST client (<code>main.go</code>):</p>
<pre class="lang-golang prettyprint-override"><code>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)
}
</code></pre>
<p>Do not forget to add RBAC marker to your project (reconciler preferably) that will generate RBAC rules allowing you to manipulate <code>External</code> resource:</p>
<pre><code>//+kubebuilder:rbac:groups=some.group.io,resources=externals,verbs=get;list;watch;create;update;patch;delete
</code></pre>
<p>After these steps, you can use REST client for manipulating <code>External</code> resource over <code>YourNativeResource</code> reconciler using <code>r.RESTClient</code>.</p>
<p><strong>EDIT:</strong></p>
<p>If you want to watch resources, dynamic clients may help. Create a dynamic client in <code>main.go</code>:</p>
<pre class="lang-golang prettyprint-override"><code>dynamicClient, err := dynamic.NewForConfig(mgr.GetConfig())
if err != nil {
    setupLog.Error(err, &quot;unable to create dynamic client&quot;)
}
</code></pre>
<p>Apply above steps, add it to your reconciler etc. Then you will be able to watch <code>External</code> resource as below:</p>
<pre class="lang-golang prettyprint-override"><code>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;)
    }
}
</code></pre>
