var longThrottleLatency … var extraLongThrottleLatency … type HTTPClient … type ResponseWrapper … type RequestConstructionError … // Error returns a textual description of 'r'. func (r *RequestConstructionError) Error() string { … } var noBackoff … type requestRetryFunc … func defaultRequestRetryFn(maxRetries int) WithRetry { … } type Request … // NewRequest creates a new request helper object for accessing runtime.Objects on a server. func NewRequest(c *RESTClient) *Request { … } // NewRequestWithClient creates a Request with an embedded RESTClient for use in test scenarios. func NewRequestWithClient(base *url.URL, versionedAPIPath string, content ClientContentConfig, client *http.Client) *Request { … } func (r *Request) UseProtobufAsDefaultIfPreferred(prefersProtobuf bool) *Request { … } func (r *Request) UseProtobufAsDefault() *Request { … } func (r *Request) setAcceptHeader() { … } // Verb sets the verb this request will use. func (r *Request) Verb(verb string) *Request { … } // Prefix adds segments to the relative beginning to the request path. These // items will be placed before the optional Namespace, Resource, or Name sections. // Setting AbsPath will clear any previously set Prefix segments func (r *Request) Prefix(segments ...string) *Request { … } // Suffix appends segments to the end of the path. These items will be placed after the prefix and optional // Namespace, Resource, or Name sections. func (r *Request) Suffix(segments ...string) *Request { … } // Resource sets the resource to access (<resource>/[ns/<namespace>/]<name>) func (r *Request) Resource(resource string) *Request { … } // BackOff sets the request's backoff manager to the one specified, // or defaults to the stub implementation if nil is provided func (r *Request) BackOff(manager BackoffManager) *Request { … } // WarningHandler sets the handler this client uses when warning headers are encountered. // If set to nil, this client will use the default warning handler (see SetDefaultWarningHandler). func (r *Request) WarningHandler(handler WarningHandler) *Request { … } // Throttle receives a rate-limiter and sets or replaces an existing request limiter func (r *Request) Throttle(limiter flowcontrol.RateLimiter) *Request { … } // SubResource sets a sub-resource path which can be multiple segments after the resource // name but before the suffix. func (r *Request) SubResource(subresources ...string) *Request { … } // Name sets the name of a resource to access (<resource>/[ns/<namespace>/]<name>) func (r *Request) Name(resourceName string) *Request { … } // Namespace applies the namespace scope to a request (<resource>/[ns/<namespace>/]<name>) func (r *Request) Namespace(namespace string) *Request { … } // NamespaceIfScoped is a convenience function to set a namespace if scoped is true func (r *Request) NamespaceIfScoped(namespace string, scoped bool) *Request { … } // AbsPath overwrites an existing path with the segments provided. Trailing slashes are preserved // when a single segment is passed. func (r *Request) AbsPath(segments ...string) *Request { … } // RequestURI overwrites existing path and parameters with the value of the provided server relative // URI. func (r *Request) RequestURI(uri string) *Request { … } // Param creates a query parameter with the given string value. func (r *Request) Param(paramName, s string) *Request { … } // VersionedParams will take the provided object, serialize it to a map[string][]string using the // implicit RESTClient API version and the default parameter codec, and then add those as parameters // to the request. Use this to provide versioned query parameters from client libraries. // VersionedParams will not write query parameters that have omitempty set and are empty. If a // parameter has already been set it is appended to (Params and VersionedParams are additive). func (r *Request) VersionedParams(obj runtime.Object, codec runtime.ParameterCodec) *Request { … } func (r *Request) SpecificallyVersionedParams(obj runtime.Object, codec runtime.ParameterCodec, version schema.GroupVersion) *Request { … } func (r *Request) setParam(paramName, value string) *Request { … } func (r *Request) SetHeader(key string, values ...string) *Request { … } // Timeout makes the request use the given duration as an overall timeout for the // request. Additionally, if set passes the value as "timeout" parameter in URL. func (r *Request) Timeout(d time.Duration) *Request { … } // MaxRetries makes the request use the given integer as a ceiling of retrying upon receiving // "Retry-After" headers and 429 status-code in the response. The default is 10 unless this // function is specifically called with a different value. // A zero maxRetries prevent it from doing retires and return an error immediately. func (r *Request) MaxRetries(maxRetries int) *Request { … } // Body makes the request use obj as the body. Optional. // If obj is a string, try to read a file of that name. // If obj is a []byte, send it directly. // If obj is an io.Reader, use it directly. // If obj is a runtime.Object, marshal it correctly, and set Content-Type header. // If obj is a runtime.Object and nil, do nothing. // Otherwise, set an error. func (r *Request) Body(obj interface{ … } // Error returns any error encountered constructing the request, if any. func (r *Request) Error() error { … } // URL returns the current working URL. Check the result of Error() to ensure // that the returned URL is valid. func (r *Request) URL() *url.URL { … } // finalURLTemplate is similar to URL(), but will make all specific parameter values equal // - instead of name or namespace, "{name}" and "{namespace}" will be used, and all query // parameters will be reset. This creates a copy of the url so as not to change the // underlying object. func (r Request) finalURLTemplate() url.URL { … } func (r *Request) tryThrottleWithInfo(ctx context.Context, retryInfo string) error { … } func (r *Request) tryThrottle(ctx context.Context) error { … } type throttleSettings … type throttledLogger … var globalThrottledLogger … func (b *throttledLogger) attemptToLog() (klog.Level, bool) { … } // Infof will write a log message at each logLevel specified by the receiver's throttleSettings // as long as it hasn't written a log message more recently than minLogInterval. func (b *throttledLogger) Infof(message string, args ...interface{ … } // Watch attempts to begin watching the requested location. // Returns a watch.Interface, or an error. func (r *Request) Watch(ctx context.Context) (watch.Interface, error) { … } func (r *Request) watchInternal(ctx context.Context) (watch.Interface, runtime.Decoder, error) { … } type WatchListResult … // Into stores the result into obj. The passed obj parameter must be a pointer to a list type. // // Note: // // Special attention should be given to the type *unstructured.Unstructured, // which represents a list type but does not have an "Items" field. // Users who directly use RESTClient may store the response in such an object. // This particular case is not handled by the current implementation of this function, // but may be considered for future updates. func (r WatchListResult) Into(obj runtime.Object) error { … } // WatchList establishes a stream to get a consistent snapshot of data // from the server as described in https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/3157-watch-list#proposal // // Note that the watchlist requires properly setting the ListOptions // otherwise it just establishes a regular watch with the server. // Check the documentation https://kubernetes.io/docs/reference/using-api/api-concepts/#streaming-lists // to see what parameters are currently required. func (r *Request) WatchList(ctx context.Context) WatchListResult { … } // handleWatchList holds the actual logic for easier unit testing. // Note that this function will close the passed watch. func (r *Request) handleWatchList(ctx context.Context, w watch.Interface, negotiatedObjectDecoder runtime.Decoder) WatchListResult { … } func (r *Request) newStreamWatcher(resp *http.Response) (watch.Interface, runtime.Decoder, error) { … } // updateRequestResultMetric increments the RequestResult metric counter, // it should be called with the (response, err) tuple from the final // reply from the server. func updateRequestResultMetric(ctx context.Context, req *Request, resp *http.Response, err error) { … } // updateRequestRetryMetric increments the RequestRetry metric counter, // it should be called with the (response, err) tuple for each retry // except for the final attempt. func updateRequestRetryMetric(ctx context.Context, req *Request, resp *http.Response, err error) { … } func sanitize(req *Request, resp *http.Response, err error) (string, string) { … } // Stream formats and executes the request, and offers streaming of the response. // Returns io.ReadCloser which could be used for streaming of the response, or an error // Any non-2xx http status code causes an error. If we get a non-2xx code, we try to convert the body into an APIStatus object. // If we can, we return that as an error. Otherwise, we create an error that lists the http status and the content of the response. func (r *Request) Stream(ctx context.Context) (io.ReadCloser, error) { … } // requestPreflightCheck looks for common programmer errors on Request. // // We tackle here two programmer mistakes. The first one is to try to create // something(POST) using an empty string as namespace with namespaceSet as // true. If namespaceSet is true then namespace should also be defined. The // second mistake is, when under the same circumstances, the programmer tries // to GET, PUT or DELETE a named resource(resourceName != ""), again, if // namespaceSet is true then namespace must not be empty. func (r *Request) requestPreflightCheck() error { … } func (r *Request) newHTTPRequest(ctx context.Context) (*http.Request, error) { … } // newDNSMetricsTrace returns an HTTP trace that tracks time spent on DNS lookups per host. // This metric is available in client as "rest_client_dns_resolution_duration_seconds". func newDNSMetricsTrace(ctx context.Context) *httptrace.ClientTrace { … } // request connects to the server and invokes the provided function when a server response is // received. It handles retry behavior and up front validation of requests. It will invoke // fn at most once. It will return an error if a problem occurred prior to connecting to the // server - the provided function is responsible for handling server errors. func (r *Request) request(ctx context.Context, fn func(*http.Request, *http.Response)) error { … } // Do formats and executes the request. Returns a Result object for easy response // processing. // // Error type: // - If the server responds with a status: *errors.StatusError or *errors.UnexpectedObjectError // - http.Client.Do errors are returned directly. func (r *Request) Do(ctx context.Context) Result { … } // DoRaw executes the request but does not process the response body. func (r *Request) DoRaw(ctx context.Context) ([]byte, error) { … } // transformResponse converts an API response into a structured API object func (r *Request) transformResponse(ctx context.Context, resp *http.Response, req *http.Request) Result { … } // truncateBody decides if the body should be truncated, based on the glog Verbosity. func truncateBody(logger klog.Logger, body string) string { … } // logBody logs a body output that could be either JSON or protobuf. It explicitly guards against // allocating a new string for the body output unless necessary. Uses a simple heuristic to determine // whether the body is printable. // // It needs to be called by all functions which send or receive the data. func logBody(ctx context.Context, callDepth int, prefix string, body []byte) { … } const maxUnstructuredResponseTextBytes … // transformUnstructuredResponseError handles an error from the server that is not in a structured form. // It is expected to transform any response that is not recognizable as a clear server sent error from the // K8S API using the information provided with the request. In practice, HTTP proxies and client libraries // introduce a level of uncertainty to the responses returned by servers that in common use result in // unexpected responses. The rough structure is: // // 1. Assume the server sends you something sane - JSON + well defined error objects + proper codes // - this is the happy path // - when you get this output, trust what the server sends // 2. Guard against empty fields / bodies in received JSON and attempt to cull sufficient info from them to // generate a reasonable facsimile of the original failure. // - Be sure to use a distinct error type or flag that allows a client to distinguish between this and error 1 above // 3. Handle true disconnect failures / completely malformed data by moving up to a more generic client error // 4. Distinguish between various connection failures like SSL certificates, timeouts, proxy errors, unexpected // initial contact, the presence of mismatched body contents from posted content types // - Give these a separate distinct error type and capture as much as possible of the original message // // TODO: introduce transformation of generic http.Client.Do() errors that separates 4. func (r *Request) transformUnstructuredResponseError(resp *http.Response, req *http.Request, body []byte) error { … } // newUnstructuredResponseError instantiates the appropriate generic error for the provided input. It also logs the body. func (r *Request) newUnstructuredResponseError(body []byte, isTextResponse bool, statusCode int, method string, retryAfter int) error { … } // isTextResponse returns true if the response appears to be a textual media type. func isTextResponse(resp *http.Response) bool { … } // retryAfterSeconds returns the value of the Retry-After header and true, or 0 and false if // the header was missing or not a valid number. func retryAfterSeconds(resp *http.Response) (int, bool) { … } type Result … // Raw returns the raw result. func (r Result) Raw() ([]byte, error) { … } // Get returns the result as an object, which means it passes through the decoder. // If the returned object is of type Status and has .Status != StatusSuccess, the // additional information in Status will be used to enrich the error. func (r Result) Get() (runtime.Object, error) { … } // StatusCode returns the HTTP status code of the request. (Only valid if no // error was returned.) func (r Result) StatusCode(statusCode *int) Result { … } // ContentType returns the "Content-Type" response header into the passed // string, returning the Result for possible chaining. (Only valid if no // error code was returned.) func (r Result) ContentType(contentType *string) Result { … } // Into stores the result into obj, if possible. If obj is nil it is ignored. // If the returned object is of type Status and has .Status != StatusSuccess, the // additional information in Status will be used to enrich the error. func (r Result) Into(obj runtime.Object) error { … } // WasCreated updates the provided bool pointer to whether the server returned // 201 created or a different response. func (r Result) WasCreated(wasCreated *bool) Result { … } // Error returns the error executing the request, nil if no error occurred. // If the returned object is of type Status and has Status != StatusSuccess, the // additional information in Status will be used to enrich the error. // See the Request.Do() comment for what errors you might get. func (r Result) Error() error { … } // Warnings returns any warning headers received in the response func (r Result) Warnings() []net.WarningHeader { … } var NameMayNotBe … var NameMayNotContain … // IsValidPathSegmentName validates the name can be safely encoded as a path segment func IsValidPathSegmentName(name string) []string { … } // IsValidPathSegmentPrefix validates the name can be used as a prefix for a name which will be encoded as a path segment // It does not check for exact matches with disallowed names, since an arbitrary suffix might make the name valid func IsValidPathSegmentPrefix(name string) []string { … } // ValidatePathSegmentName validates the name can be safely encoded as a path segment func ValidatePathSegmentName(name string, prefix bool) []string { … } func objectKeyFromMeta(objMeta metav1.Object) string { … }