Kubebuilder: How to generate client code in v2 version

Created on 5 Nov 2019  路  15Comments  路  Source: kubernetes-sigs/kubebuilder

Hi,
kubebuilder V1 version use this command to generate client code:
vendor/k8s.io/code-generator/generate-groups.sh all github.com/ghostbaby/test/pkg/client github.com/ghostbaby/test/pkg/apis database.v1beta1

But How to generate client code in v2 version?

/triage support

kinsupport

Most helpful comment

I'm not sure I understand the distinction you're making? You're basically just saying you want the go types to be known at compile time, which is equally true for what I'm suggesting people do? e.g.:

import (
        "log"
        corev1 "k8s.io/api/core/v1"
    ctrl "sigs.k8s.io/controller-runtime"
    "k8s.io/apimachinery/pkg/runtime"
    clientgoscheme "k8s.io/client-go/kubernetes/scheme"
        "sigs.k8s.io/controller-runtime/pkg/client"

        yourCRDScheme "some/import/path"
)
scheme := runtime.New()
_ = clientgoscheme.AddToScheme(scheme)
_ = yourCRDScheme.AddToScheme(scheme)

kubeconfig := ctrl.GetConfigOrDie()
kubeclient, err := client.New(kubeconfig, client.Options{ Scheme: scheme })
if err != nil {
        log.Fatal(err)
}

# replace with some yourCRDScheme type here
var pod corev1.Pod
err = c.Get(context.Background(), client.ObjectKey{
    Namespace: "namespace",
    Name:      "name",
}, &pod)

This is fairly similar to the generated code linked by @stigsb, except users no longer need a clientset per type. So if they are already using any sort of k8s client, they can just add the compile-time types to their scheme and save enormous amounts of boilerplate generated code.

Does that address your point, or am I misunderstanding?

All 15 comments

HI @Ghostbaby,

It shows exactly the same scenario of https://github.com/kubernetes-sigs/kubebuilder/issues/488. Do you mind sharing reasons for using the generated client over the one provided by controller-runtime ?

We don't support generating clients in kubebuilder

you might be able to restructure your project to use the upstream client-gen, but we have no intention of supporting it.

Hi @camilamacedo86 ,
In our environment, our operator needs to be called by other applications, either a management platform or another operator, so we need to provide a client.

Hi @Ghostbaby,

I still not thinking that a client needs to be provided to achieve this need.

When you say our operator needs to be called by other applications I understand that other applications will "install/uninstall" the operator according to some business requirements. Then, it can be done in many ways, and I'd recommend you use the Makefile targets to achieve it. E.g. other applications will exec the command make install to apply all resources in the cluster.

Note that the go-client in the operator project will be used for your operator call the k8s API in order to create/delete/updated/read resources on the cluster. So, I cannot see how it could allow external systems to do calls to the operator itself.

Also, regards the scenario one operator which calls other operators I'd suggest you check OLM and it's Dependency Resolution. If you would like to provide your solutions in a catalogue for k8s by integrating them with, then you would be able to use it. See https://operatorhub.io/ to having a better idea.

I think @Ghostbaby means they need a Go client, not OLM-style dependency resolution, because other things need to operate on the types.

Is there an issue/doc to explain why the generated client was removed?

@Ghostbaby I have a super hacky workaround for generating client from another project that uses kubebuilder v2 at https://gitlab.com/zedge-oss/zeppa/taxman/blob/master/hack/update-client.sh

This approach also locks the version of the code generator.

This is in the migration guide, FWIW: https://github.com/kubernetes-sigs/kubebuilder/blob/master/docs/migration_guide.md#copy-and-update-reconcile-function

Is there a reason people want to generate typed clients over using the dynamic client provided by controller-runtime? I find it is much better to work with: https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client#example-Client--Update

If the answer is "I need to external users to have Go clients", then export your API types, not the clientsets. Users can import your types and use the dynamic client (above) as usual.

Generated clients have static, compile-time types and are easier for the consumer-side to deal with.

I'm not sure I understand the distinction you're making? You're basically just saying you want the go types to be known at compile time, which is equally true for what I'm suggesting people do? e.g.:

import (
        "log"
        corev1 "k8s.io/api/core/v1"
    ctrl "sigs.k8s.io/controller-runtime"
    "k8s.io/apimachinery/pkg/runtime"
    clientgoscheme "k8s.io/client-go/kubernetes/scheme"
        "sigs.k8s.io/controller-runtime/pkg/client"

        yourCRDScheme "some/import/path"
)
scheme := runtime.New()
_ = clientgoscheme.AddToScheme(scheme)
_ = yourCRDScheme.AddToScheme(scheme)

kubeconfig := ctrl.GetConfigOrDie()
kubeclient, err := client.New(kubeconfig, client.Options{ Scheme: scheme })
if err != nil {
        log.Fatal(err)
}

# replace with some yourCRDScheme type here
var pod corev1.Pod
err = c.Get(context.Background(), client.ObjectKey{
    Namespace: "namespace",
    Name:      "name",
}, &pod)

This is fairly similar to the generated code linked by @stigsb, except users no longer need a clientset per type. So if they are already using any sort of k8s client, they can just add the compile-time types to their scheme and save enormous amounts of boilerplate generated code.

Does that address your point, or am I misunderstanding?

One downside for informers is the dynamic client will store things as Unstructured, so when we do List() calls we need to do conversions, which has a large cost. With generated clients the cache stores the object already marshaled which is much more efficient as it happens only once. The alternative,as far as I can tell, is implementing a cache outside of the informer which is error prone

I want to write one comandLine tool and do some read/write operation custom resource. I think controller-runtime client is not sufficent. As far as i know(maybe wrong), controller-runtime client will start list-watch background and cache all objects of resource what i do get/list, also APIReader only support read operation.

@DirectXMan12 @camilamacedo86 How can I implement commandLine tool, use which client? Thanks.

I want to write one comandLine tool and do some read/write operation on custom resource. I think controller-runtime client is not sufficent. As far as i know(maybe wrong), controller-runtime client will start list-watch background and cache all objects of resource what i do get/list, also APIReader only support read operation.

@DirectXMan12 @camilamacedo86 Any suggestion? Thanks.

FWIW I鈥檝e tried to capture all the details of migrating from using a ClientSet to controller-runtime client in this article

Was this page helpful?
0 / 5 - 0 ratings