kuberneteskubectlpatchannotate

Why does kubectl annotate does work and kubectl patch does not?


I am trying to use ‘kubectl patch’ to provide an annotation to a default service account in a namespace. This is because the JavaScript client does not seem to have a kubectl annotate function. So now I wonder: Why does the following patch command not work?

kubectl patch sa default -n somenamespace -v8 --type=json -p='[{"op": "add", "path": "annotations/http://eks.amazonaws.com~1role-arn", "value": "ueah"}]'

While the following statement using annotate does work?


kubectl annotate --overwrite -v8 sa default -n t-werwww2 http://eks.amazonaws.com/role-arn="ueah"

What would be the correct kubectl patch command?


Solution

  • @hiroyukik seems to have partially answered your question by pointing out that you have the path wrong and it should be "/metadata/annotations".

    You used the JSON Merge Patch strategy in your comment. I don't think you need to find a JSON Patch alternative as you suggested, as the Javascript Kubernetes client supports JSON Merge Patch.

    My understanding is that you just add a header in the options to set the strategy you want, like so:

    const options = { "headers": { "Content-type": PatchUtils.PATCH_FORMAT_JSON_MERGE_PATCH } }
    

    See the docs for how to add this to the function call:

    https://kubernetes-client.github.io/javascript/classes/corev1api.corev1api-1.html#patchnamespacedserviceaccount

    However, if you do really need to use the JSON Patch strategy, you'll need to check whether the service account has annotations first as that strategy has no way of creating and adding a field in a single operation. See this Github comment for an explanation:

    https://github.com/kubernetes/kubernetes/issues/90623#issuecomment-621584160

    So a complete shell script example using the JSON Patch strategy would look like this:

    kubectl get sa default -n somenamespace -o json \
      | jq -e '.metadata | has("annotations")' && \
    kubectl patch sa default -n somenamespace --type=json \
        -p='[{"op": "add", "path": "/metadata/annotations/eks.amazonaws.com~1role-arn", "value": "ueah"}]' || \
    kubectl patch sa default -n somenamespace --type=json \
        -p='[{"op":"add","path":"/metadata/annotations","value":{}},{"op":"add","path":"/metadata/annotations/eks.amazonaws.com~1role-arn","value": "ueah"}]'