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

Replace PatchSliceOfMaps #7707

Closed
wants to merge 2 commits into from
Closed

Conversation

dnephin
Copy link
Contributor

@dnephin dnephin commented Apr 24, 2020

Relates to #4971, but the fix for that has moved to #7935

PatchSliceOfMaps was being used to normalize parsed HCL into a canonical form. It has a number of rough edges which make it prone to errors. Having to identify fields so far away from the struct which contains the fields meant that there were slices that were not properly added to the exclude list. It also duplicated the tree walking that already exists in mapstructure.

To use a mapstructure hook I first had to replace lib.TranslateKeys, as that was called in between PatchSliceOfMaps and mapstructure.Decode. lib.TranslateKeys had some of the same problems. The rules for modifying fields were very far from the struct which defined the fields, and it also duplicated tree walking.

This PR replaces both PatchSliceOfMaps and lib.TranslateKeys with mapstructure hooks. It maintains the current behaviour of modifying opaque configuration, but makes it possible to fix that behaviour in the future. It also removes a panic that was unnecessary because mapstructure will error if the from and to types are not compatible. Added a test to show that behaviour.

Copy link
Member

@mkeeler mkeeler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you still have some todos open so I wont approve just yet. This is looking good so far though.

One thing to keep in mind is that there are performance issues with mapstructure especially when using decode hooks. That was the original reason why we moved mapstructure usage out of the HTTP APIs and in particular the Txn API at some point last year. I don't think any of these changes would be cause for concern as they all look to be just config parsing related.

api/config_entry_gateways.go Outdated Show resolved Hide resolved
lib/decode/decode.go Outdated Show resolved Hide resolved
Copy link
Contributor Author

@dnephin dnephin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

One thing to keep in mind is that there are performance issues with mapstructure especially when using decode hooks. That was the original reason why we moved mapstructure usage out of the HTTP APIs and in particular the Txn API at some point last year

I found that PR while I was working on this. What I found (ex: #7689) was that in some cases these performance optimizations were not actually being used. The decodeBody function is being called on a map[string]interface{}, not a struct, so the UnmarshalJSON is not doing anything. I tested by adding a panic to the unmarshal function. #7689 found one case, but I believe I found another couple cases that I haven't PR'ed yet.

In general I completely agree that mapstructure is not well suited for decode request bodies from API endpoints.

lib/decode/decode.go Outdated Show resolved Hide resolved
@dnephin dnephin force-pushed the dnephin/remove-patch-slice-of-maps branch 2 times, most recently from 8525d59 to aa9aae1 Compare May 8, 2020 21:04
@dnephin dnephin changed the base branch from dnephin/remove-deadcode-1 to master May 13, 2020 18:02
@dnephin dnephin force-pushed the dnephin/remove-patch-slice-of-maps branch 2 times, most recently from 524bf5d to 325689b Compare May 13, 2020 22:12
@dnephin
Copy link
Contributor Author

dnephin commented May 20, 2020

This is ready for a review. I moved the change in behaviour to #7935 so this PR is now only a refactor to enable that change.

@dnephin dnephin requested a review from a team May 20, 2020 17:49
@dnephin dnephin force-pushed the dnephin/remove-patch-slice-of-maps branch from 325689b to 7f49759 Compare May 20, 2020 20:48
This decode hook has a number of advantages:

1. It no longer panics. It allows mapstructure to report the error
2. It no longer requires the user to declare which fields are slices of
   structs. It can deduce that information from the 'to' value.
3. It will make it possible to preserve opaque configuration, allowing
   for structured opaque config.

Also replace TranslateKeys with HookTranslateKeys, as this function was
in-between PatchSliceOfMaps and mapstructure.Decode, so it had to be
moved to a decode hook to allow PatchSliceOfMaps to become a decode
hook.

One call of TranslateKeys remains for CA config.
Now that the original config parsing leaves the opaque maps unmodified
these secondary decodes must use the hooks to normalize fields.
@dnephin
Copy link
Contributor Author

dnephin commented May 27, 2020

Replaced by #7963 and subsequent PRs.

@dnephin dnephin closed this May 27, 2020
@dnephin dnephin deleted the dnephin/remove-patch-slice-of-maps branch June 9, 2020 22:55
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

Successfully merging this pull request may close these issues.

3 participants