mirror of
https://github.com/kubernetes/client-go.git
synced 2026-01-30 05:50:01 +00:00
Automatic merge from submit-queue (batch tested with PRs 51480, 49616, 50123, 50846, 50404) Kubectl to use http caching to cache openapi responses from the server **What this PR does / why we need it**: This PR is trying to address the problems raised in #50254 > * uses a disk-based cache that is not safe between processes (does not use atomic fs operations) > * writes get/list responses to disk that should not be cached (like kubectl get secrets) > * is vulnerable to partially written cache responses being used as responses to future requests > * breaks uses of the client transport that make use of websockets > * defaults to enabling the cache for any client builder using RecommendedConfigOverrideFlags or DefaultClientConfig which affects more components than just kubectl All of these points are addressed by this pull-request: 1. It now uses atomic fs operations 2. Doesn't cache by default, only if requested by the client (and it's only done by openapi client) 3. Fixed because of atomic fs operations 4. Found the reason for the bug: Cache wrapper couldn't be unwrapped. I implemented the `WrappedRoundTripper` interface. 5. Since 2. is fixed, I think that should be fine @smarterclayton @liggitt **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #50254 **Special notes for your reviewer**: **Release note**: ```release-note Allows kubectl to use http caching mechanism for the OpenAPI schema. The cache directory can be configured through `--cache-dir` command line flag to kubectl. If set to empty string, caching will be disabled. ``` Kubernetes-commit: 0f2c2bd847ca7a66035b2289e83359ef4c923617
62 lines
1.4 KiB
Go
62 lines
1.4 KiB
Go
// Package diskcache provides an implementation of httpcache.Cache that uses the diskv package
|
|
// to supplement an in-memory map with persistent storage
|
|
//
|
|
package diskcache
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/md5"
|
|
"encoding/hex"
|
|
"github.com/peterbourgon/diskv"
|
|
"io"
|
|
)
|
|
|
|
// Cache is an implementation of httpcache.Cache that supplements the in-memory map with persistent storage
|
|
type Cache struct {
|
|
d *diskv.Diskv
|
|
}
|
|
|
|
// Get returns the response corresponding to key if present
|
|
func (c *Cache) Get(key string) (resp []byte, ok bool) {
|
|
key = keyToFilename(key)
|
|
resp, err := c.d.Read(key)
|
|
if err != nil {
|
|
return []byte{}, false
|
|
}
|
|
return resp, true
|
|
}
|
|
|
|
// Set saves a response to the cache as key
|
|
func (c *Cache) Set(key string, resp []byte) {
|
|
key = keyToFilename(key)
|
|
c.d.WriteStream(key, bytes.NewReader(resp), true)
|
|
}
|
|
|
|
// Delete removes the response with key from the cache
|
|
func (c *Cache) Delete(key string) {
|
|
key = keyToFilename(key)
|
|
c.d.Erase(key)
|
|
}
|
|
|
|
func keyToFilename(key string) string {
|
|
h := md5.New()
|
|
io.WriteString(h, key)
|
|
return hex.EncodeToString(h.Sum(nil))
|
|
}
|
|
|
|
// New returns a new Cache that will store files in basePath
|
|
func New(basePath string) *Cache {
|
|
return &Cache{
|
|
d: diskv.New(diskv.Options{
|
|
BasePath: basePath,
|
|
CacheSizeMax: 100 * 1024 * 1024, // 100MB
|
|
}),
|
|
}
|
|
}
|
|
|
|
// NewWithDiskv returns a new Cache using the provided Diskv as underlying
|
|
// storage.
|
|
func NewWithDiskv(d *diskv.Diskv) *Cache {
|
|
return &Cache{d}
|
|
}
|