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

viper.GetStringMapString(key) doesn't work with AutomaticEnv #911

Open
amir20 opened this issue May 11, 2020 · 9 comments
Open

viper.GetStringMapString(key) doesn't work with AutomaticEnv #911

amir20 opened this issue May 11, 2020 · 9 comments

Comments

@amir20
Copy link

amir20 commented May 11, 2020

I currently use Viper to configure a Docker service. It doesn't make sense for people to change the entrypoint. So I rely on ENV vars heavily.

Following up with #608, using AutomaticEnv() with GetStringMapString() still doesn't work.

Looking through the source code, Viper branches based on the source. I debugged and found the function below gets an exception because it can't parse foo=bar style values with JSON. It also unexpectedly swallows and exception here :/

func ToStringMapString(i interface{}) map[string]string {
	v, _ := ToStringMapStringE(i)
	return v
}

As a user, I expect viper.Get***() to work regardless of the source.

I believe the chang would actually have to be in https://github.com/spf13/cast/blob/master/cast.go#L108-L110.

@amir20
Copy link
Author

amir20 commented May 11, 2020

@sagikazarmark
Copy link
Collaborator

I'm not sure this needs fixing. In environment variables Viper already accepts JSON strings which is more flexible than the key-value pairs supported by pflags.

@amir20
Copy link
Author

amir20 commented May 12, 2020

Hmm. That seems confusing. I prioritize for users' ease of use. It would be confusing for some flags via --filter to take key=value while using ENV requiring JSON. That seems counterintuitive.

Also, to provide some context, my project is an open source tool paired with Docker. Docker uses key=value for --filter so I wanted to mirror the same behavior. For a user, it would be much easier to provide DOZZLE_FILTER=name=dozzle in docker-compose than {"DOZZLE_FILTER": "name=dozzle"}.

For anybody who is interested, I handle this myself.

if value, ok := os.LookupEnv("DOZZLE_FILTER"); ok {
	log.Infof("Parsing %s", value)
	urlValues, err := url.ParseQuery(strings.ReplaceAll(value, ",", "&"))
	if err != nil {
		log.Fatal(err)
	}
	filters = map[string]string{}
	for k, v := range urlValues {
		filters[k] = v[0]
	}
}

I can add a PR for the above code. But maybe it doesn't make sense to have JSON and key value format.

@sagikazarmark
Copy link
Collaborator

sagikazarmark commented May 12, 2020

Well, whether it's confusing or not, this is the current behavior. Breaking it is not an option at the moment, but I agree it would be nice to have a key-value pair like format for environment variables.

This is exactly why I don't really like the current getter-based fetching, because it doesn't give you enough flexibility. You would assume that an env var should behave the same way as this type of flag, others need the flexibility of JSON. (Keep in mind that flags are registered for each type whereas env vars are just key-value pairs, so flags can support both styles at the same time, env vars can't.)

I usually suggest everyone to create a config struct with customized types, for example:

type config struct{
    filter filterType
}

type filterType map[string]string

Then for this filter type you can create your own mapstructure decoding hook, which can decode both strings (env vars) and maps (flags).

After that, you can unmarshal your config onto that struct:

var c config

viper.Unmarshal(&c)

// or even
viper.UnmarshalKey("filter", &c.filter)

Don't think of it as a workaround, for me this is the de facto solution for these (and basically all) use cases.

@amir20
Copy link
Author

amir20 commented May 12, 2020

Interesting, I hadn't pursued creating my own config struct. I started with only a few flags which then ended up needing more. I'll look at it again.

@sagikazarmark
Copy link
Collaborator

IMHO using a config struct is always superior to everything else.

Here is an example: https://github.com/sagikazarmark/modern-go-application/blob/master/cmd/modern-go-application/config.go

@amir20
Copy link
Author

amir20 commented May 12, 2020

Thanks! I was about to ping you for an example :)

@sagikazarmark
Copy link
Collaborator

You can also find a couple decoding hook examples here:

