问题现象
--> DELETE https://x.x.x.x:6443/api/v1/namespaces/default/pods/test-pod?gracePeriodSeconds=0 HTTP/1.1 Accept: application/json User-Agent: Swagger-Codegen/1.0-SNAPSHOT/java --> END DELETE <-- HTTP/1.1 200 OK (26ms) Content-Type: application/json Date: Tue, 12 Nov 2019 16:58:14 GMT Transfer-Encoding: chunked OkHttp-Sent-Millis: 1573577894623 OkHttp-Received-Millis: 1573577894647 {"kind":"Pod","apiVersion":"v1","metadata":{"name":"test-pod","namespace":"default","selfLink":"/api/v1/namespaces/default/pods/test-pod","uid":"9dca2781-056d-11ea-8252-005056916bf2","resourceVersion":"27423207","creationTimestamp":"2019-11-12T16:58:14Z","deletionTimestamp":"2019-11-12T16:58:14Z","deletionGracePeriodSeconds":0},"spec":{"volumes":[{"name":"default-token-fj7s5","secret":{"secretName":"default-token-fj7s5","defaultMode":420}}],"containers":[{"name":"test-pod","image":"busybox","command":["sh","-c","sleep 3600"],"resources":{},"volumeMounts":[{"name":"default-token-fj7s5","readOnly":true,"mountPath":"/var/run/secrets/kubernetes.io/serviceaccount"}],"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File","imagePullPolicy":"Always"}],"restartPolicy":"Always","terminationGracePeriodSeconds":30,"dnsPolicy":"ClusterFirst","serviceAccountName":"default","serviceAccount":"default","nodeName":"worker.xxx.com","securityContext":{},"schedulerName":"default-scheduler","tolerations":[{"key":"node.kubernetes.io/not-ready","operator":"Exists","effect":"NoExecute","tolerationSeconds":300},{"key":"node.kubernetes.io/unreachable","operator":"Exists","effect":"NoExecute","tolerationSeconds":300}],"priority":0,"enableServiceLinks":true},"status":{"phase":"Pending","conditions":[{"type":"Initialized","status":"True","lastProbeTime":null,"lastTransitionTime":"2019-11-12T16:58:14Z"},{"type":"Ready","status":"False","lastProbeTime":null,"lastTransitionTime":"2019-11-12T16:58:14Z","reason":"ContainersNotReady","message":"containers with unready status: [test-pod]"},{"type":"ContainersReady","status":"False","lastProbeTime":null,"lastTransitionTime":"2019-11-12T16:58:14Z","reason":"ContainersNotReady","message":"containers with unready status: [test-pod]"},{"type":"PodScheduled","status":"True","lastProbeTime":null,"lastTransitionTime":"2019-11-12T16:58:14Z"}],"hostIP":"x.x.x.x","startTime":"2019-11-12T16:58:14Z","containerStatuses":[{"name":"test-pod","state":{"waiting":{"reason":"ContainerCreating"}},"lastState":{},"ready":false,"restartCount":0,"image":"busybox","imageID":""}],"qosClass":"BestEffort"}} <-- END HTTP (2175-byte body) com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 1303 path $.status at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:226) at com.google.gson.Gson.fromJson(Gson.java:927) at com.google.gson.Gson.fromJson(Gson.java:892) at com.google.gson.Gson.fromJson(Gson.java:841) at io.kubernetes.client.JSON.deserialize(JSON.java:108) at io.kubernetes.client.ApiClient.deserialize(ApiClient.java:668) at io.kubernetes.client.ApiClient.handleResponse(ApiClient.java:871) at io.kubernetes.client.ApiClient.execute(ApiClient.java:798) at io.kubernetes.client.apis.CoreV1Api.deleteNamespacedPodWithHttpInfo(CoreV1Api.java:13297) at io.kubernetes.client.apis.CoreV1Api.deleteNamespacedPod(CoreV1Api.java:13276) at com.nuance.ndep.c3p.services.K8sService.createAndDeletePod(K8sService.java:437) at com.nuance.ndep.c3p.services.K8sServiceIT.createAndDeletePod(K8sServiceIT.java:51) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:628) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:117) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:184) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:180) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:127) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80) at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80) at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229) at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197) at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128) at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69) at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) Caused by: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 1303 path $.status at com.google.gson.stream.JsonReader.nextString(JsonReader.java:825) at com.google.gson.internal.bind.TypeAdapters$16.read(TypeAdapters.java:402) at com.google.gson.internal.bind.TypeAdapters$16.read(TypeAdapters.java:390) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222) ... 62 more
I've looked in the code a bit and I think that the issue is caused because you guys are expecting a V1Status in CoreV1Api.java:13296 when it is actually a V1PodStatus response that is returned from the kubernetes API
public ApiResponse<V1Status> deleteNamespacedPodWithHttpInfo(String name, String namespace, String pretty, V1DeleteOptions body, String dryRun, Integer gracePeriodSeconds, Boolean orphanDependents, String propagationPolicy) throws ApiException { com.squareup.okhttp.Call call = deleteNamespacedPodValidateBeforeCall(name, namespace, pretty, body, dryRun, gracePeriodSeconds, orphanDependents, propagationPolicy, null, null); Type localVarReturnType = new TypeToken<V1Status>(){}.getType(); // <-- bad type here ? return apiClient.execute(call, localVarReturnType); }
问题原因:
When you delete a StatefulSet (and probably a ReplicaSet too) it initially returns a
StatefulSet
object, but eventually it returns aStatus
object.This means that the Swagger should be
oneOf(StatefulSet, Status)
But the Kubernetes Swagger here:
https://raw.githubusercontent.com/kubernetes/kubernetes/master/api/openapi-spec/swagger.json
Only has the
Status
object.大体意思就是:kubernetes-client:的通过Swagger生成代码,只有
Status
对象,不能解析资源对象(如:StatefulSet
)
问题解决
捕捉这个异常,当作正常处理