Viper: Get config values from environment variables

Created on 3 Jun 2015  路  12Comments  路  Source: spf13/viper

It is common to use environment variables in container systems as docker to configure settings. It would be great if viper would handle this too:

Defaults -> Environment Variables -> Settings Files -> Command Options

Most helpful comment

Is there any updates on @scotthew1's question? Using the options like StringVar or StringVarP and having the config value be populated into the var would be ideal. There shouldn't be a need to call Viper.Get() in order to get the value from the CLI options, config file, environment variables, etc.

All 12 comments

It's already possible, with https://github.com/spf13/cobra / https://github.com/spf13/pflag and viper, something like that :

viper.AutomaticEnv()
flags := rootCmd.Flags()
flags.StringVarP(&username, "username", "u", "", "username, facultative if you have config file")
viper.BindPFlag("username", flags.Lookup("username"))

Perfect, thank you!

Working fine, I like!

Does it make sense to close this issue if the indicated functionality is present (and therefore not an issue) ?

does anyone have a full working example of this env binding? i've seen @yesnault's snippit in a few different places, but i'm not actually getting the var i care about populated with the env. am i missing something here?

package main

import (
    "fmt"

    "github.com/spf13/cobra"
    "github.com/spf13/viper"
)

func main() {
    var thing1 string
    var thing2 string

    var cmd = &cobra.Command{
        Use:   "viper-test",
        Short: "testing viper",
        Run: func(command *cobra.Command, args []string) {
            fmt.Printf("thing1: %q\n", thing1)
            fmt.Printf("thing2: %q\n", thing2)
        },
    }

    viper.AutomaticEnv()
    flags := cmd.Flags()
    flags.StringVar(&thing1, "thing1", "", "The first thing")
    viper.BindPFlag("thing1", flags.Lookup("thing1"))
    flags.StringVar(&thing2, "thing2", "", "The second thing")
    viper.BindPFlag("thing2", flags.Lookup("thing2"))

    cmd.Execute()
}
$ export THING1=hello THING2=world

$ ./viper-test
thing1: ""
thing2: ""

$ ./viper-test --thing1 hello --thing2 world
thing1: "hello"
thing2: "world"

@scotthew1

package main

import (
    "fmt"

    "github.com/spf13/cobra"
    "github.com/spf13/viper"
)

func main() {
    var cmd = &cobra.Command{
        Use:   "viper-test",
        Short: "testing viper",
        Run: func(command *cobra.Command, args []string) {
            fmt.Printf("thing1: %q\n", viper.GetString("thing1"))
            fmt.Printf("thing2: %q\n", viper.GetString("thing2"))
        },
    }

    viper.AutomaticEnv()
    flags := cmd.Flags()
    flags.String("thing1", "", "The first thing")
    viper.BindPFlag("thing1", flags.Lookup("thing1"))
    flags.String("thing2", "", "The second thing")
    viper.BindPFlag("thing2", flags.Lookup("thing2"))

    cmd.Execute()
}

@yesnault yeah i was able to get something like that working, but i was hoping viper would work with the *Var() flags.. your example from before uses StringVarP() and the example from the cobra readme shows the same. i was ultimately hoping to have a config struct that viper/pflags would populate that my code could use without having to cal viper.Get(). is this not possible as the examples imply?

ah... i just read past further past the example i linked...

Note, that the variable author will not be set to the value from config, when the --author flag is not provided by user.

that makes for a pretty unfortunate example... any ideas for doing what i described in my previous comment? or am i misunderstanding viper's utility?

Is there any updates on @scotthew1's question? Using the options like StringVar or StringVarP and having the config value be populated into the var would be ideal. There shouldn't be a need to call Viper.Get() in order to get the value from the CLI options, config file, environment variables, etc.

I truly don't understand the usefulness of the viper integration if I still have to call Viper.get() instead of it automatically being bound to the variable. Is there any movement on this?

You don't have to call Get. You can unmarshal values into a struct from Viper.

*Var will never work though, because pflag is integrated into Viper, not the other way around. pflag is used as a source, values never travel from viper to pflag and *Var is a pflag feature.

Closing as this feature is already implemented. Please open separate discussions.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

therealfakemoot picture therealfakemoot  路  5Comments

xh3b4sd picture xh3b4sd  路  6Comments

TheHackerDev picture TheHackerDev  路  3Comments

gmaxwell94 picture gmaxwell94  路  5Comments

kubaugustyn picture kubaugustyn  路  3Comments