https://github.com/banzaicloud/pipeline/blob/f30951333348d54ad9055cafd876e2aa3c4fa3de/pkg/hook/hook.go#L24

sayboras added a commit to sayboras/cilium that referenced this issue Jan 20, 2022
As mentioned in below upstream issue, there is a discrepancy in viper
while reading string map string data type i.e. kv pair format was not
supported, only `{"k":"v"}` format is allowed. This commit is to wrap
GetStringMapString implementation to handle such case.

Also, during the bootstrap, if there is any flag having invalid value,
fatal log will be printed for early detection and awareness.

Relates spf13/viper#911
Fixes cilium#18328

Signed-off-by: Tam Mach <tam.mach@isovalent.com>
glibsm pushed a commit to cilium/cilium that referenced this issue Jan 31, 2022
As mentioned in below upstream issue, there is a discrepancy in viper
while reading string map string data type i.e. kv pair format was not
supported, only `{"k":"v"}` format is allowed. This commit is to wrap
GetStringMapString implementation to handle such case.

Also, during the bootstrap, if there is any flag having invalid value,
fatal log will be printed for early detection and awareness.

Relates spf13/viper#911
Fixes #18328

Signed-off-by: Tam Mach <tam.mach@isovalent.com>
joamaki pushed a commit to joamaki/cilium that referenced this issue Feb 7, 2022
[ upstream commit 768659f ]

As mentioned in below upstream issue, there is a discrepancy in viper
while reading string map string data type i.e. kv pair format was not
supported, only `{"k":"v"}` format is allowed. This commit is to wrap
GetStringMapString implementation to handle such case.

Also, during the bootstrap, if there is any flag having invalid value,
fatal log will be printed for early detection and awareness.

Relates spf13/viper#911
Fixes cilium#18328

Signed-off-by: Tam Mach <tam.mach@isovalent.com>
Signed-off-by: Jussi Maki <jussi@isovalent.com>
joamaki pushed a commit to joamaki/cilium that referenced this issue Feb 7, 2022
[ upstream commit 768659f ]

As mentioned in below upstream issue, there is a discrepancy in viper
while reading string map string data type i.e. kv pair format was not
supported, only `{"k":"v"}` format is allowed. This commit is to wrap
GetStringMapString implementation to handle such case.

Also, during the bootstrap, if there is any flag having invalid value,
fatal log will be printed for early detection and awareness.

Relates spf13/viper#911
Fixes cilium#18328

Signed-off-by: Tam Mach <tam.mach@isovalent.com>
Signed-off-by: Jussi Maki <jussi@isovalent.com>
joamaki pushed a commit to cilium/cilium that referenced this issue Feb 8, 2022
[ upstream commit 768659f ]

As mentioned in below upstream issue, there is a discrepancy in viper
while reading string map string data type i.e. kv pair format was not
supported, only `{"k":"v"}` format is allowed. This commit is to wrap
GetStringMapString implementation to handle such case.

Also, during the bootstrap, if there is any flag having invalid value,
fatal log will be printed for early detection and awareness.

Relates spf13/viper#911
Fixes #18328

Signed-off-by: Tam Mach <tam.mach@isovalent.com>
Signed-off-by: Jussi Maki <jussi@isovalent.com>
joamaki pushed a commit to cilium/cilium that referenced this issue Feb 8, 2022
[ upstream commit 768659f ]

As mentioned in below upstream issue, there is a discrepancy in viper
while reading string map string data type i.e. kv pair format was not
supported, only `{"k":"v"}` format is allowed. This commit is to wrap
GetStringMapString implementation to handle such case.

Also, during the bootstrap, if there is any flag having invalid value,
fatal log will be printed for early detection and awareness.

Relates spf13/viper#911
Fixes #18328

Signed-off-by: Tam Mach <tam.mach@isovalent.com>
Signed-off-by: Jussi Maki <jussi@isovalent.com>
@digitebs
Copy link

Correction, the fix would need to be at https://github.com/spf13/cast/blob/1ffadf551085444af981432dd0f6d1160c11ec64/caste.go#L855-L880

why no merge?

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

3 participants