diff --git a/config/config.go b/config/config.go index 6a159f82..9f41fb79 100644 --- a/config/config.go +++ b/config/config.go @@ -43,7 +43,6 @@ package config import ( "fmt" "os" - "strings" ) // Configer defines how to get and set value from configuration raw data. @@ -107,17 +106,17 @@ func NewConfigData(adapterName string, data []byte) (Configer, error) { return adapter.ParseData(data) } -// ChooseRealValueForMap convert all string value with environment variable. -func ChooseRealValueForMap(m map[string]interface{}) map[string]interface{} { +// ExpandValueEnvForMap convert all string value with environment variable. +func ExpandValueEnvForMap(m map[string]interface{}) map[string]interface{} { for k, v := range m { switch value := v.(type) { case string: - m[k] = ChooseRealValue(value) + m[k] = ExpandValueEnv(value) case map[string]interface{}: - m[k] = ChooseRealValueForMap(value) + m[k] = ExpandValueEnvForMap(value) case map[string]string: for k2, v2 := range value { - value[k2] = ChooseRealValue(v2) + value[k2] = ExpandValueEnv(v2) } m[k] = value } @@ -125,42 +124,48 @@ func ChooseRealValueForMap(m map[string]interface{}) map[string]interface{} { return m } -// ChooseRealValue returns value of convert with environment variable. +// ExpandValueEnv returns value of convert with environment variable. // -// Return environment variable if value start with "$$". +// Return environment variable if value start with "${" and end with "}". // Return default value if environment variable is empty or not exist. // -// It accept value formats "$$env" , "$$env||" , "$$env||defaultValue" , "defaultvalue". +// It accept value formats "${env}" , "${env||}}" , "${env||defaultValue}" , "defaultvalue". // Examples: -// v1 := config.ChooseRealValue("$$GOPATH") // return the GOPATH environment variable. -// v2 := config.ChooseRealValue("$$GOAsta||/usr/local/go/") // return the default value "/usr/local/go/". -// v3 := config.ChooseRealValue("Astaxie") // return the value "Astaxie". -func ChooseRealValue(value string) (realValue string) { +// v1 := config.ExpandValueEnv("${GOPATH}") // return the GOPATH environment variable. +// v2 := config.ExpandValueEnv("${GOAsta||/usr/local/go}") // return the default value "/usr/local/go/". +// v3 := config.ExpandValueEnv("Astaxie") // return the value "Astaxie". +func ExpandValueEnv(value string) (realValue string) { realValue = value - if value == "" { + vLen := len(value) + // 3 = ${} + if vLen < 3 { + return + } + // Need start with "${" and end with "}", then return. + if value[0] != '$' || value[1] != '{' || value[vLen-1] != '}' { return } - sign := "$$" // Environment variable identifier. - sep := "||" // Environment variable and default value separator. - - // Not use environment variable. - if strings.HasPrefix(value, sign) == false { - return - } - - sepIndex := strings.Index(value, sep) - if sepIndex == -1 { - realValue = os.Getenv(string(value[len(sign):])) - } else { - realValue = os.Getenv(string(value[len(sign):sepIndex])) - // Find defalut value. - if realValue == "" { - realValue = string(value[sepIndex+len(sep):]) + key := "" + defalutV := "" + // value start with "${" + for i := 2; i < vLen; i++ { + if value[i] == '|' && (i+1 < vLen && value[i+1] == '|') { + key = value[2:i] + defalutV = value[i+2 : vLen-1] // other string is default value. + break + } else if value[i] == '}' { + key = value[2:i] + break } } + realValue = os.Getenv(key) + if realValue == "" { + realValue = defalutV + } + return } diff --git a/config/config_test.go b/config/config_test.go new file mode 100644 index 00000000..15d6ffa6 --- /dev/null +++ b/config/config_test.go @@ -0,0 +1,55 @@ +// Copyright 2016 beego Author. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package config + +import ( + "os" + "testing" +) + +func TestExpandValueEnv(t *testing.T) { + + testCases := []struct { + item string + want string + }{ + {"", ""}, + {"$", "$"}, + {"{", "{"}, + {"{}", "{}"}, + {"${}", ""}, + {"${|}", ""}, + {"${}", ""}, + {"${{}}", ""}, + {"${{||}}", "}"}, + {"${pwd||}", ""}, + {"${pwd||}", ""}, + {"${pwd||}", ""}, + {"${pwd||}}", "}"}, + {"${pwd||{{||}}}", "{{||}}"}, + {"${GOPATH}", os.Getenv("GOPATH")}, + {"${GOPATH||}", os.Getenv("GOPATH")}, + {"${GOPATH||root}", os.Getenv("GOPATH")}, + {"${GOPATH_NOT||root}", "root"}, + {"${GOPATH_NOT||||root}", "||root"}, + } + + for _, c := range testCases { + if got := ExpandValueEnv(c.item); got != c.want { + t.Errorf("expand value error, item %q want %q, got %q", c.item, c.want, got) + } + } + +} diff --git a/config/ini.go b/config/ini.go index 1ec56238..53bd992d 100644 --- a/config/ini.go +++ b/config/ini.go @@ -166,7 +166,7 @@ func (ini *IniConfig) parseFile(name string) (*IniConfigContainer, error) { val = bytes.Trim(val, `"`) } - cfg.data[section][key] = ChooseRealValue(string(val)) + cfg.data[section][key] = ExpandValueEnv(string(val)) if comment.Len() > 0 { cfg.keyComment[section+"."+key] = comment.String() comment.Reset() diff --git a/config/ini_test.go b/config/ini_test.go index a6a66198..83ff3668 100644 --- a/config/ini_test.go +++ b/config/ini_test.go @@ -42,20 +42,14 @@ needlogin = ON enableSession = Y enableCookie = N flag = 1 -path1 = $$GOPATH -path2 = $$GOPATH||/home/go -path3 = $$GOPATH$$GOPATH2||/home/go -token1 = $$TOKEN -token2 = $$TOKEN|| -token3 = $$TOKEN||astaxie -token4 = token$$TOKEN -token5 = $$TOKEN$$TOKEN||TOKEN +path1 = ${GOPATH} +path2 = ${GOPATH||/home/go} [demo] key1="asta" key2 = "xie" CaseInsensitive = true peers = one;two;three -password = $$GOPATH +password = ${GOPATH} ` keyValue = map[string]interface{}{ @@ -75,12 +69,6 @@ password = $$GOPATH "flag": true, "path1": os.Getenv("GOPATH"), "path2": os.Getenv("GOPATH"), - "path3": "/home/go", - "token1": "", - "token2": "", - "token3": "astaxie", - "token4": "token$$TOKEN", - "token5": "TOKEN", "demo::key1": "asta", "demo::key2": "xie", "demo::CaseInsensitive": true, diff --git a/config/json.go b/config/json.go index 3b4569b8..a0d93210 100644 --- a/config/json.go +++ b/config/json.go @@ -58,7 +58,7 @@ func (js *JSONConfig) ParseData(data []byte) (Configer, error) { x.data["rootArray"] = wrappingArray } - x.data = ChooseRealValueForMap(x.data) + x.data = ExpandValueEnvForMap(x.data) return x, nil } diff --git a/config/json_test.go b/config/json_test.go index 940916a1..24ff9644 100644 --- a/config/json_test.go +++ b/config/json_test.go @@ -86,25 +86,19 @@ func TestJson(t *testing.T) { "enableSession": "Y", "enableCookie": "N", "flag": 1, -"path1": "$$GOPATH", -"path2": "$$GOPATH||/home/go", -"path3": "$$GOPATH$$GOPATH2||/home/go", -"token1": "$$TOKEN", -"token2": "$$TOKEN||", -"token3": "$$TOKEN||astaxie", -"token4": "token$$TOKEN", -"token5": "$$TOKEN$$TOKEN||TOKEN", +"path1": "${GOPATH}", +"path2": "${GOPATH||/home/go}", "database": { "host": "host", "port": "port", "database": "database", "username": "username", - "password": "$$GOPATH", + "password": "${GOPATH}", "conns":{ "maxconnection":12, "autoconnect":true, "connectioninfo":"info", - "root": "$$GOPATH" + "root": "${GOPATH}" } } }` @@ -126,12 +120,6 @@ func TestJson(t *testing.T) { "flag": true, "path1": os.Getenv("GOPATH"), "path2": os.Getenv("GOPATH"), - "path3": "/home/go", - "token1": "", - "token2": "", - "token3": "astaxie", - "token4": "token$$TOKEN", - "token5": "TOKEN", "database::host": "host", "database::port": "port", "database::database": "database", diff --git a/config/xml/xml.go b/config/xml/xml.go index 63f3cb23..0c4e4d27 100644 --- a/config/xml/xml.go +++ b/config/xml/xml.go @@ -69,7 +69,7 @@ func (xc *Config) Parse(filename string) (config.Configer, error) { return nil, err } - x.data = config.ChooseRealValueForMap(d["config"].(map[string]interface{})) + x.data = config.ExpandValueEnvForMap(d["config"].(map[string]interface{})) return x, nil } diff --git a/config/xml/xml_test.go b/config/xml/xml_test.go index 825f4d0d..d8a09a59 100644 --- a/config/xml/xml_test.go +++ b/config/xml/xml_test.go @@ -35,14 +35,8 @@ func TestXML(t *testing.T) { dev false true -$$GOPATH -$$GOPATH||/home/go -$$GOPATH$$GOPATH2||/home/go -$$TOKEN -$$TOKEN|| -$$TOKEN||astaxie -token$$TOKEN -$$TOKEN$$TOKEN||TOKEN +${GOPATH} +${GOPATH||/home/go} ` keyValue = map[string]interface{}{ @@ -55,12 +49,6 @@ func TestXML(t *testing.T) { "copyrequestbody": true, "path1": os.Getenv("GOPATH"), "path2": os.Getenv("GOPATH"), - "path3": "/home/go", - "token1": "", - "token2": "", - "token3": "astaxie", - "token4": "token$$TOKEN", - "token5": "TOKEN", "error": "", "emptystrings": []string{}, } diff --git a/config/yaml/yaml.go b/config/yaml/yaml.go index 6a6f07c7..64e25cb3 100644 --- a/config/yaml/yaml.go +++ b/config/yaml/yaml.go @@ -110,7 +110,7 @@ func ReadYmlReader(path string) (cnf map[string]interface{}, err error) { log.Println("Not a Map? >> ", string(buf), data) cnf = nil } - cnf = config.ChooseRealValueForMap(cnf) + cnf = config.ExpandValueEnvForMap(cnf) return } diff --git a/config/yaml/yaml_test.go b/config/yaml/yaml_test.go index 0731778f..49cc1d1e 100644 --- a/config/yaml/yaml_test.go +++ b/config/yaml/yaml_test.go @@ -34,14 +34,8 @@ func TestYaml(t *testing.T) { "autorender": false "copyrequestbody": true "PATH": GOPATH -"path1": $$GOPATH -"path2": $$GOPATH||/home/go -"path3": $$GOPATH$$GOPATH2||/home/go -"token1": $$TOKEN -"token2": $$TOKEN|| -"token3": $$TOKEN||astaxie -"token4": token$$TOKEN -"token5": $$TOKEN$$TOKEN||TOKEN +"path1": ${GOPATH} +"path2": ${GOPATH||/home/go} "empty": "" ` @@ -56,12 +50,6 @@ func TestYaml(t *testing.T) { "PATH": "GOPATH", "path1": os.Getenv("GOPATH"), "path2": os.Getenv("GOPATH"), - "path3": "/home/go", - "token1": "", - "token2": "", - "token3": "astaxie", - "token4": "token$$TOKEN", - "token5": "TOKEN", "error": "", "emptystrings": []string{}, }