Commit dc9c08d
Don't call Marshal in unmarshalerEmbeddedStructsHookFunc (#14213)
## Context
`confmap` uses a `mapstructure` hook to call the `Unmarshal` method on
types which define it as part of the unmarshaling process, but
`mapstructure` hooks are not called for squashed fields, so we have a
separate hook which manually inspects all structs for squashed fields
that implement `Unmarshaler`.
This second hook currently returns a modified version of the raw YAML
config, to be used by `mapstructure` to finish unmarshaling the full
struct. This is a problem, because an `Unmarshal` method can set the
state of the struct in arbitrary ways, which we want to preserve without
`mapstructure` overwriting fields. (See `TestEmbeddedUnmarshaler`)
The way this is currently worked around is by marshaling the embedded
struct into a map, and then copying that map back into the raw config,
in the hope that nothing will change when the raw config is mapped back
into the struct.
However, this assumption breaks when dealing with a
`configopaque.String` inside an embedded `Unmarshaler`. That type has
the very deliberate behavior of returning `[REDACTED]` when marshaled
instead of its true contents, meaning marshaling then unmarshaling does
not round trip.
## Description
This PR attempts to fix this issue and make embedded `Unmarshaler`s more
reliable by modifying the hook so that it returns a fully unmarshaled
struct, leading `mapstructure` to do nothing. (This is what the basic
`Unmarshaler` hook does to avoid "interference".)
This means the hook needs to somehow unmarshal the non-`Unmarshaler`
subfields manually, without affecting the input or output of
`Unmarshal`. I did this by constructing a custom "partial" struct using
`reflect.StructOf` which only contains the non-`Unmarshaler` fields,
copying the initial values into it, calling `Decode` on it, then copying
the output values back into the original struct.
In a previous version of this PR, I kept most of the hook intact, but
changed the logic so that we clear fields from the raw config when they
might conflict with the embedded struct (instead of setting those fields
to the embedded struct's current value). However, this has the side
effect of breaking unmarshaling of structs with multiple
identically-named fields, of which there is [at least one in
contrib](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/320ef1ca9bb4593b498eb3d849659c55d6a7eccc/receiver/dockerstatsreceiver/config.go#L17)
(both `docker.Config` and `scraperhelper.ControllerConfig` have a
`Timeout` field, and one of them implements `Unmarshaler`).
---------
Co-authored-by: Pablo Baeyens <pablo.baeyens@datadoghq.com>1 parent 0f06212 commit dc9c08d
File tree
3 files changed
+138
-25
lines changed- .chloggen
- confmap/internal
3 files changed
+138
-25
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
| |||
559 | 560 | | |
560 | 561 | | |
561 | 562 | | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
562 | 610 | | |
563 | 611 | | |
564 | 612 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
10 | | - | |
11 | 10 | | |
12 | 11 | | |
13 | 12 | | |
| |||
57 | 56 | | |
58 | 57 | | |
59 | 58 | | |
60 | | - | |
| 59 | + | |
61 | 60 | | |
62 | 61 | | |
63 | 62 | | |
| |||
189 | 188 | | |
190 | 189 | | |
191 | 190 | | |
192 | | - | |
| 191 | + | |
193 | 192 | | |
194 | 193 | | |
195 | 194 | | |
| |||
198 | 197 | | |
199 | 198 | | |
200 | 199 | | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
201 | 203 | | |
202 | | - | |
203 | 204 | | |
204 | | - | |
205 | | - | |
206 | | - | |
207 | | - | |
208 | | - | |
209 | | - | |
210 | | - | |
211 | | - | |
212 | | - | |
213 | | - | |
214 | | - | |
215 | | - | |
216 | | - | |
217 | | - | |
218 | | - | |
219 | | - | |
220 | | - | |
221 | | - | |
222 | | - | |
223 | | - | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
224 | 215 | | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
225 | 227 | | |
226 | | - | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
227 | 266 | | |
228 | 267 | | |
229 | 268 | | |
| |||
0 commit comments