In this article, we will focus on how to use the K8s code-generator from scratch.
Let's assume we want to create CRD in group "foo.com", and there is a type called "HelloType" with a "message" field in the spec:
# Definition---apiVersion:apiextensions.k8s.io/v1beta1kind:CustomResourceDefinitionmetadata:name:hellotypes.foo.comspec:group:foo.comversion:v1scope:Namespacednames:kind:HelloTypeshortNames:htplural:hellotypessingular:hellotype# HelloType---apiVersion:foo.com/v1kind:HelloTypemetadata:name:superman-hellospec:message:hello world
There are two steps to generate the CRD resource code:
Write the type definition code with code generator tags
Run run the generator to create the client codes which include: clientset, informers, listers for your customer resource
Write type definition code
cd $GOPATH/src
mkdir -p github.com/superman/demo
cd $GOPATH/src/github.com/superman/demo
Create the skeleton files as below under $GOPATH/src/github.com/superman/demo
This file provide controls of the global tags that will apply to every type in the same version with default setting.
The tags compose of two parts, the function name and the value to pass in normally. For example in+k8s:deepcopy-gen=package, deepcopy-gen is the function to call for generating the deep copies codes for types. packagedenotes applying the function to the whole v1 package in this case.
types.go
types.go
packagev1import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"// +genclient// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object// HelloType is a top-level typetypeHelloTypestruct {metav1.TypeMeta`json:",inline"`// +optionalmetav1.ObjectMeta`json:"metadata,omitempty"`// +optional Status HelloTypeStatus`json:"status,omitempty"`// This is where you can define// your own custom spec Spec HelloSpec`json:"spec,omitempty"`}// custom spec typeHelloSpecstruct { Message string`json:"message,omitempty"`}// custom statustypeHelloTypeStatusstruct { Name string}// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object// no client needed for list as it's been created in abovetypeHelloTypeListstruct {metav1.TypeMeta`json:",inline"`// +optionalmetav1.ListMeta`son:"metadata,omitempty"` Items []HelloType`json:"items"`}
+genclient means generating API client for the type.
+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Objectmeans when generating deepcopy for the type, use runtime.Object interface.
+optional indicates the field is optional. The data can be empty for the field.
register.go
register.go
packagev1import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/apimachinery/pkg/runtime""k8s.io/apimachinery/pkg/runtime/schema")// Define your schema name and the versionvar SchemeGroupVersion =schema.GroupVersion{ Group: "foo.com", Version: "v1",}var ( SchemeBuilder runtime.SchemeBuilder localSchemeBuilder =&SchemeBuilder AddToScheme = localSchemeBuilder.AddToScheme)funcinit() {// We only register manually written functions here. The registration of the// generated functions takes place in the generated files. The separation// makes the code compile even when the generated files are missing. localSchemeBuilder.Register(addKnownTypes)}// Resource takes an unqualified resource and returns a Group qualified GroupResourcefuncResource(resource string) schema.GroupResource {return SchemeGroupVersion.WithResource(resource).GroupResource()}// Adds the list of known types to the given scheme.funcaddKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes( SchemeGroupVersion,&HelloType{},&HelloTypeList{}, ) scheme.AddKnownTypes( SchemeGroupVersion,&metav1.Status{}, ) metav1.AddToGroupVersion( scheme, SchemeGroupVersion, )returnnil}
The register.go file contains the functions registering the new types we just created to the schema so the API server can recognize them.
Run code-generator to create client codes
go get -u k8s.io/code-generator/...
go get k8s.io/apimachinery
cd $GOPATH/src/k8s.io/code-generator
./generate-groups.sh all "github.com/superman/demo/pkg/client" "github.com/superman/demo/pkg/apis" "foo:v1"
The usage of generate-groups.sh. More details could be found here.
Usage: $(basename "$0") <generators> <output-package> <apis-package> <groups-versions> ...
<generators> the generators comma separated to run (deepcopy,defaulter,client,lister,informer) or "all".
<output-package> the output package name (e.g. github.com/example/project/pkg/generated).
<apis-package> the external types dir (e.g. github.com/example/api or github.com/example/project/pkg/apis).
<groups-versions> the groups and their versions in the format "groupA:v1,v2 groupB:v1 groupC:v2", relative
to <api-package>.
... arbitrary flags passed to all generator binaries.
After above steps, you will see the following file structure: