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", }) ....
|
类似于这种