blob: 5e01aa5210f4acc9d363f44e6f84e71b2f58ad85 [file] [log] [blame]
spf1398be0712014-04-04 17:21:59 -04001// Copyright © 2014 Steve Francia <spf@spf13.com>.
2//
3// Use of this source code is governed by an MIT-style
4// license that can be found in the LICENSE file.
5
spf13181a3b52014-09-27 14:03:00 -07006// Viper is a application configuration system.
7// It believes that applications can be configured a variety of ways
Brian Ketelsen3d818242014-10-24 15:38:01 -04008// via flags, ENVIRONMENT variables, configuration files retrieved
9// from the file system, or a remote key/value store.
spf13181a3b52014-09-27 14:03:00 -070010
11// Each item takes precedence over the item below it:
12
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -040013// overrides
spf13181a3b52014-09-27 14:03:00 -070014// flag
15// env
16// config
Brian Ketelsen3d818242014-10-24 15:38:01 -040017// key/value store
spf13181a3b52014-09-27 14:03:00 -070018// default
19
spf1398be0712014-04-04 17:21:59 -040020package viper
21
22import (
23 "bytes"
spf1398be0712014-04-04 17:21:59 -040024 "fmt"
25 "io"
26 "io/ioutil"
27 "os"
spf1398be0712014-04-04 17:21:59 -040028 "path/filepath"
Brian Ketelsen3d818242014-10-24 15:38:01 -040029 "reflect"
spf13bcb02e22014-04-05 01:19:39 -040030 "strings"
spf1398be0712014-04-04 17:21:59 -040031 "time"
32
spf1398be0712014-04-04 17:21:59 -040033 "github.com/kr/pretty"
spf13af373af2014-06-26 17:58:55 -040034 "github.com/mitchellh/mapstructure"
jackspiroud028fd62015-07-30 15:44:12 -050035 "github.com/spf13/cast"
spf1398be0712014-04-04 17:21:59 -040036 jww "github.com/spf13/jwalterweatherman"
spf137c427402014-06-27 12:29:37 -040037 "github.com/spf13/pflag"
spf1398be0712014-04-04 17:21:59 -040038)
39
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -050040var v *Viper
spf1329f18582014-12-05 03:55:51 +010041
42func init() {
43 v = New()
44}
45
bepbe5ff3e2015-05-30 21:28:33 +020046type remoteConfigFactory interface {
47 Get(rp RemoteProvider) (io.Reader, error)
48 Watch(rp RemoteProvider) (io.Reader, error)
49}
50
51// RemoteConfig is optional, see the remote package
52var RemoteConfig remoteConfigFactory
53
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -040054// Denotes encountering an unsupported
55// configuration filetype.
spf1329f18582014-12-05 03:55:51 +010056type UnsupportedConfigError string
57
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -040058// Returns the formatted configuration error.
spf1329f18582014-12-05 03:55:51 +010059func (str UnsupportedConfigError) Error() string {
60 return fmt.Sprintf("Unsupported Config Type %q", string(str))
61}
62
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -040063// Denotes encountering an unsupported remote
64// provider. Currently only Etcd and Consul are
65// supported.
spf1329f18582014-12-05 03:55:51 +010066type UnsupportedRemoteProviderError string
67
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -040068// Returns the formatted remote provider error.
spf1329f18582014-12-05 03:55:51 +010069func (str UnsupportedRemoteProviderError) Error() string {
70 return fmt.Sprintf("Unsupported Remote Provider Type %q", string(str))
71}
72
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -040073// Denotes encountering an error while trying to
74// pull the configuration from the remote provider.
spf1329f18582014-12-05 03:55:51 +010075type RemoteConfigError string
76
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -040077// Returns the formatted remote provider error
spf1329f18582014-12-05 03:55:51 +010078func (rce RemoteConfigError) Error() string {
79 return fmt.Sprintf("Remote Configurations Error: %s", string(rce))
80}
81
Vlad Didenko9fca1012015-08-01 19:37:27 -050082// Denotes failing to find configuration file.
83type ConfigFileNotFoundError struct {
84 name, locations string
85}
86
87// Returns the formatted configuration error.
88func (fnfe ConfigFileNotFoundError) Error() string {
89 return fmt.Sprintf("Config File %q Not Found in %q", fnfe.name, fnfe.locations)
90}
91
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -040092// Viper is a prioritized configuration registry. It
93// maintains a set of configuration sources, fetches
94// values to populate those, and provides them according
95// to the source's priority.
96// The priority of the sources is the following:
97// 1. overrides
98// 2. flags
99// 3. env. variables
100// 4. config file
101// 5. key/value store
102// 6. defaults
103//
104// For example, if values from the following sources were loaded:
105//
106// Defaults : {
107// "secret": "",
108// "user": "default",
109// "endpoint": "https://localhost"
110// }
111// Config : {
112// "user": "root"
113// "secret": "defaultsecret"
114// }
115// Env : {
116// "secret": "somesecretkey"
117// }
118//
119// The resulting config will have the following values:
120//
121// {
122// "secret": "somesecretkey",
123// "user": "root",
124// "endpoint": "https://localhost"
125// }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500126type Viper struct {
Kiril Zvezdarovc174e242015-04-26 15:02:19 -0400127 // Delimiter that separates a list of keys
128 // used to access a nested value in one go
129 keyDelim string
130
spf1329f18582014-12-05 03:55:51 +0100131 // A set of paths to look for the config file in
132 configPaths []string
133
134 // A set of remote providers to search for the configuration
bepbe5ff3e2015-05-30 21:28:33 +0200135 remoteProviders []*defaultRemoteProvider
spf1329f18582014-12-05 03:55:51 +0100136
137 // Name of file to look for inside the path
138 configName string
139 configFile string
140 configType string
spf131022d752014-12-22 18:31:11 -0500141 envPrefix string
spf1329f18582014-12-05 03:55:51 +0100142
spf13d8f2aa72014-12-22 22:47:25 -0500143 automaticEnvApplied bool
Chance Zibolski03fb74b2015-03-06 11:21:17 -0800144 envKeyReplacer *strings.Replacer
spf13d8f2aa72014-12-22 22:47:25 -0500145
spf1329f18582014-12-05 03:55:51 +0100146 config map[string]interface{}
147 override map[string]interface{}
148 defaults map[string]interface{}
149 kvstore map[string]interface{}
150 pflags map[string]*pflag.Flag
151 env map[string]string
152 aliases map[string]string
153}
154
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400155// Returns an initialized Viper instance.
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500156func New() *Viper {
157 v := new(Viper)
Kiril Zvezdarovc174e242015-04-26 15:02:19 -0400158 v.keyDelim = "."
spf1329f18582014-12-05 03:55:51 +0100159 v.configName = "config"
160 v.config = make(map[string]interface{})
161 v.override = make(map[string]interface{})
162 v.defaults = make(map[string]interface{})
163 v.kvstore = make(map[string]interface{})
164 v.pflags = make(map[string]*pflag.Flag)
165 v.env = make(map[string]string)
166 v.aliases = make(map[string]string)
167
168 return v
169}
170
Ross Cooperman90734832015-02-19 10:39:44 -0500171// Intended for testing, will reset all to default settings.
172// In the public interface for the viper package so applications
173// can use it in their testing as well.
174func Reset() {
175 v = New()
176 SupportedExts = []string{"json", "toml", "yaml", "yml"}
177 SupportedRemoteProviders = []string{"etcd", "consul"}
178}
179
bepbe5ff3e2015-05-30 21:28:33 +0200180type defaultRemoteProvider struct {
Brian Ketelsen3d818242014-10-24 15:38:01 -0400181 provider string
182 endpoint string
183 path string
184 secretKeyring string
185}
186
bepbe5ff3e2015-05-30 21:28:33 +0200187func (rp defaultRemoteProvider) Provider() string {
188 return rp.provider
189}
190
191func (rp defaultRemoteProvider) Endpoint() string {
192 return rp.endpoint
193}
194
195func (rp defaultRemoteProvider) Path() string {
196 return rp.path
197}
198
199func (rp defaultRemoteProvider) SecretKeyring() string {
200 return rp.secretKeyring
201}
202
203// RemoteProvider stores the configuration necessary
204// to connect to a remote key/value store.
205// Optional secretKeyring to unencrypt encrypted values
206// can be provided.
207type RemoteProvider interface {
208 Provider() string
209 Endpoint() string
210 Path() string
211 SecretKeyring() string
212}
213
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400214// Universally supported extensions.
Wayne Walkerba3382d2015-04-14 13:15:02 -0500215var SupportedExts []string = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop"}
spf1398be0712014-04-04 17:21:59 -0400216
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400217// Universally supported remote providers.
spf1329f18582014-12-05 03:55:51 +0100218var SupportedRemoteProviders []string = []string{"etcd", "consul"}
spf1398be0712014-04-04 17:21:59 -0400219
spf1338c6d9e2014-07-11 10:42:07 -0400220// Explicitly define the path, name and extension of the config file
221// Viper will use this and not check any of the config paths
spf1329f18582014-12-05 03:55:51 +0100222func SetConfigFile(in string) { v.SetConfigFile(in) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500223func (v *Viper) SetConfigFile(in string) {
spf1398be0712014-04-04 17:21:59 -0400224 if in != "" {
spf1329f18582014-12-05 03:55:51 +0100225 v.configFile = in
spf1398be0712014-04-04 17:21:59 -0400226 }
227}
228
spf131022d752014-12-22 18:31:11 -0500229// Define a prefix that ENVIRONMENT variables will use.
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400230// E.g. if your prefix is "spf", the env registry
231// will look for env. variables that start with "SPF_"
spf131022d752014-12-22 18:31:11 -0500232func SetEnvPrefix(in string) { v.SetEnvPrefix(in) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500233func (v *Viper) SetEnvPrefix(in string) {
spf131022d752014-12-22 18:31:11 -0500234 if in != "" {
235 v.envPrefix = in
236 }
237}
238
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500239func (v *Viper) mergeWithEnvPrefix(in string) string {
spf131022d752014-12-22 18:31:11 -0500240 if v.envPrefix != "" {
spf13d8f2aa72014-12-22 22:47:25 -0500241 return strings.ToUpper(v.envPrefix + "_" + in)
spf131022d752014-12-22 18:31:11 -0500242 }
243
spf13d8f2aa72014-12-22 22:47:25 -0500244 return strings.ToUpper(in)
spf131022d752014-12-22 18:31:11 -0500245}
246
Chance Zibolski03fb74b2015-03-06 11:21:17 -0800247// TODO: should getEnv logic be moved into find(). Can generalize the use of
248// rewriting keys many things, Ex: Get('someKey') -> some_key
249// (cammel case to snake case for JSON keys perhaps)
250
251// getEnv s a wrapper around os.Getenv which replaces characters in the original
252// key. This allows env vars which have different keys then the config object
253// keys
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500254func (v *Viper) getEnv(key string) string {
Chance Zibolski03fb74b2015-03-06 11:21:17 -0800255 if v.envKeyReplacer != nil {
256 key = v.envKeyReplacer.Replace(key)
257 }
258 return os.Getenv(key)
259}
260
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400261// Return the file used to populate the config registry
spf1329f18582014-12-05 03:55:51 +0100262func ConfigFileUsed() string { return v.ConfigFileUsed() }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500263func (v *Viper) ConfigFileUsed() string { return v.configFile }
spf138b744a92014-04-07 23:35:40 -0400264
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500265// Add a path for Viper to search for the config file in.
spf1338c6d9e2014-07-11 10:42:07 -0400266// Can be called multiple times to define multiple search paths.
spf1329f18582014-12-05 03:55:51 +0100267func AddConfigPath(in string) { v.AddConfigPath(in) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500268func (v *Viper) AddConfigPath(in string) {
spf1398be0712014-04-04 17:21:59 -0400269 if in != "" {
270 absin := absPathify(in)
271 jww.INFO.Println("adding", absin, "to paths to search")
spf1329f18582014-12-05 03:55:51 +0100272 if !stringInSlice(absin, v.configPaths) {
273 v.configPaths = append(v.configPaths, absin)
spf1398be0712014-04-04 17:21:59 -0400274 }
275 }
276}
277
Brian Ketelsen3d818242014-10-24 15:38:01 -0400278// AddRemoteProvider adds a remote configuration source.
279// Remote Providers are searched in the order they are added.
280// provider is a string value, "etcd" or "consul" are currently supported.
281// endpoint is the url. etcd requires http://ip:port consul requires ip:port
282// path is the path in the k/v store to retrieve configuration
283// To retrieve a config file called myapp.json from /configs/myapp.json
284// you should set path to /configs and set config name (SetConfigName()) to
285// "myapp"
286func AddRemoteProvider(provider, endpoint, path string) error {
spf1329f18582014-12-05 03:55:51 +0100287 return v.AddRemoteProvider(provider, endpoint, path)
288}
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500289func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error {
Brian Ketelsen3d818242014-10-24 15:38:01 -0400290 if !stringInSlice(provider, SupportedRemoteProviders) {
291 return UnsupportedRemoteProviderError(provider)
292 }
293 if provider != "" && endpoint != "" {
294 jww.INFO.Printf("adding %s:%s to remote provider list", provider, endpoint)
bepbe5ff3e2015-05-30 21:28:33 +0200295 rp := &defaultRemoteProvider{
Brian Ketelsen3d818242014-10-24 15:38:01 -0400296 endpoint: endpoint,
297 provider: provider,
Brian Ketelsen5e1d5e72014-10-27 12:21:03 -0400298 path: path,
Brian Ketelsen3d818242014-10-24 15:38:01 -0400299 }
spf1329f18582014-12-05 03:55:51 +0100300 if !v.providerPathExists(rp) {
301 v.remoteProviders = append(v.remoteProviders, rp)
Brian Ketelsen3d818242014-10-24 15:38:01 -0400302 }
303 }
304 return nil
305}
306
307// AddSecureRemoteProvider adds a remote configuration source.
308// Secure Remote Providers are searched in the order they are added.
309// provider is a string value, "etcd" or "consul" are currently supported.
310// endpoint is the url. etcd requires http://ip:port consul requires ip:port
311// secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg
312// path is the path in the k/v store to retrieve configuration
313// To retrieve a config file called myapp.json from /configs/myapp.json
314// you should set path to /configs and set config name (SetConfigName()) to
315// "myapp"
316// Secure Remote Providers are implemented with github.com/xordataexchange/crypt
Brian Ketelsen5e1d5e72014-10-27 12:21:03 -0400317func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
spf1329f18582014-12-05 03:55:51 +0100318 return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring)
319}
320
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500321func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
Brian Ketelsen3d818242014-10-24 15:38:01 -0400322 if !stringInSlice(provider, SupportedRemoteProviders) {
323 return UnsupportedRemoteProviderError(provider)
324 }
325 if provider != "" && endpoint != "" {
326 jww.INFO.Printf("adding %s:%s to remote provider list", provider, endpoint)
bepbe5ff3e2015-05-30 21:28:33 +0200327 rp := &defaultRemoteProvider{
Kiril Zvezdarovdb7ff932015-06-21 19:19:00 -0400328 endpoint: endpoint,
329 provider: provider,
330 path: path,
331 secretKeyring: secretkeyring,
Brian Ketelsen3d818242014-10-24 15:38:01 -0400332 }
spf1329f18582014-12-05 03:55:51 +0100333 if !v.providerPathExists(rp) {
334 v.remoteProviders = append(v.remoteProviders, rp)
Brian Ketelsen3d818242014-10-24 15:38:01 -0400335 }
336 }
337 return nil
338}
339
bepbe5ff3e2015-05-30 21:28:33 +0200340func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool {
spf1329f18582014-12-05 03:55:51 +0100341 for _, y := range v.remoteProviders {
Brian Ketelsen3d818242014-10-24 15:38:01 -0400342 if reflect.DeepEqual(y, p) {
343 return true
344 }
345 }
346 return false
347}
348
Kiril Zvezdarovc174e242015-04-26 15:02:19 -0400349func (v *Viper) searchMap(source map[string]interface{}, path []string) interface{} {
350
351 if len(path) == 0 {
352 return source
353 }
354
355 if next, ok := source[path[0]]; ok {
356 switch next.(type) {
Dotan Nahum28ada1e2015-05-27 18:15:02 +0300357 case map[interface{}]interface{}:
358 return v.searchMap(cast.ToStringMap(next), path[1:])
Kiril Zvezdarovc174e242015-04-26 15:02:19 -0400359 case map[string]interface{}:
360 // Type assertion is safe here since it is only reached
361 // if the type of `next` is the same as the type being asserted
362 return v.searchMap(next.(map[string]interface{}), path[1:])
363 default:
364 return next
365 }
366 } else {
367 return nil
368 }
369}
370
spf1318a87c02014-12-05 17:04:40 +0100371// Viper is essentially repository for configurations
372// Get can retrieve any value given the key to use
373// Get has the behavior of returning the value associated with the first
374// place from where it is set. Viper will check in the following order:
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400375// override, flag, env, config file, key/value store, default
spf1318a87c02014-12-05 17:04:40 +0100376//
377// Get returns an interface. For a specific value use one of the Get____ methods.
378func Get(key string) interface{} { return v.Get(key) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500379func (v *Viper) Get(key string) interface{} {
Kiril Zvezdarovc174e242015-04-26 15:02:19 -0400380 path := strings.Split(key, v.keyDelim)
381
382 val := v.find(strings.ToLower(key))
spf1318a87c02014-12-05 17:04:40 +0100383
384 if val == nil {
Kiril Zvezdarovc174e242015-04-26 15:02:19 -0400385 source := v.find(path[0])
386 if source == nil {
387 return nil
388 }
389
390 if reflect.TypeOf(source).Kind() == reflect.Map {
391 val = v.searchMap(cast.ToStringMap(source), path[1:])
392 }
spf1318a87c02014-12-05 17:04:40 +0100393 }
394
395 switch val.(type) {
396 case bool:
397 return cast.ToBool(val)
398 case string:
399 return cast.ToString(val)
400 case int64, int32, int16, int8, int:
401 return cast.ToInt(val)
402 case float64, float32:
403 return cast.ToFloat64(val)
404 case time.Time:
405 return cast.ToTime(val)
Chance Zibolskiededa042015-02-18 19:03:20 -0800406 case time.Duration:
407 return cast.ToDuration(val)
spf1318a87c02014-12-05 17:04:40 +0100408 case []string:
409 return val
410 }
411 return val
412}
413
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400414// Returns the value associated with the key as a string
spf1329f18582014-12-05 03:55:51 +0100415func GetString(key string) string { return v.GetString(key) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500416func (v *Viper) GetString(key string) string {
kgv29092392014-12-09 15:42:09 +0300417 return cast.ToString(v.Get(key))
spf1398be0712014-04-04 17:21:59 -0400418}
419
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400420// Returns the value associated with the key asa boolean
spf1329f18582014-12-05 03:55:51 +0100421func GetBool(key string) bool { return v.GetBool(key) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500422func (v *Viper) GetBool(key string) bool {
kgv29092392014-12-09 15:42:09 +0300423 return cast.ToBool(v.Get(key))
spf1398be0712014-04-04 17:21:59 -0400424}
425
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400426// Returns the value associated with the key as an integer
spf1329f18582014-12-05 03:55:51 +0100427func GetInt(key string) int { return v.GetInt(key) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500428func (v *Viper) GetInt(key string) int {
kgv29092392014-12-09 15:42:09 +0300429 return cast.ToInt(v.Get(key))
spf1398be0712014-04-04 17:21:59 -0400430}
431
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400432// Returns the value associated with the key as a float64
spf1329f18582014-12-05 03:55:51 +0100433func GetFloat64(key string) float64 { return v.GetFloat64(key) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500434func (v *Viper) GetFloat64(key string) float64 {
kgv29092392014-12-09 15:42:09 +0300435 return cast.ToFloat64(v.Get(key))
spf1398be0712014-04-04 17:21:59 -0400436}
437
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400438// Returns the value associated with the key as time
spf1329f18582014-12-05 03:55:51 +0100439func GetTime(key string) time.Time { return v.GetTime(key) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500440func (v *Viper) GetTime(key string) time.Time {
kgv29092392014-12-09 15:42:09 +0300441 return cast.ToTime(v.Get(key))
spf1398be0712014-04-04 17:21:59 -0400442}
443
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400444// Returns the value associated with the key as a duration
Chance Zibolskiededa042015-02-18 19:03:20 -0800445func GetDuration(key string) time.Duration { return v.GetDuration(key) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500446func (v *Viper) GetDuration(key string) time.Duration {
Chance Zibolskiededa042015-02-18 19:03:20 -0800447 return cast.ToDuration(v.Get(key))
448}
449
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400450// Returns the value associated with the key as a slice of strings
spf1329f18582014-12-05 03:55:51 +0100451func GetStringSlice(key string) []string { return v.GetStringSlice(key) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500452func (v *Viper) GetStringSlice(key string) []string {
kgv29092392014-12-09 15:42:09 +0300453 return cast.ToStringSlice(v.Get(key))
spf13bcb02e22014-04-05 01:19:39 -0400454}
455
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400456// Returns the value associated with the key as a map of interfaces
spf1329f18582014-12-05 03:55:51 +0100457func GetStringMap(key string) map[string]interface{} { return v.GetStringMap(key) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500458func (v *Viper) GetStringMap(key string) map[string]interface{} {
kgv29092392014-12-09 15:42:09 +0300459 return cast.ToStringMap(v.Get(key))
spf13bcb02e22014-04-05 01:19:39 -0400460}
461
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400462// Returns the value associated with the key as a map of strings
spf1329f18582014-12-05 03:55:51 +0100463func GetStringMapString(key string) map[string]string { return v.GetStringMapString(key) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500464func (v *Viper) GetStringMapString(key string) map[string]string {
kgv29092392014-12-09 15:42:09 +0300465 return cast.ToStringMapString(v.Get(key))
spf1398be0712014-04-04 17:21:59 -0400466}
467
jackspirou3c0ff862015-08-03 11:42:26 -0500468// Returns the value associated with the key as a map to a slice of strings.
jackspiroucc1c9a82015-07-30 15:43:18 -0500469func GetStringMapStringSlice(key string) map[string][]string { return v.GetStringMapStringSlice(key) }
jackspirou09ba0a62015-07-30 15:46:38 -0500470func (v *Viper) GetStringMapStringSlice(key string) map[string][]string {
jackspiroub9316c32015-07-30 15:27:34 -0500471 return cast.ToStringMapStringSlice(v.Get(key))
472}
473
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400474// Returns the size of the value associated with the given key
475// in bytes.
Daniel Eloffe1339042015-02-28 16:03:22 -0500476func GetSizeInBytes(key string) uint { return v.GetSizeInBytes(key) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500477func (v *Viper) GetSizeInBytes(key string) uint {
Daniel Eloffe1339042015-02-28 16:03:22 -0500478 sizeStr := cast.ToString(v.Get(key))
479 return parseSizeInBytes(sizeStr)
480}
481
spf13c5a90562014-07-11 10:41:45 -0400482// Takes a single key and marshals it into a Struct
spf1329f18582014-12-05 03:55:51 +0100483func MarshalKey(key string, rawVal interface{}) error { return v.MarshalKey(key, rawVal) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500484func (v *Viper) MarshalKey(key string, rawVal interface{}) error {
kgv29092392014-12-09 15:42:09 +0300485 return mapstructure.Decode(v.Get(key), rawVal)
spf13af373af2014-06-26 17:58:55 -0400486}
487
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400488// Marshals the config into a Struct. Make sure that the tags
489// on the fields of the structure are properly set.
spf1329f18582014-12-05 03:55:51 +0100490func Marshal(rawVal interface{}) error { return v.Marshal(rawVal) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500491func (v *Viper) Marshal(rawVal interface{}) error {
Kiril Zvezdarov2e2f3b22015-02-16 23:42:08 -0500492 err := mapstructure.WeakDecode(v.AllSettings(), rawVal)
493
Brian Ketelsen3d818242014-10-24 15:38:01 -0400494 if err != nil {
495 return err
496 }
Nate Finch2b24bea2014-08-05 07:35:21 -0400497
Anthony Fok5b0b9262015-01-22 00:43:42 -0700498 v.insensitiviseMaps()
Nate Finch2b24bea2014-08-05 07:35:21 -0400499
500 return nil
spf13af373af2014-06-26 17:58:55 -0400501}
502
Kiril Zvezdarov24dd8772015-04-01 21:38:54 -0400503// Bind a full flag set to the configuration, using each flag's long
504// name as the config key.
505func BindPFlags(flags *pflag.FlagSet) (err error) { return v.BindPFlags(flags) }
506func (v *Viper) BindPFlags(flags *pflag.FlagSet) (err error) {
507 flags.VisitAll(func(flag *pflag.Flag) {
508 if err != nil {
509 // an error has been encountered in one of the previous flags
510 return
511 }
512
513 err = v.BindPFlag(flag.Name, flag)
Kiril Zvezdarovc861bde2015-04-01 21:42:06 -0400514 switch flag.Value.Type() {
515 case "int", "int8", "int16", "int32", "int64":
516 v.SetDefault(flag.Name, cast.ToInt(flag.Value.String()))
517 case "bool":
518 v.SetDefault(flag.Name, cast.ToBool(flag.Value.String()))
519 default:
520 v.SetDefault(flag.Name, flag.Value.String())
521 }
Kiril Zvezdarov24dd8772015-04-01 21:38:54 -0400522 })
523 return
524}
525
spf1338c6d9e2014-07-11 10:42:07 -0400526// Bind a specific key to a flag (as used by cobra)
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400527// Example(where serverCmd is a Cobra instance):
spf1338c6d9e2014-07-11 10:42:07 -0400528//
529// serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500530// Viper.BindPFlag("port", serverCmd.Flags().Lookup("port"))
spf1338c6d9e2014-07-11 10:42:07 -0400531//
spf1329f18582014-12-05 03:55:51 +0100532func BindPFlag(key string, flag *pflag.Flag) (err error) { return v.BindPFlag(key, flag) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500533func (v *Viper) BindPFlag(key string, flag *pflag.Flag) (err error) {
spf137c427402014-06-27 12:29:37 -0400534 if flag == nil {
535 return fmt.Errorf("flag for %q is nil", key)
536 }
spf1329f18582014-12-05 03:55:51 +0100537 v.pflags[strings.ToLower(key)] = flag
spf131cebee82014-07-11 10:28:03 -0400538
539 switch flag.Value.Type() {
540 case "int", "int8", "int16", "int32", "int64":
Vlad Didenkof14e1ba2015-07-18 17:30:30 -0500541 v.SetDefault(key, cast.ToInt(flag.Value.String()))
spf131cebee82014-07-11 10:28:03 -0400542 case "bool":
Vlad Didenkof14e1ba2015-07-18 17:30:30 -0500543 v.SetDefault(key, cast.ToBool(flag.Value.String()))
spf131cebee82014-07-11 10:28:03 -0400544 default:
Vlad Didenkof14e1ba2015-07-18 17:30:30 -0500545 v.SetDefault(key, flag.Value.String())
spf131cebee82014-07-11 10:28:03 -0400546 }
spf137c427402014-06-27 12:29:37 -0400547 return nil
548}
549
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500550// Binds a Viper key to a ENV variable
spf13181a3b52014-09-27 14:03:00 -0700551// ENV variables are case sensitive
552// If only a key is provided, it will use the env key matching the key, uppercased.
spf131022d752014-12-22 18:31:11 -0500553// EnvPrefix will be used when set when env name is not provided.
spf1329f18582014-12-05 03:55:51 +0100554func BindEnv(input ...string) (err error) { return v.BindEnv(input...) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500555func (v *Viper) BindEnv(input ...string) (err error) {
spf13181a3b52014-09-27 14:03:00 -0700556 var key, envkey string
557 if len(input) == 0 {
558 return fmt.Errorf("BindEnv missing key to bind to")
559 }
560
Chris Hamant1b8adf42014-10-09 16:39:24 -0400561 key = strings.ToLower(input[0])
spf13181a3b52014-09-27 14:03:00 -0700562
563 if len(input) == 1 {
spf13d8f2aa72014-12-22 22:47:25 -0500564 envkey = v.mergeWithEnvPrefix(key)
spf13181a3b52014-09-27 14:03:00 -0700565 } else {
566 envkey = input[1]
567 }
568
spf1329f18582014-12-05 03:55:51 +0100569 v.env[key] = envkey
spf13181a3b52014-09-27 14:03:00 -0700570
571 return nil
572}
573
spf1318a87c02014-12-05 17:04:40 +0100574// Given a key, find the value
575// Viper will check in the following order:
576// flag, env, config file, key/value store, default
577// Viper will check to see if an alias exists first
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500578func (v *Viper) find(key string) interface{} {
spf1398be0712014-04-04 17:21:59 -0400579 var val interface{}
580 var exists bool
581
spf13bcb02e22014-04-05 01:19:39 -0400582 // if the requested key is an alias, then return the proper key
spf1329f18582014-12-05 03:55:51 +0100583 key = v.realKey(key)
spf1398be0712014-04-04 17:21:59 -0400584
spf137c427402014-06-27 12:29:37 -0400585 // PFlag Override first
spf1329f18582014-12-05 03:55:51 +0100586 flag, exists := v.pflags[key]
spf137c427402014-06-27 12:29:37 -0400587 if exists {
588 if flag.Changed {
589 jww.TRACE.Println(key, "found in override (via pflag):", val)
590 return flag.Value.String()
591 }
592 }
593
spf1329f18582014-12-05 03:55:51 +0100594 val, exists = v.override[key]
spf1398be0712014-04-04 17:21:59 -0400595 if exists {
596 jww.TRACE.Println(key, "found in override:", val)
597 return val
598 }
599
spf13d8f2aa72014-12-22 22:47:25 -0500600 if v.automaticEnvApplied {
601 // even if it hasn't been registered, if automaticEnv is used,
602 // check any Get request
Chance Zibolski03fb74b2015-03-06 11:21:17 -0800603 if val = v.getEnv(v.mergeWithEnvPrefix(key)); val != "" {
spf13d8f2aa72014-12-22 22:47:25 -0500604 jww.TRACE.Println(key, "found in environment with val:", val)
605 return val
606 }
607 }
608
spf1329f18582014-12-05 03:55:51 +0100609 envkey, exists := v.env[key]
spf13181a3b52014-09-27 14:03:00 -0700610 if exists {
611 jww.TRACE.Println(key, "registered as env var", envkey)
Chance Zibolski03fb74b2015-03-06 11:21:17 -0800612 if val = v.getEnv(envkey); val != "" {
Kevin Bowrin6c340f22014-11-07 18:14:27 +0000613 jww.TRACE.Println(envkey, "found in environment with val:", val)
spf13181a3b52014-09-27 14:03:00 -0700614 return val
615 } else {
616 jww.TRACE.Println(envkey, "env value unset:")
617 }
618 }
619
spf1329f18582014-12-05 03:55:51 +0100620 val, exists = v.config[key]
spf1398be0712014-04-04 17:21:59 -0400621 if exists {
622 jww.TRACE.Println(key, "found in config:", val)
623 return val
624 }
625
spf1329f18582014-12-05 03:55:51 +0100626 val, exists = v.kvstore[key]
Brian Ketelsen3d818242014-10-24 15:38:01 -0400627 if exists {
628 jww.TRACE.Println(key, "found in key/value store:", val)
629 return val
630 }
631
spf1329f18582014-12-05 03:55:51 +0100632 val, exists = v.defaults[key]
spf1398be0712014-04-04 17:21:59 -0400633 if exists {
634 jww.TRACE.Println(key, "found in defaults:", val)
635 return val
636 }
637
638 return nil
639}
640
spf1318a87c02014-12-05 17:04:40 +0100641// Check to see if the key has been set in any of the data locations
spf1329f18582014-12-05 03:55:51 +0100642func IsSet(key string) bool { return v.IsSet(key) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500643func (v *Viper) IsSet(key string) bool {
spf1329f18582014-12-05 03:55:51 +0100644 t := v.Get(key)
spf1398be0712014-04-04 17:21:59 -0400645 return t != nil
646}
647
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500648// Have Viper check ENV variables for all
spf1383fd9262014-09-27 14:01:11 -0700649// keys set in config, default & flags
spf1329f18582014-12-05 03:55:51 +0100650func AutomaticEnv() { v.AutomaticEnv() }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500651func (v *Viper) AutomaticEnv() {
spf13d8f2aa72014-12-22 22:47:25 -0500652 v.automaticEnvApplied = true
spf1383fd9262014-09-27 14:01:11 -0700653}
654
Chance Zibolski03fb74b2015-03-06 11:21:17 -0800655// SetEnvKeyReplacer sets the strings.Replacer on the viper object
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400656// Useful for mapping an environmental variable to a key that does
657// not match it.
Chance Zibolski03fb74b2015-03-06 11:21:17 -0800658func SetEnvKeyReplacer(r *strings.Replacer) { v.SetEnvKeyReplacer(r) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500659func (v *Viper) SetEnvKeyReplacer(r *strings.Replacer) {
Chance Zibolski03fb74b2015-03-06 11:21:17 -0800660 v.envKeyReplacer = r
661}
662
spf1338c6d9e2014-07-11 10:42:07 -0400663// Aliases provide another accessor for the same key.
664// This enables one to change a name without breaking the application
spf1329f18582014-12-05 03:55:51 +0100665func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500666func (v *Viper) RegisterAlias(alias string, key string) {
spf1329f18582014-12-05 03:55:51 +0100667 v.registerAlias(alias, strings.ToLower(key))
spf13bcb02e22014-04-05 01:19:39 -0400668}
669
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500670func (v *Viper) registerAlias(alias string, key string) {
spf13bcb02e22014-04-05 01:19:39 -0400671 alias = strings.ToLower(alias)
spf1329f18582014-12-05 03:55:51 +0100672 if alias != key && alias != v.realKey(key) {
673 _, exists := v.aliases[alias]
Nate Finch2b24bea2014-08-05 07:35:21 -0400674
spf13bcb02e22014-04-05 01:19:39 -0400675 if !exists {
Nate Finch2b24bea2014-08-05 07:35:21 -0400676 // if we alias something that exists in one of the maps to another
677 // name, we'll never be able to get that value using the original
678 // name, so move the config value to the new realkey.
spf1329f18582014-12-05 03:55:51 +0100679 if val, ok := v.config[alias]; ok {
680 delete(v.config, alias)
681 v.config[key] = val
Nate Finch2b24bea2014-08-05 07:35:21 -0400682 }
spf1329f18582014-12-05 03:55:51 +0100683 if val, ok := v.kvstore[alias]; ok {
684 delete(v.kvstore, alias)
685 v.kvstore[key] = val
Brian Ketelsen3d818242014-10-24 15:38:01 -0400686 }
spf1329f18582014-12-05 03:55:51 +0100687 if val, ok := v.defaults[alias]; ok {
688 delete(v.defaults, alias)
689 v.defaults[key] = val
Nate Finch2b24bea2014-08-05 07:35:21 -0400690 }
spf1329f18582014-12-05 03:55:51 +0100691 if val, ok := v.override[alias]; ok {
692 delete(v.override, alias)
693 v.override[key] = val
Nate Finch2b24bea2014-08-05 07:35:21 -0400694 }
spf1329f18582014-12-05 03:55:51 +0100695 v.aliases[alias] = key
spf13bcb02e22014-04-05 01:19:39 -0400696 }
697 } else {
spf1329f18582014-12-05 03:55:51 +0100698 jww.WARN.Println("Creating circular reference alias", alias, key, v.realKey(key))
spf13bcb02e22014-04-05 01:19:39 -0400699 }
700}
701
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500702func (v *Viper) realKey(key string) string {
spf1329f18582014-12-05 03:55:51 +0100703 newkey, exists := v.aliases[key]
spf13bcb02e22014-04-05 01:19:39 -0400704 if exists {
705 jww.DEBUG.Println("Alias", key, "to", newkey)
spf1329f18582014-12-05 03:55:51 +0100706 return v.realKey(newkey)
spf13bcb02e22014-04-05 01:19:39 -0400707 } else {
708 return key
709 }
spf1398be0712014-04-04 17:21:59 -0400710}
711
spf1318a87c02014-12-05 17:04:40 +0100712// Check to see if the given key (or an alias) is in the config file
spf1329f18582014-12-05 03:55:51 +0100713func InConfig(key string) bool { return v.InConfig(key) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500714func (v *Viper) InConfig(key string) bool {
spf13bcb02e22014-04-05 01:19:39 -0400715 // if the requested key is an alias, then return the proper key
spf1329f18582014-12-05 03:55:51 +0100716 key = v.realKey(key)
spf13bcb02e22014-04-05 01:19:39 -0400717
spf1329f18582014-12-05 03:55:51 +0100718 _, exists := v.config[key]
spf1398be0712014-04-04 17:21:59 -0400719 return exists
720}
721
spf1338c6d9e2014-07-11 10:42:07 -0400722// Set the default value for this key.
723// Default only used when no value is provided by the user via flag, config or ENV.
spf1329f18582014-12-05 03:55:51 +0100724func SetDefault(key string, value interface{}) { v.SetDefault(key, value) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500725func (v *Viper) SetDefault(key string, value interface{}) {
spf1398be0712014-04-04 17:21:59 -0400726 // If alias passed in, then set the proper default
spf1329f18582014-12-05 03:55:51 +0100727 key = v.realKey(strings.ToLower(key))
728 v.defaults[key] = value
spf1398be0712014-04-04 17:21:59 -0400729}
730
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400731// Sets the value for the key in the override regiser.
Brian Ketelsen3d818242014-10-24 15:38:01 -0400732// Will be used instead of values obtained via
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400733// flags, config file, ENV, default, or key/value store
spf1329f18582014-12-05 03:55:51 +0100734func Set(key string, value interface{}) { v.Set(key, value) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500735func (v *Viper) Set(key string, value interface{}) {
spf1398be0712014-04-04 17:21:59 -0400736 // If alias passed in, then set the proper override
spf1329f18582014-12-05 03:55:51 +0100737 key = v.realKey(strings.ToLower(key))
738 v.override[key] = value
Joshua Rubin1a2e68e2014-04-08 16:57:45 -0600739}
740
spf1338c6d9e2014-07-11 10:42:07 -0400741// Viper will discover and load the configuration file from disk
Brian Ketelsen3d818242014-10-24 15:38:01 -0400742// and key/value stores, searching in one of the defined paths.
spf1329f18582014-12-05 03:55:51 +0100743func ReadInConfig() error { return v.ReadInConfig() }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500744func (v *Viper) ReadInConfig() error {
spf1398be0712014-04-04 17:21:59 -0400745 jww.INFO.Println("Attempting to read in config file")
spf1329f18582014-12-05 03:55:51 +0100746 if !stringInSlice(v.getConfigType(), SupportedExts) {
747 return UnsupportedConfigError(v.getConfigType())
spf1398be0712014-04-04 17:21:59 -0400748 }
749
spf1329f18582014-12-05 03:55:51 +0100750 file, err := ioutil.ReadFile(v.getConfigFile())
Joshua Rubin1a2e68e2014-04-08 16:57:45 -0600751 if err != nil {
752 return err
spf1398be0712014-04-04 17:21:59 -0400753 }
Joshua Rubin1a2e68e2014-04-08 16:57:45 -0600754
Kiril Zvezdarov54e585a2015-04-26 15:08:10 -0400755 v.config = make(map[string]interface{})
756
Vlad Didenkofa137322015-08-01 20:32:35 -0500757 return v.marshalReader(bytes.NewReader(file), v.config)
spf1398be0712014-04-04 17:21:59 -0400758}
spf1329f18582014-12-05 03:55:51 +0100759
oliveaglef3482af2015-05-14 17:40:59 +0800760func ReadConfig(in io.Reader) error { return v.ReadConfig(in) }
761func (v *Viper) ReadConfig(in io.Reader) error {
oliveagle34928852015-05-08 17:13:33 +0800762 v.config = make(map[string]interface{})
Vlad Didenkofa137322015-08-01 20:32:35 -0500763 return v.marshalReader(in, v.config)
oliveagle34928852015-05-08 17:13:33 +0800764}
765
oliveaglef3482af2015-05-14 17:40:59 +0800766// func ReadBufConfig(buf *bytes.Buffer) error { return v.ReadBufConfig(buf) }
767// func (v *Viper) ReadBufConfig(buf *bytes.Buffer) error {
768// v.config = make(map[string]interface{})
Vlad Didenkofa137322015-08-01 20:32:35 -0500769// return v.marshalReader(buf, v.config)
oliveaglef3482af2015-05-14 17:40:59 +0800770// }
771
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400772// Attempts to get configuration from a remote source
773// and read it in the remote configuration registry.
spf1329f18582014-12-05 03:55:51 +0100774func ReadRemoteConfig() error { return v.ReadRemoteConfig() }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500775func (v *Viper) ReadRemoteConfig() error {
spf1329f18582014-12-05 03:55:51 +0100776 err := v.getKeyValueConfig()
Brian Ketelsenc33e6902014-10-27 10:14:45 -0400777 if err != nil {
778 return err
779 }
780 return nil
781}
spf1329f18582014-12-05 03:55:51 +0100782
oliveagle34928852015-05-08 17:13:33 +0800783func WatchRemoteConfig() error { return v.WatchRemoteConfig() }
784func (v *Viper) WatchRemoteConfig() error {
785 err := v.watchKeyValueConfig()
786 if err != nil {
787 return err
788 }
789 return nil
790}
791
spf1318a87c02014-12-05 17:04:40 +0100792// Marshall a Reader into a map
793// Should probably be an unexported function
Vlad Didenkofa137322015-08-01 20:32:35 -0500794func marshalReader(in io.Reader, c map[string]interface{}) error {
795 return v.marshalReader(in, c)
796}
797
798func (v *Viper) marshalReader(in io.Reader, c map[string]interface{}) error {
799 return marshallConfigReader(in, c, v.getConfigType())
spf13bcb02e22014-04-05 01:19:39 -0400800}
801
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500802func (v *Viper) insensitiviseMaps() {
Anthony Fok5b0b9262015-01-22 00:43:42 -0700803 insensitiviseMap(v.config)
804 insensitiviseMap(v.defaults)
805 insensitiviseMap(v.override)
806 insensitiviseMap(v.kvstore)
Brian Ketelsen3d818242014-10-24 15:38:01 -0400807}
808
809// retrieve the first found remote configuration
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500810func (v *Viper) getKeyValueConfig() error {
bepbe5ff3e2015-05-30 21:28:33 +0200811 if RemoteConfig == nil {
812 return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'")
813 }
814
spf1329f18582014-12-05 03:55:51 +0100815 for _, rp := range v.remoteProviders {
816 val, err := v.getRemoteConfig(rp)
Brian Ketelsen3d818242014-10-24 15:38:01 -0400817 if err != nil {
Brian Ketelsena28bee12014-10-26 09:42:03 -0400818 continue
Brian Ketelsen3d818242014-10-24 15:38:01 -0400819 }
spf1329f18582014-12-05 03:55:51 +0100820 v.kvstore = val
Brian Ketelsena28bee12014-10-26 09:42:03 -0400821 return nil
Brian Ketelsen3d818242014-10-24 15:38:01 -0400822 }
Brian Ketelsend2d8f6c2014-10-27 11:03:11 -0400823 return RemoteConfigError("No Files Found")
824}
825
bepbe5ff3e2015-05-30 21:28:33 +0200826func (v *Viper) getRemoteConfig(provider *defaultRemoteProvider) (map[string]interface{}, error) {
Brian Ketelsena28bee12014-10-26 09:42:03 -0400827
bepbe5ff3e2015-05-30 21:28:33 +0200828 reader, err := RemoteConfig.Get(provider)
Brian Ketelsena28bee12014-10-26 09:42:03 -0400829 if err != nil {
830 return nil, err
831 }
Vlad Didenkofa137322015-08-01 20:32:35 -0500832 err = v.marshalReader(reader, v.kvstore)
spf1329f18582014-12-05 03:55:51 +0100833 return v.kvstore, err
Brian Ketelsena28bee12014-10-26 09:42:03 -0400834}
835
oliveagle34928852015-05-08 17:13:33 +0800836// retrieve the first found remote configuration
837func (v *Viper) watchKeyValueConfig() error {
oliveagle34928852015-05-08 17:13:33 +0800838 for _, rp := range v.remoteProviders {
839 val, err := v.watchRemoteConfig(rp)
840 if err != nil {
841 continue
842 }
843 v.kvstore = val
844 return nil
845 }
846 return RemoteConfigError("No Files Found")
847}
848
bepbe5ff3e2015-05-30 21:28:33 +0200849func (v *Viper) watchRemoteConfig(provider *defaultRemoteProvider) (map[string]interface{}, error) {
850 reader, err := RemoteConfig.Watch(provider)
oliveagle34928852015-05-08 17:13:33 +0800851 if err != nil {
852 return nil, err
853 }
Vlad Didenkofa137322015-08-01 20:32:35 -0500854 err = v.marshalReader(reader, v.kvstore)
oliveagle34928852015-05-08 17:13:33 +0800855 return v.kvstore, err
856}
857
spf1318a87c02014-12-05 17:04:40 +0100858// Return all keys regardless where they are set
spf1329f18582014-12-05 03:55:51 +0100859func AllKeys() []string { return v.AllKeys() }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500860func (v *Viper) AllKeys() []string {
spf13aacc3042014-09-27 14:00:51 -0700861 m := map[string]struct{}{}
862
spf1329f18582014-12-05 03:55:51 +0100863 for key, _ := range v.defaults {
spf13aacc3042014-09-27 14:00:51 -0700864 m[key] = struct{}{}
865 }
866
spf1329f18582014-12-05 03:55:51 +0100867 for key, _ := range v.config {
spf13aacc3042014-09-27 14:00:51 -0700868 m[key] = struct{}{}
869 }
870
spf1329f18582014-12-05 03:55:51 +0100871 for key, _ := range v.kvstore {
Brian Ketelsen3d818242014-10-24 15:38:01 -0400872 m[key] = struct{}{}
873 }
874
spf1329f18582014-12-05 03:55:51 +0100875 for key, _ := range v.override {
spf13aacc3042014-09-27 14:00:51 -0700876 m[key] = struct{}{}
877 }
878
879 a := []string{}
880 for x, _ := range m {
881 a = append(a, x)
882 }
883
884 return a
885}
886
spf1318a87c02014-12-05 17:04:40 +0100887// Return all settings as a map[string]interface{}
spf1329f18582014-12-05 03:55:51 +0100888func AllSettings() map[string]interface{} { return v.AllSettings() }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500889func (v *Viper) AllSettings() map[string]interface{} {
spf13aacc3042014-09-27 14:00:51 -0700890 m := map[string]interface{}{}
spf1329f18582014-12-05 03:55:51 +0100891 for _, x := range v.AllKeys() {
892 m[x] = v.Get(x)
spf13aacc3042014-09-27 14:00:51 -0700893 }
894
895 return m
896}
897
spf1338c6d9e2014-07-11 10:42:07 -0400898// Name for the config file.
899// Does not include extension.
spf1329f18582014-12-05 03:55:51 +0100900func SetConfigName(in string) { v.SetConfigName(in) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500901func (v *Viper) SetConfigName(in string) {
spf1398be0712014-04-04 17:21:59 -0400902 if in != "" {
spf1329f18582014-12-05 03:55:51 +0100903 v.configName = in
spf1398be0712014-04-04 17:21:59 -0400904 }
905}
906
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400907// Sets the type of the configuration returned by the
908// remote source, e.g. "json".
spf1329f18582014-12-05 03:55:51 +0100909func SetConfigType(in string) { v.SetConfigType(in) }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500910func (v *Viper) SetConfigType(in string) {
spf1398be0712014-04-04 17:21:59 -0400911 if in != "" {
spf1329f18582014-12-05 03:55:51 +0100912 v.configType = in
spf1398be0712014-04-04 17:21:59 -0400913 }
914}
915
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500916func (v *Viper) getConfigType() string {
spf1329f18582014-12-05 03:55:51 +0100917 if v.configType != "" {
918 return v.configType
spf1398be0712014-04-04 17:21:59 -0400919 }
920
spf1329f18582014-12-05 03:55:51 +0100921 cf := v.getConfigFile()
Andrew Cohen5aa14372014-11-13 14:43:51 -0500922 ext := filepath.Ext(cf)
spf1398be0712014-04-04 17:21:59 -0400923
924 if len(ext) > 1 {
925 return ext[1:]
926 } else {
927 return ""
928 }
929}
930
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500931func (v *Viper) getConfigFile() string {
spf1398be0712014-04-04 17:21:59 -0400932 // if explicitly set, then use it
spf1329f18582014-12-05 03:55:51 +0100933 if v.configFile != "" {
934 return v.configFile
spf1398be0712014-04-04 17:21:59 -0400935 }
936
spf1329f18582014-12-05 03:55:51 +0100937 cf, err := v.findConfigFile()
spf1398be0712014-04-04 17:21:59 -0400938 if err != nil {
Joshua Rubin1a2e68e2014-04-08 16:57:45 -0600939 return ""
spf1398be0712014-04-04 17:21:59 -0400940 }
Joshua Rubin1a2e68e2014-04-08 16:57:45 -0600941
spf1329f18582014-12-05 03:55:51 +0100942 v.configFile = cf
943 return v.getConfigFile()
spf1398be0712014-04-04 17:21:59 -0400944}
945
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500946func (v *Viper) searchInPath(in string) (filename string) {
spf1398be0712014-04-04 17:21:59 -0400947 jww.DEBUG.Println("Searching for config in ", in)
948 for _, ext := range SupportedExts {
spf1329f18582014-12-05 03:55:51 +0100949 jww.DEBUG.Println("Checking for", filepath.Join(in, v.configName+"."+ext))
950 if b, _ := exists(filepath.Join(in, v.configName+"."+ext)); b {
951 jww.DEBUG.Println("Found: ", filepath.Join(in, v.configName+"."+ext))
952 return filepath.Join(in, v.configName+"."+ext)
spf1398be0712014-04-04 17:21:59 -0400953 }
954 }
955
956 return ""
957}
958
spf1318a87c02014-12-05 17:04:40 +0100959// search all configPaths for any config file.
960// Returns the first path that exists (and is a config file)
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500961func (v *Viper) findConfigFile() (string, error) {
Vlad Didenko9fca1012015-08-01 19:37:27 -0500962
spf1329f18582014-12-05 03:55:51 +0100963 jww.INFO.Println("Searching for config in ", v.configPaths)
spf1398be0712014-04-04 17:21:59 -0400964
spf1329f18582014-12-05 03:55:51 +0100965 for _, cp := range v.configPaths {
966 file := v.searchInPath(cp)
spf1398be0712014-04-04 17:21:59 -0400967 if file != "" {
968 return file, nil
969 }
970 }
Vlad Didenko9fca1012015-08-01 19:37:27 -0500971 return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
spf1398be0712014-04-04 17:21:59 -0400972}
973
Kiril Zvezdarov9a0a6692015-04-01 17:08:42 -0400974// Prints all configuration registries for debugging
975// purposes.
spf1329f18582014-12-05 03:55:51 +0100976func Debug() { v.Debug() }
Kiril Zvezdarov700eefa2015-02-17 09:22:37 -0500977func (v *Viper) Debug() {
spf13541c1f82014-05-29 16:48:24 -0400978 fmt.Println("Aliases:")
spf1329f18582014-12-05 03:55:51 +0100979 pretty.Println(v.aliases)
Kiril Zvezdarovb22fa2b2015-05-01 15:14:41 -0400980 fmt.Println("Override:")
981 pretty.Println(v.override)
Kiril Zvezdarov19ed4962015-04-01 21:39:09 -0400982 fmt.Println("PFlags")
983 pretty.Println(v.pflags)
Kiril Zvezdarovb22fa2b2015-05-01 15:14:41 -0400984 fmt.Println("Env:")
985 pretty.Println(v.env)
986 fmt.Println("Key/Value Store:")
987 pretty.Println(v.kvstore)
988 fmt.Println("Config:")
989 pretty.Println(v.config)
990 fmt.Println("Defaults:")
991 pretty.Println(v.defaults)
spf1398be0712014-04-04 17:21:59 -0400992}