<p>I have added a new CRD <code>ApiGateway</code> to Kubernetes and I want to watch for new/changed resources of it.</p>

<p>This works with a simple Rest Client as shown in the example below. </p>

<p>But I´d like to watch for these resources with <code>k8s.io/client-go/kubernetes</code>. </p>

<p>While it is simple to get the standard resources like in the client-go example below , I don´t get anything working for CRDs.
Is it possible to get that done with client-go?</p>

<p><strong>client-go example for standard resources</strong></p>

<pre><code>import (
    ....
    "k8s.io/api/core/v1"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
)

func handleNewServices(clientset *kubernetes.Clientset) {
    for {
        serviceStreamWatcher, err := clientset.CoreV1().Services("").Watch(metav1.ListOptions{})
        if err != nil {
            panic(err.Error())
        }
        //fmt.Printf("%T\n", serviceStreamWatcher)
        for {
            select {
            case event := &lt;-serviceStreamWatcher.ResultChan():
            service := event.Object.(*v1.Service)

            for key, value := range service.Labels {
                fmt.Printf("Key, VAlue: %s %s\n", key, value)
            }
...
</code></pre>

<p><strong>RestClient (working fine)</strong></p>

<pre><code>package main

import (
    "net/http"
    ....

)

func main() {
    for {
        // Url "cw.com" must match the config spec.group in api-gateway-crd.yaml
        // URL "apigateways" must match the config spec.names.plural in api-gateway-crd.yaml
        resp, err := http.Get("http://localhost:8001/apis/cw.com/v1/apigateways?watch=true")
        if err != nil {
            panic(err)
        }
        defer resp.Body.Close()
        decoder := json.NewDecoder(resp.Body)
        for {
            var event v1.ApiGatewayWatchEvent
            if err := decoder.Decode(&amp;event); err == io.EOF {
                break
            } else if err != nil {
                log.Fatal(err)
            }
            log.Printf("Received watch event: %s: %s: \n", event.Type, event.Object.Metadata.Name)

        }
    }

}
</code></pre>

<p><strong>CRD</strong></p>

<pre><code>apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: apigateways.cw.com
spec:
  scope: Namespaced
  group: cw.com
  version: v1
  names:
    kind: ApiGateway
    singular: apigateway
    plural: apigateways
</code></pre>

<p>If you think about it, <code>client-go</code> knows about <code>deployments</code>, <code>services</code>, <code>pods</code> etc resources. But it doesn't recognize your CRD <code>ApiGateway</code>.</p>
<p>So, <code>client-go</code> can't be used as a client for your custom made resources (wait-for-it), unless you made them recognizable to <code>client-go</code>!</p>
<p><strong>How?!</strong></p>
<p>You have to generate your own client for the CRDs. Kubernetes already have the tools to auto-generate the clients, all you need to specify the <code>structs</code> of <code>API</code>. This is known as <code>code-generation</code>.</p>
<p>Here is a <a href="https://blog.openshift.com/kubernetes-deep-dive-code-generation-customresources/" rel="noreferrer">blog post about code generation</a> by <a href="https://github.com/sttts" rel="noreferrer">STEFAN SCHIMANSKI</a> (who is one of the top contributors to kubernetes).</p>
<p><strong>Example Controller</strong></p>
<p>Here is a <a href="https://github.com/kubernetes/sample-controller" rel="noreferrer">sample-controller</a> example given by kubernetes itself. The <code>pkg</code> folder contains all the <code>APIS</code> and <code>Client</code>. The <code>main.go</code> and <code>controller.go</code> contains the sample code to watch for the CRD and do some task accordingly.</p>
<p><strong>!!Update!!</strong></p>
<p>It's easier now to generate client configs and controllers with kubebuilder (<a href="https://github.com/kubernetes-sigs/kubebuilder" rel="noreferrer">github repo</a>), which is maintained by kubernetes-sigs.</p>
