一篇带你kubebuilder 进阶: 测试

Operator 的篇带测试是一个比较头疼的问题,在 kubernetes 资源是进阶测在不断变化的,并且想要在测试的篇带时候跑一整套的 kubernetes 环境也不是一件容易的事情,今天我们大概看一下单元测试和集成测试怎么做。进阶测

单元测试

单元测试和 golang 的篇带单元测试没有什么太大的区别,一般可以通过单元测试搞定的进阶测首先使用单元测试,因为单元测试写起来最容易,篇带例如下面这一段对节点标签更新逻辑进行测试

func TestNodePoolSpec_ApplyNode(t *testing.T) {   type fields struct {    Taints  []corev1.Taint   Labels  map[string]string   Handler string  }  type args struct {    node v1.Node  }  tests := []struct {    name   string   fields fields   args   args   want   *corev1.Node  }{    {     name: "label",进阶测    fields: fields{      Labels: map[string]string{       "node-pool.lailin.xyz/test": "",     },    },    args: args{      node: v1.Node{       ObjectMeta: metav1.ObjectMeta{        Name: "worker",       Labels: map[string]string{         "kubernetes.io/arch": "amd64",        "a":                  "b",       },      },     },    },    want: &v1.Node{      ObjectMeta: metav1.ObjectMeta{       Name: "worker",      Labels: map[string]string{        "kubernetes.io/arch":        "amd64",       "node-pool.lailin.xyz/test": "",      },     },    },   },  }  for _, tt := range tests {    t.Run(tt.name, func(t *testing.T) {     s := &NodePoolSpec{      Taints:  tt.fields.Taints,     Labels:  tt.fields.Labels,     Handler: tt.fields.Handler,    }    assert.Equal(t, tt.want, s.ApplyNode(tt.args.node))   })  } } 

集成测试

controller-runtime 提供 envtest ,亿华云计算这个包可以帮助你为你在 etcd 和 Kubernetes API server 中设置并启动的篇带 controllers 实例来写集成测试,不需要 kubelet,进阶测controller-manager 或者其他组件。篇带

envtest

一个 envtest 的进阶测简单例子如下

import sigs.k8s.io/controller-runtime/pkg/envtest //指定 testEnv 配置 testEnv = &envtest.Environment{      CRDDirectoryPaths: []string{ filepath.Join("..", "config", "crd", "bases")}, } //启动 testEnv cfg, err = testEnv.Start() //编写测试逻辑 //停止 testEnv err = testEnv.Stop() 

envtest 在启动的时候需要设置一些环境变量来说明我们使用什么控制平面来进行测试

USE_EXISTING_CLUSTER表示使用一个已经存在的控制平面 KUBEBUILDER_ASSETS 本地控制平面二进制文件的文件夹路径,里面包含了 kubectl apiserver和 etcd KUBEBUILDER_CONTROLPLANE_START_TIMEOUT控制平面启动的篇带超时时间 KUBEBUILDER_CONTROLPLANE_STOP_TIMEOUT控制平面停止的超时时间

编写测试

kubebuilder 在生成代码的时候已经帮我们生成好了相关的脚手架,已经环境配置,进阶测我们只需要写具体的篇带测试逻辑就行了

下面我们就以创建一个 NodePool 为例子看看集成测试怎么写

controllers/suite_test.go 

var _ = Describe("node labels", func() {   pool := &nodesv1.NodePool{    ObjectMeta: metav1.ObjectMeta{     Name: "test",   },   Spec: nodesv1.NodePoolSpec{     Labels: map[string]string{      "node-pool.lailin.xyz/xxx": "",    },    Handler: "",   },  }  It("create pool", func() {    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)   defer cancel()   err := k8sClient.Create(ctx, pool)   Expect(err).NotTo(HaveOccurred())  }) }) 

使用 make test 执行测试

Using cached envtest tools from blog-code/k8s-operator/07-node-pool-operator/testbin setting up env vars ?       github.com/mohuishou/blog-code/k8s-operator/node-pool-operator  [no test files] ok      github.com/mohuishou/blog-code/k8s-operator/node-pool-operator/api/v1   9.403s  coverage: 24.5% of statements ok      github.com/mohuishou/blog-code/k8s-operator/node-pool-operator/controllers      10.390s coverage: 0.0% of statements 

总结

今天这篇文章主要还是希望起一个抛砖引玉的作用,亿华云没有过多的去深入具体改如何写单元测试和集成测试,只是给了两个例子,关于集成测试如果感兴趣可以看看 https://onsi.github.io/ginkgo 和 envtest 的相关文档。

对于 Operator 来说建议能写单元测试的还是写单元测试,能够本地写集成测试的就写集成测试这样我们在实际上线的时候就会减少 bug 的概率,因为相对于业务代码来说 Operator 的测试实在是比较麻烦,对于测试同学的要求也比较高,一不小心就有可能遗漏一些问题。源码库

人工智能
上一篇:2022 ODCC峰会即将开幕,宝存科技的企业级SSD创新之道
下一篇:8.25,戴尔科技峰会定了!