Search code examples
jsonpython-3.xkubernetes-python-client

Cannot patch Kubernetes node using python kubernetes-client library


I'm trying to patch a kube node using the Python kubernetes-client library.

Specifically, I'm trying to cordon the node. Using kubectl, I'm able to do it successfully:

kubectl patch node mynode -json --patch={"op":"replace", "path":"/spec/unschedulable", "value":true}`

But using the python kubernetes-client library fails:

from kubernetes import client, config

config.load_kube_config()
body='{"op":"replace", "path":"/spec/unschedulable", "value":true}'
# also have tried body='[{"op":"replace", "path":"/spec/unschedulable", "value":true}]'
v1=client.CoreV1Api()
ret=v1.patch_node(name="mynode", body=body)
print (ret)

The return contains the message:

"json: cannot unmarshal object into Go value of type jsonpatch.Patch"

Some research led me to this bug. It refers to using the kubernetes api directly, but the issue appears to be the same. Unfortunately, the solution - passing an array - doesn't help.

Unfortunately, the documentation doesn't help, here. The required type for body is shown as UNKNOWN_BASE_TYPE, which is not useful. I've looked at the code, but there's no clue there as to how I should be formatting the body - I'm at a loss.


Solution

  • So, it turns out that json.loads() is the answer, and upper casing the bool, so that loads() works. Also, although a non-array body does not raise an error, neither does it actually make the desired change, so an array is required:

    from kubernetes import client, config
    import json
    
    config.load_kube_config()
    v1=client.CoreV1Api()
    
    body='[{"op": "add", "path": "/spec/unschedulable", "value": True}]'
    print(json.loads(body)) #Debug
    ret=v1.patch_node(name="mynode", body=json.loads(body))
    print (ret)
    

    It's worth pointing out that the resulting body has the bool capitalised, whereas for the kubectl command-line operation it must be lower-case.

    Also, oddly, if I replace:
    body=json.loads(body)
    with
    body="[{'op': 'add', 'path': '/spec/unschedulable', 'value': False}]"

    Which is the output of the earlier print statement, it fails in the original manner.