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