Fix all possible setting error related storages and added some tests (#23911)

Follow up #22405

Fix #20703 

This PR rewrites storage configuration read sequences with some breaks
and tests. It becomes more strict than before and also fixed some
inherit problems.

- Move storage's MinioConfig struct into setting, so after the
configuration loading, the values will be stored into the struct but not
still on some section.
- All storages configurations should be stored on one section,
configuration items cannot be overrided by multiple sections. The
prioioty of configuration is `[attachment]` > `[storage.attachments]` |
`[storage.customized]` > `[storage]` > `default`
- For extra override configuration items, currently are `SERVE_DIRECT`,
`MINIO_BASE_PATH`, `MINIO_BUCKET`, which could be configured in another
section. The prioioty of the override configuration is `[attachment]` >
`[storage.attachments]` > `default`.
- Add more tests for storages configurations.
- Update the storage documentations.

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
Lunny Xiao 2023-06-14 11:42:38 +08:00 committed by GitHub
parent dc0a7168f1
commit d6dd6d641b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 1152 additions and 452 deletions

View file

@ -4,14 +4,14 @@
package setting
import (
"code.gitea.io/gitea/modules/log"
"fmt"
)
// Actions settings
var (
Actions = struct {
LogStorage Storage // how the created logs should be stored
ArtifactStorage Storage // how the created artifacts should be stored
LogStorage *Storage // how the created logs should be stored
ArtifactStorage *Storage // how the created artifacts should be stored
Enabled bool
DefaultActionsURL string `ini:"DEFAULT_ACTIONS_URL"`
}{
@ -20,15 +20,22 @@ var (
}
)
func loadActionsFrom(rootCfg ConfigProvider) {
func loadActionsFrom(rootCfg ConfigProvider) error {
sec := rootCfg.Section("actions")
if err := sec.MapTo(&Actions); err != nil {
log.Fatal("Failed to map Actions settings: %v", err)
err := sec.MapTo(&Actions)
if err != nil {
return fmt.Errorf("failed to map Actions settings: %v", err)
}
actionsSec := rootCfg.Section("actions.artifacts")
storageType := actionsSec.Key("STORAGE_TYPE").MustString("")
// don't support to read configuration from [actions]
Actions.LogStorage, err = getStorage(rootCfg, "actions_log", "", nil)
if err != nil {
return err
}
Actions.LogStorage = getStorage(rootCfg, "actions_log", "", nil)
Actions.ArtifactStorage = getStorage(rootCfg, "actions_artifacts", storageType, actionsSec)
actionsSec, _ := rootCfg.GetSection("actions.artifacts")
Actions.ArtifactStorage, err = getStorage(rootCfg, "actions_artifacts", "", actionsSec)
return err
}

View file

@ -0,0 +1,97 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package setting
import (
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
)
func Test_getStorageInheritNameSectionTypeForActions(t *testing.T) {
iniStr := `
[storage]
STORAGE_TYPE = minio
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadActionsFrom(cfg))
assert.EqualValues(t, "minio", Actions.LogStorage.Type)
assert.EqualValues(t, "actions_log/", Actions.LogStorage.MinioConfig.BasePath)
assert.EqualValues(t, "minio", Actions.ArtifactStorage.Type)
assert.EqualValues(t, "actions_artifacts/", Actions.ArtifactStorage.MinioConfig.BasePath)
iniStr = `
[storage.actions_log]
STORAGE_TYPE = minio
`
cfg, err = NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadActionsFrom(cfg))
assert.EqualValues(t, "minio", Actions.LogStorage.Type)
assert.EqualValues(t, "actions_log/", Actions.LogStorage.MinioConfig.BasePath)
assert.EqualValues(t, "local", Actions.ArtifactStorage.Type)
assert.EqualValues(t, "actions_artifacts", filepath.Base(Actions.ArtifactStorage.Path))
iniStr = `
[storage.actions_log]
STORAGE_TYPE = my_storage
[storage.my_storage]
STORAGE_TYPE = minio
`
cfg, err = NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadActionsFrom(cfg))
assert.EqualValues(t, "minio", Actions.LogStorage.Type)
assert.EqualValues(t, "actions_log/", Actions.LogStorage.MinioConfig.BasePath)
assert.EqualValues(t, "local", Actions.ArtifactStorage.Type)
assert.EqualValues(t, "actions_artifacts", filepath.Base(Actions.ArtifactStorage.Path))
iniStr = `
[storage.actions_artifacts]
STORAGE_TYPE = my_storage
[storage.my_storage]
STORAGE_TYPE = minio
`
cfg, err = NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadActionsFrom(cfg))
assert.EqualValues(t, "local", Actions.LogStorage.Type)
assert.EqualValues(t, "actions_log", filepath.Base(Actions.LogStorage.Path))
assert.EqualValues(t, "minio", Actions.ArtifactStorage.Type)
assert.EqualValues(t, "actions_artifacts/", Actions.ArtifactStorage.MinioConfig.BasePath)
iniStr = `
[storage.actions_artifacts]
STORAGE_TYPE = my_storage
[storage.my_storage]
STORAGE_TYPE = minio
`
cfg, err = NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadActionsFrom(cfg))
assert.EqualValues(t, "local", Actions.LogStorage.Type)
assert.EqualValues(t, "actions_log", filepath.Base(Actions.LogStorage.Path))
assert.EqualValues(t, "minio", Actions.ArtifactStorage.Type)
assert.EqualValues(t, "actions_artifacts/", Actions.ArtifactStorage.MinioConfig.BasePath)
iniStr = ``
cfg, err = NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadActionsFrom(cfg))
assert.EqualValues(t, "local", Actions.LogStorage.Type)
assert.EqualValues(t, "actions_log", filepath.Base(Actions.LogStorage.Path))
assert.EqualValues(t, "local", Actions.ArtifactStorage.Type)
assert.EqualValues(t, "actions_artifacts", filepath.Base(Actions.ArtifactStorage.Path))
}

View file

@ -5,29 +5,31 @@ package setting
// Attachment settings
var Attachment = struct {
Storage
Storage *Storage
AllowedTypes string
MaxSize int64
MaxFiles int
Enabled bool
}{
Storage: Storage{
ServeDirect: false,
},
AllowedTypes: "image/jpeg,image/png,application/zip,application/gzip",
Storage: &Storage{},
AllowedTypes: ".csv,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip",
MaxSize: 4,
MaxFiles: 5,
Enabled: true,
}
func loadAttachmentFrom(rootCfg ConfigProvider) {
sec := rootCfg.Section("attachment")
storageType := sec.Key("STORAGE_TYPE").MustString("")
Attachment.Storage = getStorage(rootCfg, "attachments", storageType, sec)
func loadAttachmentFrom(rootCfg ConfigProvider) (err error) {
sec, _ := rootCfg.GetSection("attachment")
if sec == nil {
Attachment.Storage, err = getStorage(rootCfg, "attachments", "", nil)
return err
}
Attachment.AllowedTypes = sec.Key("ALLOWED_TYPES").MustString(".csv,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip")
Attachment.MaxSize = sec.Key("MAX_SIZE").MustInt64(4)
Attachment.MaxFiles = sec.Key("MAX_FILES").MustInt(5)
Attachment.Enabled = sec.Key("ENABLED").MustBool(true)
Attachment.Storage, err = getStorage(rootCfg, "attachments", "", sec)
return err
}

View file

@ -0,0 +1,133 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package setting
import (
"testing"
"github.com/stretchr/testify/assert"
)
func Test_getStorageCustomType(t *testing.T) {
iniStr := `
[attachment]
STORAGE_TYPE = my_minio
MINIO_BUCKET = gitea-attachment
[storage.my_minio]
STORAGE_TYPE = minio
MINIO_ENDPOINT = my_minio:9000
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadAttachmentFrom(cfg))
assert.EqualValues(t, "minio", Attachment.Storage.Type)
assert.EqualValues(t, "my_minio:9000", Attachment.Storage.MinioConfig.Endpoint)
assert.EqualValues(t, "gitea-attachment", Attachment.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "attachments/", Attachment.Storage.MinioConfig.BasePath)
}
func Test_getStorageTypeSectionOverridesStorageSection(t *testing.T) {
iniStr := `
[attachment]
STORAGE_TYPE = minio
[storage.minio]
MINIO_BUCKET = gitea-minio
[storage]
MINIO_BUCKET = gitea
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadAttachmentFrom(cfg))
assert.EqualValues(t, "minio", Attachment.Storage.Type)
assert.EqualValues(t, "gitea-minio", Attachment.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "attachments/", Attachment.Storage.MinioConfig.BasePath)
}
func Test_getStorageSpecificOverridesStorage(t *testing.T) {
iniStr := `
[attachment]
STORAGE_TYPE = minio
MINIO_BUCKET = gitea-attachment
[storage.attachments]
MINIO_BUCKET = gitea
[storage]
STORAGE_TYPE = local
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadAttachmentFrom(cfg))
assert.EqualValues(t, "minio", Attachment.Storage.Type)
assert.EqualValues(t, "gitea-attachment", Attachment.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "attachments/", Attachment.Storage.MinioConfig.BasePath)
}
func Test_getStorageGetDefaults(t *testing.T) {
cfg, err := NewConfigProviderFromData("")
assert.NoError(t, err)
assert.NoError(t, loadAttachmentFrom(cfg))
// default storage is local, so bucket is empty
assert.EqualValues(t, "", Attachment.Storage.MinioConfig.Bucket)
}
func Test_getStorageInheritNameSectionType(t *testing.T) {
iniStr := `
[storage.attachments]
STORAGE_TYPE = minio
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadAttachmentFrom(cfg))
assert.EqualValues(t, "minio", Attachment.Storage.Type)
}
func Test_AttachmentStorage(t *testing.T) {
iniStr := `
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[storage]
STORAGE_TYPE = minio
MINIO_ENDPOINT = s3.my-domain.net
MINIO_BUCKET = gitea
MINIO_LOCATION = homenet
MINIO_USE_SSL = true
MINIO_ACCESS_KEY_ID = correct_key
MINIO_SECRET_ACCESS_KEY = correct_key
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadAttachmentFrom(cfg))
storage := Attachment.Storage
assert.EqualValues(t, "minio", storage.Type)
assert.EqualValues(t, "gitea", storage.MinioConfig.Bucket)
}
func Test_AttachmentStorage1(t *testing.T) {
iniStr := `
[storage]
STORAGE_TYPE = minio
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadAttachmentFrom(cfg))
assert.EqualValues(t, "minio", Attachment.Storage.Type)
assert.EqualValues(t, "gitea", Attachment.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "attachments/", Attachment.Storage.MinioConfig.BasePath)
}

View file

@ -7,6 +7,7 @@ import (
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
"time"
@ -95,6 +96,18 @@ func ConfigSectionKeyString(sec ConfigSection, key string, def ...string) string
return ""
}
func ConfigSectionKeyBool(sec ConfigSection, key string, def ...bool) bool {
k := ConfigSectionKey(sec, key)
if k != nil && k.String() != "" {
b, _ := strconv.ParseBool(k.String())
return b
}
if len(def) > 0 {
return def[0]
}
return false
}
// ConfigInheritedKey works like ini.Section.Key(), but it always returns a new key instance, it is O(n) because NewKey is O(n)
// and the returned key is safe to be used with "MustXxx", it doesn't change the parent's values.
// Otherwise, ini.Section.Key().MustXxx would pollute the parent section's keys.
@ -287,6 +300,12 @@ func deprecatedSetting(rootCfg ConfigProvider, oldSection, oldKey, newSection, n
}
}
func deprecatedSettingFatal(rootCfg ConfigProvider, oldSection, oldKey, newSection, newKey, version string) {
if rootCfg.Section(oldSection).HasKey(oldKey) {
log.Fatal("Deprecated fallback `[%s]` `%s` present. Use `[%s]` `%s` instead. This fallback will be/has been removed in %s", oldSection, oldKey, newSection, newKey, version)
}
}
// deprecatedSettingDB add a hint that the configuration has been moved to database but still kept in app.ini
func deprecatedSettingDB(rootCfg ConfigProvider, oldSection, oldKey string) {
if rootCfg.Section(oldSection).HasKey(oldKey) {

View file

@ -5,10 +5,10 @@ package setting
import (
"encoding/base64"
"fmt"
"time"
"code.gitea.io/gitea/modules/generate"
"code.gitea.io/gitea/modules/log"
)
// LFS represents the configuration for Git LFS
@ -20,25 +20,27 @@ var LFS = struct {
MaxFileSize int64 `ini:"LFS_MAX_FILE_SIZE"`
LocksPagingNum int `ini:"LFS_LOCKS_PAGING_NUM"`
Storage
Storage *Storage
}{}
func loadLFSFrom(rootCfg ConfigProvider) {
func loadLFSFrom(rootCfg ConfigProvider) error {
sec := rootCfg.Section("server")
if err := sec.MapTo(&LFS); err != nil {
log.Fatal("Failed to map LFS settings: %v", err)
return fmt.Errorf("failed to map LFS settings: %v", err)
}
lfsSec := rootCfg.Section("lfs")
storageType := lfsSec.Key("STORAGE_TYPE").MustString("")
lfsSec, _ := rootCfg.GetSection("lfs")
// Specifically default PATH to LFS_CONTENT_PATH
// DEPRECATED should not be removed because users maybe upgrade from lower version to the latest version
// if these are removed, the warning will not be shown
deprecatedSetting(rootCfg, "server", "LFS_CONTENT_PATH", "lfs", "PATH", "v1.19.0")
lfsSec.Key("PATH").MustString(sec.Key("LFS_CONTENT_PATH").String())
deprecatedSettingFatal(rootCfg, "server", "LFS_CONTENT_PATH", "lfs", "PATH", "v1.19.0")
LFS.Storage = getStorage(rootCfg, "lfs", storageType, lfsSec)
var err error
LFS.Storage, err = getStorage(rootCfg, "lfs", "", lfsSec)
if err != nil {
return err
}
// Rest of LFS service settings
if LFS.LocksPagingNum == 0 {
@ -47,23 +49,25 @@ func loadLFSFrom(rootCfg ConfigProvider) {
LFS.HTTPAuthExpiry = sec.Key("LFS_HTTP_AUTH_EXPIRY").MustDuration(24 * time.Hour)
if LFS.StartServer {
LFS.JWTSecretBytes = make([]byte, 32)
n, err := base64.RawURLEncoding.Decode(LFS.JWTSecretBytes, []byte(LFS.JWTSecretBase64))
if !LFS.StartServer {
return nil
}
if err != nil || n != 32 {
LFS.JWTSecretBase64, err = generate.NewJwtSecretBase64()
if err != nil {
log.Fatal("Error generating JWT Secret for custom config: %v", err)
return
}
LFS.JWTSecretBytes = make([]byte, 32)
n, err := base64.RawURLEncoding.Decode(LFS.JWTSecretBytes, []byte(LFS.JWTSecretBase64))
// Save secret
sec.Key("LFS_JWT_SECRET").SetValue(LFS.JWTSecretBase64)
if err := rootCfg.Save(); err != nil {
log.Fatal("Error saving JWT Secret for custom config: %v", err)
return
}
if err != nil || n != 32 {
LFS.JWTSecretBase64, err = generate.NewJwtSecretBase64()
if err != nil {
return fmt.Errorf("Error generating JWT Secret for custom config: %v", err)
}
// Save secret
sec.Key("LFS_JWT_SECRET").SetValue(LFS.JWTSecretBase64)
if err := rootCfg.Save(); err != nil {
return fmt.Errorf("Error saving JWT Secret for custom config: %v", err)
}
}
return nil
}

View file

@ -0,0 +1,77 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package setting
import (
"testing"
"github.com/stretchr/testify/assert"
)
func Test_getStorageInheritNameSectionTypeForLFS(t *testing.T) {
iniStr := `
[storage]
STORAGE_TYPE = minio
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadLFSFrom(cfg))
assert.EqualValues(t, "minio", LFS.Storage.Type)
assert.EqualValues(t, "lfs/", LFS.Storage.MinioConfig.BasePath)
iniStr = `
[storage.lfs]
STORAGE_TYPE = minio
`
cfg, err = NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadLFSFrom(cfg))
assert.EqualValues(t, "minio", LFS.Storage.Type)
assert.EqualValues(t, "lfs/", LFS.Storage.MinioConfig.BasePath)
iniStr = `
[lfs]
STORAGE_TYPE = my_minio
[storage.my_minio]
STORAGE_TYPE = minio
`
cfg, err = NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadLFSFrom(cfg))
assert.EqualValues(t, "minio", LFS.Storage.Type)
assert.EqualValues(t, "lfs/", LFS.Storage.MinioConfig.BasePath)
iniStr = `
[lfs]
STORAGE_TYPE = my_minio
MINIO_BASE_PATH = my_lfs/
[storage.my_minio]
STORAGE_TYPE = minio
`
cfg, err = NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadLFSFrom(cfg))
assert.EqualValues(t, "minio", LFS.Storage.Type)
assert.EqualValues(t, "my_lfs/", LFS.Storage.MinioConfig.BasePath)
}
func Test_LFSStorage1(t *testing.T) {
iniStr := `
[storage]
STORAGE_TYPE = minio
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadLFSFrom(cfg))
assert.EqualValues(t, "minio", LFS.Storage.Type)
assert.EqualValues(t, "gitea", LFS.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "lfs/", LFS.Storage.MinioConfig.BasePath)
}

View file

@ -4,20 +4,19 @@
package setting
import (
"fmt"
"math"
"net/url"
"os"
"path/filepath"
"code.gitea.io/gitea/modules/log"
"github.com/dustin/go-humanize"
)
// Package registry settings
var (
Packages = struct {
Storage
Storage *Storage
Enabled bool
ChunkedUploadPath string
RegistryHost string
@ -51,13 +50,21 @@ var (
}
)
func loadPackagesFrom(rootCfg ConfigProvider) {
sec := rootCfg.Section("packages")
if err := sec.MapTo(&Packages); err != nil {
log.Fatal("Failed to map Packages settings: %v", err)
func loadPackagesFrom(rootCfg ConfigProvider) (err error) {
sec, _ := rootCfg.GetSection("packages")
if sec == nil {
Packages.Storage, err = getStorage(rootCfg, "packages", "", nil)
return err
}
Packages.Storage = getStorage(rootCfg, "packages", "", nil)
if err = sec.MapTo(&Packages); err != nil {
return fmt.Errorf("failed to map Packages settings: %v", err)
}
Packages.Storage, err = getStorage(rootCfg, "packages", "", sec)
if err != nil {
return err
}
appURL, _ := url.Parse(AppURL)
Packages.RegistryHost = appURL.Host
@ -68,7 +75,7 @@ func loadPackagesFrom(rootCfg ConfigProvider) {
}
if err := os.MkdirAll(Packages.ChunkedUploadPath, os.ModePerm); err != nil {
log.Error("Unable to create chunked upload directory: %s (%v)", Packages.ChunkedUploadPath, err)
return fmt.Errorf("unable to create chunked upload directory: %s (%v)", Packages.ChunkedUploadPath, err)
}
Packages.LimitTotalOwnerSize = mustBytes(sec, "LIMIT_TOTAL_OWNER_SIZE")
@ -93,6 +100,7 @@ func loadPackagesFrom(rootCfg ConfigProvider) {
Packages.LimitSizeRubyGems = mustBytes(sec, "LIMIT_SIZE_RUBYGEMS")
Packages.LimitSizeSwift = mustBytes(sec, "LIMIT_SIZE_SWIFT")
Packages.LimitSizeVagrant = mustBytes(sec, "LIMIT_SIZE_VAGRANT")
return nil
}
func mustBytes(section ConfigSection, key string) int64 {

View file

@ -29,3 +29,170 @@ func TestMustBytes(t *testing.T) {
assert.EqualValues(t, 1782579, test("1.7mib"))
assert.EqualValues(t, -1, test("1 yib")) // too large
}
func Test_getStorageInheritNameSectionTypeForPackages(t *testing.T) {
// packages storage inherits from storage if nothing configured
iniStr := `
[storage]
STORAGE_TYPE = minio
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadPackagesFrom(cfg))
assert.EqualValues(t, "minio", Packages.Storage.Type)
assert.EqualValues(t, "packages/", Packages.Storage.MinioConfig.BasePath)
// we can also configure packages storage directly
iniStr = `
[storage.packages]
STORAGE_TYPE = minio
`
cfg, err = NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadPackagesFrom(cfg))
assert.EqualValues(t, "minio", Packages.Storage.Type)
assert.EqualValues(t, "packages/", Packages.Storage.MinioConfig.BasePath)
// or we can indicate the storage type in the packages section
iniStr = `
[packages]
STORAGE_TYPE = my_minio
[storage.my_minio]
STORAGE_TYPE = minio
`
cfg, err = NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadPackagesFrom(cfg))
assert.EqualValues(t, "minio", Packages.Storage.Type)
assert.EqualValues(t, "packages/", Packages.Storage.MinioConfig.BasePath)
// or we can indicate the storage type and minio base path in the packages section
iniStr = `
[packages]
STORAGE_TYPE = my_minio
MINIO_BASE_PATH = my_packages/
[storage.my_minio]
STORAGE_TYPE = minio
`
cfg, err = NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadPackagesFrom(cfg))
assert.EqualValues(t, "minio", Packages.Storage.Type)
assert.EqualValues(t, "my_packages/", Packages.Storage.MinioConfig.BasePath)
}
func Test_PackageStorage1(t *testing.T) {
iniStr := `
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[packages]
MINIO_BASE_PATH = packages/
SERVE_DIRECT = true
[storage]
STORAGE_TYPE = minio
MINIO_ENDPOINT = s3.my-domain.net
MINIO_BUCKET = gitea
MINIO_LOCATION = homenet
MINIO_USE_SSL = true
MINIO_ACCESS_KEY_ID = correct_key
MINIO_SECRET_ACCESS_KEY = correct_key
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadPackagesFrom(cfg))
storage := Packages.Storage
assert.EqualValues(t, "minio", storage.Type)
assert.EqualValues(t, "gitea", storage.MinioConfig.Bucket)
assert.EqualValues(t, "packages/", storage.MinioConfig.BasePath)
assert.True(t, storage.MinioConfig.ServeDirect)
}
func Test_PackageStorage2(t *testing.T) {
iniStr := `
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[storage.packages]
MINIO_BASE_PATH = packages/
SERVE_DIRECT = true
[storage]
STORAGE_TYPE = minio
MINIO_ENDPOINT = s3.my-domain.net
MINIO_BUCKET = gitea
MINIO_LOCATION = homenet
MINIO_USE_SSL = true
MINIO_ACCESS_KEY_ID = correct_key
MINIO_SECRET_ACCESS_KEY = correct_key
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadPackagesFrom(cfg))
storage := Packages.Storage
assert.EqualValues(t, "minio", storage.Type)
assert.EqualValues(t, "gitea", storage.MinioConfig.Bucket)
assert.EqualValues(t, "packages/", storage.MinioConfig.BasePath)
assert.True(t, storage.MinioConfig.ServeDirect)
}
func Test_PackageStorage3(t *testing.T) {
iniStr := `
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[packages]
STORAGE_TYPE = my_cfg
MINIO_BASE_PATH = my_packages/
SERVE_DIRECT = true
[storage.my_cfg]
STORAGE_TYPE = minio
MINIO_ENDPOINT = s3.my-domain.net
MINIO_BUCKET = gitea
MINIO_LOCATION = homenet
MINIO_USE_SSL = true
MINIO_ACCESS_KEY_ID = correct_key
MINIO_SECRET_ACCESS_KEY = correct_key
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadPackagesFrom(cfg))
storage := Packages.Storage
assert.EqualValues(t, "minio", storage.Type)
assert.EqualValues(t, "gitea", storage.MinioConfig.Bucket)
assert.EqualValues(t, "my_packages/", storage.MinioConfig.BasePath)
assert.True(t, storage.MinioConfig.ServeDirect)
}
func Test_PackageStorage4(t *testing.T) {
iniStr := `
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[storage.packages]
STORAGE_TYPE = my_cfg
MINIO_BASE_PATH = my_packages/
SERVE_DIRECT = true
[storage.my_cfg]
STORAGE_TYPE = minio
MINIO_ENDPOINT = s3.my-domain.net
MINIO_BUCKET = gitea
MINIO_LOCATION = homenet
MINIO_USE_SSL = true
MINIO_ACCESS_KEY_ID = correct_key
MINIO_SECRET_ACCESS_KEY = correct_key
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadPackagesFrom(cfg))
storage := Packages.Storage
assert.EqualValues(t, "minio", storage.Type)
assert.EqualValues(t, "gitea", storage.MinioConfig.Bucket)
assert.EqualValues(t, "my_packages/", storage.MinioConfig.BasePath)
assert.True(t, storage.MinioConfig.ServeDirect)
}

