Codebase list golang-github-spf13-viper / e194ae9
New upstream version 1.0.0+git20171109.4dddf7c Dr. Tobias Quathamer 6 years ago
8 changed file(s) with 65 addition(s) and 45 deletion(s). Raw diff Collapse all Expand all
1616
1717 script:
1818 - go install ./...
19 - diff -u <(echo -n) <(gofmt -d .)
1920 - go test -v ./...
2021
2122 after_success:
55
66 * [Hugo](http://gohugo.io)
77 * [EMC RexRay](http://rexray.readthedocs.org/en/stable/)
8 * [Imgur's Incus](https://github.com/Imgur/incus)
8 * [Imgur’s Incus](https://github.com/Imgur/incus)
99 * [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack)
1010 * [Docker Notary](https://github.com/docker/Notary)
1111 * [BloomApi](https://www.bloomapi.com/)
1212 * [doctl](https://github.com/digitalocean/doctl)
13 * [Clairctl](https://github.com/jgsqware/clairctl)
1314
1415 [![Build Status](https://travis-ci.org/spf13/viper.svg)](https://travis-ci.org/spf13/viper) [![Join the chat at https://gitter.im/spf13/viper](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![GoDoc](https://godoc.org/github.com/spf13/viper?status.svg)](https://godoc.org/github.com/spf13/viper)
1516
1617
1718 ## What is Viper?
1819
19 Viper is a complete configuration solution for go applications including 12 factor apps. It is designed
20 Viper is a complete configuration solution for Go applications including 12-Factor apps. It is designed
2021 to work within an application, and can handle all types of configuration needs
2122 and formats. It supports:
2223
6768 ### Establishing Defaults
6869
6970 A good configuration system will support default values. A default value is not
70 required for a key, but it's useful in the event that a key hasn’t been set via
71 required for a key, but it’s useful in the event that a key hasn’t been set via
7172 config file, environment variable, remote configuration or flag.
7273
7374 Examples:
115116 **Make sure you add all of the configPaths prior to calling `WatchConfig()`**
116117
117118 ```go
118 viper.WatchConfig()
119 viper.OnConfigChange(func(e fsnotify.Event) {
120 fmt.Println("Config file changed:", e.Name)
121 })
119 viper.WatchConfig()
120 viper.OnConfigChange(func(e fsnotify.Event) {
121 fmt.Println("Config file changed:", e.Name)
122 })
122123 ```
123124
124125 ### Reading Config from io.Reader
183184 * `AutomaticEnv()`
184185 * `BindEnv(string...) : error`
185186 * `SetEnvPrefix(string)`
186 * `SetEnvReplacer(string...) *strings.Replacer`
187 * `SetEnvKeyReplacer(string...) *strings.Replacer`
187188
188189 _When working with ENV variables, it’s important to recognize that Viper
189190 treats ENV variables as case sensitive._
210211 check for a environment variable with a name matching the key uppercased and
211212 prefixed with the `EnvPrefix` if set.
212213
213 `SetEnvReplacer` allows you to use a `strings.Replacer` object to rewrite Env
214 `SetEnvKeyReplacer` allows you to use a `strings.Replacer` object to rewrite Env
214215 keys to an extent. This is useful if you want to use `-` or something in your
215216 `Get()` calls, but want your environmental variables to use `_` delimiters. An
216217 example of using it can be found in `viper_test.go`.
235236 it is accessed. This means you can bind as early as you want, even in an
236237 `init()` function.
237238
238 The `BindPFlag()` method provides this functionality.
239 For individual flags, the `BindPFlag()` method provides this functionality.
239240
240241 Example:
241242
242243 ```go
243244 serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
244245 viper.BindPFlag("port", serverCmd.Flags().Lookup("port"))
246 ```
247
248 You can also bind an existing set of pflags (pflag.FlagSet):
249
250 Example:
251
252 ```go
253 pflag.Int("flagname", 1234, "help message for flagname")
254
255 pflag.Parse()
256 viper.BindPFlags(pflag.CommandLine)
257
258 i := viper.GetInt("flagname") // retrieve values from viper instead of pflag
245259 ```
246260
247261 The use of [pflag](https://github.com/spf13/pflag/) in Viper does not preclude
262276 )
263277
264278 func main() {
279
280 // using standard library "flag" package
281 flag.Int("flagname", 1234, "help message for flagname")
282
265283 pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
266284 pflag.Parse()
267 ...
285 viper.BindPFlags(pflag.CommandLine)
286
287 i := viper.GetInt("flagname") // retrieve value from viper
288
289 ...
268290 }
269291 ```
270292
271293 #### Flag interfaces
272294
273 Viper provides two Go interfaces to bind other flag systems if you don't use `Pflags`.
295 Viper provides two Go interfaces to bind other flag systems if you don’t use `Pflags`.
274296
275297 `FlagValue` represents a single flag. This is a very simple example on how to implement this interface:
276298
400422
401423 ## Getting Values From Viper
402424
403 In Viper, there are a few ways to get a value depending on the value's type.
425 In Viper, there are a few ways to get a value depending on the value’s type.
404426 The following functions and methods exist:
405427
406428 * `Get(key string) : interface{}`
530552 ```
531553
532554 which creates a cache based on config information formatted as `subv`.
533 Now it's easy to create these 2 caches separately as:
555 Now it’s easy to create these 2 caches separately as:
534556
535557 ```go
536558 cfg1 := viper.Sub("app.cache1")
6161 flag.Changed = true //hack for pflag usage
6262
6363 assert.Equal(t, "testing_mutate", Get("testvalue"))
64
6564 }
3232 if err != nil {
3333 return nil, err
3434 }
35 resp,err := cm.Get(rp.Path())
35 resp, err := cm.Get(rp.Path())
3636 if err != nil {
3737 return nil, err
3838 }
3939
4040 return bytes.NewReader(resp), nil
4141 }
42
4243 func (rc remoteConfigProvider) WatchChannel(rp viper.RemoteProvider) (<-chan *viper.RemoteResponse, chan bool) {
4344 cm, err := getConfigManager(rp)
4445 if err != nil {
4647 }
4748 quit := make(chan bool)
4849 quitwc := make(chan bool)
49 viperResponsCh := make(chan *viper.RemoteResponse)
50 viperResponsCh := make(chan *viper.RemoteResponse)
5051 cryptoResponseCh := cm.Watch(rp.Path(), quit)
5152 // need this function to convert the Channel response form crypt.Response to viper.Response
52 go func(cr <-chan *crypt.Response,vr chan<- *viper.RemoteResponse, quitwc <-chan bool, quit chan<- bool) {
53 go func(cr <-chan *crypt.Response, vr chan<- *viper.RemoteResponse, quitwc <-chan bool, quit chan<- bool) {
5354 for {
5455 select {
55 case <- quitwc:
56 case <-quitwc:
5657 quit <- true
5758 return
5859 case resp := <-cr:
6465 }
6566
6667 }
67 }(cryptoResponseCh,viperResponsCh,quitwc,quit)
68 }(cryptoResponseCh, viperResponsCh, quitwc, quit)
6869
69 return viperResponsCh,quitwc
70
70 return viperResponsCh, quitwc
7171 }
7272
73
7473 func getConfigManager(rp viper.RemoteProvider) (crypt.ConfigManager, error) {
75
7674 var cm crypt.ConfigManager
7775 var err error
7876
9896 return nil, err
9997 }
10098 return cm, nil
101
10299 }
103100
104101 func init() {
2323 "github.com/hashicorp/hcl"
2424 "github.com/magiconair/properties"
2525 toml "github.com/pelletier/go-toml"
26 "github.com/spf13/afero"
2627 "github.com/spf13/cast"
2728 jww "github.com/spf13/jwalterweatherman"
2829 "gopkg.in/yaml.v2"
120121 }
121122
122123 // Check if File / Directory Exists
123 func exists(path string) (bool, error) {
124 _, err := v.fs.Stat(path)
124 func exists(fs afero.Fs, path string) (bool, error) {
125 _, err := fs.Stat(path)
125126 if err == nil {
126127 return true, nil
127128 }
1515 )
1616
1717 func TestCopyAndInsensitiviseMap(t *testing.T) {
18
1918 var (
2019 given = map[string]interface{}{
2120 "Foo": 32,
6868 }
6969
7070 // UnsupportedRemoteProviderError denotes encountering an unsupported remote
71 // provider. Currently only etcd and Consul are
72 // supported.
71 // provider. Currently only etcd and Consul are supported.
7372 type UnsupportedRemoteProviderError string
7473
7574 // Error returns the formatted remote provider error.
282281 }()
283282 }
284283
285 // SetConfigFile explicitly defines the path, name and extension of the config file
286 // Viper will use this and not check any of the config paths
284 // SetConfigFile explicitly defines the path, name and extension of the config file.
285 // Viper will use this and not check any of the config paths.
287286 func SetConfigFile(in string) { v.SetConfigFile(in) }
288287 func (v *Viper) SetConfigFile(in string) {
289288 if in != "" {
292291 }
293292
294293 // SetEnvPrefix defines a prefix that ENVIRONMENT variables will use.
295 // E.g. if your prefix is "spf", the env registry
296 // will look for env. variables that start with "SPF_"
294 // E.g. if your prefix is "spf", the env registry will look for env
295 // variables that start with "SPF_".
297296 func SetEnvPrefix(in string) { v.SetEnvPrefix(in) }
298297 func (v *Viper) SetEnvPrefix(in string) {
299298 if in != "" {
311310
312311 // TODO: should getEnv logic be moved into find(). Can generalize the use of
313312 // rewriting keys many things, Ex: Get('someKey') -> some_key
314 // (cammel case to snake case for JSON keys perhaps)
313 // (camel case to snake case for JSON keys perhaps)
315314
316315 // getEnv is a wrapper around os.Getenv which replaces characters in the original
317 // key. This allows env vars which have different keys then the config object
318 // keys
316 // key. This allows env vars which have different keys than the config object
317 // keys.
319318 func (v *Viper) getEnv(key string) string {
320319 if v.envKeyReplacer != nil {
321320 key = v.envKeyReplacer.Replace(key)
323322 return os.Getenv(key)
324323 }
325324
326 // ConfigFileUsed returns the file used to populate the config registry
325 // ConfigFileUsed returns the file used to populate the config registry.
327326 func ConfigFileUsed() string { return v.ConfigFileUsed() }
328327 func (v *Viper) ConfigFileUsed() string { return v.configFile }
329328
747746 }
748747
749748 // defaultDecoderConfig returns default mapsstructure.DecoderConfig with suppot
750 // of time.Duration values
749 // of time.Duration values & string slices
751750 func defaultDecoderConfig(output interface{}) *mapstructure.DecoderConfig {
752751 return &mapstructure.DecoderConfig{
753752 Metadata: nil,
754753 Result: output,
755754 WeaklyTypedInput: true,
756 DecodeHook: mapstructure.StringToTimeDurationHookFunc(),
755 DecodeHook: mapstructure.ComposeDecodeHookFunc(
756 mapstructure.StringToTimeDurationHookFunc(),
757 mapstructure.StringToSliceHookFunc(","),
758 ),
757759 }
758760 }
759761
814816 }
815817
816818 // BindFlagValue binds a specific key to a FlagValue.
817 // Example(where serverCmd is a Cobra instance):
819 // Example (where serverCmd is a Cobra instance):
818820 //
819821 // serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
820822 // Viper.BindFlagValue("port", serverCmd.Flags().Lookup("port"))
12871289 return v.watchKeyValueConfigOnChannel()
12881290 }
12891291
1290 // Unmarshall a Reader into a map.
1292 // Unmarshal a Reader into a map.
12911293 // Should probably be an unexported function.
12921294 func unmarshalReader(in io.Reader, c map[string]interface{}) error {
12931295 return v.unmarshalReader(in, c)
15341536 jww.DEBUG.Println("Searching for config in ", in)
15351537 for _, ext := range SupportedExts {
15361538 jww.DEBUG.Println("Checking for", filepath.Join(in, v.configName+"."+ext))
1537 if b, _ := exists(filepath.Join(in, v.configName+"."+ext)); b {
1539 if b, _ := exists(v.fs, filepath.Join(in, v.configName+"."+ext)); b {
15381540 jww.DEBUG.Println("Found: ", filepath.Join(in, v.configName+"."+ext))
15391541 return filepath.Join(in, v.configName+"."+ext)
15401542 }
15461548 // Search all configPaths for any config file.
15471549 // Returns the first path that exists (and is a config file).
15481550 func (v *Viper) findConfigFile() (string, error) {
1549
15501551 jww.INFO.Println("Searching for config in ", v.configPaths)
15511552
15521553 for _, cp := range v.configPaths {
416416 assert.Equal(t, "13", Get("bar"))
417417 }
418418
419 func TestSetEnvReplacer(t *testing.T) {
419 func TestSetEnvKeyReplacer(t *testing.T) {
420420 Reset()
421421
422422 AutomaticEnv()