上一篇文章里,我们主要介绍了 kubernetes 世界中 client go 这个基础组件,它的主要职责是负责与 API server 进行通讯交互。其中负责资源调度的 kube-scheduler 组件,负责资源管理的 controller manager 组件,以及负责 pod 生命周期的 kublet 组件,负责网络管理的 kube-proxy 组件都会依赖于这个组件。而该组件在通讯的时候又依赖于 request 对象,并且得到相应的 result 对象,在本篇文章里我们主要来介绍 request 和 result 对象。
Request 结构体
该结构体主要封装了上一篇文章中介绍的 RESTClient 对象,用以完成和 API server 之间的通讯,其图解和相关源码如下:
type Request struct {
c *RESTClient
warningHandler WarningHandler
rateLimiter flowcontrol.RateLimiter
backoff BackoffManager
timeout time.Duration
maxRetries int
verb string
pathPrefix string
subpath string
params url.Values
headers http.Header
namespace string
namespaceSet bool
resource string
resourceName string
subresource string
err error
body io.Reader
}
func (r *Request) Do(ctx context.Context) Result {
var result Result
err := r.request(ctx, func(req *http.Request, resp *http.Response) {
result = r.transformResponse(resp, req)
})
if err != nil {
return Result{err: err}
}
return result
}
func (r *Request) transformResponse(resp *http.Response, req *http.Request) Result {
............
var decoder runtime.Decoder
contentType := resp.Header.Get("Content-Type")
if len(contentType) == 0 {
contentType = r.c.content.ContentType
}
............
decoder, err = r.c.content.Negotiator.Decoder(mediaType, params)
............
return Result{
body: body,
contentType: contentType,
statusCode: resp.StatusCode,
decoder: decoder,
warnings: handleWarnings(resp.Header, r.warningHandler),
}
}
Result 结构体
该结构体主要封装了请求对象和 API server 交互的结果,并提供反序列化得到相应资源对象的功能,其图解和相关源码如下:
type Result struct {
body []byte
warnings []net.WarningHeader
contentType string
err error
statusCode int
decoder runtime.Decoder
}
func (r Result) Into(obj runtime.Object) error {
if r.err != nil {
// Check whether the result has a Status object in the body and prefer that.
return r.Error()
}
if r.decoder == nil {
return fmt.Errorf("serializer for %s doesn't exist", r.contentType)
}
if len(r.body) == 0 {
return fmt.Errorf("0-length response with status code: %d and content type: %s",
r.statusCode, r.contentType)
}
out, _, err := r.decoder.Decode(r.body, nil, obj)
if err != nil || out == obj {
return err
}
// if a different object is returned, see if it is Status and avoid double decoding
// the object.
switch t := out.(type) {
case *metav1.Status:
// any status besides StatusSuccess is considered an error.
if t.Status != metav1.StatusSuccess {
return errors.FromObject(t)
}
}
return nil
}
目前先我们写到这里,在下一篇文章中我们继续来介绍对于不同 group/version 的资源是如何通过发送请求来操作的。