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

hive: Unify parsing of string slices #29848

Merged
merged 1 commit into from
Dec 21, 2023

Conversation

joamaki
Copy link
Contributor

@joamaki joamaki commented Dec 13, 2023

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:

  • 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:

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

Unify parsing of StringSlice flags and allow splitting by commas (preferably) or by spaces. This fixes parsing of 'prometheus.metrics'.

@joamaki joamaki added the release-blocker/1.15 This issue will prevent the release of the next version of Cilium. label Dec 13, 2023
@joamaki joamaki requested a review from a team as a code owner December 13, 2023 10:25
@joamaki joamaki requested a review from ti-mo December 13, 2023 10:25
@maintainer-s-little-helper maintainer-s-little-helper bot added the dont-merge/needs-release-note-label The author needs to describe the release impact of these changes. label Dec 13, 2023
@joamaki joamaki added the release-note/bug This PR fixes an issue in a previous release of Cilium. label Dec 13, 2023
@maintainer-s-little-helper maintainer-s-little-helper bot removed the dont-merge/needs-release-note-label The author needs to describe the release impact of these changes. label Dec 13, 2023
@joamaki joamaki added the needs-backport/1.14 This PR / issue needs backporting to the v1.14 branch label Dec 13, 2023
@joamaki
Copy link
Contributor Author

joamaki commented Dec 13, 2023

Marking with needs-backport/1.14 as pkg/metrics was modularized in v1.14 and thus split '--metrics' by comma resulting in prometheus.metrics helm value to be incorrectly set. (e.g. via Helm we'd get config-map file metrics with content +metric1 +metric2 which would get parsed to []string{"+metric1 +metric2"} and not []string{"+metric1", "+metric2"}).

Looking at go run ./daemon hive for v1.14 the other []string config fields are --enable-cilium-api-server-access and --enable-cilium-health-api-server-access, but these are not configured via helm templates and thus not an issue.

pkg/hive/cell/config.go Outdated Show resolved Hide resolved
Copy link
Member

@giorio94 giorio94 left a 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.

pkg/hive/cell/config.go Show resolved Hide resolved
pkg/hive/cell/config.go Outdated Show resolved Hide resolved
pkg/hive/hive_test.go Outdated Show resolved Hide resolved
@joamaki joamaki force-pushed the pr/joamaki/stringslice-split-both-ways branch 3 times, most recently from 700cb23 to 1a17e90 Compare December 13, 2023 13:46
@joamaki
Copy link
Contributor Author

joamaki commented Dec 13, 2023

/test

pkg/hive/cell/config.go Outdated Show resolved Hide resolved
pkg/hive/cell/config.go Outdated Show resolved Hide resolved
@joestringer joestringer added the needs-backport/1.15 This PR / issue needs backporting to the v1.15 branch label Dec 14, 2023
Copy link
Contributor

@ti-mo ti-mo left a 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. 👍

@joestringer joestringer added this to Needs backport from main in v1.15.0-rc.1 Dec 14, 2023
@joamaki
Copy link
Contributor Author

joamaki commented Dec 15, 2023

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.

stringToSliceHookFunc is getting the input as string (e.g. from environment or configmap), fixupStringSliceHookFunc is getting the input from pflag's StringSlice where it's already of type []string and split by comma and we're post-processing it to split the same way as we do when it's coming from environment variables or configmap.

Also, isn't is possible to wrap mapstructure.StringToSliceHookFunc() and make one take precedence over the other?

Ah now that you said it, yes I think we can just have StringToSliceHookFunc split by commas and then have fixupStringSliceHookFunc do the rest. I'll try it out.

EDIT: Worked nicely!

A quick overview of all the kinds of expected inputs would be nice to have as a comment. 👍

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!

@joamaki joamaki force-pushed the pr/joamaki/stringslice-split-both-ways branch from 1a17e90 to 433af69 Compare December 15, 2023 09:06
Copy link
Member

@joestringer joestringer left a 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.

pkg/hive/cell/config.go Show resolved Hide resolved
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>
@joamaki joamaki force-pushed the pr/joamaki/stringslice-split-both-ways branch from 433af69 to 2e2a466 Compare December 18, 2023 15:00
@joamaki
Copy link
Contributor Author

joamaki commented Dec 18, 2023

/test

@joamaki joamaki added this pull request to the merge queue Dec 21, 2023
Merged via the queue into cilium:main with commit 0bf036e Dec 21, 2023
62 checks passed
@joamaki joamaki deleted the pr/joamaki/stringslice-split-both-ways branch December 21, 2023 09:36
@pippolo84 pippolo84 mentioned this pull request Jan 2, 2024
17 tasks
@pippolo84 pippolo84 added backport-pending/1.15 The backport for Cilium 1.15.x for this PR is in progress. and removed needs-backport/1.15 This PR / issue needs backporting to the v1.15 branch labels Jan 2, 2024
@maintainer-s-little-helper maintainer-s-little-helper bot added this to Needs backport from main in 1.14.6 Jan 2, 2024
@maintainer-s-little-helper maintainer-s-little-helper bot moved this from Needs backport from main to Backport pending to v1.15 in v1.15.0-rc.1 Jan 2, 2024
@pippolo84 pippolo84 mentioned this pull request Jan 2, 2024
8 tasks
@pippolo84 pippolo84 added backport-pending/1.14 The backport for Cilium 1.14.x for this PR is in progress. and removed needs-backport/1.14 This PR / issue needs backporting to the v1.14 branch labels Jan 2, 2024
@maintainer-s-little-helper maintainer-s-little-helper bot moved this from Needs backport from main to Backport pending to v1.14 in 1.14.6 Jan 2, 2024
@github-actions github-actions bot added backport-done/1.14 The backport for Cilium 1.14.x for this PR is done. and removed backport-pending/1.14 The backport for Cilium 1.14.x for this PR is in progress. labels Jan 9, 2024
@maintainer-s-little-helper maintainer-s-little-helper bot removed this from Backport pending to v1.14 in 1.14.6 Jan 9, 2024
@aanm aanm added backport-done/1.15 The backport for Cilium 1.15.x for this PR is done. and removed backport-pending/1.15 The backport for Cilium 1.15.x for this PR is in progress. labels Jan 16, 2024
@aanm aanm added this to Backport pending to v1.15 in 1.15.1 Jan 31, 2024
@aanm aanm removed this from Backport pending to vv1.15.0-rc in v1.15.0-rc.1 Jan 31, 2024
@aanm aanm removed this from Backport pending to v1.15 in 1.15.1 Jan 31, 2024
@aanm aanm added this to Backport done to v1.15 in v1.15.0-rc.1 Jan 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport-done/1.14 The backport for Cilium 1.14.x for this PR is done. backport-done/1.15 The backport for Cilium 1.15.x for this PR is done. release-blocker/1.15 This issue will prevent the release of the next version of Cilium. release-note/bug This PR fixes an issue in a previous release of Cilium.
Projects
No open projects
v1.15.0-rc.1
Backport done to v1.15
Development

Successfully merging this pull request may close these issues.

StringSlice no longer works for values splitted by spaces on hive cells
8 participants