diff --git a/README.md b/README.md index 4e72e97..cd42a2f 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,9 @@ configuration. It supports * setting defaults * reading from json, toml and yaml config files * reading from environment variables -* reading from remote config systems (Etcd or Consul) +* reading from remote config systems (Etcd or Consul), watching changes * reading from command line flags +* reading from buffer * setting explicit values It can be thought of as a registry for all of your applications @@ -81,6 +82,36 @@ currently a single viper only supports a single config file. panic(fmt.Errorf("Fatal error config file: %s \n", err)) } +### Reading Config from bytes.Buffer + +Viper predefined many configuration sources, such as files, environment variables, flags and +remote K/V store. But you are not bound to them. You can also implement your own way to +require configuration and feed it to viper. + +````go +viper.SetConfigType("yaml") // or viper.SetConfigType("YAML") + +// any approach to require this configuration into your program. +var yamlExample = []byte(` +Hacker: true +name: steve +hobbies: +- skateboarding +- snowboarding +- go +clothing: + jacket: leather + trousers: denim +age: 35 +eyes : brown +beard: true +`) + +viper.ReadBufConfig(bytes.NewBuffer(yamlExample)) + +viper.Get("name") // this would be "steve" +```` + ### Setting Overrides These could be from a command line flag, or from your own application logic. @@ -208,6 +239,38 @@ to use Consul. viper.SetConfigType("json") // because there is no file extension in a stream of bytes err := viper.ReadRemoteConfig() +### Watching Changes in Etcd - Unencrypted + + // alternatively, you can create a new viper instance. + var runtime_viper = viper.New() + + runtime_viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001", "/config/hugo.yml") + runtime_viper.SetConfigType("yaml") // because there is no file extension in a stream of bytes + + // read from remote config the first time. + err := runtime_viper.ReadRemoteConfig() + + // marshal config + runtime_viper.Marshal(&runtime_conf) + + // open a goroutine to wath remote changes forever + go func(){ + for { + time.Sleep(time.Second * 5) // delay after each request + + // currenlty, only tested with etcd support + err := runtime_viper.WatchRemoteConfig() + if err != nil { + log.Errorf("unable to read remote config: %v", err) + continue + } + + // marshal new config into our runtime config struct. you can also use channel + // to implement a signal to notify the system of the changes + runtime_viper.Marshal(&runtime_conf) + } + }() + ## Getting Values From Viper diff --git a/util.go b/util.go index 7c5d21a..7904b1a 100644 --- a/util.go +++ b/util.go @@ -123,7 +123,7 @@ func marshallConfigReader(in io.Reader, c map[string]interface{}, configType str buf := new(bytes.Buffer) buf.ReadFrom(in) - switch configType { + switch strings.ToLower(configType) { case "yaml", "yml": if err := yaml.Unmarshal(buf.Bytes(), &c); err != nil { jww.ERROR.Fatalf("Error parsing config: %s", err)