View file

@ -7,7 +7,7 @@ package setting
var (
Avatar = struct {
Storage
Storage *Storage
MaxWidth int
MaxHeight int
@ -27,23 +27,26 @@ var (
EnableFederatedAvatar bool // Depreciated: migrated to database
RepoAvatar = struct {
Storage
Storage *Storage
Fallback string
FallbackImage string
}{}
)
func loadPictureFrom(rootCfg ConfigProvider) {
func loadAvatarsFrom(rootCfg ConfigProvider) error {
sec := rootCfg.Section("picture")
avatarSec := rootCfg.Section("avatar")
storageType := sec.Key("AVATAR_STORAGE_TYPE").MustString("")
// Specifically default PATH to AVATAR_UPLOAD_PATH
avatarSec.Key("PATH").MustString(
sec.Key("AVATAR_UPLOAD_PATH").String())
avatarSec.Key("PATH").MustString(sec.Key("AVATAR_UPLOAD_PATH").String())
Avatar.Storage = getStorage(rootCfg, "avatars", storageType, avatarSec)
var err error
Avatar.Storage, err = getStorage(rootCfg, "avatars", storageType, avatarSec)
if err != nil {
return err
}
Avatar.MaxWidth = sec.Key("AVATAR_MAX_WIDTH").MustInt(4096)
Avatar.MaxHeight = sec.Key("AVATAR_MAX_HEIGHT").MustInt(4096)
@ -67,7 +70,7 @@ func loadPictureFrom(rootCfg ConfigProvider) {
EnableFederatedAvatar = sec.Key("ENABLE_FEDERATED_AVATAR").MustBool(GetDefaultEnableFederatedAvatar(DisableGravatar))
deprecatedSettingDB(rootCfg, "", "ENABLE_FEDERATED_AVATAR")
loadRepoAvatarFrom(rootCfg)
return nil
}
func GetDefaultDisableGravatar() bool {
@ -85,17 +88,22 @@ func GetDefaultEnableFederatedAvatar(disableGravatar bool) bool {
return v
}
func loadRepoAvatarFrom(rootCfg ConfigProvider) {
func loadRepoAvatarFrom(rootCfg ConfigProvider) error {
sec := rootCfg.Section("picture")
repoAvatarSec := rootCfg.Section("repo-avatar")
storageType := sec.Key("REPOSITORY_AVATAR_STORAGE_TYPE").MustString("")
// Specifically default PATH to AVATAR_UPLOAD_PATH
repoAvatarSec.Key("PATH").MustString(
sec.Key("REPOSITORY_AVATAR_UPLOAD_PATH").String())
repoAvatarSec.Key("PATH").MustString(sec.Key("REPOSITORY_AVATAR_UPLOAD_PATH").String())
RepoAvatar.Storage = getStorage(rootCfg, "repo-avatars", storageType, repoAvatarSec)
var err error
RepoAvatar.Storage, err = getStorage(rootCfg, "repo-avatars", storageType, repoAvatarSec)
if err != nil {
return err
}
RepoAvatar.Fallback = sec.Key("REPOSITORY_AVATAR_FALLBACK").MustString("none")
RepoAvatar.FallbackImage = sec.Key("REPOSITORY_AVATAR_FALLBACK_IMAGE").MustString(AppSubURL + "/assets/img/repo_default.png")
return nil
}

View file

@ -265,10 +265,6 @@ var (
}
RepoRootPath string
ScriptType = "bash"
RepoArchive = struct {
Storage
}{}
)
func loadRepositoryFrom(rootCfg ConfigProvider) {
@ -359,5 +355,7 @@ func loadRepositoryFrom(rootCfg ConfigProvider) {
Repository.Upload.TempPath = path.Join(AppWorkPath, Repository.Upload.TempPath)
}
RepoArchive.Storage = getStorage(rootCfg, "repo-archive", "", nil)
if err := loadRepoArchiveFrom(rootCfg); err != nil {
log.Fatal("loadRepoArchiveFrom: %v", err)
}
}

View file

@ -0,0 +1,25 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package setting
import "fmt"
var RepoArchive = struct {
Storage *Storage
}{}
func loadRepoArchiveFrom(rootCfg ConfigProvider) (err error) {
sec, _ := rootCfg.GetSection("repo-archive")
if sec == nil {
RepoArchive.Storage, err = getStorage(rootCfg, "repo-archive", "", nil)
return err
}
if err := sec.MapTo(&RepoArchive); err != nil {
return fmt.Errorf("mapto repoarchive failed: %v", err)
}
RepoArchive.Storage, err = getStorage(rootCfg, "repo-archive", "", sec)
return err
}

View file

@ -0,0 +1,111 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package setting
import (
"testing"
"github.com/stretchr/testify/assert"
)
func Test_getStorageInheritNameSectionTypeForRepoArchive(t *testing.T) {
// packages storage inherits from storage if nothing configured
iniStr := `
[storage]
STORAGE_TYPE = minio
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadRepoArchiveFrom(cfg))
assert.EqualValues(t, "minio", RepoArchive.Storage.Type)
assert.EqualValues(t, "repo-archive/", RepoArchive.Storage.MinioConfig.BasePath)
// we can also configure packages storage directly
iniStr = `
[storage.repo-archive]
STORAGE_TYPE = minio
`
cfg, err = NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadRepoArchiveFrom(cfg))
assert.EqualValues(t, "minio", RepoArchive.Storage.Type)
assert.EqualValues(t, "repo-archive/", RepoArchive.Storage.MinioConfig.BasePath)
// or we can indicate the storage type in the packages section
iniStr = `
[repo-archive]
STORAGE_TYPE = my_minio
[storage.my_minio]
STORAGE_TYPE = minio
`
cfg, err = NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadRepoArchiveFrom(cfg))
assert.EqualValues(t, "minio", RepoArchive.Storage.Type)
assert.EqualValues(t, "repo-archive/", RepoArchive.Storage.MinioConfig.BasePath)
// or we can indicate the storage type and minio base path in the packages section
iniStr = `
[repo-archive]
STORAGE_TYPE = my_minio
MINIO_BASE_PATH = my_archive/
[storage.my_minio]
STORAGE_TYPE = minio
`
cfg, err = NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadRepoArchiveFrom(cfg))
assert.EqualValues(t, "minio", RepoArchive.Storage.Type)
assert.EqualValues(t, "my_archive/", RepoArchive.Storage.MinioConfig.BasePath)
}
func Test_RepoArchiveStorage(t *testing.T) {
iniStr := `
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[storage]
STORAGE_TYPE = minio
MINIO_ENDPOINT = s3.my-domain.net
MINIO_BUCKET = gitea
MINIO_LOCATION = homenet
MINIO_USE_SSL = true
MINIO_ACCESS_KEY_ID = correct_key
MINIO_SECRET_ACCESS_KEY = correct_key
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadRepoArchiveFrom(cfg))
storage := RepoArchive.Storage
assert.EqualValues(t, "minio", storage.Type)
assert.EqualValues(t, "gitea", storage.MinioConfig.Bucket)
iniStr = `
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[storage.repo-archive]
STORAGE_TYPE = s3
[storage.s3]
STORAGE_TYPE = minio
MINIO_ENDPOINT = s3.my-domain.net
MINIO_BUCKET = gitea
MINIO_LOCATION = homenet
MINIO_USE_SSL = true
MINIO_ACCESS_KEY_ID = correct_key
MINIO_SECRET_ACCESS_KEY = correct_key
`
cfg, err = NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
assert.NoError(t, loadRepoArchiveFrom(cfg))
storage = RepoArchive.Storage
assert.EqualValues(t, "minio", storage.Type)
assert.EqualValues(t, "gitea", storage.MinioConfig.Bucket)
}

View file

@ -203,16 +203,18 @@ func Init(opts *Options) {
var err error
CfgProvider, err = NewConfigProviderFromFile(opts)
if err != nil {
log.Fatal("Init[%v]: %v", opts, err)
log.Fatal("newConfigProviderFromFile[%v]: %v", opts, err)
}
if !opts.DisableLoadCommonSettings {
loadCommonSettingsFrom(CfgProvider)
if err := loadCommonSettingsFrom(CfgProvider); err != nil {
log.Fatal("loadCommonSettingsFrom[%v]: %v", opts, err)
}
}
}
// loadCommonSettingsFrom loads common configurations from a configuration provider.
func loadCommonSettingsFrom(cfg ConfigProvider) {
// WARNING: don't change the sequence except you know what you are doing.
func loadCommonSettingsFrom(cfg ConfigProvider) error {
// WARNNING: don't change the sequence except you know what you are doing.
loadRunModeFrom(cfg)
loadLogGlobalFrom(cfg)
loadServerFrom(cfg)
@ -222,13 +224,26 @@ func loadCommonSettingsFrom(cfg ConfigProvider) {
loadOAuth2From(cfg)
loadSecurityFrom(cfg)
loadAttachmentFrom(cfg)
loadLFSFrom(cfg)
if err := loadAttachmentFrom(cfg); err != nil {
return err
}
if err := loadLFSFrom(cfg); err != nil {
return err
}
loadTimeFrom(cfg)
loadRepositoryFrom(cfg)
loadPictureFrom(cfg)
loadPackagesFrom(cfg)
loadActionsFrom(cfg)
if err := loadAvatarsFrom(cfg); err != nil {
return err
}
if err := loadRepoAvatarFrom(cfg); err != nil {
return err
}
if err := loadPackagesFrom(cfg); err != nil {
return err
}
if err := loadActionsFrom(cfg); err != nil {
return err
}
loadUIFrom(cfg)
loadAdminFrom(cfg)
loadAPIFrom(cfg)
@ -239,6 +254,7 @@ func loadCommonSettingsFrom(cfg ConfigProvider) {
loadMirrorFrom(cfg)
loadMarkupFrom(cfg)
loadOtherFrom(cfg)
return nil
}
func loadRunModeFrom(rootCfg ConfigProvider) {

View file

@ -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
}
func getStorage(rootCfg ConfigProvider, name, typ string, sec ConfigSection) (*Storage, error) {
if name == "" {
return nil, errors.New("no name for storage")
}
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)
}
}
}
storageNameSec, _ := rootCfg.GetSection(storageSectionName + "." + name)
if targetSec == nil {
targetSec, _ = rootCfg.NewSection(name)
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)
}
}
}
}
}
targetType := targetSec.Key("STORAGE_TYPE").String()
if !IsValidStorageType(StorageType(targetType)) {
return nil, fmt.Errorf("invalid storage type %q", targetType)
}
var storage Storage
storage.Section = targetSec
storage.Type = typ
storage.Type = StorageType(targetType)
overrides := make([]ConfigSection, 0, 3)
nameSec, err := rootCfg.GetSection(sectionName + "." + name)
if err == nil {
overrides = append(overrides, nameSec)
}
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)
}
case string(MinioStorageType):
storage.MinioConfig.BasePath = name + "/"
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
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
}
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)
}
}
overrides = append(overrides, sec)
for _, override := range overrides {
for _, key := range override.Keys() {
if !targetSec.HasKey(key.Name()) {
_, _ = targetSec.NewKey(key.Name(), key.Value())
}
}
if len(storage.Type) == 0 {
storage.Type = override.Key("STORAGE_TYPE").String()
}
}
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)
}
storage.Section.Key("MINIO_BASE_PATH").MustString(name + "/")
return storage
return &storage, nil
}

