I've spotted that when defining a custom REST storage, its constructor is being called both from apiserver and controller-manager binaries (panic() is inserted manually in the code):
$ bin/controller-manager --kubeconfig=kubeconfig
panic: panic
goroutine 1 [running]:
test/pkg/handler.NewHandler(0xc42078a380, 0xc42068f6b0, 0xc42078a380, 0xc42068f6b0, 0x0)
/go/src/test/pkg/handler/handler.go:56 +0x99
test/pkg/apis/apps/v1.NewApplicationREST(0x3c95540, 0xc4207fe640)
/go/src/test/pkg/apis/apps/v1/application_rest.go:203 +0xc0
test/pkg/apis/apps/v1.init()
/go/src/test/pkg/apis/apps/v1/zz_generated.api.register.go:49 +0x1eb
test/pkg/controller/application.init()
/go/src/test/pkg/controller/application/zz_generated.api.register.go:99 +0x5d
test/pkg/controller.init()
/go/src/test/pkg/controller/zz_generated.api.register.go:41 +0x44
main.init()
/go/src/test/cmd/controller/main.go:31 +0x5a```
This happens because NewXxxRest() is called during package-level variable initialization in v1/zz_generated.api.register.go:
appsApplicationStorage = builders.NewApiResourceWithStorage( // Resource status endpoint
apps.InternalApplication,
ApplicationSchemeFns{},
func() runtime.Object { return &Application{} }, // Register versioned resource
func() runtime.Object { return &ApplicationList{} }, // Register versioned resource list
NewApplicationREST(),
)
NewXxxREST() constructor may contain some other logic besides simply initializing the custom REST registry type. For example it may establish a connection to some service. And we'll end up with an extra unused connection to the external service, established from the controller manager.
I think we should either fix this or explicitly state (in the documentation and/or in the generated code) that NewXxxREST() should only construct new empty instance of XxxREST without performing any heavy initialization.