Files
client-go/vendor/github.com/gregjones/httpcache/diskcache/diskcache.go
Kubernetes Publisher 00f65f7d44 Merge pull request #50404 from apelisse/http-cache
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
2017-09-01 16:19:32 +00:00

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}
}