diff options
Diffstat (limited to 'modules/setting/storage.go')
-rw-r--r-- | modules/setting/storage.go | 209 |
1 files changed, 152 insertions, 57 deletions
diff --git a/modules/setting/storage.go b/modules/setting/storage.go index 6da52807ec..ed804a910a 100644 --- a/modules/setting/storage.go +++ b/modules/setting/storage.go @@ -4,87 +4,182 @@ package setting import ( + "errors" + "fmt" "path/filepath" - "reflect" ) +// StorageType is a type of Storage +type StorageType string + +const ( + // LocalStorageType is the type descriptor for local storage + LocalStorageType StorageType = "local" + // MinioStorageType is the type descriptor for minio storage + MinioStorageType StorageType = "minio" +) + +var storageTypes = []StorageType{ + LocalStorageType, + MinioStorageType, +} + +// IsValidStorageType returns true if the given storage type is valid +func IsValidStorageType(storageType StorageType) bool { + for _, t := range storageTypes { + if t == storageType { + return true + } + } + return false +} + +// MinioStorageConfig represents the configuration for a minio storage +type MinioStorageConfig struct { + Endpoint string `ini:"MINIO_ENDPOINT" json:",omitempty"` + AccessKeyID string `ini:"MINIO_ACCESS_KEY_ID" json:",omitempty"` + SecretAccessKey string `ini:"MINIO_SECRET_ACCESS_KEY" json:",omitempty"` + Bucket string `ini:"MINIO_BUCKET" json:",omitempty"` + Location string `ini:"MINIO_LOCATION" json:",omitempty"` + BasePath string `ini:"MINIO_BASE_PATH" json:",omitempty"` + UseSSL bool `ini:"MINIO_USE_SSL"` + InsecureSkipVerify bool `ini:"MINIO_INSECURE_SKIP_VERIFY"` + ChecksumAlgorithm string `ini:"MINIO_CHECKSUM_ALGORITHM" json:",omitempty"` + ServeDirect bool `ini:"SERVE_DIRECT"` +} + // Storage represents configuration of storages type Storage struct { - Type string - Path string - Section ConfigSection - ServeDirect bool + Type StorageType // local or minio + Path string `json:",omitempty"` // for local type + TemporaryPath string `json:",omitempty"` + MinioConfig MinioStorageConfig // for minio type } -// MapTo implements the Mappable interface -func (s *Storage) MapTo(v interface{}) error { - pathValue := reflect.ValueOf(v).Elem().FieldByName("Path") - if pathValue.IsValid() && pathValue.Kind() == reflect.String { - pathValue.SetString(s.Path) +func (storage *Storage) ToShadowCopy() Storage { + shadowStorage := *storage + if shadowStorage.MinioConfig.AccessKeyID != "" { + shadowStorage.MinioConfig.AccessKeyID = "******" } - if s.Section != nil { - return s.Section.MapTo(v) + if shadowStorage.MinioConfig.SecretAccessKey != "" { + shadowStorage.MinioConfig.SecretAccessKey = "******" } - return nil + return shadowStorage } -func getStorage(rootCfg ConfigProvider, name, typ string, targetSec ConfigSection) Storage { - const sectionName = "storage" - sec := rootCfg.Section(sectionName) +const storageSectionName = "storage" +func getDefaultStorageSection(rootCfg ConfigProvider) ConfigSection { + storageSec := rootCfg.Section(storageSectionName) // Global Defaults - sec.Key("MINIO_ENDPOINT").MustString("localhost:9000") - sec.Key("MINIO_ACCESS_KEY_ID").MustString("") - sec.Key("MINIO_SECRET_ACCESS_KEY").MustString("") - sec.Key("MINIO_BUCKET").MustString("gitea") - sec.Key("MINIO_LOCATION").MustString("us-east-1") - sec.Key("MINIO_USE_SSL").MustBool(false) - sec.Key("MINIO_INSECURE_SKIP_VERIFY").MustBool(false) - sec.Key("MINIO_CHECKSUM_ALGORITHM").MustString("default") + storageSec.Key("STORAGE_TYPE").MustString("local") + storageSec.Key("MINIO_ENDPOINT").MustString("localhost:9000") + storageSec.Key("MINIO_ACCESS_KEY_ID").MustString("") + storageSec.Key("MINIO_SECRET_ACCESS_KEY").MustString("") + storageSec.Key("MINIO_BUCKET").MustString("gitea") + storageSec.Key("MINIO_LOCATION").MustString("us-east-1") + storageSec.Key("MINIO_USE_SSL").MustBool(false) + storageSec.Key("MINIO_INSECURE_SKIP_VERIFY").MustBool(false) + storageSec.Key("MINIO_CHECKSUM_ALGORITHM").MustString("default") + return storageSec +} - if targetSec == nil { - targetSec, _ = rootCfg.NewSection(name) +func getStorage(rootCfg ConfigProvider, name, typ string, sec ConfigSection) (*Storage, error) { + if name == "" { + return nil, errors.New("no name for storage") } - var storage Storage - storage.Section = targetSec - storage.Type = typ - - overrides := make([]ConfigSection, 0, 3) - nameSec, err := rootCfg.GetSection(sectionName + "." + name) - if err == nil { - overrides = append(overrides, nameSec) + var targetSec ConfigSection + if typ != "" { + var err error + targetSec, err = rootCfg.GetSection(storageSectionName + "." + typ) + if err != nil { + if !IsValidStorageType(StorageType(typ)) { + return nil, fmt.Errorf("get section via storage type %q failed: %v", typ, err) + } + } + if targetSec != nil { + targetType := targetSec.Key("STORAGE_TYPE").String() + if targetType == "" { + if !IsValidStorageType(StorageType(typ)) { + return nil, fmt.Errorf("unknow storage type %q", typ) + } + targetSec.Key("STORAGE_TYPE").SetValue(typ) + } else if !IsValidStorageType(StorageType(targetType)) { + return nil, fmt.Errorf("unknow storage type %q for section storage.%v", targetType, typ) + } + } } - typeSec, err := rootCfg.GetSection(sectionName + "." + typ) - if err == nil { - overrides = append(overrides, typeSec) - nextType := typeSec.Key("STORAGE_TYPE").String() - if len(nextType) > 0 { - storage.Type = nextType // Support custom STORAGE_TYPE + storageNameSec, _ := rootCfg.GetSection(storageSectionName + "." + name) + + if targetSec == nil { + targetSec = sec + } + if targetSec == nil { + targetSec = storageNameSec + } + if targetSec == nil { + targetSec = getDefaultStorageSection(rootCfg) + } else { + targetType := targetSec.Key("STORAGE_TYPE").String() + switch { + case targetType == "": + if targetSec.Key("PATH").String() == "" { + targetSec = getDefaultStorageSection(rootCfg) + } else { + targetSec.Key("STORAGE_TYPE").SetValue("local") + } + default: + newTargetSec, _ := rootCfg.GetSection(storageSectionName + "." + targetType) + if newTargetSec == nil { + if !IsValidStorageType(StorageType(targetType)) { + return nil, fmt.Errorf("invalid storage section %s.%q", storageSectionName, targetType) + } + } else { + targetSec = newTargetSec + if IsValidStorageType(StorageType(targetType)) { + tp := targetSec.Key("STORAGE_TYPE").String() + if tp == "" { + targetSec.Key("STORAGE_TYPE").SetValue(targetType) + } + } + } } } - overrides = append(overrides, sec) - for _, override := range overrides { - for _, key := range override.Keys() { - if !targetSec.HasKey(key.Name()) { - _, _ = targetSec.NewKey(key.Name(), key.Value()) - } + targetType := targetSec.Key("STORAGE_TYPE").String() + if !IsValidStorageType(StorageType(targetType)) { + return nil, fmt.Errorf("invalid storage type %q", targetType) + } + + var storage Storage + storage.Type = StorageType(targetType) + + switch targetType { + case string(LocalStorageType): + storage.Path = ConfigSectionKeyString(targetSec, "PATH", filepath.Join(AppDataPath, name)) + if !filepath.IsAbs(storage.Path) { + storage.Path = filepath.Join(AppWorkPath, storage.Path) } - if len(storage.Type) == 0 { - storage.Type = override.Key("STORAGE_TYPE").String() + case string(MinioStorageType): + storage.MinioConfig.BasePath = name + "/" + + if err := targetSec.MapTo(&storage.MinioConfig); err != nil { + return nil, fmt.Errorf("map minio config failed: %v", err) + } + // extra config section will be read SERVE_DIRECT, PATH, MINIO_BASE_PATH to override the targetsec + extraConfigSec := sec + if extraConfigSec == nil { + extraConfigSec = storageNameSec } - } - storage.ServeDirect = storage.Section.Key("SERVE_DIRECT").MustBool(false) - // Specific defaults - storage.Path = storage.Section.Key("PATH").MustString(filepath.Join(AppDataPath, name)) - if !filepath.IsAbs(storage.Path) { - storage.Path = filepath.Join(AppWorkPath, storage.Path) - storage.Section.Key("PATH").SetValue(storage.Path) + if extraConfigSec != nil { + storage.MinioConfig.ServeDirect = ConfigSectionKeyBool(extraConfigSec, "SERVE_DIRECT", storage.MinioConfig.ServeDirect) + storage.MinioConfig.BasePath = ConfigSectionKeyString(extraConfigSec, "MINIO_BASE_PATH", storage.MinioConfig.BasePath) + storage.MinioConfig.Bucket = ConfigSectionKeyString(extraConfigSec, "MINIO_BUCKET", storage.MinioConfig.Bucket) + } } - storage.Section.Key("MINIO_BASE_PATH").MustString(name + "/") - return storage + return &storage, nil } |