2018-07-02 13:34:04 +02:00
|
|
|
package chartserver
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
2018-07-11 11:31:34 +02:00
|
|
|
"fmt"
|
2018-07-02 13:34:04 +02:00
|
|
|
"net/url"
|
2018-07-11 11:31:34 +02:00
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
|
2018-08-23 09:02:20 +02:00
|
|
|
hlog "github.com/goharbor/harbor/src/common/utils/log"
|
2018-07-11 11:31:34 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
userName = "chart_controller"
|
|
|
|
passwordKey = "UI_SECRET"
|
2018-07-02 13:34:04 +02:00
|
|
|
)
|
|
|
|
|
2018-09-05 10:16:31 +02:00
|
|
|
// Credential keeps the username and password for the basic auth
|
2018-07-11 11:31:34 +02:00
|
|
|
type Credential struct {
|
|
|
|
Username string
|
|
|
|
Password string
|
|
|
|
}
|
|
|
|
|
2018-09-05 10:16:31 +02:00
|
|
|
// Controller is used to handle flows of related requests based on the corresponding handlers
|
|
|
|
// A reverse proxy will be created and managed to proxy the related traffics between API and
|
|
|
|
// backend chart server
|
2018-07-02 13:34:04 +02:00
|
|
|
type Controller struct {
|
2018-09-05 10:16:31 +02:00
|
|
|
// The access endpoint of the backend chart repository server
|
2018-07-02 13:34:04 +02:00
|
|
|
backendServerAddr *url.URL
|
|
|
|
|
2018-09-05 10:16:31 +02:00
|
|
|
// To cover the server info and status requests
|
2018-07-02 13:34:04 +02:00
|
|
|
baseHandler *BaseHandler
|
|
|
|
|
2018-09-05 10:16:31 +02:00
|
|
|
// To cover the chart repository requests
|
2018-07-02 13:34:04 +02:00
|
|
|
repositoryHandler *RepositoryHandler
|
|
|
|
|
2018-09-05 10:16:31 +02:00
|
|
|
// To cover all the manipulation requests
|
2018-07-02 13:34:04 +02:00
|
|
|
manipulationHandler *ManipulationHandler
|
2018-08-03 11:50:03 +02:00
|
|
|
|
2018-09-05 10:16:31 +02:00
|
|
|
// To cover the other utility requests
|
2018-08-03 11:50:03 +02:00
|
|
|
utilityHandler *UtilityHandler
|
2018-07-02 13:34:04 +02:00
|
|
|
}
|
|
|
|
|
2018-09-05 10:16:31 +02:00
|
|
|
// NewController is constructor of the chartserver.Controller
|
2018-07-02 13:34:04 +02:00
|
|
|
func NewController(backendServer *url.URL) (*Controller, error) {
|
|
|
|
if backendServer == nil {
|
|
|
|
return nil, errors.New("failed to create chartserver.Controller: backend sever address is required")
|
|
|
|
}
|
|
|
|
|
2018-09-05 10:16:31 +02:00
|
|
|
// Try to create credential
|
2018-07-11 11:31:34 +02:00
|
|
|
cred := &Credential{
|
|
|
|
Username: userName,
|
|
|
|
Password: os.Getenv(passwordKey),
|
|
|
|
}
|
|
|
|
|
2018-09-05 10:16:31 +02:00
|
|
|
// Use customized reverse proxy
|
2018-07-11 11:31:34 +02:00
|
|
|
proxy := NewProxyEngine(backendServer, cred)
|
2018-07-02 13:34:04 +02:00
|
|
|
|
2018-09-05 10:16:31 +02:00
|
|
|
// Create http client with customized timeouts
|
2018-07-11 11:31:34 +02:00
|
|
|
client := NewChartClient(cred)
|
2018-07-05 12:07:00 +02:00
|
|
|
|
2018-09-05 10:16:31 +02:00
|
|
|
// Initialize chart operator for use
|
2018-07-02 13:34:04 +02:00
|
|
|
operator := &ChartOperator{}
|
|
|
|
|
2018-09-05 10:16:31 +02:00
|
|
|
// Creat cache
|
2018-07-11 11:31:34 +02:00
|
|
|
cacheCfg, err := getCacheConfig()
|
|
|
|
if err != nil {
|
2018-09-05 10:16:31 +02:00
|
|
|
// just log the error
|
|
|
|
// will not break the whole flow if failed to create cache
|
2018-07-11 11:31:34 +02:00
|
|
|
hlog.Errorf("failed to get cache configuration with error: %s", err)
|
|
|
|
}
|
|
|
|
cache := NewChartCache(cacheCfg)
|
|
|
|
if !cache.IsEnabled() {
|
|
|
|
hlog.Info("No cache is enabled for chart caching")
|
|
|
|
}
|
2018-07-08 05:17:55 +02:00
|
|
|
|
2018-07-02 13:34:04 +02:00
|
|
|
return &Controller{
|
|
|
|
backendServerAddr: backendServer,
|
|
|
|
baseHandler: &BaseHandler{proxy},
|
2018-07-05 12:07:00 +02:00
|
|
|
repositoryHandler: &RepositoryHandler{
|
|
|
|
trafficProxy: proxy,
|
|
|
|
apiClient: client,
|
|
|
|
backendServerAddress: backendServer,
|
|
|
|
},
|
2018-07-02 13:34:04 +02:00
|
|
|
manipulationHandler: &ManipulationHandler{
|
2018-07-06 14:53:13 +02:00
|
|
|
trafficProxy: proxy,
|
|
|
|
chartOperator: operator,
|
|
|
|
apiClient: client,
|
|
|
|
backendServerAddress: backendServer,
|
2018-07-08 05:17:55 +02:00
|
|
|
chartCache: cache,
|
2018-07-02 13:34:04 +02:00
|
|
|
},
|
2018-08-03 11:50:03 +02:00
|
|
|
utilityHandler: &UtilityHandler{
|
|
|
|
apiClient: client,
|
|
|
|
backendServerAddress: backendServer,
|
|
|
|
chartOperator: operator,
|
|
|
|
},
|
2018-07-02 13:34:04 +02:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2018-09-05 10:16:31 +02:00
|
|
|
// GetBaseHandler returns the reference of BaseHandler
|
2018-07-02 13:34:04 +02:00
|
|
|
func (c *Controller) GetBaseHandler() *BaseHandler {
|
|
|
|
return c.baseHandler
|
|
|
|
}
|
|
|
|
|
2018-09-05 10:16:31 +02:00
|
|
|
// GetRepositoryHandler returns the reference of RepositoryHandler
|
2018-07-02 13:34:04 +02:00
|
|
|
func (c *Controller) GetRepositoryHandler() *RepositoryHandler {
|
|
|
|
return c.repositoryHandler
|
|
|
|
}
|
|
|
|
|
2018-09-05 10:16:31 +02:00
|
|
|
// GetManipulationHandler returns the reference of ManipulationHandler
|
2018-07-02 13:34:04 +02:00
|
|
|
func (c *Controller) GetManipulationHandler() *ManipulationHandler {
|
|
|
|
return c.manipulationHandler
|
|
|
|
}
|
2018-07-11 11:31:34 +02:00
|
|
|
|
2018-09-05 10:16:31 +02:00
|
|
|
// GetUtilityHandler returns the reference of UtilityHandler
|
2018-08-03 11:50:03 +02:00
|
|
|
func (c *Controller) GetUtilityHandler() *UtilityHandler {
|
|
|
|
return c.utilityHandler
|
|
|
|
}
|
|
|
|
|
2018-09-05 10:16:31 +02:00
|
|
|
// What's the cache driver if it is set
|
2018-07-11 11:31:34 +02:00
|
|
|
func parseCacheDriver() (string, bool) {
|
|
|
|
driver, ok := os.LookupEnv(cacheDriverENVKey)
|
|
|
|
return strings.ToLower(driver), ok
|
|
|
|
}
|
|
|
|
|
2018-09-05 10:16:31 +02:00
|
|
|
// Get and parse the configuration for the chart cache
|
2018-07-11 11:31:34 +02:00
|
|
|
func getCacheConfig() (*ChartCacheConfig, error) {
|
|
|
|
driver, isSet := parseCacheDriver()
|
|
|
|
if !isSet {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if driver != cacheDriverMem && driver != cacheDriverRedis {
|
|
|
|
return nil, fmt.Errorf("cache driver '%s' is not supported, only support 'memory' and 'redis'", driver)
|
|
|
|
}
|
|
|
|
|
|
|
|
if driver == cacheDriverMem {
|
|
|
|
return &ChartCacheConfig{
|
|
|
|
DriverType: driver,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
redisConfigV := os.Getenv(redisENVKey)
|
|
|
|
redisCfg, err := parseRedisConfig(redisConfigV)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to parse redis configurations from '%s' with error: %s", redisCfg, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &ChartCacheConfig{
|
|
|
|
DriverType: driver,
|
|
|
|
Config: redisCfg,
|
|
|
|
}, nil
|
|
|
|
}
|