-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
hive: Unify parsing of string slices #29848
hive: Unify parsing of string slices #29848
Conversation
Marking with Looking at |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/lgtm, thanks!
I've just left a couple of minor comments inline.
700cb23
to
1a17e90
Compare
/test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not clear to me why we need both stringToSliceHookFunc
and fixupStringSliceHookFunc
. Doesn't mapstructure.StringToSliceHookFunc(","),
already split by comma? There's some overlap between both functions introduced here.
Also, isn't is possible to wrap mapstructure.StringToSliceHookFunc()
and make one take precedence over the other?
A quick overview of all the kinds of expected inputs would be nice to have as a comment. 👍
Ah now that you said it, yes I think we can just have EDIT: Worked nicely!
Doesn't the commit description list them? ("So to summarize the different ways a StringSlice can be parsed:"). EDIT: Ah as comment in code? Adding! |
1a17e90
to
433af69
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the fix and the great writeup on the origins of how we got into this confusing situation. I think that the approach used here is a reasonable way to fix the backwards compatibility while defining some consistency going forward.
Hive uses pflag and viper to parse configuration flags from multiple sources. If a flag is set via command-line then the pflag parser is invoked to get to the destination type as defined in the FlagSet ("flags.StringSlice" [1]), however if the flag comes from environment or config-map, then the parsing was done by a mapstructure hook [2]. This is all well and good as long as these two ways of parsing into say []string are aligned with each other. And they were. Unfortunately these were not aligned with the pre-Hive way of parsing which used viper.GetStringSlice and similar methods. Specifically viper.GetStringSlice is implemented ([3]) via cast.ToStringSlice, which uses strings.Fields that splits by whitespace instead of by commas. So to summarize the different ways a StringSlice can be parsed: - [1]: flags.StringSlice: parses with csv.Reader (split by comma) - [2]: stringToSliceHookFunc: splits by comma - [3]: viper.GetStringSlice: splits by whitespaces So while arguably the first two are more consistent, we can't just flip from splitting by spaces to splitting by commas as that creates a huge foot-gun when fields are moved from option.Config to individual hive.Config structs. To solve this we allow splitting both ways by using two mapstructure hooks that process the values before they're pushed to the config struct: - mapstructure.StringToSliceHookFunc(",") splits first string by commas. This only impacts input coming from environment, configmap or flags.String and going to []string. - fixupStringSliceHookFunc takes []string coming from flags.StringSlice or from the StringToSliceHookFunc and resplits it by whitespace if it was of length 1. With this, we have unified the parsing of []string across all the config input methods: "foo,bar,baz" => []string{"foo", "bar", "baz"} "foo bar baz" => []string{"foo", "bar", "baz"} "foo bar,baz" => []string{"foo bar", "baz"} [1]: https://github.com/spf13/pflag/blob/master/string_slice.go#L27 [2]: https://github.com/mitchellh/mapstructure/blob/main/decode_hooks.go#L104 [3]: https://github.com/spf13/viper/blob/9154b900c34ad9d88897f7e5288ce43f457f698b/viper.go#L1067 Fixes: cilium#29210 Fixes: b407ffc ("hive: Reimplement on top of dig") Signed-off-by: Jussi Maki <jussi@isovalent.com>
433af69
to
2e2a466
Compare
/test |
Hive uses pflag and viper to parse configuration flags from multiple sources. If a flag is set via command-line then the pflag parser is invoked to get to the destination type as defined in the FlagSet ("flags.StringSlice" 1), however if the flag comes from enviroment or config-map, then the parsing was done by a mapstructure hook 2.
This is all well and good as long as these two ways of parsing into say []string are aligned with each other. And they were. Unfortunately these were not aligned with the pre-Hive way of parsing which used viper.GetStringSlice and similar methods. Specifically viper.GetStringSlice is implemented (3) via cast.ToStringSlice, which uses strings.Fields that splits by whitespace instead of by commas.
So to summarize the different ways a StringSlice can be parsed:
So while arguably the first two are more consistent, we can't just flip from splitting by spaces to splitting by commas as that creates a huge foot-gun when fields are moved from option.Config to individual hive.Config structs.
To solve this we allow splitting both ways by using two mapstructure hooks that process the values before they're pushed to the config struct:
stringToSliceHookFunc now splits first by commas and if it doesn't produce multiple values it will split by commas. This handles the values going to []string and coming from "flags.String", config file, config map and the environment.
fixupStringSliceHookFunc takes []string coming from flags.StringSlice that was split by comma and resplits it if splitting by comma resulted in a single value.
With this, we have unified the parsing of []string across all the config input methods:
"foo,bar,baz" => []string{"foo", "bar", "baz"}
"foo bar baz" => []string{"foo", "bar", "baz"}
"foo bar,baz" => []string{"foo bar", "baz"}
Fixes: #29210
Fixes: b407ffc ("hive: Reimplement on top of dig")