cache schemas downloaded over HTTP

This commit is contained in:
Yann Hamon 2021-01-01 14:45:20 +01:00
parent 1a76217195
commit 18927ddf75
10 changed files with 144 additions and 52 deletions

6
pkg/cache/cache.go vendored Normal file
View file

@ -0,0 +1,6 @@
package cache
type Cache interface {
Get(resourceKind, resourceAPIVersion, k8sVersion string) (interface{}, error)
Set(resourceKind, resourceAPIVersion, k8sVersion string, schema interface{}) error
}

49
pkg/cache/inmemory.go vendored Normal file
View file

@ -0,0 +1,49 @@
package cache
import (
"fmt"
"sync"
)
// SchemaCache is a cache for downloaded schemas, so each file is only retrieved once
// It is different from pkg/registry/http_cache.go in that:
// - This cache caches the parsed Schemas
type inMemory struct {
sync.RWMutex
schemas map[string]interface{}
}
// New creates a new cache for downloaded schemas
func NewInMemoryCache() Cache {
return &inMemory{
schemas: map[string]interface{}{},
}
}
func key(resourceKind, resourceAPIVersion, k8sVersion string) string {
return fmt.Sprintf("%s-%s-%s", resourceKind, resourceAPIVersion, k8sVersion)
}
// Get retrieves the JSON schema given a resource signature
func (c *inMemory) Get(resourceKind, resourceAPIVersion, k8sVersion string) (interface{}, error) {
k := key(resourceKind, resourceAPIVersion, k8sVersion)
c.RLock()
defer c.RUnlock()
schema, ok := c.schemas[k]
if ok == false {
return nil, fmt.Errorf("schema not found in in-memory cache")
}
return schema, nil
}
// Set adds a JSON schema to the schema cache
func (c *inMemory) Set(resourceKind, resourceAPIVersion, k8sVersion string, schema interface{}) error {
k := key(resourceKind, resourceAPIVersion, k8sVersion)
c.Lock()
defer c.Unlock()
c.schemas[k] = schema
return nil
}

48
pkg/cache/ondisk.go vendored Normal file
View file

@ -0,0 +1,48 @@
package cache
import (
"crypto/md5"
"encoding/hex"
"fmt"
"io/ioutil"
"os"
"path"
"sync"
)
type onDisk struct {
sync.RWMutex
folder string
}
// New creates a new cache for downloaded schemas
func NewOnDiskCache(cache string) Cache {
return &onDisk{
folder: cache,
}
}
func cachePath(folder, resourceKind, resourceAPIVersion, k8sVersion string) string {
hash := md5.Sum([]byte(fmt.Sprintf("%s-%s-%s", resourceKind, resourceAPIVersion, k8sVersion)))
return path.Join(folder, hex.EncodeToString(hash[:]))
}
// Get retrieves the JSON schema given a resource signature
func (c *onDisk) Get(resourceKind, resourceAPIVersion, k8sVersion string) (interface{}, error) {
c.RLock()
defer c.RUnlock()
f, err := os.Open(cachePath(c.folder, resourceKind, resourceAPIVersion, k8sVersion))
if err != nil {
return nil, err
}
return ioutil.ReadAll(f)
}
// Set adds a JSON schema to the schema cache
func (c *onDisk) Set(resourceKind, resourceAPIVersion, k8sVersion string, schema interface{}) error {
c.Lock()
defer c.Unlock()
return ioutil.WriteFile(cachePath(c.folder, resourceKind, resourceAPIVersion, k8sVersion), schema.([]byte), 0644)
}

View file

@ -1,42 +0,0 @@
package cache
import (
"fmt"
"sync"
"github.com/xeipuuv/gojsonschema"
)
// SchemaCache is a cache for downloaded schemas, so each file is only retrieved once
type SchemaCache struct {
sync.RWMutex
schemas map[string]*gojsonschema.Schema
}
// New creates a new cache for downloaded schemas
func New() *SchemaCache {
return &SchemaCache{
schemas: map[string]*gojsonschema.Schema{},
}
}
// Key computes a key for a specific JSON schema from its Kind, the resource API Version, and the
// Kubernetes version
func Key(resourceKind, resourceAPIVersion, k8sVersion string) string {
return fmt.Sprintf("%s-%s-%s", resourceKind, resourceAPIVersion, k8sVersion)
}
// Get retrieves the JSON schema given a resource signature
func (c *SchemaCache) Get(key string) (*gojsonschema.Schema, bool) {
c.RLock()
defer c.RUnlock()
schema, ok := c.schemas[key]
return schema, ok
}
// Set adds a JSON schema to the schema cache
func (c *SchemaCache) Set(key string, schema *gojsonschema.Schema) {
c.Lock()
defer c.Unlock()
c.schemas[key] = schema
}