Automatic generate kubernetes custom resources api go language code

Why does this article exist because when we use Kubesphere. the go client code need to use the client objects of K8s but dosen’t provider the s2ibinary object client code. https://github.com/kubesphere/s2ioperator/tree/master/pkg/client/clientset/versioned/typed/devops/v1alpha1

  1. Prepare directory structure and resource defination files

k8s rds generate prepare dir structure

  • The doc.go include content:
1// +k8s:deepcopy-gen=package,register
2// +k8s:defaulter-gen=TypeMeta
3// +groupName=devops.kubesphere.io
4package v1alpha1
  • The register.go main defination custom resources GroupName and GroupVersion
 1package v1alpha1
 2
 3import (
 4  "k8s.io/apimachinery/pkg/runtime/schema"
 5  "sigs.k8s.io/controller-runtime/pkg/scheme"
 6)
 7
 8type CodeFramework string
 9
10const (
11  Ruby         CodeFramework = "ruby"
12  Go           CodeFramework = "go"
13  Java         CodeFramework = "Java"
14  JavaTomcat   CodeFramework = "JavaTomcat"
15  Nodejs       CodeFramework = "Nodejs"
16  Python       CodeFramework = "python"
17  GroupName    string        = "devops.kubesphere.io"
18  GroupVersion string        = "v1alpha1"
19)
20
21var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: GroupVersion}
22
23var (
24  SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion}
25  AddToScheme   = SchemeBuilder.AddToScheme
26)
27
28// Resource is required by pkg/client/listers/...
29func Resource(resource string) schema.GroupResource {
30  return SchemeGroupVersion.WithResource(resource).GroupResource()
31}
  • The types.go mainly include CRD’s Object using in library
 1package v1alpha1
 2
 3import (
 4  metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 5)
 6
 7// +genclient
 8// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 9// S2iBinary is the Schema for the s2ibinary API
10type S2iBinary struct {
11  metav1.TypeMeta   `json:",inline"`
12  metav1.ObjectMeta `json:"metadata,omitempty"`
13  Spec   S2iBinarySpec   `json:"spec,omitempty"`
14  Status S2iBinaryStatus `json:"status,omitempty"`
15}
16
17type S2iBinarySpec struct {
18  DownloadURL string `json:"downloadURL,omitempty"`
19  FileName string `json:"fileName, omitempty"`
20  Md5 string `json:"md5, omitempty"`
21  Size int `json:"size, omitempty"`
22  UploadTimeStamp string `json:"uploadTimeStamp, omitempty"`
23}
24
25type S2iBinaryStatus struct {
26  Phase string `json:"phase, omitempty"`
27}
28
29// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
30// S2iBinaryList contains a list of S2iBinary
31type S2iBinaryList struct {
32  metav1.TypeMeta `json:",inline"`
33  metav1.ListMeta `json:"metadata,omitempty"`
34  Items           []S2iBinary `json:"items"`
35}

Note: The annotations is important and no blank lines.

  1. Use Dockerfile as build client code environment

 1    FROM golang:1.11.2
 2    ENV GO111MODULE=off
 3
 4    RUN go get k8s.io/code-generator; exit 0
 5    RUN go get k8s.io/apimachinery; exit 0
 6    RUN go get github.com/spf13/pflag; exit 0
 7    RUN go get k8s.io/gengo; exit 0
 8    RUN go get k8s.io/klog; exit 0
 9    RUN go get golang.org/x/tools; exit 0
10    RUN go get golang.org/x/mod; exit 0
11    RUN go get golang.org/x/xerrors; exit 0
12    ARG repo="${GOPATH}/src/github.com/xiao.chen/s2ibinary"
13    RUN mkdir -p $repo
14    WORKDIR $GOPATH/src/k8s.io/code-generator
15    VOLUME $repo
  1. Use bash script generate clients library

 1#!/bin/bash -e
 2
 3CURRENT_DIR=$(pwd)
 4GEN_DIR=$(dirname $0)
 5REPO_DIR="$CURRENT_DIR/$GEN_DIR/"
 6
 7PROJECT_MODULE="devops/s2ibinary"
 8IMAGE_NAME="k8s-codegen:latest"
 9
10CUSTOM_RESOURCE_NAME="devops"
11CUSTOM_RESOURCE_VERSION="v1alpha1"
12
13echo "Building codegen Docker image..."
14docker build -f "${GEN_DIR}/Dockerfile" \
15             -t "${IMAGE_NAME}" \
16             "${REPO_DIR}"
17
18cmd="./generate-groups.sh all \
19    "$PROJECT_MODULE/pkg/client" \
20    "$PROJECT_MODULE/pkg/apis" \
21    $CUSTOM_RESOURCE_NAME:$CUSTOM_RESOURCE_VERSION"
22
23echo "Generating client codes..."
24docker run --rm \
25           -v "${REPO_DIR}:/go/src/${PROJECT_MODULE}" \
26           "${IMAGE_NAME}" $cmd

This bash script should take pkg/apis/devops/v1alpha1 generate to client code through doc.go types.go and register.go with types.go file include’s annotations

  • exectue ./gen-client.sh late, will generate client and deepcopy.go in pkg directory
  1. And it turns out there’s a simpler way to do it

 1package main
 2
 3import (
 4	logs "github.com/prometheus/common/log"
 5	"golang.org/x/net/context"
 6	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 7	"k8s.io/apimachinery/pkg/runtime/schema"
 8	"k8s.io/client-go/dynamic"
 9	"snc.com/cleanup/resources/config"
10)
11
12func main() {
13	k8sClient, err := config.NewK8s()
14	if err != nil {
15		logs.Fatal("Init kubernetes error.", err)
16	}
17	
18	dyClient, err := dynamic.NewForConfig(k8sClient.Config)
19	dyResource := dyClient.Resource(schema.GroupVersionResource{Version: "v1alpha1", Group: "devops.kubesphere.io", Resource: "s2ibinaries"})
20	result, _ := dyResource.List(context.TODO(), v1.ListOptions{})
21	for _, item := range result.Items {
22		logs.Info("Name:", item.GetName(), "\t Namespace: ", item.GetNamespace())
23	}
24	
25}

Use Dynamic resource interface so easy!