2018-07-08 05:17:55 +02:00
|
|
|
package chartserver
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
beego_cache "github.com/astaxie/beego/cache"
|
|
|
|
hlog "github.com/vmware/harbor/src/common/utils/log"
|
|
|
|
|
|
|
|
//Enable redis cache adaptor
|
|
|
|
_ "github.com/astaxie/beego/cache/redis"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
standardExpireTime = 3600 * time.Second
|
|
|
|
redisENVKey = "_REDIS_URL"
|
|
|
|
cacheDriverENVKey = "CHART_CACHE_DRIVER" //"memory" or "redis"
|
|
|
|
cacheDriverMem = "memory"
|
|
|
|
cacheDriverRedis = "redis"
|
|
|
|
cacheCollectionName = "helm_chart_cache"
|
|
|
|
)
|
|
|
|
|
|
|
|
//ChartCache is designed to cache some processed data for repeated accessing
|
|
|
|
//to improve the performance
|
|
|
|
type ChartCache struct {
|
2018-07-11 11:31:34 +02:00
|
|
|
//Cache driver
|
2018-07-08 05:17:55 +02:00
|
|
|
cache beego_cache.Cache
|
|
|
|
|
2018-07-11 11:31:34 +02:00
|
|
|
//Keep the driver type
|
|
|
|
driverType string
|
|
|
|
|
|
|
|
//To indicate if the chart cache is enabled
|
2018-07-08 05:17:55 +02:00
|
|
|
isEnabled bool
|
2018-07-11 11:31:34 +02:00
|
|
|
}
|
2018-07-08 05:17:55 +02:00
|
|
|
|
2018-07-11 11:31:34 +02:00
|
|
|
//ChartCacheConfig keeps the configurations of ChartCache
|
|
|
|
type ChartCacheConfig struct {
|
|
|
|
//Only support 'in-memory' and 'redis' now
|
|
|
|
DriverType string
|
|
|
|
|
|
|
|
//Align with config
|
|
|
|
Config string
|
2018-07-08 05:17:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//NewChartCache is constructor of ChartCache
|
2018-07-11 11:31:34 +02:00
|
|
|
//If return nil, that means no cache is enabled for chart repository server
|
|
|
|
func NewChartCache(config *ChartCacheConfig) *ChartCache {
|
|
|
|
//Never return nil object
|
2018-07-08 05:17:55 +02:00
|
|
|
chartCache := &ChartCache{
|
2018-07-11 11:31:34 +02:00
|
|
|
isEnabled: false,
|
2018-07-08 05:17:55 +02:00
|
|
|
}
|
2018-07-11 11:31:34 +02:00
|
|
|
|
|
|
|
//Double check the configurations are what we want
|
|
|
|
if config == nil {
|
|
|
|
return chartCache
|
|
|
|
}
|
|
|
|
|
|
|
|
if config.DriverType != cacheDriverMem && config.DriverType != cacheDriverRedis {
|
2018-07-08 05:17:55 +02:00
|
|
|
return chartCache
|
|
|
|
}
|
|
|
|
|
2018-07-11 11:31:34 +02:00
|
|
|
if config.DriverType == cacheDriverRedis {
|
|
|
|
if len(config.Config) == 0 {
|
|
|
|
return chartCache
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Try to create the upstream cache
|
|
|
|
cache := initCacheDriver(config)
|
|
|
|
if cache == nil {
|
|
|
|
return chartCache
|
|
|
|
}
|
|
|
|
|
|
|
|
//Cache enabled
|
|
|
|
chartCache.isEnabled = true
|
|
|
|
chartCache.driverType = config.DriverType
|
2018-07-08 05:17:55 +02:00
|
|
|
chartCache.cache = cache
|
|
|
|
|
|
|
|
return chartCache
|
|
|
|
}
|
|
|
|
|
2018-07-11 11:31:34 +02:00
|
|
|
//IsEnabled to indicate if the chart cache is successfully enabled
|
|
|
|
//The cache may be disabled if
|
|
|
|
// user does not set
|
|
|
|
// wrong configurations
|
2018-07-08 05:17:55 +02:00
|
|
|
func (chc *ChartCache) IsEnabled() bool {
|
|
|
|
return chc.isEnabled
|
|
|
|
}
|
|
|
|
|
|
|
|
//PutChart caches the detailed data of chart version
|
|
|
|
func (chc *ChartCache) PutChart(chart *ChartVersionDetails) {
|
2018-07-11 11:31:34 +02:00
|
|
|
//If cache is not enabled, do nothing
|
|
|
|
if !chc.IsEnabled() {
|
2018-07-08 05:17:55 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
//As it's a valid json data anymore when retrieving back from redis cache,
|
|
|
|
//here we use separate methods to handle the data according to the driver type
|
|
|
|
if chart != nil {
|
|
|
|
var err error
|
|
|
|
|
|
|
|
switch chc.driverType {
|
|
|
|
case cacheDriverMem:
|
|
|
|
//Directly put object in
|
|
|
|
err = chc.cache.Put(chart.Metadata.Digest, chart, standardExpireTime)
|
|
|
|
case cacheDriverRedis:
|
|
|
|
//Marshal to json data before saving
|
|
|
|
var jsonData []byte
|
|
|
|
if jsonData, err = json.Marshal(chart); err == nil {
|
|
|
|
err = chc.cache.Put(chart.Metadata.Digest, jsonData, standardExpireTime)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
//Should not reach here, but still put guard code here
|
2018-07-11 11:31:34 +02:00
|
|
|
err = errors.New("Meet invalid cache driver")
|
2018-07-08 05:17:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
//Just logged
|
|
|
|
hlog.Errorf("Failed to cache chart object with error: %s\n", err)
|
|
|
|
hlog.Warningf("If cache driver is using 'redis', please check the related configurations or the network connection")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//GetChart trys to retrieve it from the cache
|
|
|
|
//If hit, return the cached item;
|
|
|
|
//otherwise, nil object is returned
|
|
|
|
func (chc *ChartCache) GetChart(chartDigest string) *ChartVersionDetails {
|
2018-07-11 11:31:34 +02:00
|
|
|
//If cache is not enabled, do nothing
|
|
|
|
if !chc.IsEnabled() {
|
2018-07-08 05:17:55 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
object := chc.cache.Get(chartDigest)
|
|
|
|
if object != nil {
|
|
|
|
//Try to convert data
|
|
|
|
//First try the normal way
|
|
|
|
if chartDetails, ok := object.(*ChartVersionDetails); ok {
|
|
|
|
return chartDetails
|
|
|
|
}
|
|
|
|
|
|
|
|
//Maybe json bytes
|
|
|
|
if bytes, yes := object.([]byte); yes {
|
|
|
|
chartDetails := &ChartVersionDetails{}
|
|
|
|
err := json.Unmarshal(bytes, chartDetails)
|
|
|
|
if err == nil {
|
|
|
|
return chartDetails
|
|
|
|
}
|
|
|
|
//Just logged the error
|
|
|
|
hlog.Errorf("Failed to retrieve chart from cache with error: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
//Initialize the cache driver based on the config
|
2018-07-11 11:31:34 +02:00
|
|
|
func initCacheDriver(cacheConfig *ChartCacheConfig) beego_cache.Cache {
|
|
|
|
switch cacheConfig.DriverType {
|
2018-07-08 05:17:55 +02:00
|
|
|
case cacheDriverMem:
|
|
|
|
hlog.Info("Enable memory cache for chart caching")
|
2018-07-11 11:31:34 +02:00
|
|
|
return beego_cache.NewMemoryCache()
|
2018-07-08 05:17:55 +02:00
|
|
|
case cacheDriverRedis:
|
2018-07-11 11:31:34 +02:00
|
|
|
redisCache, err := beego_cache.NewCache(cacheDriverRedis, cacheConfig.Config)
|
2018-07-08 05:17:55 +02:00
|
|
|
if err != nil {
|
|
|
|
//Just logged
|
|
|
|
hlog.Errorf("Failed to initialize redis cache: %s", err)
|
2018-07-11 11:31:34 +02:00
|
|
|
return nil
|
2018-07-08 05:17:55 +02:00
|
|
|
}
|
|
|
|
|
2018-07-11 11:31:34 +02:00
|
|
|
hlog.Info("Enable redis cache for chart caching")
|
|
|
|
return redisCache
|
2018-07-08 05:17:55 +02:00
|
|
|
default:
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2018-07-11 11:31:34 +02:00
|
|
|
//Any other cases
|
|
|
|
hlog.Info("No cache is enabled for chart caching")
|
|
|
|
return nil
|
2018-07-08 05:17:55 +02:00
|
|
|
}
|