kubernetes-sigs / controller-runtime

Repo for the controller-runtime subproject of kubebuilder (sig-apimachinery)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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