View file

@ -9,106 +9,6 @@ import (
"github.com/stretchr/testify/assert"
)
func Test_getStorageCustomType(t *testing.T) {
iniStr := `
[attachment]
STORAGE_TYPE = my_minio
MINIO_BUCKET = gitea-attachment
[storage.my_minio]
STORAGE_TYPE = minio
MINIO_ENDPOINT = my_minio:9000
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
sec := cfg.Section("attachment")
storageType := sec.Key("STORAGE_TYPE").MustString("")
storage := getStorage(cfg, "attachments", storageType, sec)
assert.EqualValues(t, "minio", storage.Type)
assert.EqualValues(t, "my_minio:9000", storage.Section.Key("MINIO_ENDPOINT").String())
assert.EqualValues(t, "gitea-attachment", storage.Section.Key("MINIO_BUCKET").String())
}
func Test_getStorageNameSectionOverridesTypeSection(t *testing.T) {
iniStr := `
[attachment]
STORAGE_TYPE = minio
[storage.attachments]
MINIO_BUCKET = gitea-attachment
[storage.minio]
MINIO_BUCKET = gitea
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
sec := cfg.Section("attachment")
storageType := sec.Key("STORAGE_TYPE").MustString("")
storage := getStorage(cfg, "attachments", storageType, sec)
assert.EqualValues(t, "minio", storage.Type)
assert.EqualValues(t, "gitea-attachment", storage.Section.Key("MINIO_BUCKET").String())
}
func Test_getStorageTypeSectionOverridesStorageSection(t *testing.T) {
iniStr := `
[attachment]
STORAGE_TYPE = minio
[storage.minio]
MINIO_BUCKET = gitea-minio
[storage]
MINIO_BUCKET = gitea
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
sec := cfg.Section("attachment")
storageType := sec.Key("STORAGE_TYPE").MustString("")
storage := getStorage(cfg, "attachments", storageType, sec)
assert.EqualValues(t, "minio", storage.Type)
assert.EqualValues(t, "gitea-minio", storage.Section.Key("MINIO_BUCKET").String())
}
func Test_getStorageSpecificOverridesStorage(t *testing.T) {
iniStr := `
[attachment]
STORAGE_TYPE = minio
MINIO_BUCKET = gitea-attachment
[storage.attachments]
MINIO_BUCKET = gitea
[storage]
STORAGE_TYPE = local
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
sec := cfg.Section("attachment")
storageType := sec.Key("STORAGE_TYPE").MustString("")
storage := getStorage(cfg, "attachments", storageType, sec)
assert.EqualValues(t, "minio", storage.Type)
assert.EqualValues(t, "gitea-attachment", storage.Section.Key("MINIO_BUCKET").String())
}
func Test_getStorageGetDefaults(t *testing.T) {
cfg, err := NewConfigProviderFromData("")
assert.NoError(t, err)
sec := cfg.Section("attachment")
storageType := sec.Key("STORAGE_TYPE").MustString("")
storage := getStorage(cfg, "attachments", storageType, sec)
assert.EqualValues(t, "gitea", storage.Section.Key("MINIO_BUCKET").String())
}
func Test_getStorageMultipleName(t *testing.T) {
iniStr := `
[lfs]
@ -118,32 +18,20 @@ MINIO_BUCKET = gitea-lfs
MINIO_BUCKET = gitea-attachment
[storage]
STORAGE_TYPE = minio
MINIO_BUCKET = gitea-storage
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
{
sec := cfg.Section("attachment")
storageType := sec.Key("STORAGE_TYPE").MustString("")
storage := getStorage(cfg, "attachments", storageType, sec)
assert.NoError(t, loadAttachmentFrom(cfg))
assert.EqualValues(t, "gitea-attachment", Attachment.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "gitea-attachment", storage.Section.Key("MINIO_BUCKET").String())
}
{
sec := cfg.Section("lfs")
storageType := sec.Key("STORAGE_TYPE").MustString("")
storage := getStorage(cfg, "lfs", storageType, sec)
assert.NoError(t, loadLFSFrom(cfg))
assert.EqualValues(t, "gitea-lfs", LFS.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "gitea-lfs", storage.Section.Key("MINIO_BUCKET").String())
}
{
sec := cfg.Section("avatar")
storageType := sec.Key("STORAGE_TYPE").MustString("")
storage := getStorage(cfg, "avatars", storageType, sec)
assert.EqualValues(t, "gitea-storage", storage.Section.Key("MINIO_BUCKET").String())
}
assert.NoError(t, loadAvatarsFrom(cfg))
assert.EqualValues(t, "gitea-storage", Avatar.Storage.MinioConfig.Bucket)
}
func Test_getStorageUseOtherNameAsType(t *testing.T) {
@ -152,25 +40,17 @@ func Test_getStorageUseOtherNameAsType(t *testing.T) {
STORAGE_TYPE = lfs
[storage.lfs]
STORAGE_TYPE = minio
MINIO_BUCKET = gitea-storage
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
{
sec := cfg.Section("attachment")
storageType := sec.Key("STORAGE_TYPE").MustString("")
storage := getStorage(cfg, "attachments", storageType, sec)
assert.NoError(t, loadAttachmentFrom(cfg))
assert.EqualValues(t, "gitea-storage", Attachment.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "gitea-storage", storage.Section.Key("MINIO_BUCKET").String())
}
{
sec := cfg.Section("lfs")
storageType := sec.Key("STORAGE_TYPE").MustString("")
storage := getStorage(cfg, "lfs", storageType, sec)
assert.EqualValues(t, "gitea-storage", storage.Section.Key("MINIO_BUCKET").String())
}
assert.NoError(t, loadLFSFrom(cfg))
assert.EqualValues(t, "gitea-storage", LFS.Storage.MinioConfig.Bucket)
}
func Test_getStorageInheritStorageType(t *testing.T) {
@ -181,24 +61,32 @@ STORAGE_TYPE = minio
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
sec := cfg.Section("attachment")
storageType := sec.Key("STORAGE_TYPE").MustString("")
storage := getStorage(cfg, "attachments", storageType, sec)
assert.NoError(t, loadPackagesFrom(cfg))
assert.EqualValues(t, "minio", Packages.Storage.Type)
assert.EqualValues(t, "gitea", Packages.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "packages/", Packages.Storage.MinioConfig.BasePath)
assert.EqualValues(t, "minio", storage.Type)
}
func Test_getStorageInheritNameSectionType(t *testing.T) {
iniStr := `
[storage.attachments]
STORAGE_TYPE = minio
`
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
sec := cfg.Section("attachment")
storageType := sec.Key("STORAGE_TYPE").MustString("")
storage := getStorage(cfg, "attachments", storageType, sec)
assert.EqualValues(t, "minio", storage.Type)
assert.NoError(t, loadRepoArchiveFrom(cfg))
assert.EqualValues(t, "minio", RepoArchive.Storage.Type)
assert.EqualValues(t, "gitea", RepoArchive.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "repo-archive/", RepoArchive.Storage.MinioConfig.BasePath)
assert.NoError(t, loadActionsFrom(cfg))
assert.EqualValues(t, "minio", Actions.LogStorage.Type)
assert.EqualValues(t, "gitea", Actions.LogStorage.MinioConfig.Bucket)
assert.EqualValues(t, "actions_log/", Actions.LogStorage.MinioConfig.BasePath)
assert.EqualValues(t, "minio", Actions.ArtifactStorage.Type)
assert.EqualValues(t, "gitea", Actions.ArtifactStorage.MinioConfig.Bucket)
assert.EqualValues(t, "actions_artifacts/", Actions.ArtifactStorage.MinioConfig.BasePath)
assert.NoError(t, loadAvatarsFrom(cfg))
assert.EqualValues(t, "minio", Avatar.Storage.Type)
assert.EqualValues(t, "gitea", Avatar.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "avatars/", Avatar.Storage.MinioConfig.BasePath)
assert.NoError(t, loadRepoAvatarFrom(cfg))
assert.EqualValues(t, "minio", RepoAvatar.Storage.Type)
assert.EqualValues(t, "gitea", RepoAvatar.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "repo-avatars/", RepoAvatar.Storage.MinioConfig.BasePath)
}