Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get config values from environment variables #85

Closed
r0l1 opened this issue Jun 3, 2015 · 12 comments
Closed

Get config values from environment variables #85

r0l1 opened this issue Jun 3, 2015 · 12 comments

Comments

@r0l1
Copy link

r0l1 commented Jun 3, 2015

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

@yesnault
Copy link

yesnault commented Jul 2, 2015

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"))

@r0l1
Copy link
Author

r0l1 commented Jul 14, 2015

Perfect, thank you!

@rogierlommers
Copy link

Working fine, I like!

@four2five
Copy link

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

@scotthew1
Copy link

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"

@yesnault
Copy link

@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()
}

@scotthew1
Copy link

@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?

@scotthew1
Copy link

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?

@danielmai
Copy link

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.

brouberol pushed a commit to DataDog/kafka-kit that referenced this issue Nov 14, 2018
`cobra` does not allow setting default values to flag via env vars
without using `viper` (see spf13/viper#85),
so I restored the previous behaviour with a little elbow grease.

```
$ TOPICMAPPR_ZK_ADDR="zookeeper-metrics-1:2181" TOPICMAPPR_ZK_PREFIX="kafka" ./topicmappr rebuild --topics test1 --brokers '1,2,3'
Failed to connect to ZooKeeper zookeeper-metrics-1:2181 within 250ms

$ ./topicmappr rebuild --topics test1 --brokers '1,2,3'
Failed to connect to ZooKeeper localhost:2181 within 250ms
```
brouberol pushed a commit to DataDog/kafka-kit that referenced this issue Nov 14, 2018
`cobra` does not allow setting default values to flag via env vars
without using `viper` (see spf13/viper#85),
so I restored the previous behaviour with a little elbow grease.

```
$ TOPICMAPPR_ZK_ADDR="zookeeper-metrics-1:2181" TOPICMAPPR_ZK_PREFIX="kafka" ./topicmappr rebuild --topics test1 --brokers '1,2,3'
Failed to connect to ZooKeeper zookeeper-metrics-1:2181 within 250ms

$ ./topicmappr rebuild --topics test1 --brokers '1,2,3'
Failed to connect to ZooKeeper localhost:2181 within 250ms
```
brouberol pushed a commit to DataDog/kafka-kit that referenced this issue Nov 14, 2018
`cobra` does not allow setting default values to flag via env vars
without using `viper` (see spf13/viper#85),
so I restored the previous behaviour with a little elbow grease.

```
$ TOPICMAPPR_ZK_ADDR="zookeeper-custom:2181" TOPICMAPPR_ZK_PREFIX="kafka" ./topicmappr rebuild --topics test1 --brokers '1,2,3'
Failed to connect to ZooKeeper zookeeper-custom:2181 within 250ms

$ ./topicmappr rebuild --topics test1 --brokers '1,2,3'
Failed to connect to ZooKeeper localhost:2181 within 250ms
```
@McShauno
Copy link

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?

@sagikazarmark
Copy link
Collaborator

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.

@sagikazarmark
Copy link
Collaborator

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants