mirror of https://github.com/goharbor/harbor.git
221 lines
6.8 KiB
Go
221 lines
6.8 KiB
Go
// Copyright Project Harbor Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package config
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
|
|
"github.com/goharbor/harbor/src/common"
|
|
"github.com/goharbor/harbor/src/common/models"
|
|
"github.com/goharbor/harbor/src/common/utils"
|
|
"github.com/goharbor/harbor/src/lib"
|
|
"github.com/goharbor/harbor/src/lib/config/metadata"
|
|
"github.com/goharbor/harbor/src/lib/errors"
|
|
"github.com/goharbor/harbor/src/lib/log"
|
|
"github.com/goharbor/harbor/src/pkg/config/store"
|
|
"github.com/goharbor/harbor/src/pkg/config/validate"
|
|
)
|
|
|
|
// CfgManager ... Configure Manager
|
|
type CfgManager struct {
|
|
Store *store.ConfigStore
|
|
}
|
|
|
|
var validateRules = []validate.Rule{
|
|
&validate.LdapGroupValidateRule{},
|
|
}
|
|
|
|
// LoadDefault ...
|
|
func (c *CfgManager) LoadDefault() {
|
|
// Init Default Value
|
|
itemArray := metadata.Instance().GetAll()
|
|
for _, item := range itemArray {
|
|
if len(item.DefaultValue) > 0 {
|
|
cfgValue, err := metadata.NewCfgValue(item.Name, item.DefaultValue)
|
|
if err != nil {
|
|
log.Errorf("LoadDefault failed, config item, key: %v, err: %v", item.Name, err)
|
|
continue
|
|
}
|
|
_ = c.Store.Set(item.Name, *cfgValue)
|
|
}
|
|
}
|
|
}
|
|
|
|
// LoadSystemConfigFromEnv ...
|
|
func (c *CfgManager) LoadSystemConfigFromEnv() {
|
|
itemArray := metadata.Instance().GetAll()
|
|
// Init System Value
|
|
for _, item := range itemArray {
|
|
if item.Scope == metadata.SystemScope && len(item.EnvKey) > 0 {
|
|
if envValue, ok := os.LookupEnv(item.EnvKey); ok {
|
|
configValue, err := metadata.NewCfgValue(item.Name, envValue)
|
|
if err != nil {
|
|
log.Errorf("LoadSystemConfigFromEnv failed, config item, key: %v, err: %v", item.Name, err)
|
|
continue
|
|
}
|
|
_ = c.Store.Set(item.Name, *configValue)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// GetAll get all settings.
|
|
func (c *CfgManager) GetAll(ctx context.Context) map[string]interface{} {
|
|
resultMap := map[string]interface{}{}
|
|
if err := c.Store.Load(ctx); err != nil {
|
|
log.Errorf("AllConfigs failed, error %v", err)
|
|
return resultMap
|
|
}
|
|
metaDataList := metadata.Instance().GetAll()
|
|
for _, item := range metaDataList {
|
|
cfgValue, err := c.Store.GetAnyType(item.Name)
|
|
if err != nil {
|
|
if err != metadata.ErrValueNotSet {
|
|
log.Errorf("Failed to get Value of key %v, error %v", item.Name, err)
|
|
}
|
|
continue
|
|
}
|
|
resultMap[item.Name] = cfgValue
|
|
}
|
|
return resultMap
|
|
}
|
|
|
|
// GetUserCfgs retrieve all user configs
|
|
func (c *CfgManager) GetUserCfgs(ctx context.Context) map[string]interface{} {
|
|
resultMap := map[string]interface{}{}
|
|
if err := c.Store.Load(ctx); err != nil {
|
|
log.Errorf("UserConfigs failed, error %v", err)
|
|
return resultMap
|
|
}
|
|
metaDataList := metadata.Instance().GetAll()
|
|
for _, item := range metaDataList {
|
|
if item.Scope == metadata.UserScope {
|
|
cfgValue, err := c.Store.GetAnyType(item.Name)
|
|
if err != nil {
|
|
if err == metadata.ErrValueNotSet {
|
|
if _, ok := item.ItemType.(*metadata.StringType); ok {
|
|
cfgValue = ""
|
|
}
|
|
if _, ok := item.ItemType.(*metadata.NonEmptyStringType); ok {
|
|
cfgValue = ""
|
|
}
|
|
} else {
|
|
log.Errorf("Failed to get Value of key %v, error %v", item.Name, err)
|
|
continue
|
|
}
|
|
}
|
|
resultMap[item.Name] = cfgValue
|
|
}
|
|
}
|
|
return resultMap
|
|
}
|
|
|
|
// Load load configuration from storage, like database or redis
|
|
func (c *CfgManager) Load(ctx context.Context) error {
|
|
return c.Store.Load(ctx)
|
|
}
|
|
|
|
// Save - Save all current configuration to storage
|
|
func (c *CfgManager) Save(ctx context.Context) error {
|
|
return c.Store.Save(ctx)
|
|
}
|
|
|
|
// Get ...
|
|
func (c *CfgManager) Get(_ context.Context, key string) *metadata.ConfigureValue {
|
|
configValue, err := c.Store.Get(key)
|
|
if err != nil {
|
|
log.Debugf("failed to get key %v, error: %v, maybe default value not defined before get", key, err)
|
|
configValue = &metadata.ConfigureValue{}
|
|
}
|
|
return configValue
|
|
}
|
|
|
|
// Set ...
|
|
func (c *CfgManager) Set(_ context.Context, key string, value interface{}) {
|
|
configValue, err := metadata.NewCfgValue(key, utils.GetStrValueOfAnyType(value))
|
|
if err != nil {
|
|
log.Errorf("error when setting key: %v, error %v", key, err)
|
|
return
|
|
}
|
|
_ = c.Store.Set(key, *configValue)
|
|
}
|
|
|
|
// GetDatabaseCfg - Get database configurations
|
|
func (c *CfgManager) GetDatabaseCfg() *models.Database {
|
|
ctx := context.Background()
|
|
return &models.Database{
|
|
Type: c.Get(ctx, common.DatabaseType).GetString(),
|
|
PostGreSQL: &models.PostGreSQL{
|
|
Host: c.Get(ctx, common.PostGreSQLHOST).GetString(),
|
|
Port: c.Get(ctx, common.PostGreSQLPort).GetInt(),
|
|
Username: c.Get(ctx, common.PostGreSQLUsername).GetString(),
|
|
Password: c.Get(ctx, common.PostGreSQLPassword).GetString(),
|
|
Database: c.Get(ctx, common.PostGreSQLDatabase).GetString(),
|
|
SSLMode: c.Get(ctx, common.PostGreSQLSSLMode).GetString(),
|
|
MaxIdleConns: c.Get(ctx, common.PostGreSQLMaxIdleConns).GetInt(),
|
|
MaxOpenConns: c.Get(ctx, common.PostGreSQLMaxOpenConns).GetInt(),
|
|
ConnMaxLifetime: c.Get(ctx, common.PostGreSQLConnMaxLifetime).GetDuration(),
|
|
ConnMaxIdleTime: c.Get(ctx, common.PostGreSQLConnMaxIdleTime).GetDuration(),
|
|
},
|
|
}
|
|
}
|
|
|
|
// UpdateConfig - Update config Store with a specified configuration and also save updated configure.
|
|
func (c *CfgManager) UpdateConfig(ctx context.Context, cfgs map[string]interface{}) error {
|
|
return c.Store.Update(ctx, cfgs)
|
|
}
|
|
|
|
// ValidateCfg validate config by metadata. return the first error if exist.
|
|
func (c *CfgManager) ValidateCfg(ctx context.Context, cfgs map[string]interface{}) error {
|
|
for key, value := range cfgs {
|
|
item, exist := metadata.Instance().GetByName(key)
|
|
if !exist {
|
|
return fmt.Errorf("invalid config, item not defined in metadatalist, %v", key)
|
|
}
|
|
if item.Scope == metadata.SystemScope {
|
|
return fmt.Errorf("system config items cannot be updated, item: %v", key)
|
|
}
|
|
|
|
strVal := utils.GetStrValueOfAnyType(value)
|
|
|
|
// check storage per project before setting it
|
|
if key == common.StoragePerProject {
|
|
storagePerProject, err := strconv.ParseInt(strVal, 10, 64)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot parse string value(%v) to int64", strVal)
|
|
}
|
|
|
|
if err := lib.ValidateQuotaLimit(storagePerProject); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
_, err := metadata.NewCfgValue(key, strVal)
|
|
if err != nil {
|
|
return errors.Wrap(err, "item name "+key)
|
|
}
|
|
}
|
|
|
|
for _, r := range validateRules {
|
|
if err := r.Validate(ctx, c, cfgs); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|