Reputation: 381
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
Upvotes: 2
Views: 4632
Reputation: 1578
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"}]'
-> failskubectl patch ns a --type='merge' -p='{"metadata": {"labels": {"test": "empty"}}}'
-> succeedsUsing 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:
Upvotes: 2