javascript icon indicating copy to clipboard operation
javascript copied to clipboard

patchNode and patchNamespacedService 415 UnsupportedMediaType Errors

Open bradthomasbrown opened this issue 3 years ago • 4 comments

Trying to patch a node or a namespaced service always returns a "415: Unsupported Media Type" error.

Client Version 0.17.0 Server Version 1.24.2-gke.1900

patchNode Code:

await kc.makeApiClient(k8s.CoreV1Api).patchNode(
    instance.name,
    { metadata: { labels: { 'foo': 'bar' }}},
    undefined, undefined, undefined, undefined, 
    { headers: { 'content-type': PATCH_TYPE }}
)

patchNamespacedService Code:

await kc.makeApiClient(k8s.CoreV1Api).patchNamespacedService(
    "nginx-svc", 
    "default",
    { spec: { externalIPs: 
        instances.map(instance =>
            instance
                .networkInterfaces[0]
                .networkIP
        )
    }},
    undefined, undefined, undefined, undefined,
    { headers: { 'content-type': PATCH_TYPE }}
)

Using any of the below as PATCH_TYPE causes the error.

  • k8s.PatchUtils.PATCH_FORMAT_JSON_PATCH
  • k8s.PatchUtils.PATCH_FORMAT_JSON_MERGE_PATCH
  • k8s.PatchUtils.PATCH_FORMAT_STRATEGIC_MERGE_PATCH

Using NodeJS v16.16.0

bradthomasbrown avatar Aug 24 '22 06:08 bradthomasbrown

From digging around the massive error response from the requests, I noticed that the headers for the requests were set to 'content-type: application/json' despite the specified content-type overrides. There were some weird hacky "force content type to merge patch json" query strings in the request URL, but whatever that is clearly does not work.

Dug around a bit more in the docs and found a _defaultHeaders property for the k8sApi object (kc.makeApiClient(k8s.CoreV1Api)) I was using to make the calls. Seemed like it couldn't possibly be right to overwrite it, since docs list it as protected, but overwriting it seemed to work.

Below code is a functioning albeit concerning and unintuitive workaround:

let k8sApi = kc.makeApiClient(k8s.CoreV1Api)
k8sApi._defaultHeaders = { 'content-type': 'application/merge-patch+json' }
await k8sApi.patchNode(
    instance.name,
    { metadata: { labels: { 'foo': 'bar' }}}
)

I want to leave this open until the issue is resolved in case others come across this and because this cannot possibly be the correct way to use this.

bradthomasbrown avatar Aug 24 '22 07:08 bradthomasbrown

The "correct" way to override the headers is via an Interceptor see this comment for more details:

https://github.com/kubernetes-client/javascript/issues/817#issuecomment-1152607117

We should expand PatchUtils to do this for you.

brendandburns avatar Aug 24 '22 17:08 brendandburns

I guess it is achievable via the Interceptor, but the patch example is showing that you can pass the options.headers for that: https://github.com/kubernetes-client/javascript/blob/6c5a58f51b8cdb01c59cbd5b433013beb4940df2/examples/patch-example.js#L19

The generated TS code is also accepting options.headers as the last param - so it feels like this is more of a regression than a deliberate breaking change?

dominykas avatar Sep 07 '22 10:09 dominykas

🤦 the old approach still works. It's just that there was a new parameter (fieldValidation) added recently, so all the params shifted.

Fix for the example: https://github.com/kubernetes-client/javascript/pull/872

Similarly, @bradthomasbrown, you need one extra undefined before the options in your calls.

dominykas avatar Sep 07 '22 11:09 dominykas

The Kubernetes project currently lacks enough contributors to adequately respond to all issues and PRs.

This bot triages issues and PRs according to the following rules:

  • After 90d of inactivity, lifecycle/stale is applied
  • After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied
  • After 30d of inactivity since lifecycle/rotten was applied, the issue is closed

You can:

  • Mark this issue or PR as fresh with /remove-lifecycle stale
  • Mark this issue or PR as rotten with /lifecycle rotten
  • Close this issue or PR with /close
  • Offer to help out with Issue Triage

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle stale

k8s-triage-robot avatar Dec 06 '22 11:12 k8s-triage-robot

Closing via https://github.com/kubernetes-client/javascript/pull/872

brendandburns avatar Dec 12 '22 18:12 brendandburns