kubernetes-client / java

Official Java client library for kubernetes
http://kubernetes.io/
Apache License 2.0
3.59k stars 1.92k forks source link

Json validation error in new version #3319

Open editcriteria opened 7 months ago

editcriteria commented 7 months ago

Describe the bug While trying to read the nodes of a server I got the following error:

java.lang.IllegalArgumentException: Expected the field `names` to be an array in the JSON string but got `null`

The line that throws the exception is V1ContainerImage.java:193 and in debug I noticed that in my case jsonObj.get("names") is JsonNull so the first condition of line 192 fails because it checks for null and the second fails because it is not an array. I tried the same call in versions 19.0.0 and even 20.0.1-legacy and I can read the nodes

Client Version 20.0.1

Kubernetes Version 1.29.1

Java Version Java 17

To Reproduce It happens on an internal server only when reading nodes

Expected behavior The Json response is parsed correctly

KubeConfig //

Server (please complete the following information):

brendandburns commented 7 months ago

Can you provide the body of the response that you got? You should be able to get it with ApiException.getResponseBody()

brendandburns commented 7 months ago

fwiw, I believe that this is either a bug in the openai spec or the kube api server.

If you look at the spec:

https://raw.githubusercontent.com/kubernetes/kubernetes/master/api/openapi-spec/swagger.json

If you search for ContainerImage you'll see that it is described as an array of string. In JSON null is not the same as []

I believe it needs to be either specified as a oneof(array, null) in that schema or the API server should never return null

editcriteria commented 7 months ago

Here is the part of the body that I think causes the error:

"images": [
    {
        "names": null,
        "sizeBytes": 974400966
    },
    ...
]

We are contacting a k0s server but the same call works with the legacy version of the client.

As a side note, the exception does not throw an ApiException, is it supposed to?

brendandburns commented 7 months ago

Thanks for the additional details. I would have thought that it would throw ApiException, but I guess there's no corresponding try/catch block.

With 20.0.0 we moved to a different code generator which is why there is a difference here.

For now, using legacy is probably the right thing to do. We need a reproduction in upstream k8s, not k0s to determine if this is really a bug.

pigstomach commented 6 months ago

I found the same error, which I can confirm is a bug, and the error message is as follows: java.lang.IllegalArgumentException: Expected the fieldnamesto be an array in the JSON string but gotnull`

at io.kubernetes.client.openapi.models.V1ContainerImage.validateJsonObject(V1ContainerImage.java:193)
at io.kubernetes.client.openapi.models.V1NodeStatus.validateJsonObject(V1NodeStatus.java:547)
at io.kubernetes.client.openapi.models.V1Node.validateJsonObject(V1Node.java:284)`
brendandburns commented 5 months ago

@pigstomach are you using k0s also? Or is this a true kubernetes api server?

brendandburns commented 5 months ago

Ok, I found the problem (I think):

https://github.com/OpenAPITools/openapi-generator/issues/12549

We need to rev. past https://github.com/OpenAPITools/openapi-generator/commit/7a7309edb87902a92d4d0e7b142e4c17dfe5e2b3 in the generator, likely update to 7.x (maybe 7.4?)

k8s-triage-robot commented 2 months ago

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

This bot triages un-triaged issues according to the following rules:

You can:

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

/lifecycle stale

k8s-triage-robot commented 1 month ago

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

This bot triages un-triaged issues according to the following rules:

You can:

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

/lifecycle rotten

jbruinink commented 1 month ago

I'm also seeing this error. In my case it's when receiving a bookmark event.

I'm using version 21.0.1 of the client and version 1.31.0 of kubernetes.

I'm creating a watch and processing the responses with code that looks something like this:

try (Watch<V1Pod> watch = Watch.createWatch(client, api.listNamespacedPod("namespace")
        .timeoutSeconds(60)
        .watch(true)
        .allowWatchBookmarks(true)
        .resourceVersion(currentVersion)
        .buildCall(null), (new TypeToken<Watch.Response<V1Pod>>() {
}).getType())) {
    for (Watch.Response<V1Pod> response : watch) {
        //do something with the response
    }
}

Now whenever I receive a bookmark response, I get this exception:

java.lang.IllegalArgumentException: Expected the field `containers` to be an array in the JSON string but got `null`
    at io.kubernetes.client.openapi.models.V1PodSpec.validateJsonObject(V1PodSpec.java:1354)
    at io.kubernetes.client.openapi.models.V1Pod.validateJsonObject(V1Pod.java:280)
    at io.kubernetes.client.openapi.models.V1Pod$CustomTypeAdapterFactory$1.read(V1Pod.java:309)
    at io.kubernetes.client.openapi.models.V1Pod$CustomTypeAdapterFactory$1.read(V1Pod.java:299)
...

The line in the response body being parsed looks like this (but without the formatting):

{
  "type": "BOOKMARK",
  "object": {
    "kind": "Pod",
    "apiVersion": "v1",
    "metadata": {
      "resourceVersion": "241268288",
      "creationTimestamp": null
    },
    "spec": {
      "containers": null
    },
    "status": {}
  }
}

I can work around this problem by using the type parameter JsonObject instead of V1Pod but that is obviously not ideal. I'd be happy to contribute a PR to (help) fix this problem, but I wouldn't really know where to start.

nickbreen commented 3 weeks ago

I encountered this error when executing io.kubernetes.client.openapi.apis.CoreV1Api#listNode against minikube.

The root cause is when the node's image list contains images that no-longer have a name. I.e. a new image has been pushed that has replaced an old image and re-used the name. I.e. the example shown in https://github.com/kubernetes-client/java/issues/3319#issuecomment-2058404461

The validation of the payload is overly strict in this case: there exist entirely valid ways to "orphan" images in a registry that supports mutable image names.

I'm not entirely convinced that an API client has the authority to determine the validity of an API server's list of images, especially when it does so with a fatal runtime exception, particularly when the node's image list may not even be relevant to the consumer of the node list.

sconstro commented 2 weeks ago

create watch with bookmark generates: ava.lang.IllegalArgumentException: Expected the field containers to be an array in the JSON string but got null

TimoBuechert commented 5 days ago

I experience the same issue with k3s v1.29.7+k3s1.