fix(configs): refactor config loader to read default, db, configs, args in order

This commit is contained in:
hexxa 2022-04-02 15:38:59 +08:00 committed by Hexxa
parent 86b2672b01
commit 2f6aa33108
6 changed files with 113 additions and 45 deletions

2
go.mod
View file

@ -10,7 +10,7 @@ require (
github.com/gin-gonic/gin v1.7.3
github.com/go-playground/validator/v10 v10.9.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/ihexxa/gocfg v0.0.0-20220128082538-9e607ebed51b
github.com/ihexxa/gocfg v0.0.1
github.com/ihexxa/multipart v0.0.0-20210916083128-8584a3f00d1d
github.com/jessevdk/go-flags v1.4.0
github.com/json-iterator/go v1.1.11 // indirect

4
go.sum
View file

@ -48,6 +48,10 @@ github.com/hashicorp/go-version v1.0.0 h1:21MVWPKDphxa7ineQQTrCU5brh7OuVVAzGOCnn
github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/ihexxa/gocfg v0.0.0-20220128082538-9e607ebed51b h1:pzx3BC3+v38POQg9sJWhfs/a4xFaJfC0Ar4RRVnFIMo=
github.com/ihexxa/gocfg v0.0.0-20220128082538-9e607ebed51b/go.mod h1:oqDTq1ywx4Qi9DdhFwwMHoPCYv6Txrfj2SY5WWcgiJs=
github.com/ihexxa/gocfg v0.0.0-20220402060620-c43339e8d159 h1:gKVyKHtTaT9UJHFjMadZEk4KW+RyMLx9N/cIIviF/nk=
github.com/ihexxa/gocfg v0.0.0-20220402060620-c43339e8d159/go.mod h1:oqDTq1ywx4Qi9DdhFwwMHoPCYv6Txrfj2SY5WWcgiJs=
github.com/ihexxa/gocfg v0.0.1 h1:3zsCHY/SYdqKSoo3pwTBWMgivEB7/ctpPPHL3p43UBg=
github.com/ihexxa/gocfg v0.0.1/go.mod h1:oqDTq1ywx4Qi9DdhFwwMHoPCYv6Txrfj2SY5WWcgiJs=
github.com/ihexxa/multipart v0.0.0-20210916083128-8584a3f00d1d h1:+v33khYHVDPEuuWO/JE1IzhoIu5uNvEcSs5GmXc5Sjw=
github.com/ihexxa/multipart v0.0.0-20210916083128-8584a3f00d1d/go.mod h1:rhOAe/52S/J1fq1VnXvKX8FHuo65I+IcYUozW4M7+wE=
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=

View file

@ -20,38 +20,41 @@ type Args struct {
Configs []string `short:"c" long:"configs" description:"config path"`
}
// LoadCfg loads the default config, the config in database, config files and arguments in order.
// All config values will be merged into one, and the latter overwrites the former.
// Each config can be part of the whole ServerCfg
func LoadCfg(args *Args) (*gocfg.Cfg, error) {
defaultCfg, err := DefaultConfig()
if err != nil {
return nil, err
}
cfg, err := gocfg.New(NewConfig()).Load(gocfg.JSONStr(defaultCfg))
if err != nil {
return nil, err
}
cfg, err = mergeConfigFiles(cfg, args.Configs)
tmpCfg := *cfg
dbPath, err := getDbPath(&tmpCfg, args.Configs, args.DbPath)
if err != nil {
return nil, err
}
dbPath := cfg.GrabString("Db.DbPath")
if args.DbPath != "" {
dbPath = args.DbPath
_, err := os.Stat(dbPath)
if err == nil {
cfg, err = mergeDbConfig(cfg, dbPath)
if err != nil {
return nil, err
}
} else if err != nil {
if !os.IsNotExist(err) {
return nil, err
} else {
fmt.Printf("warning: Database does not exist in (%s), skipped", dbPath)
}
_, err = os.Stat(dbPath)
if err == nil {
cfg, err = mergeDbConfig(cfg, dbPath)
if err != nil {
return nil, err
}
} else if err != nil {
if !os.IsNotExist(err) {
return nil, err
} else {
fmt.Printf("warning: Database does not exist in (%s), skipped", dbPath)
}
}
cfg, err = mergeConfigFiles(cfg, args.Configs)
if err != nil {
return nil, err
}
return mergeArgs(cfg, args)
@ -83,6 +86,31 @@ func mergeDbConfig(cfg *gocfg.Cfg, dbPath string) (*gocfg.Cfg, error) {
return cfg.Load(gocfg.JSONStr(cfgStr))
}
// getDbPath returns db path from arguments, configs, default config in order
// this is a little tricky
func getDbPath(cfg *gocfg.Cfg, configPaths []string, argDbPath string) (string, error) {
if argDbPath != "" {
return argDbPath, nil
}
var err error
for _, configPath := range configPaths {
if strings.HasSuffix(configPath, ".yml") || strings.HasSuffix(configPath, ".yaml") {
cfg, err = cfg.Load(gocfg.YAML(configPath))
} else if strings.HasSuffix(configPath, ".json") {
cfg, err = cfg.Load(gocfg.JSON(configPath))
} else {
return "", fmt.Errorf("unknown config file type (.yml .yaml .json are supported): %s", configPath)
}
if err != nil {
return "", err
}
}
return cfg.GrabString("Db.DbPath"), nil
}
func mergeConfigFiles(cfg *gocfg.Cfg, configPaths []string) (*gocfg.Cfg, error) {
var err error

View file

@ -3,6 +3,7 @@ package server
import (
"encoding/json"
"fmt"
"reflect"
"testing"
"github.com/ihexxa/gocfg"
@ -19,14 +20,28 @@ func TestLoadCfg(t *testing.T) {
DbPath: "",
Configs: []string{},
},
// default config + config_1
// default config + db
&Args{
Host: "",
Port: 0,
DbPath: "testdata/test_quickshare.db",
Configs: []string{},
},
// default config + db + config_1 (dbPath is from config_1)
&Args{
Host: "",
Port: 0,
DbPath: "",
Configs: []string{"testdata/config_1.yml"},
},
// default config + config_1 + config_4
// // default config + db + config_1 (dbPath is from args)
&Args{
Host: "",
Port: 0,
DbPath: "testdata/test_quickshare.db",
Configs: []string{"testdata/config_1.yml"},
},
// default config + db + config_1 + config_4
&Args{
Host: "",
Port: 0,
@ -45,7 +60,7 @@ func TestLoadCfg(t *testing.T) {
"testdata/config_partial_db.yml",
},
},
// default config + config_1 + config_4 + db_partial + args(db)
// default config + db + config_1 + config_4 + config_partial_users.yml + config_partial_db.yml + args(db)
&Args{
Host: "",
Port: 0,
@ -61,6 +76,21 @@ func TestLoadCfg(t *testing.T) {
cfgDefault := DefaultConfigStruct()
cfgDBOnly := *cfgDefault
cfgDBOnly.Site = &db.SiteConfig{
ClientCfg: &db.ClientConfig{
SiteName: "Quickshare",
SiteDesc: "quick and simple file sharing",
Bg: &db.BgConfig{
Url: "/static/img/textured_paper.png",
Repeat: "repeat",
Position: "center",
Align: "fixed",
BgColor: "#ccc",
},
},
}
cfg1 := &Config{
Fs: &FSConfig{
Root: "1",
@ -111,19 +141,19 @@ func TestLoadCfg(t *testing.T) {
},
Site: &db.SiteConfig{
ClientCfg: &db.ClientConfig{
SiteName: "1",
SiteDesc: "1",
SiteName: "Quickshare",
SiteDesc: "quick and simple file sharing",
Bg: &db.BgConfig{
Url: "1",
Repeat: "1",
Position: "1",
Align: "1",
BgColor: "1",
Url: "/static/img/textured_paper.png",
Repeat: "repeat",
Position: "center",
Align: "fixed",
BgColor: "#ccc",
},
},
},
Db: &DbConfig{
DbPath: "1",
DbPath: "testdata/test_quickshare.db",
},
}
@ -259,7 +289,7 @@ func TestLoadCfg(t *testing.T) {
},
}
cfgWithDB := &Config{
cfgWithPartialCfg := &Config{
Fs: &FSConfig{
Root: "4",
OpensLimit: 4,
@ -321,16 +351,18 @@ func TestLoadCfg(t *testing.T) {
},
},
Db: &DbConfig{
DbPath: "testdata/test_quickshare.db",
DbPath: "5",
},
}
expects := []*Config{
cfgDefault,
&cfgDBOnly,
cfg1,
cfg1,
cfg4,
cfg5,
cfgWithDB,
cfgWithPartialCfg,
}
testLoadCfg := func(t *testing.T) {
@ -351,7 +383,11 @@ func TestLoadCfg(t *testing.T) {
t.Fatal(err)
}
if !Equal(gotCfg, expectCfg) {
if !reflect.DeepEqual(gotCfg.Template(), expectCfg.Template()) {
gotJSON, _ := gotCfg.JSON()
expectJSON, _ := expectCfg.JSON()
fmt.Printf("\ngot\n%s\n", gotJSON)
fmt.Printf("\nexpected\n%s\n", expectJSON)
t.Fatalf("%d, cfgs are not identical", i)
}
}

View file

@ -37,16 +37,16 @@ workers:
queueSize: 1
sleepCyc: 1
workerCount: 1
site:
clientCfg:
siteName: "1"
siteDesc: "1"
bg:
url: "1"
repeat: "1"
position: "1"
align: "1"
bgColor: "1"
# site:
# clientCfg:
# siteName: "1"
# siteDesc: "1"
# bg:
# url: "1"
# repeat: "1"
# position: "1"
# align: "1"
# bgColor: "1"
db:
dbPath: "1"
dbPath: "testdata/test_quickshare.db"

Binary file not shown.