您现在的位置是:网站首页> 编程资料编程资料
go语言代码生成器code generator使用示例介绍_Golang_
2023-05-26
422人已围观
简介 go语言代码生成器code generator使用示例介绍_Golang_
代码生成器介绍
client-go为每种k8s内置资源提供了对应的clientset和informer。那么我们要监听和操作自定义资源对象,应该如何做呢?
方式一:使用client-go提供的dynamicClient来操作自定义资源对象,当然由于dynamicClient是基于RESTClient实现的,所以我们可以使用RESTClient来达到同样的目的。
方式二: 使用conde-generator来帮我们生成我们需要的代码,这样我们就可以像使用client-go为k8s内置资源对象提供的方式监听和操作自定义资源了。
code-generator
code-generator 就是 Kubernetes 提供的一个用于代码生成的项目,它提供了以下工具为 Kubernetes 中的资源生成代码:
- deepcopy-gen: 生成深度拷贝方法,为每个 T 类型生成 func (t* T) DeepCopy() *T 方法,API 类型都需要实现深拷贝
- client-gen: 为资源生成标准的 clientset
- informer-gen: 生成 informer,提供事件机制来响应资源的事件
- lister-gen: 生成 Lister,为 get 和 list 请求提供只读缓存层(通过 indexer 获取)
Informer 和 Lister 是构建控制器的基础,使用这4个代码生成器可以创建全功能的、和 Kubernetes 上游控制器工作机制相同的 production-ready 的控制器。
code-generator 还包含一些其它的代码生成器,例如 Conversion-gen 负责产生内外部类型的转换函数、Defaulter-gen 负责处理字段默认值。
大部分的生成器支持--input-dirs参数来读取一系列输入包,处理其中的每个类型,然后生成代码:
1、部分代码生成到输入包所在目录,例如 deepcopy-gen 生成器,也可以使用参数--output-file-base "zz_generated.deepcopy" 来定义输出文件名
2、其它代码生成到 --output-package 指定的目录,例如 client-gen、informer-gen、lister-gen 等生成器
示例
接来下我们使用code-generator进行实战演示:
首先我们将项目拉到本地:
$ git clone https://github.com/kubernetes/code-generator.git $ git checkout 0.23.3
然后我们进入到cmd目录下,就会看到我们上面介绍的工具:

接着我们对client-gen,deepcopy-gen,infromer-gen,lister-gen进行安装,会安装到GOPATH的bin目录下:
# 进行安装 $ go install ./cmd/{client-gen,deepcopy-gen,informer-gen,lister-gen} # 获取GOPATH路径 $ go env | grep GOPATH GOPATH="/Users/Christian/go" # 查看 ls /Users/Christian/go/bin client-gen deepcopy-gen goimports lister-gen controller-gen defaulter-gen informer-gen type-scaffold发现我们已经成功的安装了,这时候我们就可以直接使用这些工具了,比如我们可以使用--help命令来查看如何使用client-gen:

