-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
structured config #1: introduce mapstructure decoder for yaml parsing #2628
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
base: master
Are you sure you want to change the base?
structured config #1: introduce mapstructure decoder for yaml parsing #2628
Conversation
710f3a7
to
72dff61
Compare
39b625e
to
3fb3c1f
Compare
7f8def6
to
cd566ee
Compare
This pull request has been inactive for 60 days. If the pull request is still relevant please comment to re-activate the pull request. If no action is taken within 7 days, the pull request will be marked closed. |
pkg/apis/options/header.go
Outdated
|
||
// Allow users to load the value from a session claim | ||
*ClaimSource `json:",omitempty"` | ||
*ClaimSource `json:"claimSource,omitempty"` |
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.
We probably want to call this something different, such as, fromValue
with the previous field being fromSecret
Adding json tags to these is odd though since they are inlined, do you recall why this was needed?
I know on another PR we are talking about moving the prefix, is this the PR where in fact we should make this a discriminated union?
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.
IssuerURL string `json:"issuerURL,omitempty"` | ||
// InsecureAllowUnverifiedEmail prevents failures if an email address in an id_token is not verified | ||
// default set to 'false' | ||
InsecureAllowUnverifiedEmail bool `json:"insecureAllowUnverifiedEmail,omitempty"` |
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.
Why no longer omitempty?
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.
I decided to not omit any booleans. To ensure that the conversion flow from toml to yaml explicitly mentions all boolean values.
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.
Booleans really want to be pointers with omitempty IMO, else we don't have a way to tell between an explicitly set false value or implicitly set false just by the fact that false is the zero value
Would making them all pointers be complex for the conversion flow do you think?
This pull request has been inactive for 60 days. If the pull request is still relevant please comment to re-activate the pull request. If no action is taken within 7 days, the pull request will be marked closed. |
4941bf1
to
629ac24
Compare
I've developped independently #3064 which just handles the upgrade of viper+mapstructure. I think it would be worth doing that to keep this (2628) focused on behaviour changes. |
4158184
to
f46e023
Compare
/e2e |
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.
Pull Request Overview
This PR introduces mapstructure as the decoder for YAML configuration parsing, replacing the previous ghodss/yaml library. The change enables better handling of default values, type conversion, and field mapping while preserving existing configuration behavior.
Key changes:
- Replaces
options.Duration
wrapper type with nativetime.Duration
throughout the codebase - Implements mapstructure-based YAML parsing with decode hooks for duration and byte conversion
- Updates struct tags from
json
toyaml
across all configuration structs
Reviewed Changes
Copilot reviewed 31 out of 32 changed files in this pull request and generated 3 comments.
Show a summary per file
File | Description |
---|---|
pkg/apis/options/load.go | Implements new LoadYAML function using mapstructure decoder with custom hooks |
pkg/apis/options/hooks.go | Adds decode hooks for duration parsing and string-to-bytes conversion |
pkg/apis/options/upstreams.go | Updates FlushInterval and Timeout from Duration wrapper to time.Duration |
pkg/apis/options/*.go | Changes struct tags from json to yaml across configuration structs |
pkg/validation/upstreams.go | Updates duration comparison logic for new time.Duration type |
pkg/upstream/http.go | Removes Duration wrapper usage in favor of direct time.Duration |
main.go | Updates configuration loading flow and YAML marshaling logic |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.
a471d71
to
bc1d897
Compare
// FromEnv expects the name of an environment variable. | ||
FromEnv string `yaml:"fromEnv,omitempty"` |
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.
Not blocking for this PR, but I thought now we have env substitution, we won't need this right?
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.
I would like to do a cleanup and review of our options API after we have the full alpha config support done
IssuerURL string `json:"issuerURL,omitempty"` | ||
// InsecureAllowUnverifiedEmail prevents failures if an email address in an id_token is not verified | ||
// default set to 'false' | ||
InsecureAllowUnverifiedEmail bool `json:"insecureAllowUnverifiedEmail,omitempty"` |
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.
Booleans really want to be pointers with omitempty IMO, else we don't have a way to tell between an explicitly set false value or implicitly set false just by the fact that false is the zero value
Would making them all pointers be complex for the conversion flow do you think?
), | ||
Metadata: nil, // Don't track any metadata | ||
Result: result, // Decode the result into the prefilled options | ||
TagName: "yaml", // Parse all fields that use the json tag |
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.
Is there a reason to switch to yaml instead of json? Is some other library relying on yaml?
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.
Yes the yaml parser expects it:
https://pkg.go.dev/gopkg.in/yaml.v3
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.
Ack, can you just explain in the comment here why we use the yaml tag
Some yaml libraries like the json
tag instead
bc1d897
to
d2f72ef
Compare
@@ -0,0 +1,5 @@ | |||
package ptr |
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.
Could create generics here?
Also, ptr.Deref
which allows you to provide a default value if the pointer is nil?
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.
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.
Good idea
f84ed08
to
179e390
Compare
func Int(v int) *int { return &v } | ||
|
||
// Ptr generically returns a pointer to the given value. | ||
func Ptr[T any](v T) *T { |
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.
Maybe To
to make it read as ptr.To
"pointer to"?
pkg/util/ptr/ptr.go
Outdated
func Bool(v bool) *bool { return &v } | ||
func String(v string) *string { return &v } | ||
func Int(v int) *int { return &v } |
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.
We shouldn't need these anymore right?
} | ||
|
||
// Deref returns the value of the pointer or def(ault) if nil. | ||
func Deref[T any](p *T, def T) T { |
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.
I saw lots of places where this isn't currently used where it could be, lets try and be exhaustive within the current PR and hopefully avoid panics
headersToStrip := []string{} | ||
for _, header := range headers { | ||
if !header.PreserveRequestValue { | ||
if !(*header.PreserveRequestValue) { |
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.
Deref?
// Change default duration for waiting for an upstream response | ||
if upstream.Timeout != nil { | ||
transport.ResponseHeaderTimeout = upstream.Timeout.Duration() | ||
transport.ResponseHeaderTimeout = *upstream.Timeout |
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.
Deref?
} | ||
|
||
if upstreams.ProxyRawPath { | ||
if *upstreams.ProxyRawPath { |
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.
Deref?
remove color output in tests for better readability in github actions bugfix: remove google as default provider for alpha options fix conversion flow for toml to yaml revert ginkgo color deactivation revert claim- and secret source back to pointers regenerate alpha config
Signed-off-by: Jan Larwig <[email protected]>
Signed-off-by: Jan Larwig <[email protected]>
Signed-off-by: Jan Larwig <[email protected]>
Signed-off-by: Jan Larwig <[email protected]>
Signed-off-by: Jan Larwig <[email protected]>
Signed-off-by: Jan Larwig <[email protected]>
Signed-off-by: Jan Larwig <[email protected]>
179e390
to
9db7738
Compare
Description
This PR introduces mapstructure for decoding and encoding the yaml files. Mapstructure is a defacto standard library used by many libraries like spf13/viper for more dynamic data loading between different interfaces.
Just using the golang json / yaml encoding / decoding would lead to overwriting the default set before loading the config file. Trying to load the default configs afterwards would be rather hard or impossible.
Motivation and Context
Cases to consider:
false
in the config file or if it was set to the boolean default of false. This is problematic as we have boolean likeCookie.Secure
that are supposed to be set totrue
by default.HeaderValues
either being aSecretSource
orClaimSource
. Which isn't supported by the default json / yaml parsertime
primitives likeDuration
orTime
through strings. If you want to be able to configureDuration
types with values like2h
. You need to implement a custom wrapper type and Marshal and Unmarshal method. Mapstructure allows for decoding hooks through the usage of relection.How Has This Been Tested?
Checklist: