diff --git a/.travis.yml b/.travis.yml index f3f1b576..67efe057 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ services: - mysql - postgresql - memcached - - etcd + - docker env: global: - GO_REPO_FULLNAME="github.com/astaxie/beego" @@ -27,17 +27,33 @@ before_install: - cd ssdb - make - cd .. + # - prepare etcd # - prepare for etcd unit tests - - git clone https://github.com/etcd-io/etcd.git - - cd etcd - - ./build - - ./bin/etcd - - ./bin/etcdctl put current.float 1.23 - - ./bin/etcdctl put current.bool true - - ./bin/etcdctl put current.int 11 - - ./bin/etcdctl put current.string hello - - ./bin/etcdctl put current.serialize.name test - - cd .. + - rm -rf /tmp/etcd-data.tmp + - mkdir -p /tmp/etcd-data.tmp + - docker rmi gcr.io/etcd-development/etcd:v3.3.25 || true && + docker run -d + -p 2379:2379 + -p 2380:2380 + --mount type=bind,source=/tmp/etcd-data.tmp,destination=/etcd-data + --name etcd-gcr-v3.3.25 + gcr.io/etcd-development/etcd:v3.3.25 + /usr/local/bin/etcd + --name s1 + --data-dir /etcd-data + --listen-client-urls http://0.0.0.0:2379 + --advertise-client-urls http://0.0.0.0:2379 + --listen-peer-urls http://0.0.0.0:2380 + --initial-advertise-peer-urls http://0.0.0.0:2380 + --initial-cluster s1=http://0.0.0.0:2380 + --initial-cluster-token tkn + --initial-cluster-state new + - docker exec etcd-gcr-v3.3.25 /bin/sh -c "ETCDCTL_API=3 /usr/local/bin/etcdctl put current.float 1.23" + - docker exec etcd-gcr-v3.3.25 /bin/sh -c "ETCDCTL_API=3 /usr/local/bin/etcdctl put current.bool true" + - docker exec etcd-gcr-v3.3.25 /bin/sh -c "ETCDCTL_API=3 /usr/local/bin/etcdctl put current.int 11" + - docker exec etcd-gcr-v3.3.25 /bin/sh -c "ETCDCTL_API=3 /usr/local/bin/etcdctl put current.string hello" + - docker exec etcd-gcr-v3.3.25 /bin/sh -c "ETCDCTL_API=3 /usr/local/bin/etcdctl put current.serialize.name test" + - docker exec etcd-gcr-v3.3.25 /bin/sh -c "ETCDCTL_API=3 /usr/local/bin/etcdctl put sub.sub.key1 sub.sub.key" install: - go get github.com/lib/pq - go get github.com/go-sql-driver/mysql @@ -64,6 +80,8 @@ install: - go get -u golang.org/x/lint/golint - go get -u github.com/go-redis/redis before_script: + + # - - psql --version # - prepare for orm unit tests - sh -c "if [ '$ORM_DRIVER' = 'postgres' ]; then psql -c 'create database orm_test;' -U postgres; fi" @@ -84,4 +102,4 @@ script: - find . ! \( -path './vendor' -prune \) -type f -name '*.go' -print0 | xargs -0 gofmt -l -s - golint ./... addons: - postgresql: "9.6" + postgresql: "9.6" \ No newline at end of file diff --git a/pkg/client/httplib/testing/client.go b/pkg/client/httplib/testing/client.go index 19e6cd23..863ed0e8 100644 --- a/pkg/client/httplib/testing/client.go +++ b/pkg/client/httplib/testing/client.go @@ -34,7 +34,10 @@ func getPort() string { if err != nil { return "8080" } - port = config.String("httpport") + port, err = config.String("httpport") + if err != nil { + return "8080" + } return port } return port diff --git a/pkg/infrastructure/config/config.go b/pkg/infrastructure/config/config.go index 3514e425..c7f45469 100644 --- a/pkg/infrastructure/config/config.go +++ b/pkg/infrastructure/config/config.go @@ -131,7 +131,7 @@ func (c *BaseConfiger) Float(key string) (float64, error) { // DefaultString returns the string value for a given key. // if err != nil or value is empty return defaultval func (c *BaseConfiger) DefaultString(key string, defaultVal string) string { - if res, err := c.String(key); res != "" && err != nil { + if res, err := c.String(key); res != "" && err == nil { return res } return defaultVal @@ -140,7 +140,7 @@ func (c *BaseConfiger) DefaultString(key string, defaultVal string) string { // DefaultStrings returns the []string value for a given key. // if err != nil return defaultval func (c *BaseConfiger) DefaultStrings(key string, defaultVal []string) []string { - if res, err := c.Strings(key); len(res) > 0 && err != nil { + if res, err := c.Strings(key); len(res) > 0 && err == nil { return res } return defaultVal diff --git a/pkg/infrastructure/config/ini.go b/pkg/infrastructure/config/ini.go index 4d3946d5..2338b3cf 100644 --- a/pkg/infrastructure/config/ini.go +++ b/pkg/infrastructure/config/ini.go @@ -17,14 +17,13 @@ package config import ( "bufio" "bytes" - "context" "errors" - "fmt" "io" "io/ioutil" "os" "os/user" "path/filepath" + "strconv" "strings" "sync" ) @@ -66,9 +65,6 @@ func (ini *IniConfig) parseData(dir string, data []byte) (*IniConfigContainer, e keyComment: make(map[string]string), RWMutex: sync.RWMutex{}, } - cfg.BaseConfiger = NewBaseConfiger(func(ctx context.Context, key string) (string, error) { - return cfg.getdata(key) - }) cfg.Lock() defer cfg.Unlock() @@ -94,7 +90,7 @@ func (ini *IniConfig) parseData(dir string, data []byte) (*IniConfigContainer, e break } - // It might be a good idea to throw a error on all unknonw errors? + //It might be a good idea to throw a error on all unknonw errors? if _, ok := err.(*os.PathError); ok { return nil, err } @@ -236,6 +232,101 @@ type IniConfigContainer struct { sync.RWMutex } +// Bool returns the boolean value for a given key. +func (c *IniConfigContainer) Bool(key string) (bool, error) { + return ParseBool(c.getdata(key)) +} + +// DefaultBool returns the boolean value for a given key. +// if err != nil return defaultval +func (c *IniConfigContainer) DefaultBool(key string, defaultval bool) bool { + v, err := c.Bool(key) + if err != nil { + return defaultval + } + return v +} + +// Int returns the integer value for a given key. +func (c *IniConfigContainer) Int(key string) (int, error) { + return strconv.Atoi(c.getdata(key)) +} + +// DefaultInt returns the integer value for a given key. +// if err != nil return defaultval +func (c *IniConfigContainer) DefaultInt(key string, defaultval int) int { + v, err := c.Int(key) + if err != nil { + return defaultval + } + return v +} + +// Int64 returns the int64 value for a given key. +func (c *IniConfigContainer) Int64(key string) (int64, error) { + return strconv.ParseInt(c.getdata(key), 10, 64) +} + +// DefaultInt64 returns the int64 value for a given key. +// if err != nil return defaultval +func (c *IniConfigContainer) DefaultInt64(key string, defaultval int64) int64 { + v, err := c.Int64(key) + if err != nil { + return defaultval + } + return v +} + +// Float returns the float value for a given key. +func (c *IniConfigContainer) Float(key string) (float64, error) { + return strconv.ParseFloat(c.getdata(key), 64) +} + +// DefaultFloat returns the float64 value for a given key. +// if err != nil return defaultval +func (c *IniConfigContainer) DefaultFloat(key string, defaultval float64) float64 { + v, err := c.Float(key) + if err != nil { + return defaultval + } + return v +} + +// String returns the string value for a given key. +func (c *IniConfigContainer) String(key string) (string, error) { + return c.getdata(key), nil +} + +// DefaultString returns the string value for a given key. +// if err != nil return defaultval +func (c *IniConfigContainer) DefaultString(key string, defaultval string) string { + v, err := c.String(key) + if v == "" || err != nil { + return defaultval + } + return v +} + +// Strings returns the []string value for a given key. +// Return nil if config value does not exist or is empty. +func (c *IniConfigContainer) Strings(key string) ([]string, error) { + v, err := c.String(key) + if v == "" || err != nil { + return nil, err + } + return strings.Split(v, ";"), nil +} + +// DefaultStrings returns the []string value for a given key. +// if err != nil return defaultval +func (c *IniConfigContainer) DefaultStrings(key string, defaultval []string) []string { + v, err := c.Strings(key) + if v == nil || err != nil { + return defaultval + } + return v +} + // GetSection returns map for the given section func (c *IniConfigContainer) GetSection(section string) (map[string]string, error) { if v, ok := c.data[section]; ok { @@ -383,9 +474,9 @@ func (c *IniConfigContainer) DIY(key string) (v interface{}, err error) { } // section.key or key -func (c *IniConfigContainer) getdata(key string) (string, error) { +func (c *IniConfigContainer) getdata(key string) string { if len(key) == 0 { - return "", errors.New("the key is empty") + return "" } c.RLock() defer c.RUnlock() @@ -403,10 +494,10 @@ func (c *IniConfigContainer) getdata(key string) (string, error) { } if v, ok := c.data[section]; ok { if vv, ok := v[k]; ok { - return vv, nil + return vv } } - return "", errors.New(fmt.Sprintf("config not found: %s", key)) + return "" } func init() { diff --git a/pkg/infrastructure/config/json/json.go b/pkg/infrastructure/config/json/json.go index b552269a..975e1523 100644 --- a/pkg/infrastructure/config/json/json.go +++ b/pkg/infrastructure/config/json/json.go @@ -165,7 +165,35 @@ func (c *JSONConfigContainer) String(key string) (string, error) { return v, nil } } - return "", errors.New(fmt.Sprintf("config not found or is not string, key: %s", key)) + return "", nil +} + +// DefaultString returns the string value for a given key. +// if err != nil return defaultval +func (c *JSONConfigContainer) DefaultString(key string, defaultval string) string { + // TODO FIXME should not use "" to replace non existence + if v, err := c.String(key); v != "" && err == nil { + return v + } + return defaultval +} + +// Strings returns the []string value for a given key. +func (c *JSONConfigContainer) Strings(key string) ([]string, error) { + stringVal, err := c.String(key) + if stringVal == "" || err != nil { + return nil, err + } + return strings.Split(stringVal, ";"), nil +} + +// DefaultStrings returns the []string value for a given key. +// if err != nil return defaultval +func (c *JSONConfigContainer) DefaultStrings(key string, defaultval []string) []string { + if v, err := c.Strings(key); v != nil && err == nil { + return v + } + return defaultval } // GetSection returns map for the given section diff --git a/pkg/infrastructure/config/xml/xml.go b/pkg/infrastructure/config/xml/xml.go index c095ef06..49aab33e 100644 --- a/pkg/infrastructure/config/xml/xml.go +++ b/pkg/infrastructure/config/xml/xml.go @@ -26,7 +26,7 @@ // // cnf, err := config.NewConfig("xml", "config.xml") // -// More docs http://beego.me/docs/module/config.md +//More docs http://beego.me/docs/module/config.md package xml import ( @@ -36,11 +36,11 @@ import ( "io/ioutil" "os" "strconv" + "strings" "sync" - "github.com/beego/x2j" - "github.com/astaxie/beego/pkg/infrastructure/config" + "github.com/beego/x2j" ) // Config is a xml config parser and implements Config interface. @@ -148,7 +148,7 @@ func (c *ConfigContainer) String(key string) (string, error) { if v, ok := c.data[key].(string); ok { return v, nil } - return "", errors.New(fmt.Sprintf("configuration not found or not string, key: %s", key)) + return "", nil } // DefaultString returns the string value for a given key. @@ -161,6 +161,25 @@ func (c *ConfigContainer) DefaultString(key string, defaultval string) string { return v } +// Strings returns the []string value for a given key. +func (c *ConfigContainer) Strings(key string) ([]string, error) { + v, err := c.String(key) + if v == "" || err != nil { + return nil, err + } + return strings.Split(v, ";"), nil +} + +// DefaultStrings returns the []string value for a given key. +// if err != nil return defaultval +func (c *ConfigContainer) DefaultStrings(key string, defaultval []string) []string { + v, err := c.Strings(key) + if v == nil || err != nil { + return defaultval + } + return v +} + // GetSection returns map for the given section func (c *ConfigContainer) GetSection(section string) (map[string]string, error) { if v, ok := c.data[section].(map[string]interface{}); ok { diff --git a/pkg/infrastructure/config/yaml/yaml.go b/pkg/infrastructure/config/yaml/yaml.go index 96045365..ddd556e6 100644 --- a/pkg/infrastructure/config/yaml/yaml.go +++ b/pkg/infrastructure/config/yaml/yaml.go @@ -214,11 +214,9 @@ func (c *ConfigContainer) String(key string) (string, error) { if v, err := c.getData(key); err == nil { if vv, ok := v.(string); ok { return vv, nil - } else { - return "", errors.New(fmt.Sprintf("the value is not string, key: %s, value: %v", key, v)) } } - return "", errors.New(fmt.Sprintf("configuration not found, key: %s", key)) + return "", nil } // DefaultString returns the string value for a given key. diff --git a/pkg/server/web/config.go b/pkg/server/web/config.go index 3abe255e..b2e38a80 100644 --- a/pkg/server/web/config.go +++ b/pkg/server/web/config.go @@ -32,8 +32,8 @@ import ( // Config is the main struct for BConfig type Config struct { - AppName string //Application name - RunMode string //Running Mode: dev | prod + AppName string // Application name + RunMode string // Running Mode: dev | prod RouterCaseSensitive bool ServerName string RecoverPanic bool @@ -113,8 +113,8 @@ type SessionConfig struct { // LogConfig holds Log related config type LogConfig struct { AccessLogs bool - EnableStaticLogs bool //log static files requests default: false - AccessLogsFormat string //access log format: JSON_FORMAT, APACHE_FORMAT or empty string + EnableStaticLogs bool // log static files requests default: false + AccessLogsFormat string // access log format: JSON_FORMAT, APACHE_FORMAT or empty string FileLineNum bool Outputs map[string]string // Store Adaptor : config } @@ -210,7 +210,7 @@ func newBConfig() *Config { RecoverFunc: recoverPanic, CopyRequestBody: false, EnableGzip: false, - MaxMemory: 1 << 26, //64MB + MaxMemory: 1 << 26, // 64MB EnableErrorsShow: true, EnableErrorsRender: true, Listen: Listen{ @@ -258,7 +258,7 @@ func newBConfig() *Config { SessionGCMaxLifetime: 3600, SessionProviderConfig: "", SessionDisableHTTPOnly: false, - SessionCookieLifeTime: 0, //set cookie default is the browser life + SessionCookieLifeTime: 0, // set cookie default is the browser life SessionAutoSetCookie: true, SessionDomain: "", SessionEnableSidInHTTPHeader: false, // enable store/get the sessionId into/from http headers @@ -292,11 +292,11 @@ func assignConfig(ac config.Configer) error { // set the run mode first if envRunMode := os.Getenv("BEEGO_RUNMODE"); envRunMode != "" { BConfig.RunMode = envRunMode - } else if runMode := ac.String("RunMode"); runMode != "" { + } else if runMode, err := ac.String("RunMode"); runMode != "" && err == nil { BConfig.RunMode = runMode } - if sd := ac.String("StaticDir"); sd != "" { + if sd, err := ac.String("StaticDir"); sd != "" && err == nil { BConfig.WebConfig.StaticDir = map[string]string{} sds := strings.Fields(sd) for _, v := range sds { @@ -308,7 +308,7 @@ func assignConfig(ac config.Configer) error { } } - if sgz := ac.String("StaticExtensionsToGzip"); sgz != "" { + if sgz, err := ac.String("StaticExtensionsToGzip"); sgz != "" && err == nil { extensions := strings.Split(sgz, ",") fileExts := []string{} for _, ext := range extensions { @@ -334,7 +334,7 @@ func assignConfig(ac config.Configer) error { BConfig.WebConfig.StaticCacheFileNum = sfn } - if lo := ac.String("LogOutputs"); lo != "" { + if lo, err := ac.String("LogOutputs"); lo != "" && err == nil { // if lo is not nil or empty // means user has set his own LogOutputs // clear the default setting to BConfig.Log.Outputs @@ -349,7 +349,7 @@ func assignConfig(ac config.Configer) error { } } - //init log + // init log logs.Reset() for adaptor, config := range BConfig.Log.Outputs { err := logs.SetLogger(adaptor, config) @@ -388,7 +388,7 @@ func assignSingleConfig(p interface{}, ac config.Configer) { pf.SetBool(ac.DefaultBool(name, pf.Bool())) case reflect.Struct: default: - //do nothing here + // do nothing here } } @@ -431,16 +431,16 @@ func (b *beegoAppConfig) Set(key, val string) error { return nil } -func (b *beegoAppConfig) String(key string) string { - if v := b.innerConfig.String(BConfig.RunMode + "::" + key); v != "" { - return v +func (b *beegoAppConfig) String(key string) (string, error) { + if v, err := b.innerConfig.String(BConfig.RunMode + "::" + key); v != "" && err == nil { + return v, nil } return b.innerConfig.String(key) } -func (b *beegoAppConfig) Strings(key string) []string { - if v := b.innerConfig.Strings(BConfig.RunMode + "::" + key); len(v) > 0 { - return v +func (b *beegoAppConfig) Strings(key string) ([]string, error) { + if v, err := b.innerConfig.Strings(BConfig.RunMode + "::" + key); len(v) > 0 && err == nil { + return v, nil } return b.innerConfig.Strings(key) } @@ -474,14 +474,14 @@ func (b *beegoAppConfig) Float(key string) (float64, error) { } func (b *beegoAppConfig) DefaultString(key string, defaultVal string) string { - if v := b.String(key); v != "" { + if v, err := b.String(key); v != "" && err == nil { return v } return defaultVal } func (b *beegoAppConfig) DefaultStrings(key string, defaultVal []string) []string { - if v := b.Strings(key); len(v) != 0 { + if v, err := b.Strings(key); len(v) != 0 && err == nil { return v } return defaultVal diff --git a/pkg/server/web/hooks.go b/pkg/server/web/hooks.go index 13194733..ae54f190 100644 --- a/pkg/server/web/hooks.go +++ b/pkg/server/web/hooks.go @@ -48,9 +48,9 @@ func registerDefaultErrorHandler() error { func registerSession() error { if BConfig.WebConfig.Session.SessionOn { var err error - sessionConfig := AppConfig.String("sessionConfig") + sessionConfig, err := AppConfig.String("sessionConfig") conf := new(session.ManagerConfig) - if sessionConfig == "" { + if sessionConfig == "" || err != nil { conf.CookieName = BConfig.WebConfig.Session.SessionName conf.EnableSetCookie = BConfig.WebConfig.Session.SessionAutoSetCookie conf.Gclifetime = BConfig.WebConfig.Session.SessionGCMaxLifetime diff --git a/pkg/server/web/templatefunc.go b/pkg/server/web/templatefunc.go index 6d132bf0..34d71aab 100644 --- a/pkg/server/web/templatefunc.go +++ b/pkg/server/web/templatefunc.go @@ -160,7 +160,7 @@ func NotNil(a interface{}) (isNil bool) { func GetConfig(returnType, key string, defaultVal interface{}) (value interface{}, err error) { switch returnType { case "String": - value = AppConfig.String(key) + value, err = AppConfig.String(key) case "Bool": value, err = AppConfig.Bool(key) case "Int": diff --git a/scripts/prepare_etcd.sh b/scripts/prepare_etcd.sh index a65f00a3..d34c05a3 100644 --- a/scripts/prepare_etcd.sh +++ b/scripts/prepare_etcd.sh @@ -4,4 +4,5 @@ etcdctl put current.float 1.23 etcdctl put current.bool true etcdctl put current.int 11 etcdctl put current.string hello -etcdctl put current.serialize.name test \ No newline at end of file +etcdctl put current.serialize.name test +etcdctl put sub.sub.key1 sub.sub.key \ No newline at end of file