Upgrade k8s package verison (#5358)
* upgrade k8s package version Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io> * Script upgrade and code formatting. Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io> Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>
This commit is contained in:
372
vendor/k8s.io/apiserver/pkg/server/genericapiserver.go
generated
vendored
372
vendor/k8s.io/apiserver/pkg/server/genericapiserver.go
generated
vendored
@@ -24,17 +24,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
systemd "github.com/coreos/go-systemd/daemon"
|
||||
"github.com/go-openapi/spec"
|
||||
systemd "github.com/coreos/go-systemd/v22/daemon"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
utilwaitgroup "k8s.io/apimachinery/pkg/util/waitgroup"
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/audit"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
@@ -50,11 +49,14 @@ import (
|
||||
utilopenapi "k8s.io/apiserver/pkg/util/openapi"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/klog/v2"
|
||||
openapibuilder "k8s.io/kube-openapi/pkg/builder"
|
||||
openapibuilder2 "k8s.io/kube-openapi/pkg/builder"
|
||||
openapicommon "k8s.io/kube-openapi/pkg/common"
|
||||
"k8s.io/kube-openapi/pkg/handler"
|
||||
"k8s.io/kube-openapi/pkg/handler3"
|
||||
openapiutil "k8s.io/kube-openapi/pkg/util"
|
||||
openapiproto "k8s.io/kube-openapi/pkg/util/proto"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
"k8s.io/utils/clock"
|
||||
)
|
||||
|
||||
// Info about an API group.
|
||||
@@ -87,6 +89,14 @@ type APIGroupInfo struct {
|
||||
StaticOpenAPISpec *spec.Swagger
|
||||
}
|
||||
|
||||
func (a *APIGroupInfo) destroyStorage() {
|
||||
for _, stores := range a.VersionedResourcesStorageMap {
|
||||
for _, store := range stores {
|
||||
store.Destroy()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GenericAPIServer contains state for a Kubernetes cluster api server.
|
||||
type GenericAPIServer struct {
|
||||
// discoveryAddresses is used to build cluster IPs for discovery.
|
||||
@@ -133,6 +143,9 @@ type GenericAPIServer struct {
|
||||
// Enable swagger and/or OpenAPI if these configs are non-nil.
|
||||
openAPIConfig *openapicommon.Config
|
||||
|
||||
// Enable swagger and/or OpenAPI V3 if these configs are non-nil.
|
||||
openAPIV3Config *openapicommon.Config
|
||||
|
||||
// SkipOpenAPIInstallation indicates not to install the OpenAPI handler
|
||||
// during PrepareRun.
|
||||
// Set this to true when the specific API Server has its own OpenAPI handler
|
||||
@@ -143,6 +156,10 @@ type GenericAPIServer struct {
|
||||
// It is set during PrepareRun if `openAPIConfig` is non-nil unless `skipOpenAPIInstallation` is true.
|
||||
OpenAPIVersionedService *handler.OpenAPIService
|
||||
|
||||
// OpenAPIV3VersionedService controls the /openapi/v3 endpoint and can be used to update the served spec.
|
||||
// It is set during PrepareRun if `openAPIConfig` is non-nil unless `skipOpenAPIInstallation` is true.
|
||||
OpenAPIV3VersionedService *handler3.OpenAPIService
|
||||
|
||||
// StaticOpenAPISpec is the spec derived from the restful container endpoints.
|
||||
// It is set during PrepareRun.
|
||||
StaticOpenAPISpec *spec.Swagger
|
||||
@@ -173,11 +190,8 @@ type GenericAPIServer struct {
|
||||
readyzChecksInstalled bool
|
||||
livezGracePeriod time.Duration
|
||||
livezClock clock.Clock
|
||||
// the readiness stop channel is used to signal that the apiserver has initiated a shutdown sequence, this
|
||||
// will cause readyz to return unhealthy.
|
||||
readinessStopCh chan struct{}
|
||||
|
||||
// auditing. The backend is started after the server starts listening.
|
||||
// auditing. The backend is started before the server starts listening.
|
||||
AuditBackend audit.Backend
|
||||
|
||||
// Authorizer determines whether a user is allowed to make a certain request. The Handler does a preliminary
|
||||
@@ -209,6 +223,30 @@ type GenericAPIServer struct {
|
||||
|
||||
// StorageVersionManager holds the storage versions of the API resources installed by this server.
|
||||
StorageVersionManager storageversion.Manager
|
||||
|
||||
// Version will enable the /version endpoint if non-nil
|
||||
Version *version.Info
|
||||
|
||||
// lifecycleSignals provides access to the various signals that happen during the life cycle of the apiserver.
|
||||
lifecycleSignals lifecycleSignals
|
||||
|
||||
// destroyFns contains a list of functions that should be called on shutdown to clean up resources.
|
||||
destroyFns []func()
|
||||
|
||||
// muxAndDiscoveryCompleteSignals holds signals that indicate all known HTTP paths have been registered.
|
||||
// it exists primarily to avoid returning a 404 response when a resource actually exists but we haven't installed the path to a handler.
|
||||
// it is exposed for easier composition of the individual servers.
|
||||
// the primary users of this field are the WithMuxCompleteProtection filter and the NotFoundHandler
|
||||
muxAndDiscoveryCompleteSignals map[string]<-chan struct{}
|
||||
|
||||
// ShutdownSendRetryAfter dictates when to initiate shutdown of the HTTP
|
||||
// Server during the graceful termination of the apiserver. If true, we wait
|
||||
// for non longrunning requests in flight to be drained and then initiate a
|
||||
// shutdown of the HTTP Server. If false, we initiate a shutdown of the HTTP
|
||||
// Server as soon as ShutdownDelayDuration has elapsed.
|
||||
// If enabled, after ShutdownDelayDuration elapses, any incoming request is
|
||||
// rejected with a 429 status code and a 'Retry-After' response.
|
||||
ShutdownSendRetryAfter bool
|
||||
}
|
||||
|
||||
// DelegationTarget is an interface which allows for composition of API servers with top level handling that works
|
||||
@@ -234,6 +272,14 @@ type DelegationTarget interface {
|
||||
|
||||
// PrepareRun does post API installation setup steps. It calls recursively the same function of the delegates.
|
||||
PrepareRun() preparedGenericAPIServer
|
||||
|
||||
// MuxAndDiscoveryCompleteSignals exposes registered signals that indicate if all known HTTP paths have been installed.
|
||||
MuxAndDiscoveryCompleteSignals() map[string]<-chan struct{}
|
||||
|
||||
// Destroy cleans up its resources on shutdown.
|
||||
// Destroy has to be implemented in thread-safe way and be prepared
|
||||
// for being called more than once.
|
||||
Destroy()
|
||||
}
|
||||
|
||||
func (s *GenericAPIServer) UnprotectedHandler() http.Handler {
|
||||
@@ -257,15 +303,55 @@ func (s *GenericAPIServer) NextDelegate() DelegationTarget {
|
||||
return s.delegationTarget
|
||||
}
|
||||
|
||||
// RegisterMuxAndDiscoveryCompleteSignal registers the given signal that will be used to determine if all known
|
||||
// HTTP paths have been registered. It is okay to call this method after instantiating the generic server but before running.
|
||||
func (s *GenericAPIServer) RegisterMuxAndDiscoveryCompleteSignal(signalName string, signal <-chan struct{}) error {
|
||||
if _, exists := s.muxAndDiscoveryCompleteSignals[signalName]; exists {
|
||||
return fmt.Errorf("%s already registered", signalName)
|
||||
}
|
||||
s.muxAndDiscoveryCompleteSignals[signalName] = signal
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *GenericAPIServer) MuxAndDiscoveryCompleteSignals() map[string]<-chan struct{} {
|
||||
return s.muxAndDiscoveryCompleteSignals
|
||||
}
|
||||
|
||||
// RegisterDestroyFunc registers a function that will be called during Destroy().
|
||||
// The function have to be idempotent and prepared to be called more than once.
|
||||
func (s *GenericAPIServer) RegisterDestroyFunc(destroyFn func()) {
|
||||
s.destroyFns = append(s.destroyFns, destroyFn)
|
||||
}
|
||||
|
||||
// Destroy cleans up all its and its delegation target resources on shutdown.
|
||||
// It starts with destroying its own resources and later proceeds with
|
||||
// its delegation target.
|
||||
func (s *GenericAPIServer) Destroy() {
|
||||
for _, destroyFn := range s.destroyFns {
|
||||
destroyFn()
|
||||
}
|
||||
if s.delegationTarget != nil {
|
||||
s.delegationTarget.Destroy()
|
||||
}
|
||||
}
|
||||
|
||||
type emptyDelegate struct {
|
||||
// handler is called at the end of the delegation chain
|
||||
// when a request has been made against an unregistered HTTP path the individual servers will simply pass it through until it reaches the handler.
|
||||
handler http.Handler
|
||||
}
|
||||
|
||||
func NewEmptyDelegate() DelegationTarget {
|
||||
return emptyDelegate{}
|
||||
}
|
||||
|
||||
// NewEmptyDelegateWithCustomHandler allows for registering a custom handler usually for special handling of 404 requests
|
||||
func NewEmptyDelegateWithCustomHandler(handler http.Handler) DelegationTarget {
|
||||
return emptyDelegate{handler}
|
||||
}
|
||||
|
||||
func (s emptyDelegate) UnprotectedHandler() http.Handler {
|
||||
return nil
|
||||
return s.handler
|
||||
}
|
||||
func (s emptyDelegate) PostStartHooks() map[string]postStartHookEntry {
|
||||
return map[string]postStartHookEntry{}
|
||||
@@ -285,6 +371,11 @@ func (s emptyDelegate) NextDelegate() DelegationTarget {
|
||||
func (s emptyDelegate) PrepareRun() preparedGenericAPIServer {
|
||||
return preparedGenericAPIServer{nil}
|
||||
}
|
||||
func (s emptyDelegate) MuxAndDiscoveryCompleteSignals() map[string]<-chan struct{} {
|
||||
return map[string]<-chan struct{}{}
|
||||
}
|
||||
func (s emptyDelegate) Destroy() {
|
||||
}
|
||||
|
||||
// preparedGenericAPIServer is a private wrapper that enforces a call of PrepareRun() before Run can be invoked.
|
||||
type preparedGenericAPIServer struct {
|
||||
@@ -298,100 +389,245 @@ func (s *GenericAPIServer) PrepareRun() preparedGenericAPIServer {
|
||||
if s.openAPIConfig != nil && !s.skipOpenAPIInstallation {
|
||||
s.OpenAPIVersionedService, s.StaticOpenAPISpec = routes.OpenAPI{
|
||||
Config: s.openAPIConfig,
|
||||
}.Install(s.Handler.GoRestfulContainer, s.Handler.NonGoRestfulMux)
|
||||
}.InstallV2(s.Handler.GoRestfulContainer, s.Handler.NonGoRestfulMux)
|
||||
}
|
||||
|
||||
if s.openAPIV3Config != nil && !s.skipOpenAPIInstallation {
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.OpenAPIV3) {
|
||||
s.OpenAPIV3VersionedService = routes.OpenAPI{
|
||||
Config: s.openAPIV3Config,
|
||||
}.InstallV3(s.Handler.GoRestfulContainer, s.Handler.NonGoRestfulMux)
|
||||
}
|
||||
}
|
||||
|
||||
s.installHealthz()
|
||||
s.installLivez()
|
||||
err := s.addReadyzShutdownCheck(s.readinessStopCh)
|
||||
|
||||
// as soon as shutdown is initiated, readiness should start failing
|
||||
readinessStopCh := s.lifecycleSignals.ShutdownInitiated.Signaled()
|
||||
err := s.addReadyzShutdownCheck(readinessStopCh)
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to install readyz shutdown check %s", err)
|
||||
}
|
||||
s.installReadyz()
|
||||
|
||||
// Register audit backend preShutdownHook.
|
||||
if s.AuditBackend != nil {
|
||||
err := s.AddPreShutdownHook("audit-backend", func() error {
|
||||
s.AuditBackend.Shutdown()
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to add pre-shutdown hook for audit-backend %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
return preparedGenericAPIServer{s}
|
||||
}
|
||||
|
||||
// Run spawns the secure http server. It only returns if stopCh is closed
|
||||
// or the secure port cannot be listened on initially.
|
||||
// This is the diagram of what channels/signals are dependent on each other:
|
||||
//
|
||||
// stopCh
|
||||
// |
|
||||
// ---------------------------------------------------------
|
||||
// | |
|
||||
// ShutdownInitiated (shutdownInitiatedCh) |
|
||||
// | |
|
||||
//
|
||||
// (ShutdownDelayDuration) (PreShutdownHooks)
|
||||
//
|
||||
// | |
|
||||
// AfterShutdownDelayDuration (delayedStopCh) PreShutdownHooksStopped (preShutdownHooksHasStoppedCh)
|
||||
// | |
|
||||
// |-------------------------------------------------------|
|
||||
// |
|
||||
// |
|
||||
// NotAcceptingNewRequest (notAcceptingNewRequestCh)
|
||||
// |
|
||||
// |
|
||||
// |---------------------------------------------------------|
|
||||
// | | | |
|
||||
// [without [with | |
|
||||
//
|
||||
// ShutdownSendRetryAfter] ShutdownSendRetryAfter] | |
|
||||
//
|
||||
// | | | |
|
||||
// | ---------------| |
|
||||
// | | |
|
||||
// | (HandlerChainWaitGroup::Wait) |
|
||||
// | | |
|
||||
// | InFlightRequestsDrained (drainedCh) |
|
||||
// | | |
|
||||
// ----------------------------------------|-----------------|
|
||||
// | |
|
||||
// stopHttpServerCh (AuditBackend::Shutdown())
|
||||
// |
|
||||
// listenerStoppedCh
|
||||
// |
|
||||
// HTTPServerStoppedListening (httpServerStoppedListeningCh)
|
||||
func (s preparedGenericAPIServer) Run(stopCh <-chan struct{}) error {
|
||||
delayedStopCh := make(chan struct{})
|
||||
delayedStopCh := s.lifecycleSignals.AfterShutdownDelayDuration
|
||||
shutdownInitiatedCh := s.lifecycleSignals.ShutdownInitiated
|
||||
|
||||
// Clean up resources on shutdown.
|
||||
defer s.Destroy()
|
||||
|
||||
// spawn a new goroutine for closing the MuxAndDiscoveryComplete signal
|
||||
// registration happens during construction of the generic api server
|
||||
// the last server in the chain aggregates signals from the previous instances
|
||||
go func() {
|
||||
for _, muxAndDiscoveryCompletedSignal := range s.GenericAPIServer.MuxAndDiscoveryCompleteSignals() {
|
||||
select {
|
||||
case <-muxAndDiscoveryCompletedSignal:
|
||||
continue
|
||||
case <-stopCh:
|
||||
klog.V(1).Infof("haven't completed %s, stop requested", s.lifecycleSignals.MuxAndDiscoveryComplete.Name())
|
||||
return
|
||||
}
|
||||
}
|
||||
s.lifecycleSignals.MuxAndDiscoveryComplete.Signal()
|
||||
klog.V(1).Infof("%s has all endpoints registered and discovery information is complete", s.lifecycleSignals.MuxAndDiscoveryComplete.Name())
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer close(delayedStopCh)
|
||||
defer delayedStopCh.Signal()
|
||||
defer klog.V(1).InfoS("[graceful-termination] shutdown event", "name", delayedStopCh.Name())
|
||||
|
||||
<-stopCh
|
||||
|
||||
// As soon as shutdown is initiated, /readyz should start returning failure.
|
||||
// This gives the load balancer a window defined by ShutdownDelayDuration to detect that /readyz is red
|
||||
// and stop sending traffic to this server.
|
||||
close(s.readinessStopCh)
|
||||
shutdownInitiatedCh.Signal()
|
||||
klog.V(1).InfoS("[graceful-termination] shutdown event", "name", shutdownInitiatedCh.Name())
|
||||
|
||||
time.Sleep(s.ShutdownDelayDuration)
|
||||
}()
|
||||
|
||||
// close socket after delayed stopCh
|
||||
stoppedCh, err := s.NonBlockingRun(delayedStopCh)
|
||||
shutdownTimeout := s.ShutdownTimeout
|
||||
if s.ShutdownSendRetryAfter {
|
||||
// when this mode is enabled, we do the following:
|
||||
// - the server will continue to listen until all existing requests in flight
|
||||
// (not including active long running requests) have been drained.
|
||||
// - once drained, http Server Shutdown is invoked with a timeout of 2s,
|
||||
// net/http waits for 1s for the peer to respond to a GO_AWAY frame, so
|
||||
// we should wait for a minimum of 2s
|
||||
shutdownTimeout = 2 * time.Second
|
||||
klog.V(1).InfoS("[graceful-termination] using HTTP Server shutdown timeout", "ShutdownTimeout", shutdownTimeout)
|
||||
}
|
||||
|
||||
notAcceptingNewRequestCh := s.lifecycleSignals.NotAcceptingNewRequest
|
||||
drainedCh := s.lifecycleSignals.InFlightRequestsDrained
|
||||
stopHttpServerCh := make(chan struct{})
|
||||
go func() {
|
||||
defer close(stopHttpServerCh)
|
||||
|
||||
timeToStopHttpServerCh := notAcceptingNewRequestCh.Signaled()
|
||||
if s.ShutdownSendRetryAfter {
|
||||
timeToStopHttpServerCh = drainedCh.Signaled()
|
||||
}
|
||||
|
||||
<-timeToStopHttpServerCh
|
||||
}()
|
||||
|
||||
// Start the audit backend before any request comes in. This means we must call Backend.Run
|
||||
// before http server start serving. Otherwise the Backend.ProcessEvents call might block.
|
||||
// AuditBackend.Run will stop as soon as all in-flight requests are drained.
|
||||
if s.AuditBackend != nil {
|
||||
if err := s.AuditBackend.Run(drainedCh.Signaled()); err != nil {
|
||||
return fmt.Errorf("failed to run the audit backend: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
stoppedCh, listenerStoppedCh, err := s.NonBlockingRun(stopHttpServerCh, shutdownTimeout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
httpServerStoppedListeningCh := s.lifecycleSignals.HTTPServerStoppedListening
|
||||
go func() {
|
||||
<-listenerStoppedCh
|
||||
httpServerStoppedListeningCh.Signal()
|
||||
klog.V(1).InfoS("[graceful-termination] shutdown event", "name", httpServerStoppedListeningCh.Name())
|
||||
}()
|
||||
|
||||
// we don't accept new request as soon as both ShutdownDelayDuration has
|
||||
// elapsed and preshutdown hooks have completed.
|
||||
preShutdownHooksHasStoppedCh := s.lifecycleSignals.PreShutdownHooksStopped
|
||||
go func() {
|
||||
defer klog.V(1).InfoS("[graceful-termination] shutdown event", "name", notAcceptingNewRequestCh.Name())
|
||||
defer notAcceptingNewRequestCh.Signal()
|
||||
|
||||
// wait for the delayed stopCh before closing the handler chain
|
||||
<-delayedStopCh.Signaled()
|
||||
|
||||
// Additionally wait for preshutdown hooks to also be finished, as some of them need
|
||||
// to send API calls to clean up after themselves (e.g. lease reconcilers removing
|
||||
// itself from the active servers).
|
||||
<-preShutdownHooksHasStoppedCh.Signaled()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer klog.V(1).InfoS("[graceful-termination] shutdown event", "name", drainedCh.Name())
|
||||
defer drainedCh.Signal()
|
||||
|
||||
// wait for the delayed stopCh before closing the handler chain (it rejects everything after Wait has been called).
|
||||
<-notAcceptingNewRequestCh.Signaled()
|
||||
|
||||
// Wait for all requests to finish, which are bounded by the RequestTimeout variable.
|
||||
// once HandlerChainWaitGroup.Wait is invoked, the apiserver is
|
||||
// expected to reject any incoming request with a {503, Retry-After}
|
||||
// response via the WithWaitGroup filter. On the contrary, we observe
|
||||
// that incoming request(s) get a 'connection refused' error, this is
|
||||
// because, at this point, we have called 'Server.Shutdown' and
|
||||
// net/http server has stopped listening. This causes incoming
|
||||
// request to get a 'connection refused' error.
|
||||
// On the other hand, if 'ShutdownSendRetryAfter' is enabled incoming
|
||||
// requests will be rejected with a {429, Retry-After} since
|
||||
// 'Server.Shutdown' will be invoked only after in-flight requests
|
||||
// have been drained.
|
||||
// TODO: can we consolidate these two modes of graceful termination?
|
||||
s.HandlerChainWaitGroup.Wait()
|
||||
}()
|
||||
|
||||
klog.V(1).Info("[graceful-termination] waiting for shutdown to be initiated")
|
||||
<-stopCh
|
||||
|
||||
// run shutdown hooks directly. This includes deregistering from the kubernetes endpoint in case of kube-apiserver.
|
||||
err = s.RunPreShutdownHooks()
|
||||
// run shutdown hooks directly. This includes deregistering from
|
||||
// the kubernetes endpoint in case of kube-apiserver.
|
||||
func() {
|
||||
defer func() {
|
||||
preShutdownHooksHasStoppedCh.Signal()
|
||||
klog.V(1).InfoS("[graceful-termination] pre-shutdown hooks completed", "name", preShutdownHooksHasStoppedCh.Name())
|
||||
}()
|
||||
err = s.RunPreShutdownHooks()
|
||||
}()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// wait for the delayed stopCh before closing the handler chain (it rejects everything after Wait has been called).
|
||||
<-delayedStopCh
|
||||
// Wait for all requests in flight to drain, bounded by the RequestTimeout variable.
|
||||
<-drainedCh.Signaled()
|
||||
|
||||
if s.AuditBackend != nil {
|
||||
s.AuditBackend.Shutdown()
|
||||
klog.V(1).InfoS("[graceful-termination] audit backend shutdown completed")
|
||||
}
|
||||
|
||||
// wait for stoppedCh that is closed when the graceful termination (server.Shutdown) is finished.
|
||||
<-listenerStoppedCh
|
||||
<-stoppedCh
|
||||
|
||||
// Wait for all requests to finish, which are bounded by the RequestTimeout variable.
|
||||
s.HandlerChainWaitGroup.Wait()
|
||||
|
||||
klog.V(1).Info("[graceful-termination] apiserver is exiting")
|
||||
return nil
|
||||
}
|
||||
|
||||
// NonBlockingRun spawns the secure http server. An error is
|
||||
// returned if the secure port cannot be listened on.
|
||||
// The returned channel is closed when the (asynchronous) termination is finished.
|
||||
func (s preparedGenericAPIServer) NonBlockingRun(stopCh <-chan struct{}) (<-chan struct{}, error) {
|
||||
// Use an stop channel to allow graceful shutdown without dropping audit events
|
||||
// after http server shutdown.
|
||||
auditStopCh := make(chan struct{})
|
||||
|
||||
// Start the audit backend before any request comes in. This means we must call Backend.Run
|
||||
// before http server start serving. Otherwise the Backend.ProcessEvents call might block.
|
||||
if s.AuditBackend != nil {
|
||||
if err := s.AuditBackend.Run(auditStopCh); err != nil {
|
||||
return nil, fmt.Errorf("failed to run the audit backend: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s preparedGenericAPIServer) NonBlockingRun(stopCh <-chan struct{}, shutdownTimeout time.Duration) (<-chan struct{}, <-chan struct{}, error) {
|
||||
// Use an internal stop channel to allow cleanup of the listeners on error.
|
||||
internalStopCh := make(chan struct{})
|
||||
var stoppedCh <-chan struct{}
|
||||
var listenerStoppedCh <-chan struct{}
|
||||
if s.SecureServingInfo != nil && s.Handler != nil {
|
||||
var err error
|
||||
stoppedCh, err = s.SecureServingInfo.Serve(s.Handler, s.ShutdownTimeout, internalStopCh)
|
||||
stoppedCh, listenerStoppedCh, err = s.SecureServingInfo.Serve(s.Handler, shutdownTimeout, internalStopCh)
|
||||
if err != nil {
|
||||
close(internalStopCh)
|
||||
close(auditStopCh)
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,11 +637,6 @@ func (s preparedGenericAPIServer) NonBlockingRun(stopCh <-chan struct{}) (<-chan
|
||||
go func() {
|
||||
<-stopCh
|
||||
close(internalStopCh)
|
||||
if stoppedCh != nil {
|
||||
<-stoppedCh
|
||||
}
|
||||
s.HandlerChainWaitGroup.Wait()
|
||||
close(auditStopCh)
|
||||
}()
|
||||
|
||||
s.RunPostStartHooks(stopCh)
|
||||
@@ -414,7 +645,7 @@ func (s preparedGenericAPIServer) NonBlockingRun(stopCh <-chan struct{}) (<-chan
|
||||
klog.Errorf("Unable to send systemd daemon successful start message: %v\n", err)
|
||||
}
|
||||
|
||||
return stoppedCh, nil
|
||||
return stoppedCh, listenerStoppedCh, nil
|
||||
}
|
||||
|
||||
// installAPIResources is a private method for installing the REST storage backing each api groupversionresource
|
||||
@@ -426,7 +657,10 @@ func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *A
|
||||
continue
|
||||
}
|
||||
|
||||
apiGroupVersion := s.getAPIGroupVersion(apiGroupInfo, groupVersion, apiPrefix)
|
||||
apiGroupVersion, err := s.getAPIGroupVersion(apiGroupInfo, groupVersion, apiPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if apiGroupInfo.OptionsExternalVersion != nil {
|
||||
apiGroupVersion.OptionsExternalVersion = apiGroupInfo.OptionsExternalVersion
|
||||
}
|
||||
@@ -449,6 +683,8 @@ func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *A
|
||||
resourceInfos = append(resourceInfos, r...)
|
||||
}
|
||||
|
||||
s.RegisterDestroyFunc(apiGroupInfo.destroyStorage)
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.StorageVersionAPI) &&
|
||||
utilfeature.DefaultFeatureGate.Enabled(features.APIServerIdentity) {
|
||||
// API installation happens before we start listening on the handlers,
|
||||
@@ -460,6 +696,9 @@ func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *A
|
||||
return nil
|
||||
}
|
||||
|
||||
// InstallLegacyAPIGroup exposes the given legacy api group in the API.
|
||||
// The <apiGroupInfo> passed into this function shouldn't be used elsewhere as the
|
||||
// underlying storage will be destroyed on this servers shutdown.
|
||||
func (s *GenericAPIServer) InstallLegacyAPIGroup(apiPrefix string, apiGroupInfo *APIGroupInfo) error {
|
||||
if !s.legacyAPIGroupPrefixes.Has(apiPrefix) {
|
||||
return fmt.Errorf("%q is not in the allowed legacy API prefixes: %v", apiPrefix, s.legacyAPIGroupPrefixes.List())
|
||||
@@ -481,7 +720,9 @@ func (s *GenericAPIServer) InstallLegacyAPIGroup(apiPrefix string, apiGroupInfo
|
||||
return nil
|
||||
}
|
||||
|
||||
// Exposes given api groups in the API.
|
||||
// InstallAPIGroups exposes given api groups in the API.
|
||||
// The <apiGroupInfos> passed into this function shouldn't be used elsewhere as the
|
||||
// underlying storage will be destroyed on this servers shutdown.
|
||||
func (s *GenericAPIServer) InstallAPIGroups(apiGroupInfos ...*APIGroupInfo) error {
|
||||
for _, apiGroupInfo := range apiGroupInfos {
|
||||
// Do not register empty group or empty version. Doing so claims /apis/ for the wrong entity to be returned.
|
||||
@@ -534,20 +775,25 @@ func (s *GenericAPIServer) InstallAPIGroups(apiGroupInfos ...*APIGroupInfo) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
// Exposes the given api group in the API.
|
||||
// InstallAPIGroup exposes the given api group in the API.
|
||||
// The <apiGroupInfo> passed into this function shouldn't be used elsewhere as the
|
||||
// underlying storage will be destroyed on this servers shutdown.
|
||||
func (s *GenericAPIServer) InstallAPIGroup(apiGroupInfo *APIGroupInfo) error {
|
||||
return s.InstallAPIGroups(apiGroupInfo)
|
||||
}
|
||||
|
||||
func (s *GenericAPIServer) getAPIGroupVersion(apiGroupInfo *APIGroupInfo, groupVersion schema.GroupVersion, apiPrefix string) *genericapi.APIGroupVersion {
|
||||
func (s *GenericAPIServer) getAPIGroupVersion(apiGroupInfo *APIGroupInfo, groupVersion schema.GroupVersion, apiPrefix string) (*genericapi.APIGroupVersion, error) {
|
||||
storage := make(map[string]rest.Storage)
|
||||
for k, v := range apiGroupInfo.VersionedResourcesStorageMap[groupVersion.Version] {
|
||||
storage[strings.ToLower(k)] = v
|
||||
if strings.ToLower(k) != k {
|
||||
return nil, fmt.Errorf("resource names must be lowercase only, not %q", k)
|
||||
}
|
||||
storage[k] = v
|
||||
}
|
||||
version := s.newAPIGroupVersion(apiGroupInfo, groupVersion)
|
||||
version.Root = apiPrefix
|
||||
version.Storage = storage
|
||||
return version
|
||||
return version, nil
|
||||
}
|
||||
|
||||
func (s *GenericAPIServer) newAPIGroupVersion(apiGroupInfo *APIGroupInfo, groupVersion schema.GroupVersion) *genericapi.APIGroupVersion {
|
||||
@@ -563,7 +809,7 @@ func (s *GenericAPIServer) newAPIGroupVersion(apiGroupInfo *APIGroupInfo, groupV
|
||||
UnsafeConvertor: runtime.UnsafeObjectConvertor(apiGroupInfo.Scheme),
|
||||
Defaulter: apiGroupInfo.Scheme,
|
||||
Typer: apiGroupInfo.Scheme,
|
||||
Linker: runtime.SelfLinker(meta.NewAccessor()),
|
||||
Namer: runtime.Namer(meta.NewAccessor()),
|
||||
|
||||
EquivalentResourceRegistry: s.EquivalentResourceRegistry,
|
||||
|
||||
@@ -603,7 +849,7 @@ func (s *GenericAPIServer) getOpenAPIModels(apiPrefix string, apiGroupInfos ...*
|
||||
}
|
||||
|
||||
// Build the openapi definitions for those resources and convert it to proto models
|
||||
openAPISpec, err := openapibuilder.BuildOpenAPIDefinitionsForResources(s.openAPIConfig, resourceNames...)
|
||||
openAPISpec, err := openapibuilder2.BuildOpenAPIDefinitionsForResources(s.openAPIConfig, resourceNames...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user