<p>I'm writing a controller that watches kubernetes <a href="https://kubernetes.io/docs/concepts/services-networking/service/" rel="nofollow noreferrer">service</a> objects, and creates <a href="https://linkerd.io/2/features/traffic-split/" rel="nofollow noreferrer">trafficsplits</a> if they contain a certain label.</p>
<p>Since the native kubernetes go client does not support the trafficsplit object, I had to find a way and extend the client so it would recognize the custom resource.
I found this <a href="https://www.martin-helmich.de/en/blog/kubernetes-crd-client.html" rel="nofollow noreferrer">guide</a> which was helpful and allowed me to tackle the issue like so -</p>
<pre><code>import (
    &quot;splitClientV1alpha1 &quot;github.com/servicemeshinterface/smi-sdk-go/pkg/gen/client/split/clientset/versioned/typed/split/v1alpha1&quot;
    &quot;k8s.io/client-go/kubernetes&quot;
    ...
)

// getting ./kube/config from file
kubehome := filepath.Join(homedir.HomeDir(), &quot;.kube&quot;, &quot;config&quot;)
// Building the config from file
kubeConfig, err = clientcmd.BuildConfigFromFlags(&quot;&quot;, kubehome)
if err != nil {
    return fmt.Errorf(&quot;error loading kubernetes configuration: %w&quot;, err)
}

// Creating the native client object
kubeClient, err := kubernetes.NewForConfig(kubeConfig)
if err != nil {
    return fmt.Errorf(&quot;error creating kubernetes client: %w&quot;, err)
}

// Creating another clientset exclusively for the custom resource
splitClient, err := splitClientV1alpha1.NewForConfig(kubeConfig)
if err != nil {
    return fmt.Errorf(&quot;error creating split client: %s&quot;, err)
}
</code></pre>
<p>I feel like there must be a way to extend the kubeClient object with the trafficsplit schema, instead of creating a separate client like I did. Is there any way to achieve this?</p>

Yaron Idan
<p>This is definitely possible! You want to use go's struct extension features :)</p>
<p>Bsasically, we create a struct that extends both <code>kubernetes.Clientset</code> and <code>splitClientV1alpha1.SplitV1alpha1Client</code> and initialize it using code very similar to yours above. We can then use methods from either client on that struct.</p>
<pre class="lang-go prettyprint-override"><code>import (
    &quot;fmt&quot;
    splitClientV1alpha1 &quot;github.com/servicemeshinterface/smi-sdk-go/pkg/gen/client/split/clientset/versioned/typed/split/v1alpha1&quot;
    &quot;k8s.io/client-go/kubernetes&quot;
    &quot;k8s.io/client-go/tools/clientcmd&quot;
    &quot;k8s.io/client-go/util/homedir&quot;
    &quot;path/filepath&quot;
)

type MyKubeClient struct {
    kubernetes.Clientset
    splitClientV1alpha1.SplitV1alpha1Client
}

func getClient() (*MyKubeClient, error) {
    // getting ./kube/config from file
    kubehome := filepath.Join(homedir.HomeDir(), &quot;.kube&quot;, &quot;config&quot;)
    // Building the config from file
    kubeConfig, err := clientcmd.BuildConfigFromFlags(&quot;&quot;, kubehome)
    if err != nil {
        return nil, fmt.Errorf(&quot;error loading kubernetes configuration: %w&quot;, err)
    }

    // Creating the native client object
    kubeClient, err := kubernetes.NewForConfig(kubeConfig)
    if err != nil {
        return nil, fmt.Errorf(&quot;error creating kubernetes client: %w&quot;, err)
    }

    // Creating another clientset exclusively for the custom resource
    splitClient, err := splitClientV1alpha1.NewForConfig(kubeConfig)
    if err != nil {
        return nil, fmt.Errorf(&quot;error creating split client: %s&quot;, err)
    }

    return &amp;MyKubeClient{
        Clientset:           *kubeClient,
        SplitV1alpha1Client: *splitClient,
    }, nil
}

func doSomething() error {
    client, err := getClient()
    if err != nil {
        return err
    }

    client.CoreV1().Pods(&quot;&quot;).Create(...)
    client.TrafficSplits(...)
}
</code></pre>
<p>If you need to pass your custom client to a function that expects only the original <code>kubernetes.ClientSet</code>, you can do that with:</p>
<pre class="lang-go prettyprint-override"><code>
func doSomething() error {
    client, err := getClient()
    if err != nil {
        return err
    }

    useClientSet(&amp;client.Clientset)
}

func useOriginalKubeClientSet(clientSet *kubernetes.Clientset) {
    # ... do things
}
</code></pre>
