From cacbc4c733a93565015f8070ab02b9752b6b02e9 Mon Sep 17 00:00:00 2001 From: spf13 Date: Sun, 7 Dec 2014 02:03:49 +0100 Subject: [PATCH] Rewriting the documentation --- README.md | 196 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 173 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index d7b1145..e9b489c 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,19 @@ Go configuration with fangs ## What is Viper? -Viper is a complete configuration solution. Designed to work within an -application to handle file based configuration and seamlessly marry that with -command line flags which can also be used to control application behavior. -Viper also supports retrieving configuration values from remote key/value stores. -Etcd and Consul are supported. +Viper is a complete configuration solution for go applications. It has +been designed to work within an application to handle all types of +configuration. It supports + +* setting defaults +* reading from yaml, toml and json config files +* reading from environment variables +* reading from remote config systems (Etcd or Consul) +* reading from command line flags +* setting explicit values + +It can be thought of as a registry for all of your applications +configuration needs. ## Why Viper? @@ -19,42 +27,66 @@ Viper is here to help with that. Viper does the following for you: -1. Find, load and marshall a configuration file in YAML, TOML or JSON. -2. Provide a mechanism to setDefault values for your different configuration options -3. Provide a mechanism to setOverride values for options specified through command line flags. -4. Provide an alias system to easily rename parameters without breaking existing code. -5. Make it easy to tell the difference between when a user has provided a command line or config file which is the same as the default. +1. Find, load and marshal a configuration file in YAML, TOML or JSON. +2. Provide a mechanism to set default values for your different + configuration options +3. Provide a mechanism to set override values for options specified + through command line flags. +4. Provide an alias system to easily rename parameters without breaking + existing code. +5. Make it easy to tell the difference between when a user has provided + a command line or config file which is the same as the default. -Viper believes that: +Viper uses the following precedence order. Each item takes precedence +over the item below it: -1. command line flags take precedence over options set in config files -2. config files take precedence over options set in remote key/value stores -3. remote key/value stores take precedence over defaults + * explicit call to Set + * flag + * env + * config + * key/value store + * default Viper configuration keys are case insensitive. ## Usage -### Initialization +### Establishing Defaults + +A good configuration system will support default values. A default value +is not required for a key, but can establish a default to be used in the +event that the key hasn’t be set via config file, environment variable, +remote configuration or flag. + +Examples: + + viper.SetDefault("ContentDir", "content") + viper.SetDefault("LayoutDir", "layouts") + viper.SetDefault("Indexes", map[string]string{"tag": "tags", "category": "categories"}) + +### Reading Config Files + +If you want to support a config file, Viper requires a minimal +configuration so it knows where to look for the config file. Viper +supports yaml, toml and json files. Viper can search multiple paths, but +currently a single viper only supports a single config file. viper.SetConfigName("config") // name of config file (without extension) viper.AddConfigPath("/etc/appname/") // path to look for the config file in viper.AddConfigPath("$HOME/.appname") // call multiple times to add many search paths viper.ReadInConfig() // Find and read the config file -### Setting Defaults - - viper.SetDefault("ContentDir", "content") - viper.SetDefault("LayoutDir", "layouts") - viper.SetDefault("Indexes", map[string]string{"tag": "tags", "category": "categories"}) - ### Setting Overrides +These could be from a command line flag, or from your own application logic. + viper.Set("Verbose", true) viper.Set("LogFile", LogFile) ### Registering and Using Aliases +Aliases permit a single value to be referenced by multiple keys + viper.RegisterAlias("loud", "Verbose") viper.Set("verbose", true) // same result as next line @@ -65,11 +97,102 @@ Viper configuration keys are case insensitive. ### Getting Values +In Viper there are a few ways to get a value depending on what type of value you want to retrieved. +The following functions and methods exist: + + * Get(key string) : interface{} + * GetBool(key string) : bool + * GetFloat64(key string) : float64 + * GetInt(key string) : int + * GetString(key string) : string + * GetStringMap(key string) : map[string]interface{} + * GetStringMapString(key string) : map[string]string + * GetStringSlice(key string) : []string + * GetTime(key string) : time.Time + * IsSet(key string) : bool + +One important thing to recognize is that each Get function will return +it’s zero value if it’s not found. To check if it’s found, the IsSet() +method has been provided. + +Example: + viper.GetString("logfile") // case insensitive Setting & Getting if viper.GetBool("verbose") { fmt.Println("verbose enabled") } +### Marshaling + +You also have the option of Marshaling all or a specific value to a struct, map, etc. + +There are two methods to do this: + + * Marshal(rawVal interface{}) : error + * MarshalKey(key string, rawVal interface{}) : error + +Example: + + type config struct { + Port int + Name string + } + + var C config + + err := Marshal(&C) + if err != nil { + t.Fatalf("unable to decode into struct, %v", err) + } + +### Working with Environment Variables + +Viper has full support for environment variables. This enables 12 factor +applications out of the box. There are two methods that exist to aid +with working with ENV: + + * AutomaticEnv() + * BindEnv(input ) : error + +When working with ENV variables it’s important to recognize that Viper +treats ENV variables as case sensitive. + +BindEnv takes one or two parameters. The first parameter is the key +name, the second is the name of the environment variable. The name of +the environment variable is case sensitive. + +If the ENV variable name is not provided then Viper will automatically +assume that the key name matches the ENV variable name but the ENV +variable is IN ALL CAPS. + +One important thing to recognize when working with ENV variables is that +the value will be read each time it is accessed. It does not fix the +value when the BindEnv is called. + + +AutomaticEnv is intended to be a convience helper. It will look for all +keys that have been set (via defaults, config file, flag, or remote key +value) and call BindEnv on that key. It does +not simply import all ENV variables. Because of this behavior it’s +usually best to call it last. + +### Working with Flags + +Viper has the ability to bind to flags. Specifically Viper supports +Pflags as used in the [Cobra](http://github.com/spf13/cobra) library. + +Like BindEnv the value is not set when the binding method is called, but +when it is accessed. This means you can bind as early as you want, even +in an init() function. + +The BindPFlag() method provides this functionality. + +Example: + + serverCmd.Flags().Int("port", 1138, "Port to run Application server on") + viper.BindPFlag("port", serverCmd.Flags().Lookup("port")) + + ### Remote Key/Value Store Support Viper will read a config string (as JSON, TOML, or YAML) retrieved from a path in a Key/Value store such as Etcd or Consul. These values take precedence @@ -110,6 +233,35 @@ to use Consul. err := viper.ReadRemoteConfig() +### Viper or Vipers? + +Viper comes ready to use out of the box. There is no configuration or +initialization needed to begin using Viper. Since most applications will +want to use a single central repository for their configuration the +viper package provides this. It is similar to a singleton. + +In all of the examples above they demonstrate using viper in it’s +singleton style approach. + +### Working with multiple vipers + +You can also create many different vipers for use in your application. +Each will have it’s own unique set of configurations and values. Each +can read from a different config file, key value store, etc. All of the +functions that viper package supports are mirrored as methods on a viper. + +Example: + + x := viper.New() + y := viper.New() + + x.SetDefault("ContentDir", "content") + y.SetDefault("ContentDir", "foobar") + + ... + +When working with multiple vipers it is up to the user to keep track of +the different vipers. ## Q & A @@ -130,5 +282,3 @@ application foundation needs. Q: Why is it called "Cobra"? A: Is there a better name for a commander? - -