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

config: Use HookWeakDecodeFromSlice in place of PatchSliceOfMaps #7964

Merged
merged 1 commit into from
Jun 8, 2020

Conversation

dnephin
Copy link
Contributor

@dnephin dnephin commented May 27, 2020

Follow up on #7963, finishes the replacement of #7707

Preserves the existing behaviour, but should enable us to change it in a future release. All lazy-decode functions will be using the HookWeakDecodeFromSlice, so even if they receive new-style config, they will be able to handle it.

Currently opaque config blocks (config entries, and CA provider config) are
modified by PatchSliceOfMaps, making it impossible for these opaque
config sections to contain slices of maps.

In order to fix this problem, any lazy-decoding of these blocks needs to support
weak decoding of []map[string]interface{} to a struct type. This is necessary because
these config blocks are persisted, and during an upgrade an older version of Consul
could read one of the new configuration values, which would cause an error.

To support the upgrade path, this commit first introduces the new hooks
for weak decoding of []map[string]interface{} and uses them in the lazy-decode paths.
That way, in a future release, new style configuration will be supported by the older version
of Consul.

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.

agent/consul/authmethod/authmethods.go Outdated Show resolved Hide resolved
agent/connect/ca/provider_aws.go Outdated Show resolved Hide resolved
@dnephin dnephin force-pushed the dnephin/remove-patch-slice-of-maps-forward-compat branch 2 times, most recently from 8a073c1 to 9e07deb Compare May 29, 2020 17:58
@dnephin dnephin requested a review from a team May 29, 2020 18:32
@dnephin
Copy link
Contributor Author

dnephin commented May 29, 2020

I think we should consider getting this merged and included in the 1.8 release. If it does not make it into 1.8 we won't be able to fix the problems in 1.9 and it will push the new envoy config features out even further.

@dnephin dnephin force-pushed the dnephin/remove-patch-slice-of-maps-forward-compat branch from 9e07deb to 4ec6036 Compare May 29, 2020 19:21
@dnephin dnephin added this to the 1.8.0 milestone Jun 5, 2020
@dnephin dnephin force-pushed the dnephin/remove-patch-slice-of-maps-forward-compat branch from 4ec6036 to 23e6750 Compare June 5, 2020 21:11
@dnephin
Copy link
Contributor Author

dnephin commented Jun 5, 2020

Rebased, and removed the changes to CA provider, since those configs are not structured.

case len(d) == 0:
return nil, nil
case len(d) == 1:
return d[0], nil
Copy link
Contributor Author

@dnephin dnephin Jun 5, 2020

Choose a reason for hiding this comment

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

For a second I was worried this un-boxing of a single item from a slice would cause problems when a partially opaque config contained slices. I verified it is not a problem because we always use WeaklyTypedInput: true in the Decodeconfig, which will handle turning it back into a slice of a single item when the target is a slice.

I wonder where I can document that. I guess in all the Parse functions

Copy link
Member

Choose a reason for hiding this comment

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

In a comment here?

@dnephin dnephin force-pushed the dnephin/remove-patch-slice-of-maps-forward-compat branch from 23e6750 to 072211c Compare June 5, 2020 21:39
Copy link
Member

@banks banks left a comment

Choose a reason for hiding this comment

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

Approved after extensive internal discussion on the approach.

@dnephin great job here! There is one TODO inline that seems like it doesn't affect anything but just wanted to flag in case you planned to fix that in this pass. I'm approving because as far as I can see it's passing tests and working as desired now.

Given the other inline comment, it might be good to double check manually the workflow of managing Config Entries defined in HCL via the CLI. I think in that case the HCL -> map parse happens in the CLI command and then the client agent HTTP handler only accepts JSON, but still must account for the JSON being the output of an HCL parse so possibly containing extra slices.

Metadata: &md,
Result: &c,
DecodeHook: mapstructure.ComposeDecodeHookFunc(
decode.HookWeakDecodeFromSlice, // TODO: only apply when format is hcl
Copy link
Member

Choose a reason for hiding this comment

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

Does this TODO block merging?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It doesn't. I'll change the comment here to be more informative.

agent/discovery_chain_endpoint.go Show resolved Hide resolved
case len(d) == 0:
return nil, nil
case len(d) == 1:
return d[0], nil
Copy link
Member

Choose a reason for hiding this comment

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

In a comment here?

Currently opaque config blocks (config entries, and CA provider config) are
modified by PatchSliceOfMaps, making it impossible for these opaque
config sections to contain slices of maps.

In order to fix this problem, any lazy-decoding of these blocks needs to support
weak decoding of []map[string]interface{} to a struct type before
PatchSliceOfMaps is replaces. This is necessary because these config
blobs are persisted, and during an upgrade an older version of Consul
could read one of the new configuration values, which would cause an error.

To support the upgrade path, this commit first introduces the new hooks
for weak decoding of []map[string]interface{} and uses them only in the
lazy-decode paths. That way, in a future release, new style
configuration will be supported by the older version of Consul.

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.
@dnephin dnephin force-pushed the dnephin/remove-patch-slice-of-maps-forward-compat branch from 072211c to 75cbbe2 Compare June 8, 2020 21:05
@dnephin dnephin merged commit c66c533 into master Jun 8, 2020
@dnephin dnephin deleted the dnephin/remove-patch-slice-of-maps-forward-compat branch June 8, 2020 23:53
hashicorp-ci pushed a commit that referenced this pull request Jun 8, 2020
…-maps-forward-compat

config: Use HookWeakDecodeFromSlice in place of PatchSliceOfMaps
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.

None yet

3 participants