From 1a931c92b6ab34dbe9d82a1f145d14fd7998ae92 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=8E=8B=E6=89=A7=E5=A7=AC?=
<35649989+esterwang@users.noreply.github.com>
Date: Mon, 1 Apr 2019 21:42:02 +0800
Subject: [PATCH 1/2] Create 2019-04-01-caasone-daily-news.md
---
posts/2019-04-01-caasone-daily-news.md | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 posts/2019-04-01-caasone-daily-news.md
diff --git a/posts/2019-04-01-caasone-daily-news.md b/posts/2019-04-01-caasone-daily-news.md
new file mode 100644
index 0000000..7e689bd
--- /dev/null
+++ b/posts/2019-04-01-caasone-daily-news.md
@@ -0,0 +1,25 @@
+---
+title: "技术日报(2019-04-01)"
+date: 2019-04-01T00:00:00+08:00
+categories: [ "daily"]
+draft: false
+---
+### [容器时代]技术日报(20180922)
+
+1. PostgreSQL on Kubernetes: How to run a stateful legacy app on a stateless microservice http://www.bmc.com/blogs/kubernetes-postgresql/
+2. Securing a dockerized plumber API with SSL and Basic Authentication https://www.tuicool.com/articles/IrqQRbi
+3. MicroK8s in the Wild https://blog.ubuntu.com/2019/03/28/microk8s-in-the-wild
+4. Docker-06-持久化存储和数据共享 https://www.cnblogs.com/liuguangjiji/p/10630801.html
+5. GoLang with Rails https://shwetakale.wordpress.com/2019/03/28/golang-with-rails/
+
+编辑:@esterwang
+
+地址:
+
+[容器时代志愿编辑招募]
+
+### 其他
+
+1、欢迎将自己的博文转载到公众号进一步推广
+
+2、想翻译文章的同学现在就可开始
From c9c17be4aa832d73540470030e1e829f503d981c Mon Sep 17 00:00:00 2001
From: "liyao.mly"
Date: Tue, 2 Jul 2019 12:55:36 +0800
Subject: [PATCH 2/2] fix conflicts
---
...ting with the Kubernetes Client Library.md | 234 ++++++++++--------
1 file changed, 125 insertions(+), 109 deletions(-)
diff --git a/translation/Unit Testing with the Kubernetes Client Library.md b/translation/Unit Testing with the Kubernetes Client Library.md
index a6f6a08..e7200d4 100644
--- a/translation/Unit Testing with the Kubernetes Client Library.md
+++ b/translation/Unit Testing with the Kubernetes Client Library.md
@@ -1,157 +1,173 @@
-# 如何进行单元测试代码来调用Kubernetes API
+使用Kubernetes客户端库进行单元测试
+=============
-使用kubernetes客户机库可以帮助您模拟出一个集群来测试您的代码。
+如何对被 Kubernetes API 调用的代码进行单元测试?
-在构建[kubernetes/minikube](https://github.com/kubernetes/minikube)时,作为[kubernetes/client-go ](https://github.com/kubernetes/client-go)库的第一个消费者之一,services、pods和deployments构建了详细的模拟,以单元测为例,现在,有一种更简单的方法可以用更少的代码行来做同样的事情。
+使用 Kubernetes 客户端库可以通过模拟集群来测试代码。
-我将演示如何测试一个简单的函数,该函数列出了集群中运行的所有容器镜像。你需要一个Kubernetes集群,我建议用GKE或桌面版的Docker。
+作为在构建 kubernetes / minikube 时,第一批使用kubernetes / client-go 库的用户之一,我曾经详尽的设计了服务、调度单元和部署来对我的代码进行单元测试。 现在,我发现有一种更简单的方法可以用更少的代码行来做同样的事情。
-## Setup
-克隆示例存储库[https://github.com/r2d4/k8s-unit-test-example ](https://github.com/r2d4/k8s-unit-test-example ),如果要运行命令并以交互方式继续操作。
+我将演示如何测试一个**列出了集群中运行的所有容器映像**的简单的函数。我建议你用 GKE 或 Docker 作为桌面,并且你还需要一个 Kubernetes 集群。
-###main.go
+### 安装程序
+
+如果你想要运行命令并以交互方式继续操作,请克隆示例仓库 https://github.com/r2d4/k8s-unit-test-example 。
+
+### main.go
```go
-import (
- "github.com/pkg/errors"
- meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "k8s.io/client-go/kubernetes/typed/core/v1"
-)
-//ListImages返回在提供的命名空间中运行的容器映像的列表
-func ListImages(client v1.CoreV1Interface, namespace string) ([]string, error) {
- pl, err := client.Pods(namespace).List(meta_v1.ListOptions{})
- if err != nil {
- return nil, errors.Wrap(err, "getting pods")
- }
- var images []string
- for _, p := range pl.Items {
- for _, c := range p.Spec.Containers {
- images = append(images, c.Image)
- }
+package main
+
+import (
+ "github.com/pkg/errors"
+ meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/client-go/kubernetes/typed/core/v1"
+)
+
+// ListImages returns a list of container images running in the provided namespace
+func ListImages(client v1.CoreV1Interface, namespace string) ([]string, error) {
+ pl, err := client.Pods(namespace).List(meta_v1.ListOptions{})
+ if err != nil {
+ return nil, errors.Wrap(err, "getting pods")
+ }
+
+ var images []string
+ for _, p := range pl.Items {
+ for _, c := range p.Spec.Containers {
+ images = append(images, c.Image)
}
- return images, nil
- }
+ }
+
+ return images, nil
+}
```
-
-
-## Writing the Tests
-从测试用例的定义开始,以及一些运行测试的框架代码。
+
+
+
+### 编写测试
+
+我们可以从测试用例的定义开始,运行一些测试的框架代码。
```go
func TestListImages(t *testing.T) {
- var tests = []struct {
- description string
- namespace string
- expected []string
- objs []runtime.Object
+ var tests = []struct {
+ description string
+ namespace string
+ expected []string
+ objs []runtime.Object
+ }{
+ {"no pods", "", nil, nil},
}
- {
- {"no pods", "", nil, nil},
- }
- // 在这写需要测试的代码
-}
-```
-
-## What's Happening
+ // Actual testing code goes here...
+}
-这种编写测试的风格称为“表驱动测试”,在Go中,这是首选的样式。实际的测试代码迭代表条目并执行必要的测试。测试代码只写一次,用于每种情况。需要注意一些事情:
+```
-* 用于保存测试用例定义的匿名结构。它们允许我们简洁地定义测试用例。
+#### 发生了什么
+这种编写测试的风格称为**“表驱动测试”**,是Go语言中首选的样式,实际测试代码会迭代表条目并执行必要的测试。测试代码只需要写一次,却可以适用于每种情况。我门可以注意到一些有趣的事情:
-* 运行时对象切片objs将保存所有希望我们的模拟API服务器保存的运行时对象。将用一些pods填充,但是您可以在这里使用任何kubernetes对象。
-
-* 琐碎的测试用例,服务器上没有pods不应返回任何image。
+- 测试用例的定义是用匿名结构保存的,因此我们可以简洁的定义测试用例。
+- 对象切片运行时,`objs`将保存我们的模拟 API 服务器保存的所有正在运行的对象,此处我们选择用一些调度单元来填充它,但其实可以在这里使用任何 Kubernetes 对象。
+- 如果测试用例非常琐碎,服务器上将没有调度单元,并且不返回任何图像。
+### 测试回路
-## Test Loop
-填写将为每个测试用例运行的实际测试代码。
+让我们来为每个测试用例都写一段实际测试代码。
```go
-for _, test := range tests {
- t.Run(test.description, func(t *testing.T) {
- client := fake.NewSimpleClientset(test.objs...)
- actual, err := ListImages(client.CoreV1(), test.namespace)
- if err != nil {
- t.Errorf("Unexpected error: %s", err)
- return
- }
- if diff := cmp.Diff(actual, test.expected); diff != "" {
- t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
- return
- }
- })
-}
+for _, test := range tests {
+ t.Run(test.description, func(t *testing.T) {
+ client := fake.NewSimpleClientset(test.objs...)
+ actual, err := ListImages(client.CoreV1(), test.namespace)
+ if err != nil {
+ t.Errorf("Unexpected error: %s", err)
+ return
+ }
+ if diff := cmp.Diff(actual, test.expected); diff != "" {
+ t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
+ return
+ }
+ })
+ }
```
-需要注意的一些有趣的事情,
-t.run运行执行子测试。为什么使用子测试?
-* 可以使用-run flg to go test
+在这里我们也可以注意到一些有趣的事情:
-* 可以做设置和拆卸子测试是并行运行测试用例的入口(这里不做)
+- 文件`t.Run` 的功能是执行子测试,那么为什么要使用子测试?
-* 实际结果和预期结果与cmp.diff不同。diff返回两个值之间差异的人类可读报告。如果相同的输入值和选项的equal返回true,则返回空字符串。
+- - 你可以使用`-run` 命令运行特定的测试用例进行测试。
-fake.newsImpleClientSet返回将使用提供的对象响应的客户端集。 它由一个非常简单的对象跟踪器提供支持,该跟踪器按原样处理增加、更新和删除操作,不应用任何验证和/或默认值。
+ - 你可以设置和清理测试代码
+ - 子测试是同时运行测试用例的入口(这篇文章将不涉及)
+- 实际结果和预期结果都与 `cmp.diff` 不同。Diff 返回的两个值之间差异是可读的,当且仅当输入值和选项相等且为真时,Diff返回空字符串。
-## Test Cases
+`fake.NewSimpleClientset` 返回一个使用提供的对象进行响应的客户端集。它由一个非常简单的对象跟踪器支持,该跟踪器按原样处理创建、更新和删除操作,而不应用任何验证和默认值。
- 创建一个pod函数,它将帮助提供一些pod供我们测试。既然我们关心namespace和image,它基于这些参数创建新的pod.
-
-```
-func pod(namespace, image string) *v1.Pod {
- return &v1.Pod{ObjectMeta: meta_v1.ObjectMeta{Namespace: namespace}, Spec: v1.PodSpec{Containers: []v1.Container{{Image: image}}}}
+### 测试用例
+
+我们来创建一个调度单元助手函数,它将帮助我们提供一些测试的调度单元。由于我们关心的是命名空间和镜像,所以我们可以创建一个可以基于这些参数创建新的调度单元的助手。
+
+```go
+func pod(namespace, image string) *v1.Pod {
+ return &v1.Pod{ObjectMeta: meta_v1.ObjectMeta{Namespace: namespace}, Spec: v1.PodSpec{Containers: []v1.Container{{Image: image}}}}
}
```
- 写三个单元测试。如果使用特殊的namespace值列出所有namespace中的pods,第一个方法将确保获取所有image。
-
-```
+我们来写三个单元测试。第一个方法能确保我门获取所有镜像,这时我们需要使用特殊的命名空间值 `“”` 来列出命名空间中所有的调度单元。
+
+```go
{"all namespaces", "", []string{"a", "b"}, []runtime.Object{pod("correct-namespace", "a"), pod("wrong-namespace", "b")}}
```
- 第二种情况将确保按namespace正确筛选,忽略错误namespace中的pod。
-```
+第二种方法能确保我们按名称空间正确筛选,忽略调度单元中的 `wrong-namespace` 。
+
+```go
{"filter namespace", "correct-namespace", []string{"a"}, []runtime.Object{pod("correct-namespace", "a"), pod("wrong-namespace", "b")}}
```
- 第三种情况将确保如果所需的namespace中没有pods,则不会返回任何内容。
-```
+第三种方法能确保如果所需的命名空间中没有调度单元,则不会返回任何内容。
+
+```go
{"wrong namespace", "correct-namespace", nil, []runtime.Object{pod("wrong-namespace", "b")}}
```
-#### Putting it all together
+
+把上面这些代码放在一起。
+
```go
-func TestListImages(t *testing.T) {
- var tests = []struct {
- description string
- namespace string
- expected []string
- objs []runtime.Object
+func TestListImages(t *testing.T) {
+ var tests = []struct {
+ description string
+ namespace string
+ expected []string
+ objs []runtime.Object
+ }{
+ {"no pods", "", nil, nil},
+ {"all namespaces", "", []string{"a", "b"}, []runtime.Object{pod("correct-namespace", "a"), pod("wrong-namespace", "b")}},
+ {"filter namespace", "correct-namespace", []string{"a"}, []runtime.Object{pod("correct-namespace", "a"), pod("wrong-namespace", "b")}},
+ {"wrong namespace", "correct-namespace", nil, []runtime.Object{pod("wrong-namespace", "b")}},
}
- {
- {"no pods", "", nil, nil},
- {"all namespaces", "", []string{"a", "b"},[]runtime.Object{pod("correct-namespace", "a"), pod("wrong-namespace", "b")}},
- {"filter namespace", "correct-namespace", []string{"a"},[]runtime.Object{pod("correct-namespace", "a"), pod("wrong-namespace", "b")}},
- {"wrong namespace", "correct-namespace", nil,[]runtime.Object{pod("wrong-namespace", "b")}},
- }
- for _, test := range tests {
- t.Run(test.description, func(t *testing.T) {
- client := fake.NewSimpleClientset(test.objs...)
- actual, err := ListImages(client.CoreV1(), test.namespace)
- if err != nil {
+
+ for _, test := range tests {
+ t.Run(test.description, func(t *testing.T) {
+ client := fake.NewSimpleClientset(test.objs...)
+ actual, err := ListImages(client.CoreV1(), test.namespace)
+ if err != nil {
t.Errorf("Unexpected error: %s", err)
- return
- }
- if diff := cmp.Diff(actual, test.expected); diff != "" {
+ return
+ }
+ if diff := cmp.Diff(actual, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
- return
+ return
}
- })
- }
- }
+ })
+ }
+}
+
```
-Matt Rickard
-[https://matt-rickard.com/kubernetes-unit-testing/](https://matt-rickard.com/kubernetes-unit-testing/)
+### 原文链接
+[原文作者:@mattrickard]
+[原文链接:https://matt-rickard.com/kubernetes-unit-testing/](https://matt-rickard.com/kubernetes-unit-testing/)