github.com/astaxie/beego@v1.12.3/config/yaml/yaml.go (about) 1 // Copyright 2014 beego Author. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package yaml for config provider 16 // 17 // depend on github.com/beego/goyaml2 18 // 19 // go install github.com/beego/goyaml2 20 // 21 // Usage: 22 // import( 23 // _ "github.com/astaxie/beego/config/yaml" 24 // "github.com/astaxie/beego/config" 25 // ) 26 // 27 // cnf, err := config.NewConfig("yaml", "config.yaml") 28 // 29 //More docs http://beego.me/docs/module/config.md 30 package yaml 31 32 import ( 33 "bytes" 34 "encoding/json" 35 "errors" 36 "fmt" 37 "io/ioutil" 38 "log" 39 "os" 40 "strings" 41 "sync" 42 43 "github.com/astaxie/beego/config" 44 "github.com/beego/goyaml2" 45 ) 46 47 // Config is a yaml config parser and implements Config interface. 48 type Config struct{} 49 50 // Parse returns a ConfigContainer with parsed yaml config map. 51 func (yaml *Config) Parse(filename string) (y config.Configer, err error) { 52 cnf, err := ReadYmlReader(filename) 53 if err != nil { 54 return 55 } 56 y = &ConfigContainer{ 57 data: cnf, 58 } 59 return 60 } 61 62 // ParseData parse yaml data 63 func (yaml *Config) ParseData(data []byte) (config.Configer, error) { 64 cnf, err := parseYML(data) 65 if err != nil { 66 return nil, err 67 } 68 69 return &ConfigContainer{ 70 data: cnf, 71 }, nil 72 } 73 74 // ReadYmlReader Read yaml file to map. 75 // if json like, use json package, unless goyaml2 package. 76 func ReadYmlReader(path string) (cnf map[string]interface{}, err error) { 77 buf, err := ioutil.ReadFile(path) 78 if err != nil { 79 return 80 } 81 82 return parseYML(buf) 83 } 84 85 // parseYML parse yaml formatted []byte to map. 86 func parseYML(buf []byte) (cnf map[string]interface{}, err error) { 87 if len(buf) < 3 { 88 return 89 } 90 91 if string(buf[0:1]) == "{" { 92 log.Println("Look like a Json, try json umarshal") 93 err = json.Unmarshal(buf, &cnf) 94 if err == nil { 95 log.Println("It is Json Map") 96 return 97 } 98 } 99 100 data, err := goyaml2.Read(bytes.NewReader(buf)) 101 if err != nil { 102 log.Println("Goyaml2 ERR>", string(buf), err) 103 return 104 } 105 106 if data == nil { 107 log.Println("Goyaml2 output nil? Pls report bug\n" + string(buf)) 108 return 109 } 110 cnf, ok := data.(map[string]interface{}) 111 if !ok { 112 log.Println("Not a Map? >> ", string(buf), data) 113 cnf = nil 114 } 115 cnf = config.ExpandValueEnvForMap(cnf) 116 return 117 } 118 119 // ConfigContainer A Config represents the yaml configuration. 120 type ConfigContainer struct { 121 data map[string]interface{} 122 sync.RWMutex 123 } 124 125 // Bool returns the boolean value for a given key. 126 func (c *ConfigContainer) Bool(key string) (bool, error) { 127 v, err := c.getData(key) 128 if err != nil { 129 return false, err 130 } 131 return config.ParseBool(v) 132 } 133 134 // DefaultBool return the bool value if has no error 135 // otherwise return the defaultval 136 func (c *ConfigContainer) DefaultBool(key string, defaultval bool) bool { 137 v, err := c.Bool(key) 138 if err != nil { 139 return defaultval 140 } 141 return v 142 } 143 144 // Int returns the integer value for a given key. 145 func (c *ConfigContainer) Int(key string) (int, error) { 146 if v, err := c.getData(key); err != nil { 147 return 0, err 148 } else if vv, ok := v.(int); ok { 149 return vv, nil 150 } else if vv, ok := v.(int64); ok { 151 return int(vv), nil 152 } 153 return 0, errors.New("not int value") 154 } 155 156 // DefaultInt returns the integer value for a given key. 157 // if err != nil return defaultval 158 func (c *ConfigContainer) DefaultInt(key string, defaultval int) int { 159 v, err := c.Int(key) 160 if err != nil { 161 return defaultval 162 } 163 return v 164 } 165 166 // Int64 returns the int64 value for a given key. 167 func (c *ConfigContainer) Int64(key string) (int64, error) { 168 if v, err := c.getData(key); err != nil { 169 return 0, err 170 } else if vv, ok := v.(int64); ok { 171 return vv, nil 172 } 173 return 0, errors.New("not bool value") 174 } 175 176 // DefaultInt64 returns the int64 value for a given key. 177 // if err != nil return defaultval 178 func (c *ConfigContainer) DefaultInt64(key string, defaultval int64) int64 { 179 v, err := c.Int64(key) 180 if err != nil { 181 return defaultval 182 } 183 return v 184 } 185 186 // Float returns the float value for a given key. 187 func (c *ConfigContainer) Float(key string) (float64, error) { 188 if v, err := c.getData(key); err != nil { 189 return 0.0, err 190 } else if vv, ok := v.(float64); ok { 191 return vv, nil 192 } else if vv, ok := v.(int); ok { 193 return float64(vv), nil 194 } else if vv, ok := v.(int64); ok { 195 return float64(vv), nil 196 } 197 return 0.0, errors.New("not float64 value") 198 } 199 200 // DefaultFloat returns the float64 value for a given key. 201 // if err != nil return defaultval 202 func (c *ConfigContainer) DefaultFloat(key string, defaultval float64) float64 { 203 v, err := c.Float(key) 204 if err != nil { 205 return defaultval 206 } 207 return v 208 } 209 210 // String returns the string value for a given key. 211 func (c *ConfigContainer) String(key string) string { 212 if v, err := c.getData(key); err == nil { 213 if vv, ok := v.(string); ok { 214 return vv 215 } 216 } 217 return "" 218 } 219 220 // DefaultString returns the string value for a given key. 221 // if err != nil return defaultval 222 func (c *ConfigContainer) DefaultString(key string, defaultval string) string { 223 v := c.String(key) 224 if v == "" { 225 return defaultval 226 } 227 return v 228 } 229 230 // Strings returns the []string value for a given key. 231 func (c *ConfigContainer) Strings(key string) []string { 232 v := c.String(key) 233 if v == "" { 234 return nil 235 } 236 return strings.Split(v, ";") 237 } 238 239 // DefaultStrings returns the []string value for a given key. 240 // if err != nil return defaultval 241 func (c *ConfigContainer) DefaultStrings(key string, defaultval []string) []string { 242 v := c.Strings(key) 243 if v == nil { 244 return defaultval 245 } 246 return v 247 } 248 249 // GetSection returns map for the given section 250 func (c *ConfigContainer) GetSection(section string) (map[string]string, error) { 251 252 if v, ok := c.data[section]; ok { 253 return v.(map[string]string), nil 254 } 255 return nil, errors.New("not exist section") 256 } 257 258 // SaveConfigFile save the config into file 259 func (c *ConfigContainer) SaveConfigFile(filename string) (err error) { 260 // Write configuration file by filename. 261 f, err := os.Create(filename) 262 if err != nil { 263 return err 264 } 265 defer f.Close() 266 err = goyaml2.Write(f, c.data) 267 return err 268 } 269 270 // Set writes a new value for key. 271 func (c *ConfigContainer) Set(key, val string) error { 272 c.Lock() 273 defer c.Unlock() 274 c.data[key] = val 275 return nil 276 } 277 278 // DIY returns the raw value by a given key. 279 func (c *ConfigContainer) DIY(key string) (v interface{}, err error) { 280 return c.getData(key) 281 } 282 283 func (c *ConfigContainer) getData(key string) (interface{}, error) { 284 285 if len(key) == 0 { 286 return nil, errors.New("key is empty") 287 } 288 c.RLock() 289 defer c.RUnlock() 290 291 keys := strings.Split(key, ".") 292 tmpData := c.data 293 for idx, k := range keys { 294 if v, ok := tmpData[k]; ok { 295 switch v.(type) { 296 case map[string]interface{}: 297 { 298 tmpData = v.(map[string]interface{}) 299 if idx == len(keys)-1 { 300 return tmpData, nil 301 } 302 } 303 default: 304 { 305 return v, nil 306 } 307 308 } 309 } 310 } 311 return nil, fmt.Errorf("not exist key %q", key) 312 } 313 314 func init() { 315 config.Register("yaml", &Config{}) 316 }