enviper

package module
v1.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 28, 2025 License: MIT Imports: 4 Imported by: 27

README

enviper

PkgGoDev Build Status Test Coverage Maintainability Go Report Card

Package enviper is a helper/wrapper for viper with the same API. It makes it possible to unmarshal config to struct considering environment variables.

Problem

Viper package doesn't consider environment variables while unmarshaling. Please, see: 188 and 761

Solution

Just wrap viper instance and use the same Unmarshal method as you did before:

e := enviper.New(viper.New())
e.Unmarshal(&config)

Example

package main

import (
	"github.com/iamolegga/enviper"
	"github.com/spf13/viper"
)

type barry struct {
    Bar int `mapstructure:"bar"`
}
type bazzy struct {
    Baz bool
}
type quxxy struct {
	Qux string
}
type config struct {
    Foo      string
    Barry    barry
    Barries  map[string]barry
    Bazzy    bazzy `mapstructure:",squash"`
    Quxxy    *quxxy
}

// For example this kind of structure can be unmarshaled with next yaml:
//  Foo: foo
//  Barry:
//    bar: 42
//  Baz: true
//  Barries: 
//    key1:
//      Bar: 255
//    key2:
//      Bar: 256
//  Quxxy:
//    Qux: "lorem"
//
// And then it could be overriden by next env variables:
//  FOO=foo
//  BARRY_BAR=42
//  BAZ=true
//  BARRIES_KEY1_BAR=42
//  QUXXY_QUX=ipsum
//
// Or with prefix:
//  MYAPP_FOO=foo
//  MYAPP_BARRY_BAR=42
//  MYAPP_BAZ=true
//  MYAPP_BARRIES_KEY1_BAR=42
//  MYAPP_QUXXY_QUX=ipsum

func main() {    
    var c config

    e := enviper.New(viper.New())
    e.SetEnvPrefix("MYAPP")
    e.AddConfigPath("/my/config/path")
    e.SetConfigName("config")

    e.Unmarshal(&c)
}

Custom Tag Names

In case you want to use custom tag name (something different from mapstructure), you have to set it explicitly via WithTagName function. The wrapper must know custom tag name in order to register all the env vars for viper so you can't just use DecoderConfigOption.

Credits

Thanks to krak3n (issuecomment-399884438) and celian-garcia (issuecomment-626122696) for inspiring.

Documentation

Overview

Package enviper is a helper/wrapper for http://github.com/spf13/viper with the same API. It makes it possible to unmarshal config to struct considering environment variables.

Problem

Viper package (https://github.com/spf13/viper) doesn't consider environment variables while unmarshaling. Please, see: https://github.com/spf13/viper/issues/188 and https://github.com/spf13/viper/issues/761

Solution

Just wrap viper instance and use the same `Unmarshal` method as you did before:

e := enviper.New(viper.New())
e.Unmarshal(&config)

Credits

Thanks to https://github.com/krak3n (https://github.com/spf13/viper/issues/188#issuecomment-399884438) and https://github.com/celian-garcia (https://github.com/spf13/viper/issues/761#issuecomment-626122696) for inspiring.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Enviper

type Enviper struct {
	*viper.Viper
	// contains filtered or unexported fields
}

Enviper is a wrapper struct for viper, that makes it possible to unmarshal config to struct considering environment variables

func New

func New(v *viper.Viper) *Enviper

New returns an initialized Enviper instance

func (*Enviper) TagName added in v1.4.0

func (e *Enviper) TagName() string

TagName returns currently used tag name (`mapstructure` by default)

func (*Enviper) Unmarshal

func (e *Enviper) Unmarshal(rawVal interface{}, opts ...viper.DecoderConfigOption) error

Unmarshal unmarshals the config into a Struct just like viper does. The difference between enviper and viper is in automatic overriding data from file by data from env variables

Example
package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path"

	"github.com/iamolegga/enviper"
	"github.com/spf13/viper"
)

func main() {
	// describe config structure

	type barry struct {
		Bar int `mapstructure:"bar"`
	}
	type bazzy struct {
		Baz bool
	}
	type config struct {
		Foo   string
		Barry barry
		Bazzy bazzy `mapstructure:",squash"`
	}

	// write config file

	dir := os.TempDir()
	defer os.RemoveAll(dir)
	p := path.Join(dir, "config.yaml")
	ioutil.WriteFile(p, []byte(`
Foo: foo
Barry:
  bar: 1
`), 0777)

	// write env vars that could override values from config file

	os.Setenv("MYAPP_BARRY_BAR", "2") // override value from file
	os.Setenv("MYAPP_BAZ", "false")
	defer os.Unsetenv("MYAPP_BARRY_BAR")
	defer os.Unsetenv("MYAPP_BAZ")

	// setup viper and enviper

	var c config
	e := enviper.New(viper.New())
	e.SetEnvPrefix("MYAPP")
	e.AddConfigPath(dir)
	e.SetConfigName("config")
	if err := e.Unmarshal(&c); err != nil {
		fmt.Printf("%+v\n", err)
	}

	fmt.Println(c.Foo)       // file only
	fmt.Println(c.Barry.Bar) // file & env, take env
	fmt.Println(c.Bazzy.Baz) // env only
}
Output:
foo
2
false

func (*Enviper) WithTagName added in v1.4.0

func (e *Enviper) WithTagName(customTagName string) *Enviper

WithTagName sets custom tag name to be used instead of default `mapstructure`

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL