Golang Kubernetes客户端 – 使用标签对现有资源进行修补

huangapple go评论73阅读模式
英文:

Golang kubernetes client - patching an existing resource with a label

问题

我想要在 Kubernetes 中修补一个现有的秘密资源。该对象在 default 命名空间中被称为 centos-secretstorage。我想要添加一个简单的标签 test: empty。然而,当秘密对象 centos-secretstorage 存在但没有任何现有标签时,这个操作会失败。如果我事先使用 kubectl label centos-secretstorage hello=world 手动给秘密对象添加其他标签,然后重新运行我的 Golang 代码,它就能成功地添加 test: empty 标签。

然而,我希望无论现有标签是否存在,都能添加一个标签。

错误信息:the server rejected our request due to an error in our request

英文:

I want to patch an existing secret resource within Kubernetes. The object is called centos-secretstorage within the default namespace. I want to add a simple label of test: empty. However, this fails when the secret object centos-secretstorage exists, but it doesn't have any existing labels. If I manually label the secret with something else beforehand via kubectl label centos-secretstorage hello=world, and rerun my golang code. It is able to add the test: empty label successfully.

However, I want to have this be able to add a label regardless if existing labels exist or not.

type secret struct {
	namespace string
	name      string
}

func main() {
	k8sClient := k8CientInit()

	vaultSecret := secret{
		namespace: "default",
		name:      "centos-secretstorage",
	}

	vaultSecret.patchSecret(k8sClient)
}

type patchStringValue struct {
	Op    string `json:"op"`
	Path  string `json:"path"`
	Value string `json:"value"`
}

func (p *secret) patchSecret(k8sClient *kubernetes.Clientset) {

	emptyPayload := []patchStringValue{{
		Op:    "add",
		Path:  "/metadata/labels/test",
		Value: "empty",
	}}

	emptyPayloadBytes, _ := json.Marshal(emptyPayload)

	fmt.Println(string(emptyPayloadBytes))
	emptyres, emptyerr := k8sClient.CoreV1().Secrets(p.namespace).Patch(p.name, types.JSONPatchType, emptyPayloadBytes)

	if emptyerr != nil {
		log.Fatal(emptyerr.Error())
	}

	fmt.Println(emptyres.Labels)

}

Error: the server rejected our request due to an error in our request

答案1

得分: 2

问题在于 JSON 补丁策略中的 add 操作要求路径指向一个已存在的映射,而你要修补的对象根本没有这个映射。这就是为什么只要存在 任何 标签,补丁就会成功。我们可以通过使用不同的补丁策略来解决这个问题。我认为 merge 策略应该能很好地工作。

我使用 kubectl(在调试 Kubernetes API 时通常很有用)复现了这个问题(在一个命名空间上,但对象并不重要):

  • kubectl patch ns a --type='json' -p='[{"op": "merge", "path": "/metadata/labels/test", "value":"empty"}]' -> 失败
  • kubectl patch ns a --type='merge' -p='{"metadata": {"labels": {"test": "empty"}}}' -> 成功

使用 Golang 的 client-go 库,代码大致如下(实际上没有编译/运行过):

    payload := `{"metadata": {"labels": {"test": "empty"}}}`
    emptyres, emptyerr := k8sClient.CoreV1().Secrets(p.namespace).Patch(p.name, types.MergePatchType, []byte(payload))

你可以使用结构体来更好地创建 payload JSON,就像你使用 patchStringValue 一样。

有关补丁策略的更多信息可以在以下链接中找到:

英文:

The problem is that the add operation in the JSON patch strategy requires the path to point to an existing map, while the object you are patching does not have this map at all. This is why when any label exists, the patch succeeds. We can work around this by using a different patch strategy. I think the merge strategy should work well.

I was able to reproduce this (on a namespace, but the object doesn't matter) using kubectl (which is generally useful when debugging the Kubernetes API):

  • kubectl patch ns a --type='json' -p='[{"op": "merge", "path": "/metadata/labels/test", "value":"empty"}]' -> fails
  • kubectl patch ns a --type='merge' -p='{"metadata": {"labels": {"test": "empty"}}}' -> succeeds

Using Golang client-go it would look something like this (didn't actually compile / run this):

    payload := `{"metadata": {"labels": {"test": "empty"}}}`
    emptyres, emptyerr := k8sClient.CoreV1().Secrets(p.namespace).Patch(p.name, types.MergePatchType, []byte(payload))

You can make the creation of the payload JSON nicer using structs, as you did with patchStringValue.

More info on patch strategies can be found here:

huangapple
  • 本文由 发表于 2021年9月10日 06:17:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/69125257.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定