当然通常情况下我们不会去单独的使用某一个工具。
接下来我们来创建我们的项目,此处我们可以仿照sample controller项目进行编写:
$ mkdir operator-test && cd operator-test $ go mod init operator-test $ mkdir -p pkg/apis/example.com/v1 ➜ operator-test tree . ├── go.mod ├── go.sum └── pkg └── apis └── example.com └── v1 ├── doc.go ├── register.go └── types.go 4 directories, 5 files
接下来我们对v1下面的三个go文件进行填充(可以直接复制sample-controller,对其进行做简单修改):
doc.go主要是用来声明要使用deepconpy-gen以及groupName。
// pkg/crd.example.com/v1/doc.go // +k8s:deepcopy-gen=package // +groupName=example.com package v1
types.go主要是定义crd资源对应的go中的结构。
// pkg/crd.example.com/v1/types.go package v1 import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // Bar is a specification for a Bar resource type Bar struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` Spec BarSpec `json:"spec"` // Status BarStatus `json:"status"` } // BarSpec is the spec for a Bar resource type BarSpec struct { DeploymentName string `json:"deploymentName"` Image string `json:"image"` Replicas *int32 `json:"replicas"` } // BarStatus is the status for a Bar resource type BarStatus struct { AvailableReplicas int32 `json:"availableReplicas"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // BarList is a list of Bar resources type BarList struct { metav1.TypeMeta `json:",inline" :"metav1.TypeMeta"` metav1.ListMeta `json:"metadata" :"metav1.ListMeta"` Items []Bar `json:"items" :"items"` } register.go顾名思义,就是注册资源。
package v1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) // SchemeGroupVersion is group version used to register these objects var SchemeGroupVersion = schema.GroupVersion{Group: "example.com", Version: "v1"} // Kind takes an unqualified kind and returns back a Group qualified GroupKind func Kind(kind string) schema.GroupKind { return SchemeGroupVersion.WithKind(kind).GroupKind() } // Resource takes an unqualified resource and returns a Group qualified GroupResource func Resource(resource string) schema.GroupResource { return SchemeGroupVersion.WithResource(resource).GroupResource() } var ( // SchemeBuilder initializes a scheme builder SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) // AddToScheme is a global function that registers this API group & version to a scheme AddToScheme = SchemeBuilder.AddToScheme ) // Adds the list of known types to Scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &Bar{}, &BarList{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil } 这时候会发现&Bar{},&BarLis{}会报错,这是因为我们还没有为其实现deepcopy方法。
由于在自动生成代码的时候,需要指定header的信息,所以我们为了方便,可以将code-generator项目下的hack包直接拷贝到我们当前项目根目录下。
接下来我们使用code-generator来为我们自动生成代码:
# 运行 code-generator/generate-group.sh ./../../github/code-generator/generate-groups.sh all \ # 指定 group 和 version,生成deeplycopy以及client operator-test/pkg/client operator-test/pkg/apis crd.example.com:v1 \ # 指定头文件 --go-header-file=./hack/boilerplate.go.txt \ # 指定输出位置,默认为GOPATH --output-base ../ Generating deepcopy funcs Generating clientset for crd.example.com:v1 at operator-test/pkg/client/clientset Generating listers for crd.example.com:v1 at operator-test/pkg/client/listers Generating informers for crd.example.com:v1 at operator-test/pkg/client/informers
这时候我们再来查看项目结构:
➜ operator-test tree . ├── go.mod ├── go.sum ├── hack │ └── boilerplate.go.txt └── pkg ├── apis │ └── crd.example.com │ └── v1 │ ├── doc.go │ ├── register.go │ ├── types.go │ └── zz_generated.deepcopy.go └── client ├── clientset │ └── versioned │ ├── clientset.go │ ├── doc.go │ ├── fake │ │ ├── clientset_generated.go │ │ ├── doc.go │ │ └── register.go │ ├── scheme │ │ ├── doc.go │ │ └── register.go │ └── typed │ └── crd.example.com │ └── v1 │ ├── bar.go │ ├── crd.example.com_client.go │ ├── doc.go │ ├── fake │ │ ├── doc.go │ │ ├── fake_bar.go │ │ └── fake_crd.example.com_client.go │ └── generated_expansion.go ├── informers │ └── externalversions │ ├── crd.example.com │ │ ├── interface.go │ │ └── v1 │ │ ├── bar.go │ │ └── interface.go │ ├── factory.go │ ├── generic.go │ └── internalinterfaces │ └── factory_interfaces.go └── listers └── crd.example.com └── v1 ├── bar.go └── expansion_generated.go 22 directories, 29 files
这时候我们就可以像操作内置资源一样,操作我们的自定义资源了。
我们先准备crd以及对应的cr,这边也是可以直接从sample-controller项目进行拷贝,做简单的修改即可。
# manifests/example.com_bars.yaml --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: (devel) creationTimestamp: null name: bars.crd.example.com spec: group: crd.example.com names: kind: Bar listKind: BarList plural: bars singular: bar scope: Namespaced versions: - name: v1 schema: openAPIV3Schema: description: Bar is a specification for a Bar resource properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the generated submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object spec: description: BarSpec is the spec for a Bar resource properties: deploymentName: type: string image: type: string replicas: format: int32 type: integer required: - deploymentName - image - replicas type: object required: - spec type: object served: true storage: true # manifests/cr.yaml --- apiVersion: crd.example.com/v1 kind: Bar metadata: name: bar-demo namespace: default spec: image: "nginx:1.17.1" deploymentName: example-bar replicas: 2
接下来我们来编写main函数,这时候我们就可以使用client-go像操作我们内置资源一样,操作crd资源了。
package main import ( "context" "fmt" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/clientcmd" "log" clientSet "operator-test/pkg/client/clientset/versioned" "operator-test/pkg/client/informers/externalversions" ) func main() { config, err := clientcmd.B
相关内容
- golang读取各种配置文件(ini、json、yaml)_Golang_
- Go语言利用Unmarshal解析json字符串的实现_Golang_
- 300行代码实现go语言即时通讯聊天室_Golang_
- go语言中如何使用select的实现示例_Golang_
- Go语言上下文context底层原理_Golang_
- Golang map实践及实现原理解析_Golang_
- go中import包的大坑解决方案_Golang_
- windows下使用GoLand生成proto文件的方法步骤_Golang_
- GoLand一键上传项目到远程服务器的方法步骤_Golang_
- GoLand利用plantuml生成UML类图_Golang_
点击排行
本栏推荐
