diff --git a/go.mod b/go.mod index 716a6a7..176b20e 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index bd5490a..26e7005 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/src/server/config_load.go b/src/server/config_load.go index 95aefd1..a14446a 100644 --- a/src/server/config_load.go +++ b/src/server/config_load.go @@ -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 diff --git a/src/server/config_load_test.go b/src/server/config_load_test.go index 8d2a373..d1bc726 100644 --- a/src/server/config_load_test.go +++ b/src/server/config_load_test.go @@ -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) } } diff --git a/src/server/testdata/config_1.yml b/src/server/testdata/config_1.yml index 62adaf6..5ece387 100644 --- a/src/server/testdata/config_1.yml +++ b/src/server/testdata/config_1.yml @@ -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" diff --git a/src/server/testdata/test_quickshare.db b/src/server/testdata/test_quickshare.db index f6e39d2..86346ce 100644 Binary files a/src/server/testdata/test_quickshare.db and b/src/server/testdata/test_quickshare.db differ