github.com/flei2000/viper@v0.0.0-20160111150723-a212099cbe6f/README.md (about)

     1  ![viper logo](https://cloud.githubusercontent.com/assets/173412/10886745/998df88a-8151-11e5-9448-4736db51020d.png)
     2  
     3  Go configuration with fangs!
     4  
     5   [![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)
     6  
     7  
     8  ## What is Viper?
     9  
    10  Viper is a complete configuration solution for go applications including 12 factor apps. It is designed
    11  to work within an application, and can handle all types of configuration needs
    12  and formats. It supports:
    13  
    14  * setting defaults
    15  * reading from JSON, TOML, YAML and HCL config files
    16  * live watching and re-reading of config files (optional)
    17  * reading from environment variables
    18  * reading from remote config systems (etcd or Consul), and watching changes
    19  * reading from command line flags
    20  * reading from buffer
    21  * setting explicit values
    22  
    23  Viper can be thought of as a registry for all of your applications
    24  configuration needs.
    25  
    26  ## Why Viper?
    27  
    28  When building a modern application, you don’t want to worry about
    29  configuration file formats; you want to focus on building awesome software.
    30  Viper is here to help with that.
    31  
    32  Viper does the following for you:
    33  
    34  1. Find, load, and unmarshal a configuration file in JSON, TOML, YAML or HCL.
    35  2. Provide a mechanism to set default values for your different
    36     configuration options.
    37  3. Provide a mechanism to set override values for options specified through
    38     command line flags.
    39  4. Provide an alias system to easily rename parameters without breaking existing
    40     code.
    41  5. Make it easy to tell the difference between when a user has provided a
    42     command line or config file which is the same as the default.
    43  
    44  Viper uses the following precedence order. Each item takes precedence over the
    45  item below it:
    46  
    47   * explicit call to Set
    48   * flag
    49   * env
    50   * config
    51   * key/value store
    52   * default
    53  
    54  Viper configuration keys are case insensitive.
    55  
    56  ## Putting Values into Viper
    57  
    58  ### Establishing Defaults
    59  
    60  A good configuration system will support default values. A default value is not
    61  required for a key, but it's useful in the event that a key hasn’t been set via
    62  config file, environment variable, remote configuration or flag.
    63  
    64  Examples:
    65  
    66  ```go
    67  viper.SetDefault("ContentDir", "content")
    68  viper.SetDefault("LayoutDir", "layouts")
    69  viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"})
    70  ```
    71  
    72  ### Reading Config Files
    73  
    74  Viper requires minimal configuration so it knows where to look for config files.
    75  Viper supports JSON, TOML, YAML and HCL files. Viper can search multiple paths, but
    76  currently a single Viper instance only supports a single configuration file.
    77  Viper does not default to any configuration search paths leaving defaults decision
    78  to an application.
    79  
    80  Here is an example of how to use Viper to search for and read a configuration file.
    81  None of the specific paths are required, but at least one path should be provided
    82  where a configuration file is expected.
    83  
    84  ```go
    85  viper.SetConfigName("config") // name of config file (without extension)
    86  viper.AddConfigPath("/etc/appname/")   // path to look for the config file in
    87  viper.AddConfigPath("$HOME/.appname")  // call multiple times to add many search paths
    88  viper.AddConfigPath(".")               // optionally look for config in the working directory
    89  err := viper.ReadInConfig() // Find and read the config file
    90  if err != nil { // Handle errors reading the config file
    91  	panic(fmt.Errorf("Fatal error config file: %s \n", err))
    92  }
    93  ```
    94  
    95  ### Watching and re-reading config files
    96  
    97  Viper supports the ability to have your application live read a config file while running.
    98  
    99  Gone are the days of needing to restart a server to have a config take effect,
   100  viper powered applications can read an update to a config file while running and
   101  not miss a beat.
   102  
   103  Simply tell the viper instance to watchConfig. 
   104  Optionally you can provide a function for Viper to run each time a change occurs.
   105  
   106  **Make sure you add all of the configPaths prior to calling `WatchConfig()`**
   107  
   108  ```go
   109  		viper.WatchConfig()
   110  		viper.OnConfigChange(func(e fsnotify.Event) {
   111  			fmt.Println("Config file changed:", e.Name)
   112  		})
   113  ```
   114  
   115  ### Reading Config from io.Reader
   116  
   117  Viper predefines many configuration sources such as files, environment
   118  variables, flags, and remote K/V store, but you are not bound to them. You can
   119  also implement your own required configuration source and feed it to viper.
   120  
   121  ```go
   122  viper.SetConfigType("yaml") // or viper.SetConfigType("YAML")
   123  
   124  // any approach to require this configuration into your program.
   125  var yamlExample = []byte(`
   126  Hacker: true
   127  name: steve
   128  hobbies:
   129  - skateboarding
   130  - snowboarding
   131  - go
   132  clothing:
   133    jacket: leather
   134    trousers: denim
   135  age: 35
   136  eyes : brown
   137  beard: true
   138  `)
   139  
   140  viper.ReadConfig(bytes.NewBuffer(yamlExample))
   141  
   142  viper.Get("name") // this would be "steve"
   143  ```
   144  
   145  ### Setting Overrides
   146  
   147  These could be from a command line flag, or from your own application logic.
   148  
   149  ```go
   150  viper.Set("Verbose", true)
   151  viper.Set("LogFile", LogFile)
   152  ```
   153  
   154  ### Registering and Using Aliases
   155  
   156  Aliases permit a single value to be referenced by multiple keys
   157  
   158  ```go
   159  viper.RegisterAlias("loud", "Verbose")
   160  
   161  viper.Set("verbose", true) // same result as next line
   162  viper.Set("loud", true)   // same result as prior line
   163  
   164  viper.GetBool("loud") // true
   165  viper.GetBool("verbose") // true
   166  ```
   167  
   168  ### Working with Environment Variables
   169  
   170  Viper has full support for environment variables. This enables 12 factor
   171  applications out of the box. There are four methods that exist to aid working
   172  with ENV:
   173  
   174   * `AutomaticEnv()`
   175   * `BindEnv(string...) : error`
   176   * `SetEnvPrefix(string)`
   177   * `SetEnvReplacer(string...) *strings.Replacer`
   178  
   179  _When working with ENV variables, it’s important to recognize that Viper
   180  treats ENV variables as case sensitive._
   181  
   182  Viper provides a mechanism to try to ensure that ENV variables are unique. By
   183  using `SetEnvPrefix`, you can tell Viper to use add a prefix while reading from
   184  the environment variables. Both `BindEnv` and `AutomaticEnv` will use this
   185  prefix.
   186  
   187  `BindEnv` takes one or two parameters. The first parameter is the key name, the
   188  second is the name of the environment variable. The name of the environment
   189  variable is case sensitive. If the ENV variable name is not provided, then
   190  Viper will automatically assume that the key name matches the ENV variable name,
   191  but the ENV variable is IN ALL CAPS. When you explicitly provide the ENV
   192  variable name, it **does not** automatically add the prefix.
   193  
   194  One important thing to recognize when working with ENV variables is that the
   195  value will be read each time it is accessed. Viper does not fix the value when
   196  the `BindEnv` is called.
   197  
   198  `AutomaticEnv` is a powerful helper especially when combined with
   199  `SetEnvPrefix`. When called, Viper will check for an environment variable any
   200  time a `viper.Get` request is made. It will apply the following rules. It will
   201  check for a environment variable with a name matching the key uppercased and
   202  prefixed with the `EnvPrefix` if set.
   203  
   204  `SetEnvReplacer` allows you to use a `strings.Replacer` object to rewrite Env
   205  keys to an extent. This is useful if you want to use `-` or something in your
   206  `Get()` calls, but want your environmental variables to use `_` delimiters. An
   207  example of using it can be found in `viper_test.go`.
   208  
   209  #### Env example
   210  
   211  ```go
   212  SetEnvPrefix("spf") // will be uppercased automatically
   213  BindEnv("id")
   214  
   215  os.Setenv("SPF_ID", "13") // typically done outside of the app
   216  
   217  id := Get("id") // 13
   218  ```
   219  
   220  ### Working with Flags
   221  
   222  Viper has the ability to bind to flags. Specifically, Viper supports `Pflags`
   223  as used in the [Cobra](https://github.com/spf13/cobra) library.
   224  
   225  Like `BindEnv`, the value is not set when the binding method is called, but when
   226  it is accessed. This means you can bind as early as you want, even in an
   227  `init()` function.
   228  
   229  The `BindPFlag()` method provides this functionality.
   230  
   231  Example:
   232  
   233  ```go
   234  serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
   235  viper.BindPFlag("port", serverCmd.Flags().Lookup("port"))
   236  ```
   237  
   238  The use of [pflag](https://github.com/spf13/pflag/) in Viper does not preclude
   239  the use of other packages that use the [flag](https://golang.org/pkg/flag/)
   240  package from the standard library. The pflag package can handle the flags
   241  defined for the flag package by importing these flags. This is accomplished
   242  by a calling a convenience function provided by the pflag package called
   243  AddGoFlagSet().
   244  
   245  Example:
   246  
   247  ```go
   248  package main
   249  
   250  import (
   251  	"flag"
   252  	"github.com/spf13/pflag"
   253  )
   254  
   255  func main() {
   256  	pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
   257  	pflag.Parse()
   258      ...
   259  }
   260  ```
   261  
   262  #### Flag interfaces
   263  
   264  Viper provides two Go interfaces to bind other flag systems if you don't use `Pflags`.
   265  
   266  `FlagValue` represents a single flag. This is a very simple example on how to implement this interface:
   267  
   268  ```go
   269  type myFlag struct {}
   270  func (f myFlag) IsChanged() { return false }
   271  func (f myFlag) Name() { return "my-flag-name" }
   272  func (f myFlag) ValueString() { return "my-flag-value" }
   273  func (f myFlag) ValueType() { return "string" }
   274  ```
   275  
   276  Once your flag implements this interface, you can simply tell Viper to bind it:
   277  
   278  ```go
   279  viper.BindFlagValue("my-flag-name", myFlag{})
   280  ```
   281  
   282  `FlagValueSet` represents a group of flags. This is a very simple example on how to implement this interface:
   283  
   284  ```go
   285  type myFlagSet struct {
   286  	flags []myFlag
   287  }
   288  
   289  func (f myFlagSet) VisitAll(fn func(FlagValue)) {
   290  	for _, flag := range flags {
   291  		fn(flag)	
   292  	}
   293  }
   294  ```
   295  
   296  Once your flag set implements this interface, you can simply tell Viper to bind it:
   297  
   298  ```go
   299  fSet := myFlagSet{
   300  	flags: []myFlag{myFlag{}, myFlag{}},
   301  }
   302  viper.BindFlagValues("my-flags", fSet)
   303  ```
   304  
   305  ### Remote Key/Value Store Support
   306  
   307  To enable remote support in Viper, do a blank import of the `viper/remote`
   308  package:
   309  
   310  `import _ "github.com/spf13/viper/remote"`
   311  
   312  Viper will read a config string (as JSON, TOML, YAML or HCL) retrieved from a path
   313  in a Key/Value store such as etcd or Consul.  These values take precedence over
   314  default values, but are overridden by configuration values retrieved from disk,
   315  flags, or environment variables.
   316  
   317  Viper uses [crypt](https://github.com/xordataexchange/crypt) to retrieve
   318  configuration from the K/V store, which means that you can store your
   319  configuration values encrypted and have them automatically decrypted if you have
   320  the correct gpg keyring.  Encryption is optional.
   321  
   322  You can use remote configuration in conjunction with local configuration, or
   323  independently of it.
   324  
   325  `crypt` has a command-line helper that you can use to put configurations in your
   326  K/V store. `crypt` defaults to etcd on http://127.0.0.1:4001.
   327  
   328  ```bash
   329  $ go get github.com/xordataexchange/crypt/bin/crypt
   330  $ crypt set -plaintext /config/hugo.json /Users/hugo/settings/config.json
   331  ```
   332  
   333  Confirm that your value was set:
   334  
   335  ```bash
   336  $ crypt get -plaintext /config/hugo.json
   337  ```
   338  
   339  See the `crypt` documentation for examples of how to set encrypted values, or
   340  how to use Consul.
   341  
   342  ### Remote Key/Value Store Example - Unencrypted
   343  
   344  ```go
   345  viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001","/config/hugo.json")
   346  viper.SetConfigType("json") // because there is no file extension in a stream of bytes
   347  err := viper.ReadRemoteConfig()
   348  ```
   349  
   350  ### Remote Key/Value Store Example - Encrypted
   351  
   352  ```go
   353  viper.AddSecureRemoteProvider("etcd","http://127.0.0.1:4001","/config/hugo.json","/etc/secrets/mykeyring.gpg")
   354  viper.SetConfigType("json") // because there is no file extension in a stream of bytes
   355  err := viper.ReadRemoteConfig()
   356  ```
   357  
   358  ### Watching Changes in etcd - Unencrypted
   359  
   360  ```go
   361  // alternatively, you can create a new viper instance.
   362  var runtime_viper = viper.New()
   363  
   364  runtime_viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001", "/config/hugo.yml")
   365  runtime_viper.SetConfigType("yaml") // because there is no file extension in a stream of bytes
   366  
   367  // read from remote config the first time.
   368  err := runtime_viper.ReadRemoteConfig()
   369  
   370  // unmarshal config
   371  runtime_viper.Unmarshal(&runtime_conf)
   372  
   373  // open a goroutine to watch remote changes forever
   374  go func(){
   375  	for {
   376  	    time.Sleep(time.Second * 5) // delay after each request
   377  
   378  	    // currently, only tested with etcd support
   379  	    err := runtime_viper.WatchRemoteConfig()
   380  	    if err != nil {
   381  	        log.Errorf("unable to read remote config: %v", err)
   382  	        continue
   383  	    }
   384  
   385  	    // unmarshal new config into our runtime config struct. you can also use channel
   386  	    // to implement a signal to notify the system of the changes
   387  	    runtime_viper.Unmarshal(&runtime_conf)
   388  	}
   389  }()
   390  ```
   391  
   392  ## Getting Values From Viper
   393  
   394  In Viper, there are a few ways to get a value depending on the value's type.
   395  The following functions and methods exist:
   396  
   397   * `Get(key string) : interface{}`
   398   * `GetBool(key string) : bool`
   399   * `GetFloat64(key string) : float64`
   400   * `GetInt(key string) : int`
   401   * `GetString(key string) : string`
   402   * `GetStringMap(key string) : map[string]interface{}`
   403   * `GetStringMapString(key string) : map[string]string`
   404   * `GetStringSlice(key string) : []string`
   405   * `GetTime(key string) : time.Time`
   406   * `GetDuration(key string) : time.Duration`
   407   * `IsSet(key string) : bool`
   408  
   409  One important thing to recognize is that each Get function will return a zero
   410  value if it’s not found. To check if a given key exists, the `IsSet()` method
   411  has been provided.
   412  
   413  Example:
   414  ```go
   415  viper.GetString("logfile") // case-insensitive Setting & Getting
   416  if viper.GetBool("verbose") {
   417      fmt.Println("verbose enabled")
   418  }
   419  ```
   420  ### Accessing nested keys
   421  
   422  The accessor methods also accept formatted paths to deeply nested keys. For
   423  example, if the following JSON file is loaded:
   424  
   425  ```json
   426  {
   427      "host": {
   428          "address": "localhost",
   429          "port": 5799
   430      },
   431      "datastore": {
   432          "metric": {
   433              "host": "127.0.0.1",
   434              "port": 3099
   435          },
   436          "warehouse": {
   437              "host": "198.0.0.1",
   438              "port": 2112
   439          }
   440      }
   441  }
   442  
   443  ```
   444  
   445  Viper can access a nested field by passing a `.` delimited path of keys:
   446  
   447  ```go
   448  GetString("datastore.metric.host") // (returns "127.0.0.1")
   449  ```
   450  
   451  This obeys the precedence rules established above; the search for the root key
   452  (in this example, `datastore`) will cascade through the remaining configuration
   453  registries until found. The search for the sub-keys (`metric` and `host`),
   454  however, will not.
   455  
   456  For example, if the `metric` key was not defined in the configuration loaded
   457  from file, but was defined in the defaults, Viper would return the zero value.
   458  
   459  On the other hand, if the primary key was not defined, Viper would go through
   460  the remaining registries looking for it.
   461  
   462  Lastly, if there exists a key that matches the delimited key path, its value
   463  will be returned instead. E.g.
   464  
   465  ```json
   466  {
   467      "datastore.metric.host": "0.0.0.0",
   468      "host": {
   469          "address": "localhost",
   470          "port": 5799
   471      },
   472      "datastore": {
   473          "metric": {
   474              "host": "127.0.0.1",
   475              "port": 3099
   476          },
   477          "warehouse": {
   478              "host": "198.0.0.1",
   479              "port": 2112
   480          }
   481      }
   482  }
   483  
   484  GetString("datastore.metric.host") //returns "0.0.0.0"
   485  ```
   486  
   487  ### Extract sub-tree
   488  
   489  Extract sub-tree from Viper.
   490  
   491  For example, `viper` represents:
   492  
   493  ```json
   494  app:
   495    cache1:
   496      max-items: 100
   497      item-size: 64
   498    cache2:
   499      max-items: 200
   500      item-size: 80
   501  ```
   502  
   503  After executing:
   504  
   505  ```go
   506  subv := viper.Sub("app.cache1")
   507  ```
   508  
   509  `subv` represents:
   510  
   511  ```json
   512  max-items: 100
   513  item-size: 64
   514  ```
   515  
   516  Suppose we have:
   517  
   518  ```go
   519  func NewCache(cfg *Viper) *Cache {...}
   520  ```
   521  
   522  which creates a cache based on config information formatted as `subv`.
   523  Now it's easy to create these 2 caches separately as:
   524  
   525  ```go
   526  cfg1 := viper.Sub("app.cache1")
   527  cache1 := NewCache(cfg1)
   528  
   529  cfg2 := viper.Sub("app.cache2")
   530  cache2 := NewCache(cfg2)
   531  ```
   532  
   533  ### Unmarshaling
   534  
   535  You also have the option of Unmarshaling all or a specific value to a struct, map,
   536  etc.
   537  
   538  There are two methods to do this:
   539  
   540   * `Unmarshal(rawVal interface{}) : error`
   541   * `UnmarshalKey(key string, rawVal interface{}) : error`
   542  
   543  Example:
   544  
   545  ```go
   546  type config struct {
   547  	Port int
   548  	Name string
   549  	PathMap string `mapstructure:"path_map"`
   550  }
   551  
   552  var C config
   553  
   554  err := Unmarshal(&C)
   555  if err != nil {
   556  	t.Fatalf("unable to decode into struct, %v", err)
   557  }
   558  ```
   559  
   560  ## Viper or Vipers?
   561  
   562  Viper comes ready to use out of the box. There is no configuration or
   563  initialization needed to begin using Viper. Since most applications will want
   564  to use a single central repository for their configuration, the viper package
   565  provides this. It is similar to a singleton.
   566  
   567  In all of the examples above, they demonstrate using viper in it's singleton
   568  style approach.
   569  
   570  ### Working with multiple vipers
   571  
   572  You can also create many different vipers for use in your application. Each will
   573  have it’s own unique set of configurations and values. Each can read from a
   574  different config file, key value store, etc. All of the functions that viper
   575  package supports are mirrored as methods on a viper.
   576  
   577  Example:
   578  
   579  ```go
   580  x := viper.New()
   581  y := viper.New()
   582  
   583  x.SetDefault("ContentDir", "content")
   584  y.SetDefault("ContentDir", "foobar")
   585  
   586  //...
   587  ```
   588  
   589  When working with multiple vipers, it is up to the user to keep track of the
   590  different vipers.
   591  
   592  ## Q & A
   593  
   594  Q: Why not INI files?
   595  
   596  A: Ini files are pretty awful. There’s no standard format, and they are hard to
   597  validate. Viper is designed to work with JSON, TOML or YAML files. If someone
   598  really wants to add this feature, I’d be happy to merge it. It’s easy to specify
   599  which formats your application will permit.
   600  
   601  Q: Why is it called “Viper”?
   602  
   603  A: Viper is designed to be a [companion](http://en.wikipedia.org/wiki/Viper_(G.I._Joe))
   604  to [Cobra](https://github.com/spf13/cobra). While both can operate completely
   605  independently, together they make a powerful pair to handle much of your
   606  application foundation needs.
   607  
   608  Q: Why is it called “Cobra”?
   609  
   610  A: Is there a better name for a [commander](http://en.wikipedia.org/wiki/Cobra_Commander)?