JSONPatch的详细说明请参考文档:http://jsonpatch.com/。JSONPatch 主要有三种操作方式:add,replace,remove。以下会以代码示例说明这三种操作在Client-go对应的代码示例来说明怎样操作K8s 的资源。
使用JSONPatch,如果Patch中带有斜杠“/”和 (~)这两个字符,不能直接传入这两个字符,需要你输入的时候就人工转换下,/转换成~1,~转换成~0。以新增labels为例,如我要新增一个”test1/test2”:”test3”的labels,可以把要传入的数据修改为”test1~1test2”:”test3”即可。
add
使用JSONPatch的方式新增一个标签,其提交的数据格式必须是[{ "op": "add/remove/replace", "path": "xxx", "value": "xxx" }] 这样的。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
   | package main
  import ( 	"context" 	"fmt" 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 	"k8s.io/apimachinery/pkg/types" 	"k8s.io/apimachinery/pkg/util/json" 	"kube-base3/lib/kubeConfig" 	"log" )
  type JsonPatch struct { 	Op    string      `json:"op"` 	Path  string      `json:"path"` 	Value interface{} `json:"value,omitempty"` }
  type JsonPatchList []*JsonPatch
  func AddJsonPatch(j ...*JsonPatch) JsonPatchList { 	list := make(JsonPatchList, len(j))
  	for i, v := range j { 		list[i] = v 	} 	return list }
  func main() { 	ctx := context.Background() 	client := kubeConfig.InitClient()
  	mydep, err := client.AppsV1().Deployments("default").Get(ctx, "myapp-deploy", metav1.GetOptions{}) 	if err != nil { 		log.Fatal(err) 	} 	 	list := AddJsonPatch(&JsonPatch{ 		Op:   "add", 		Path: "/spec/template/spec/containers/0", 		Value: map[string]interface{}{ 			"name":  "redis", 			"image": "redis:5-alpine", 		}, 	}) 	b, err := json.Marshal(list) 	fmt.Println(string(b)) 	if err != nil { 		log.Fatal(err) 	} 	_, err = client.AppsV1().Deployments(mydep.Namespace).Patch(ctx, mydep.Name, types.JSONPatchType, b, metav1.PatchOptions{}) 	if err != nil { 		log.Fatal(err) 	} 	fmt.Println("patch success") }
   | 
 
使用add有个需要注意的地方就是,当你的Path是使用的/metadata/labels而不是/metadata/labels/labelkey的时候,那你这个add操作实际是对整个labels进行替换,而不是新增,一定要注意避免踩坑。 如果要操作某个key  这个key要写编号  一般是编号从0开始     比如path:”/spec/template/spec/containers/0”     PS:如果不喜欢使用上面struct的方式组成数据,可以使用如下的方式 labelsPatch := fmt.Sprintf([{“op”:”add”,”path”:”/metadata/labels/%s”,”value”:”%s” }], labelkey, labelvalue) 直接代替上面示例中的patchData
这里还有个要注意的地方就是:
当这个path里面的路径上没有值的时候  这个时候增加是会报错的  比如说 path: “/metadata/annotations/version”  value:”v1.0”    这个时候 如果这个annotation没有值 是空的话  这个会报错的  所以添加的路径上一定要存在才能添加值   没有的话 就用这种形式path: “/metadata/annotations”  value: map[string]interface{}{ “version”:””v1.0}    这样就可以了     记得上面的path写annotation的话 不要多写一个/ 路径不要写错了
remove
要删除一个标签的话,代码和增加区别不大,唯一的区别就是提交的数据要由键值对修改成 没有value类型的  op和path  2个就够了
1 2 3 4 5 6 7 8 9 10
   | .... list := AddJsonPatch(&JsonPatch{ 		Op:   "remove", 		Path: "/spec/template/spec/containers/0", 		 		 		 		 	}) ....
   | 
 
类似于这种