从代码的内容来看,如果资源不存在 get 方法应该返回一个 null 值。与此相对的,还有一个 require 方法:
@OverridepublicTrequire() throwsResourceNotFoundException {try {Tanswer=getMandatory();if (answer==null) {thrownewResourceNotFoundException("The resource you request doesn't exist or couldn't be fetched."); }if (answerinstanceofHasMetadata) {HasMetadatahasMetadata= (HasMetadata) answer;updateApiVersion(hasMetadata); } elseif (answerinstanceofKubernetesResourceList) {KubernetesResourceListlist= (KubernetesResourceList) answer;updateApiVersion(list); }returnanswer; } catch (KubernetesClientExceptione) {if (e.getCode() !=HttpURLConnection.HTTP_NOT_FOUND) {throwe; }thrownewResourceNotFoundException("Resource not found : "+e.getMessage()); } }
如果不存在则会抛出一个 ResourceNotFoundException。
io.fabric8.kubernetes.client.KubernetesClientException: Failure executing: GET at: https://master01.dev.rack.xxxxx.com:6443/apis/batch/v1/namespaces/ares-worker/jobs/demo-data. Message: Forbidden! User ares-worker doesn't have permission. jobs.extensions "demo-data" is forbidden: User "system:serviceaccount:ares-worker:ares-worker" cannot get resource "jobs" in API group "extensions" in the namespace "ares-worker".
打个断点,可以看到如下情况:
Response 的 code 竟然是 403!错误提示的内容表示 cannot get resource "jobs" in API group "extensions"。
publicResponseintercept(Chainchain) throwsIOException {Requestrequest=chain.request();Responseresponse=chain.proceed(request);if (!response.isSuccessful() &&responseCodeToTransformations.keySet().contains(response.code())) {Stringurl=request.url().toString();Matchermatcher=getMatcher(url);ResourceKeykey=getKey(matcher);ResourceKeytarget=responseCodeToTransformations.get(response.code()).get(key);if (target!=null) {response.close(); // At this point, we know we won't reuse or return the response; so close it to avoid a connection leak.StringnewUrl=newStringBuilder(url) .replace(matcher.start(API_VERSION), matcher.end(API_VERSION), target.version) // Order matters: We need to substitute right to left, so that former substitution don't affect the indexes of later. .replace(matcher.start(API_GROUP), matcher.end(API_GROUP), target.group) .toString();Request.BuildernewRequest=request.newBuilder() .url(newUrl);Bufferbuffer=newBuffer();if (request.body() !=null&&!request.method().equalsIgnoreCase(PATCH)) {request.body().writeTo(buffer);Objectobject=Serialization.unmarshal(buffer.inputStream());if (objectinstanceofHasMetadata) {HasMetadatah= (HasMetadata) object;h.setApiVersion(target.group+"/"+target.version);newRequest=newRequest.method(request.method(), RequestBody.create(OperationSupport.JSON, Serialization.asJson(h))); } }returnchain.proceed(newRequest.build()); } }returnresponse; }
简单来说,如果 Kubenetes API Server 响应的 code 不是 200 并且在代码硬编码的某种配置中,会使用一个新的 URL 来请求。目的是实现向下的版本兼容性!
而这个新的 URL 采用了老版本的接口访问资源,所在的 API group 即为 extensions,导致返回了上面的错误信息。
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Illegal character ((CTRL-CHAR, code 31)): only regular white space (\r, \n, \t) is allowed between tokens; nested exception is com.fasterxml.jackson.core.JsonParseException: Illegal character ((CTRL-CHAR, code 31)): only regular white space (\r, \n, \t) is allowed between tokens at [Source: (PushbackInputStream); line: 1, column: 2]