Unstructured converter panics if the destination struct contains private fields
hugoShaka opened this issue · comments
Using the DefaultUnsatructuredConverter with a destination struct containing a non-exported field throws a panic.
I might be in a specific edge case, but we're using protobuf to generate gRPC structs. Those structs contain private fields holding the grpc state and cause the controller to panic, even if the unstructured object only contain the public user-facing fields.
I would expect the converter to ignore private fields. I can send a PR if you confirm this should be fixed and that the fix is to skip the private fields.
Reproducing
Run the following snippet:
package main
import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"log"
)
type StructuredObject struct {
Spec StructuredObjectSpec
}
type StructuredObjectSpec struct {
bar []byte
Foo string
}
func main() {
u := &unstructured.Unstructured{
Object: map[string]interface{}{
"spec": map[string]interface{}{
"foo": "value",
},
},
}
structured := StructuredObject{}
err := runtime.DefaultUnstructuredConverter.FromUnstructuredWithValidation(
u.Object,
&structured,
true, /* returnUnknownFields */
)
if err != nil {
log.Fatal(err)
}
}
Observe the panic
panic: reflect: reflect.Value.Set using value obtained using unexported field
goroutine 1 [running]:
reflect.flag.mustBeAssignableSlow(0x140000337a8?)
/usr/local/go/src/reflect/value.go:269 +0xb4
reflect.flag.mustBeAssignable(...)
/usr/local/go/src/reflect/value.go:259
reflect.Value.Set({0x100f4c3e0?, 0x14000169800?, 0x14000011168?}, {0x100f4c3e0?, 0x101232e40?, 0x98?})
/usr/local/go/src/reflect/value.go:2319 +0x58
k8s.io/apimachinery/pkg/runtime.structFromUnstructured({0x100f63c60?, 0x140001697d0?, 0x1012f0248?}, {0x100f7e000?, 0x14000169800?, 0x100c2d5f8?}, 0x14000033e60)
/Users/shaka/go/pkg/mod/k8s.io/apimachinery@v0.29.3/pkg/runtime/converter.go:556 +0x490
k8s.io/apimachinery/pkg/runtime.fromUnstructured({0x100f63c60?, 0x140001697d0?, 0x1400001115c?}, {0x100f7e000?, 0x14000169800?, 0x98?}, 0x14000033e60)
/Users/shaka/go/pkg/mod/k8s.io/apimachinery@v0.29.3/pkg/runtime/converter.go:359 +0x2c4
k8s.io/apimachinery/pkg/runtime.structFromUnstructured({0x100f63c60?, 0x140001697a0?, 0x14000033c48?}, {0x100f71840?, 0x14000169800?, 0x100cabbf4?}, 0x14000033e60)
/Users/shaka/go/pkg/mod/k8s.io/apimachinery@v0.29.3/pkg/runtime/converter.go:550 +0x64c
k8s.io/apimachinery/pkg/runtime.fromUnstructured({0x100f63c60?, 0x140001697a0?, 0x10?}, {0x100f71840?, 0x14000169800?, 0x100c35cec?}, 0x14000033e60)
/Users/shaka/go/pkg/mod/k8s.io/apimachinery@v0.29.3/pkg/runtime/converter.go:359 +0x2c4
k8s.io/apimachinery/pkg/runtime.(*unstructuredConverter).FromUnstructuredWithValidation(0x1011c8df0, 0x140001697a0, {0x100f44b20, 0x14000169800}, 0x1)
/Users/shaka/go/pkg/mod/k8s.io/apimachinery@v0.29.3/pkg/runtime/converter.go:247 +0x20c
main.main()
/Users/shaka/playground/repro-runtime-panic/main.go:30 +0x110
This might be an issue for api machinery, rather than controller runtime
Something to try, use json:"-"
tag in private fields
Something to try, use
json:"-"
tag in private fields
The protobuf folks seem opinionated against doing so: golang/protobuf#1379.
I missed that this was in the apimachinery module, sorry for the spam. I'll go open an issue there.
Edit: opened kubernetes/kubernetes#124154