1
0
mirror of https://github.com/rancher/steve.git synced 2025-07-14 15:14:44 +00:00

[main] block UI until we receive requests from kube-apiserver (#668)

* block UI until we receive requests from kube-apiserver

* satisfy CI

* undo test code

---------

Co-authored-by: joshmeranda <joshua.meranda@gmail.com>
This commit is contained in:
Josh Meranda 2025-06-11 14:58:36 -04:00 committed by GitHub
parent 1157865ea3
commit c67ddf2de4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 43 additions and 2 deletions

View File

@ -108,6 +108,8 @@ type ExtensionAPIServer struct {
handlerMu sync.RWMutex
handler http.Handler
registeredChan <-chan struct{}
}
type emptyAddresses struct{}
@ -129,15 +131,38 @@ func NewExtensionAPIServer(scheme *runtime.Scheme, codecs serializer.CodecFactor
return nil, fmt.Errorf("listener must be provided")
}
if opts.GetOpenAPIDefinitions == nil {
return nil, fmt.Errorf("GetOpenAPIDefinitions must be provided")
}
if opts.Authorizer == nil {
// We need an authorizer to allow us to wrap it with a check for kube-apisevrer registration requests.
return nil, fmt.Errorf("authorizer must be provided")
}
recommendedOpts := genericoptions.NewRecommendedOptions("", codecs.LegacyCodec())
recommendedOpts.SecureServing.Listener = opts.Listener
registered := make(chan struct{})
var once sync.Once
resolver := &request.RequestInfoFactory{APIPrefixes: sets.NewString("apis", "api"), GrouplessAPIPrefixes: sets.NewString("api")}
config := genericapiserver.NewRecommendedConfig(codecs)
config.RequestInfoResolver = resolver
config.Authorization = genericapiserver.AuthorizationInfo{
Authorizer: opts.Authorizer,
Authorizer: authorizer.AuthorizerFunc(func(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) {
switch a.GetUser().GetName() {
case "system:aggregator", "system:kube-aggregator":
once.Do(func() {
close(registered)
})
}
return opts.Authorizer.Authorize(ctx, a)
}),
}
// The default kube effective version ends up being the version of the
// library. (The value is hardcoded but it is kept up-to-date via some
// automation)
@ -189,6 +214,7 @@ func NewExtensionAPIServer(scheme *runtime.Scheme, codecs serializer.CodecFactor
genericAPIServer: genericServer,
apiGroups: make(map[string]genericapiserver.APIGroupInfo),
authorizer: opts.Authorizer,
registeredChan: registered,
}
return extensionAPIServer, nil
@ -301,3 +327,7 @@ func getDefinitionName(scheme *runtime.Scheme, replacements map[string]string) f
return definitionName, defGVK
}
}
func (s *ExtensionAPIServer) Registered() <-chan struct{} {
return s.registeredChan
}

View File

@ -44,6 +44,8 @@ type ExtensionAPIServer interface {
http.Handler
// Run configures the API server and make the HTTP handler available
Run(ctx context.Context) error
// Registered returns a channel that will be close once the registration requests are received from the kube-apiserver.
Registered() <-chan struct{}
}
type Server struct {
@ -253,7 +255,16 @@ func setup(ctx context.Context, server *Server) error {
onSchemasHandler,
sf)
apiServer, handler, err := handler.New(server.RESTConfig, sf, server.authMiddleware, server.next, server.router, server.extensionAPIServer)
next := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
select {
case <-server.extensionAPIServer.Registered():
server.next.ServeHTTP(rw, req)
default:
http.NotFoundHandler().ServeHTTP(rw, req)
}
})
apiServer, handler, err := handler.New(server.RESTConfig, sf, server.authMiddleware, next, server.router, server.extensionAPIServer)
if err != nil {
return err
}