Update go dependencies

This commit is contained in:
Manuel Alejandro de Brito Fontes 2019-03-28 20:43:46 -03:00
parent 14a9e9f3fa
commit 14f4a7b8e8
No known key found for this signature in database
GPG key ID: 786136016A8BA02A
1349 changed files with 128369 additions and 32627 deletions

View file

@ -26,9 +26,10 @@ import (
"sort"
"strconv"
"strings"
"sync/atomic"
"time"
"github.com/emicklei/go-restful-swagger12"
jsonpatch "github.com/evanphx/json-patch"
"github.com/go-openapi/spec"
"github.com/pborman/uuid"
"k8s.io/klog"
@ -59,10 +60,10 @@ import (
"k8s.io/apiserver/pkg/server/routes"
serverstore "k8s.io/apiserver/pkg/server/storage"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/apiserver/pkg/util/logs"
"k8s.io/client-go/informers"
restclient "k8s.io/client-go/rest"
certutil "k8s.io/client-go/util/cert"
"k8s.io/component-base/logs"
openapicommon "k8s.io/kube-openapi/pkg/common"
// install apis
@ -101,7 +102,6 @@ type Config struct {
AdmissionControl admission.Interface
CorsAllowedOriginList []string
EnableSwaggerUI bool
EnableIndex bool
EnableProfiling bool
EnableDiscovery bool
@ -145,8 +145,6 @@ type Config struct {
Serializer runtime.NegotiatedSerializer
// OpenAPIConfig will be used in generating OpenAPI spec. This is nil by default. Use DefaultOpenAPIConfig for "working" defaults.
OpenAPIConfig *openapicommon.Config
// SwaggerConfig will be used in generating Swagger spec. This is nil by default. Use DefaultSwaggerConfig for "working" defaults.
SwaggerConfig *swagger.Config
// RESTOptionsGetter is used to construct RESTStorage types via the generic registry.
RESTOptionsGetter genericregistry.RESTOptionsGetter
@ -157,6 +155,13 @@ type Config struct {
// If specified, long running requests such as watch will be allocated a random timeout between this value, and
// twice this value. Note that it is up to the request handlers to ignore or honor this timeout. In seconds.
MinRequestTimeout int
// The limit on the total size increase all "copy" operations in a json
// patch may cause.
// This affects all places that applies json patch in the binary.
JSONPatchMaxCopyBytes int64
// The limit on the request body size that would be accepted and decoded in a write request.
// 0 means no limit.
MaxRequestBodyBytes int64
// MaxRequestsInFlight is the maximum number of parallel non-long-running requests. Every further
// request has to wait. Applies only to non-mutating requests.
MaxRequestsInFlight int
@ -247,20 +252,36 @@ type AuthorizationInfo struct {
// NewConfig returns a Config struct with the default values
func NewConfig(codecs serializer.CodecFactory) *Config {
return &Config{
Serializer: codecs,
BuildHandlerChainFunc: DefaultBuildHandlerChain,
HandlerChainWaitGroup: new(utilwaitgroup.SafeWaitGroup),
LegacyAPIGroupPrefixes: sets.NewString(DefaultLegacyAPIPrefix),
DisabledPostStartHooks: sets.NewString(),
HealthzChecks: []healthz.HealthzChecker{healthz.PingHealthz, healthz.LogHealthz},
EnableIndex: true,
EnableDiscovery: true,
EnableProfiling: true,
EnableMetrics: true,
MaxRequestsInFlight: 400,
MaxMutatingRequestsInFlight: 200,
RequestTimeout: time.Duration(60) * time.Second,
MinRequestTimeout: 1800,
Serializer: codecs,
BuildHandlerChainFunc: DefaultBuildHandlerChain,
HandlerChainWaitGroup: new(utilwaitgroup.SafeWaitGroup),
LegacyAPIGroupPrefixes: sets.NewString(DefaultLegacyAPIPrefix),
DisabledPostStartHooks: sets.NewString(),
HealthzChecks: []healthz.HealthzChecker{healthz.PingHealthz, healthz.LogHealthz},
EnableIndex: true,
EnableDiscovery: true,
EnableProfiling: true,
EnableMetrics: true,
MaxRequestsInFlight: 400,
MaxMutatingRequestsInFlight: 200,
RequestTimeout: time.Duration(60) * time.Second,
MinRequestTimeout: 1800,
// 10MB is the recommended maximum client request size in bytes
// the etcd server should accept. See
// https://github.com/etcd-io/etcd/blob/release-3.3/etcdserver/server.go#L90.
// A request body might be encoded in json, and is converted to
// proto when persisted in etcd. Assuming the upper bound of
// the size ratio is 10:1, we set 100MB as the largest size
// increase the "copy" operations in a json patch may cause.
JSONPatchMaxCopyBytes: int64(100 * 1024 * 1024),
// 10MB is the recommended maximum client request size in bytes
// the etcd server should accept. See
// https://github.com/etcd-io/etcd/blob/release-3.3/etcdserver/server.go#L90.
// A request body might be encoded in json, and is converted to
// proto when persisted in etcd. Assuming the upper bound of
// the size ratio is 10:1, we set 100MB as the largest request
// body size to be accepted and decoded in a write request.
MaxRequestBodyBytes: int64(100 * 1024 * 1024),
EnableAPIResponseCompression: utilfeature.DefaultFeatureGate.Enabled(features.APIResponseCompression),
// Default to treating watch as a long-running operation
@ -279,7 +300,7 @@ func NewRecommendedConfig(codecs serializer.CodecFactory) *RecommendedConfig {
func DefaultOpenAPIConfig(getDefinitions openapicommon.GetOpenAPIDefinitions, defNamer *apiopenapi.DefinitionNamer) *openapicommon.Config {
return &openapicommon.Config{
ProtocolList: []string{"https"},
IgnorePrefixes: []string{"/swaggerapi"},
IgnorePrefixes: []string{},
Info: &spec.Info{
InfoProps: spec.InfoProps{
Title: "Generic API Server",
@ -296,23 +317,6 @@ func DefaultOpenAPIConfig(getDefinitions openapicommon.GetOpenAPIDefinitions, de
}
}
// DefaultSwaggerConfig returns a default configuration without WebServiceURL and
// WebServices set.
func DefaultSwaggerConfig() *swagger.Config {
return &swagger.Config{
ApiPath: "/swaggerapi",
SwaggerPath: "/swaggerui/",
SwaggerFilePath: "/swagger-ui/",
SchemaFormatHandler: func(typeName string) string {
switch typeName {
case "metav1.Time", "*metav1.Time":
return "date-time"
}
return ""
},
}
}
func (c *AuthenticationInfo) ApplyClientCert(clientCAFile string, servingInfo *SecureServingInfo) error {
if servingInfo != nil {
if len(clientCAFile) > 0 {
@ -403,13 +407,6 @@ func (c *Config) Complete(informers informers.SharedInformerFactory) CompletedCo
}
}
}
if c.SwaggerConfig != nil && len(c.SwaggerConfig.WebServicesUrl) == 0 {
if c.SecureServing != nil {
c.SwaggerConfig.WebServicesUrl = "https://" + c.ExternalAddress
} else {
c.SwaggerConfig.WebServicesUrl = "http://" + c.ExternalAddress
}
}
if c.DiscoveryAddresses == nil {
c.DiscoveryAddresses = discovery.DefaultAddresses{DefaultAddress: c.ExternalAddress}
}
@ -466,7 +463,6 @@ func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*G
listedPathProvider: apiServerHandler,
swaggerConfig: c.SwaggerConfig,
openAPIConfig: c.OpenAPIConfig,
postStartHooks: map[string]postStartHookEntry{},
@ -478,6 +474,20 @@ func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*G
DiscoveryGroupManager: discovery.NewRootAPIsHandler(c.DiscoveryAddresses, c.Serializer),
enableAPIResponseCompression: c.EnableAPIResponseCompression,
maxRequestBodyBytes: c.MaxRequestBodyBytes,
}
for {
if c.JSONPatchMaxCopyBytes <= 0 {
break
}
existing := atomic.LoadInt64(&jsonpatch.AccumulatedCopySizeLimit)
if existing > 0 && existing < c.JSONPatchMaxCopyBytes {
break
}
if atomic.CompareAndSwapInt64(&jsonpatch.AccumulatedCopySizeLimit, existing, c.JSONPatchMaxCopyBytes) {
break
}
}
for k, v := range delegationTarget.PostStartHooks() {
@ -550,9 +560,6 @@ func installAPI(s *GenericAPIServer, c *Config) {
if c.EnableIndex {
routes.Index{}.Install(s.listedPathProvider, s.Handler.NonGoRestfulMux)
}
if c.SwaggerConfig != nil && c.EnableSwaggerUI {
routes.SwaggerUI{}.Install(s.Handler.NonGoRestfulMux)
}
if c.EnableProfiling {
routes.Profiling{}.Install(s.Handler.NonGoRestfulMux)
if c.EnableContentionProfiling {

View file

@ -50,7 +50,9 @@ func (s *DeprecatedInsecureServingInfo) Serve(handler http.Handler, shutdownTime
} else {
klog.Infof("Serving insecurely on %s", s.Listener.Addr())
}
return RunServer(insecureServer, s.Listener, shutdownTimeout, stopCh)
_, err := RunServer(insecureServer, s.Listener, shutdownTimeout, stopCh)
// NOTE: we do not handle stoppedCh returned by RunServer for graceful termination here
return err
}
func (s *DeprecatedInsecureServingInfo) NewLoopbackClientConfig() (*rest.Config, error) {

View file

@ -15,4 +15,4 @@ limitations under the License.
*/
// Package server contains the plumbing to create kubernetes-like API server command.
package server
package server // import "k8s.io/apiserver/pkg/server"

View file

@ -25,7 +25,7 @@ import (
"time"
systemd "github.com/coreos/go-systemd/daemon"
"github.com/emicklei/go-restful-swagger12"
"github.com/go-openapi/spec"
"k8s.io/klog"
"k8s.io/apimachinery/pkg/api/meta"
@ -47,6 +47,7 @@ import (
restclient "k8s.io/client-go/rest"
openapibuilder "k8s.io/kube-openapi/pkg/builder"
openapicommon "k8s.io/kube-openapi/pkg/common"
"k8s.io/kube-openapi/pkg/handler"
openapiutil "k8s.io/kube-openapi/pkg/util"
openapiproto "k8s.io/kube-openapi/pkg/util/proto"
)
@ -121,9 +122,16 @@ type GenericAPIServer struct {
DiscoveryGroupManager discovery.GroupManager
// Enable swagger and/or OpenAPI if these configs are non-nil.
swaggerConfig *swagger.Config
openAPIConfig *openapicommon.Config
// OpenAPIVersionedService controls the /openapi/v2 endpoint, and can be used to update the served spec.
// It is set during PrepareRun.
OpenAPIVersionedService *handler.OpenAPIService
// StaticOpenAPISpec is the spec derived from the restful container endpoints.
// It is set during PrepareRun.
StaticOpenAPISpec *spec.Swagger
// PostStartHooks are each called after the server has started listening, in a separate go func for each
// with no guarantee of ordering between them. The map key is a name used for error reporting.
// It may kill the process with a panic if it wishes to by returning an error.
@ -158,6 +166,10 @@ type GenericAPIServer struct {
// HandlerChainWaitGroup allows you to wait for all chain handlers finish after the server shutdown.
HandlerChainWaitGroup *utilwaitgroup.SafeWaitGroup
// The limit on the request body size that would be accepted and decoded in a write request.
// 0 means no limit.
maxRequestBodyBytes int64
}
// DelegationTarget is an interface which allows for composition of API servers with top level handling that works
@ -236,11 +248,8 @@ type preparedGenericAPIServer struct {
// PrepareRun does post API installation setup steps.
func (s *GenericAPIServer) PrepareRun() preparedGenericAPIServer {
if s.swaggerConfig != nil {
routes.Swagger{Config: s.swaggerConfig}.Install(s.Handler.GoRestfulContainer)
}
if s.openAPIConfig != nil {
routes.OpenAPI{
s.OpenAPIVersionedService, s.StaticOpenAPISpec = routes.OpenAPI{
Config: s.openAPIConfig,
}.Install(s.Handler.GoRestfulContainer, s.Handler.NonGoRestfulMux)
}
@ -296,9 +305,11 @@ func (s preparedGenericAPIServer) NonBlockingRun(stopCh <-chan struct{}) error {
// Use an internal stop channel to allow cleanup of the listeners on error.
internalStopCh := make(chan struct{})
var stoppedCh <-chan struct{}
if s.SecureServingInfo != nil && s.Handler != nil {
if err := s.SecureServingInfo.Serve(s.Handler, s.ShutdownTimeout, internalStopCh); err != nil {
var err error
stoppedCh, err = s.SecureServingInfo.Serve(s.Handler, s.ShutdownTimeout, internalStopCh)
if err != nil {
close(internalStopCh)
return err
}
@ -310,6 +321,9 @@ func (s preparedGenericAPIServer) NonBlockingRun(stopCh <-chan struct{}) error {
go func() {
<-stopCh
close(internalStopCh)
if stoppedCh != nil {
<-stoppedCh
}
s.HandlerChainWaitGroup.Wait()
close(auditStopCh)
}()
@ -324,11 +338,7 @@ func (s preparedGenericAPIServer) NonBlockingRun(stopCh <-chan struct{}) error {
}
// installAPIResources is a private method for installing the REST storage backing each api groupversionresource
func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *APIGroupInfo) error {
openAPIGroupModels, err := s.getOpenAPIModelsForGroup(apiPrefix, apiGroupInfo)
if err != nil {
return fmt.Errorf("unable to get openapi models for group %v: %v", apiPrefix, err)
}
func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *APIGroupInfo, openAPIModels openapiproto.Models) error {
for _, groupVersion := range apiGroupInfo.PrioritizedVersions {
if len(apiGroupInfo.VersionedResourcesStorageMap[groupVersion.Version]) == 0 {
klog.Warningf("Skipping API %v because it has no resources.", groupVersion)
@ -339,7 +349,8 @@ func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *A
if apiGroupInfo.OptionsExternalVersion != nil {
apiGroupVersion.OptionsExternalVersion = apiGroupInfo.OptionsExternalVersion
}
apiGroupVersion.OpenAPIModels = openAPIGroupModels
apiGroupVersion.OpenAPIModels = openAPIModels
apiGroupVersion.MaxRequestBodyBytes = s.maxRequestBodyBytes
if err := apiGroupVersion.InstallREST(s.Handler.GoRestfulContainer); err != nil {
return fmt.Errorf("unable to setup API %v: %v", apiGroupInfo, err)
@ -353,7 +364,13 @@ func (s *GenericAPIServer) InstallLegacyAPIGroup(apiPrefix string, apiGroupInfo
if !s.legacyAPIGroupPrefixes.Has(apiPrefix) {
return fmt.Errorf("%q is not in the allowed legacy API prefixes: %v", apiPrefix, s.legacyAPIGroupPrefixes.List())
}
if err := s.installAPIResources(apiPrefix, apiGroupInfo); err != nil {
openAPIModels, err := s.getOpenAPIModels(apiPrefix, apiGroupInfo)
if err != nil {
return fmt.Errorf("unable to get openapi models: %v", err)
}
if err := s.installAPIResources(apiPrefix, apiGroupInfo, openAPIModels); err != nil {
return err
}
@ -364,49 +381,62 @@ func (s *GenericAPIServer) InstallLegacyAPIGroup(apiPrefix string, apiGroupInfo
return nil
}
// Exposes given api groups in the API.
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.
// Catching these here places the error much closer to its origin
if len(apiGroupInfo.PrioritizedVersions[0].Group) == 0 {
return fmt.Errorf("cannot register handler with an empty group for %#v", *apiGroupInfo)
}
if len(apiGroupInfo.PrioritizedVersions[0].Version) == 0 {
return fmt.Errorf("cannot register handler with an empty version for %#v", *apiGroupInfo)
}
}
openAPIModels, err := s.getOpenAPIModels(APIGroupPrefix, apiGroupInfos...)
if err != nil {
return fmt.Errorf("unable to get openapi models: %v", err)
}
for _, apiGroupInfo := range apiGroupInfos {
if err := s.installAPIResources(APIGroupPrefix, apiGroupInfo, openAPIModels); err != nil {
return fmt.Errorf("unable to install api resources: %v", err)
}
// setup discovery
// Install the version handler.
// Add a handler at /apis/<groupName> to enumerate all versions supported by this group.
apiVersionsForDiscovery := []metav1.GroupVersionForDiscovery{}
for _, groupVersion := range apiGroupInfo.PrioritizedVersions {
// Check the config to make sure that we elide versions that don't have any resources
if len(apiGroupInfo.VersionedResourcesStorageMap[groupVersion.Version]) == 0 {
continue
}
apiVersionsForDiscovery = append(apiVersionsForDiscovery, metav1.GroupVersionForDiscovery{
GroupVersion: groupVersion.String(),
Version: groupVersion.Version,
})
}
preferredVersionForDiscovery := metav1.GroupVersionForDiscovery{
GroupVersion: apiGroupInfo.PrioritizedVersions[0].String(),
Version: apiGroupInfo.PrioritizedVersions[0].Version,
}
apiGroup := metav1.APIGroup{
Name: apiGroupInfo.PrioritizedVersions[0].Group,
Versions: apiVersionsForDiscovery,
PreferredVersion: preferredVersionForDiscovery,
}
s.DiscoveryGroupManager.AddGroup(apiGroup)
s.Handler.GoRestfulContainer.Add(discovery.NewAPIGroupHandler(s.Serializer, apiGroup).WebService())
}
return nil
}
// Exposes the given api group in the API.
func (s *GenericAPIServer) InstallAPIGroup(apiGroupInfo *APIGroupInfo) error {
// Do not register empty group or empty version. Doing so claims /apis/ for the wrong entity to be returned.
// Catching these here places the error much closer to its origin
if len(apiGroupInfo.PrioritizedVersions[0].Group) == 0 {
return fmt.Errorf("cannot register handler with an empty group for %#v", *apiGroupInfo)
}
if len(apiGroupInfo.PrioritizedVersions[0].Version) == 0 {
return fmt.Errorf("cannot register handler with an empty version for %#v", *apiGroupInfo)
}
if err := s.installAPIResources(APIGroupPrefix, apiGroupInfo); err != nil {
return err
}
// setup discovery
// Install the version handler.
// Add a handler at /apis/<groupName> to enumerate all versions supported by this group.
apiVersionsForDiscovery := []metav1.GroupVersionForDiscovery{}
for _, groupVersion := range apiGroupInfo.PrioritizedVersions {
// Check the config to make sure that we elide versions that don't have any resources
if len(apiGroupInfo.VersionedResourcesStorageMap[groupVersion.Version]) == 0 {
continue
}
apiVersionsForDiscovery = append(apiVersionsForDiscovery, metav1.GroupVersionForDiscovery{
GroupVersion: groupVersion.String(),
Version: groupVersion.Version,
})
}
preferredVersionForDiscovery := metav1.GroupVersionForDiscovery{
GroupVersion: apiGroupInfo.PrioritizedVersions[0].String(),
Version: apiGroupInfo.PrioritizedVersions[0].Version,
}
apiGroup := metav1.APIGroup{
Name: apiGroupInfo.PrioritizedVersions[0].Group,
Versions: apiVersionsForDiscovery,
PreferredVersion: preferredVersionForDiscovery,
}
s.DiscoveryGroupManager.AddGroup(apiGroup)
s.Handler.GoRestfulContainer.Add(discovery.NewAPIGroupHandler(s.Serializer, apiGroup).WebService())
return nil
return s.InstallAPIGroups(apiGroupInfo)
}
func (s *GenericAPIServer) getAPIGroupVersion(apiGroupInfo *APIGroupInfo, groupVersion schema.GroupVersion, apiPrefix string) *genericapi.APIGroupVersion {
@ -455,12 +485,31 @@ func NewDefaultAPIGroupInfo(group string, scheme *runtime.Scheme, parameterCodec
}
}
// getOpenAPIModelsForGroup is a private method for getting the OpenAPI Schemas for each api group
func (s *GenericAPIServer) getOpenAPIModelsForGroup(apiPrefix string, apiGroupInfo *APIGroupInfo) (openapiproto.Models, error) {
// getOpenAPIModels is a private method for getting the OpenAPI models
func (s *GenericAPIServer) getOpenAPIModels(apiPrefix string, apiGroupInfos ...*APIGroupInfo) (openapiproto.Models, error) {
if s.openAPIConfig == nil {
return nil, nil
}
pathsToIgnore := openapiutil.NewTrie(s.openAPIConfig.IgnorePrefixes)
resourceNames := make([]string, 0)
for _, apiGroupInfo := range apiGroupInfos {
groupResources, err := getResourceNamesForGroup(apiPrefix, apiGroupInfo, pathsToIgnore)
if err != nil {
return nil, err
}
resourceNames = append(resourceNames, groupResources...)
}
// Build the openapi definitions for those resources and convert it to proto models
openAPISpec, err := openapibuilder.BuildOpenAPIDefinitionsForResources(s.openAPIConfig, resourceNames...)
if err != nil {
return nil, err
}
return utilopenapi.ToProtoModels(openAPISpec)
}
// getResourceNamesForGroup is a private method for getting the canonical names for each resource to build in an api group
func getResourceNamesForGroup(apiPrefix string, apiGroupInfo *APIGroupInfo, pathsToIgnore openapiutil.Trie) ([]string, error) {
// Get the canonical names of every resource we need to build in this api group
resourceNames := make([]string, 0)
for _, groupVersion := range apiGroupInfo.PrioritizedVersions {
@ -481,10 +530,5 @@ func (s *GenericAPIServer) getOpenAPIModelsForGroup(apiPrefix string, apiGroupIn
}
}
// Build the openapi definitions for those resources and convert it to proto models
openAPISpec, err := openapibuilder.BuildOpenAPIDefinitionsForResources(s.openAPIConfig, resourceNames...)
if err != nil {
return nil, err
}
return utilopenapi.ToProtoModels(openAPISpec)
return resourceNames, nil
}

View file

@ -167,7 +167,7 @@ func handleRootHealthz(checks ...HealthzChecker) http.HandlerFunc {
if err := check.Check(r); err != nil {
// don't include the error since this endpoint is public. If someone wants more detail
// they should have explicit permission to the detailed checks.
klog.V(6).Infof("healthz check %v failed: %v", check.Name(), err)
klog.V(4).Infof("healthz check %v failed: %v", check.Name(), err)
fmt.Fprintf(&verboseOut, "[-]%v failed: reason withheld\n", check.Name())
failed = true
} else {
@ -185,6 +185,8 @@ func handleRootHealthz(checks ...HealthzChecker) http.HandlerFunc {
return
}
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.Header().Set("X-Content-Type-Options", "nosniff")
if _, found := r.URL.Query()["verbose"]; !found {
fmt.Fprint(w, "ok")
return

View file

@ -20,6 +20,7 @@ import (
"errors"
"fmt"
"net/http"
"runtime/debug"
"k8s.io/klog"
@ -58,6 +59,9 @@ type PostStartHookProvider interface {
type postStartHookEntry struct {
hook PostStartHookFunc
// originatingStack holds the stack that registered postStartHooks. This allows us to show a more helpful message
// for duplicate registration.
originatingStack string
// done will be closed when the postHook is finished
done chan struct{}
@ -85,15 +89,18 @@ func (s *GenericAPIServer) AddPostStartHook(name string, hook PostStartHookFunc)
if s.postStartHooksCalled {
return fmt.Errorf("unable to add %q because PostStartHooks have already been called", name)
}
if _, exists := s.postStartHooks[name]; exists {
return fmt.Errorf("unable to add %q because it is already registered", name)
if postStartHook, exists := s.postStartHooks[name]; exists {
// this is programmer error, but it can be hard to debug
return fmt.Errorf("unable to add %q because it was already registered by: %s", name, postStartHook.originatingStack)
}
// done is closed when the poststarthook is finished. This is used by the health check to be able to indicate
// that the poststarthook is finished
done := make(chan struct{})
s.AddHealthzChecks(postStartHookHealthz{name: "poststarthook/" + name, done: done})
s.postStartHooks[name] = postStartHookEntry{hook: hook, done: done}
if err := s.AddHealthzChecks(postStartHookHealthz{name: "poststarthook/" + name, done: done}); err != nil {
return err
}
s.postStartHooks[name] = postStartHookEntry{hook: hook, originatingStack: string(debug.Stack()), done: done}
return nil
}

View file

@ -19,7 +19,6 @@ package server
// This file exists to force the desired plugin implementations to be linked into genericapi pkg.
import (
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/plugin/initialization"
"k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle"
mutatingwebhook "k8s.io/apiserver/pkg/admission/plugin/webhook/mutating"
validatingwebhook "k8s.io/apiserver/pkg/admission/plugin/webhook/validating"
@ -28,7 +27,6 @@ import (
// RegisterAllAdmissionPlugins registers all admission plugins
func RegisterAllAdmissionPlugins(plugins *admission.Plugins) {
lifecycle.Register(plugins)
initialization.Register(plugins)
validatingwebhook.Register(plugins)
mutatingwebhook.Register(plugins)
}

View file

@ -37,12 +37,12 @@ const (
defaultKeepAlivePeriod = 3 * time.Minute
)
// serveSecurely runs the secure http server. It fails only if certificates cannot
// be loaded or the initial listen call fails. The actual server loop (stoppable by closing
// stopCh) runs in a go routine, i.e. serveSecurely does not block.
func (s *SecureServingInfo) Serve(handler http.Handler, shutdownTimeout time.Duration, stopCh <-chan struct{}) error {
// Serve runs the secure http server. It fails only if certificates cannot be loaded or the initial listen call fails.
// The actual server loop (stoppable by closing stopCh) runs in a go routine, i.e. Serve does not block.
// It returns a stoppedCh that is closed when all non-hijacked active requests have been processed.
func (s *SecureServingInfo) Serve(handler http.Handler, shutdownTimeout time.Duration, stopCh <-chan struct{}) (<-chan struct{}, error) {
if s.Listener == nil {
return fmt.Errorf("listener must not be nil")
return nil, fmt.Errorf("listener must not be nil")
}
secureServer := &http.Server{
@ -110,7 +110,7 @@ func (s *SecureServingInfo) Serve(handler http.Handler, shutdownTimeout time.Dur
// apply settings to the server
if err := http2.ConfigureServer(secureServer, http2Options); err != nil {
return fmt.Errorf("error configuring http2: %v", err)
return nil, fmt.Errorf("error configuring http2: %v", err)
}
klog.Infof("Serving securely on %s", secureServer.Addr)
@ -118,21 +118,25 @@ func (s *SecureServingInfo) Serve(handler http.Handler, shutdownTimeout time.Dur
}
// RunServer listens on the given port if listener is not given,
// then spawns a go-routine continuously serving
// until the stopCh is closed. This function does not block.
// then spawns a go-routine continuously serving until the stopCh is closed.
// It returns a stoppedCh that is closed when all non-hijacked active requests
// have been processed.
// This function does not block
// TODO: make private when insecure serving is gone from the kube-apiserver
func RunServer(
server *http.Server,
ln net.Listener,
shutDownTimeout time.Duration,
stopCh <-chan struct{},
) error {
) (<-chan struct{}, error) {
if ln == nil {
return fmt.Errorf("listener must not be nil")
return nil, fmt.Errorf("listener must not be nil")
}
// Shutdown server gracefully.
stoppedCh := make(chan struct{})
go func() {
defer close(stoppedCh)
<-stopCh
ctx, cancel := context.WithTimeout(context.Background(), shutDownTimeout)
server.Shutdown(ctx)
@ -159,18 +163,18 @@ func RunServer(
}
}()
return nil
return stoppedCh, nil
}
type NamedTLSCert struct {
TLSCert tls.Certificate
// names is a list of domain patterns: fully qualified domain names, possibly prefixed with
// Names is a list of domain patterns: fully qualified domain names, possibly prefixed with
// wildcard segments.
Names []string
}
// getNamedCertificateMap returns a map of *tls.Certificate by name. It's is
// GetNamedCertificateMap returns a map of *tls.Certificate by name. It's
// suitable for use in tls.Config#NamedCertificates. Returns an error if any of the certs
// cannot be loaded. Returns nil if len(certs) == 0
func GetNamedCertificateMap(certs []NamedTLSCert) (map[string]*tls.Certificate, error) {

View file

@ -22,6 +22,7 @@ import (
)
var onlyOneSignalHandler = make(chan struct{})
var shutdownHandler chan os.Signal
// SetupSignalHandler registered for SIGTERM and SIGINT. A stop channel is returned
// which is closed on one of these signals. If a second signal is caught, the program
@ -29,15 +30,30 @@ var onlyOneSignalHandler = make(chan struct{})
func SetupSignalHandler() <-chan struct{} {
close(onlyOneSignalHandler) // panics when called twice
shutdownHandler = make(chan os.Signal, 2)
stop := make(chan struct{})
c := make(chan os.Signal, 2)
signal.Notify(c, shutdownSignals...)
signal.Notify(shutdownHandler, shutdownSignals...)
go func() {
<-c
<-shutdownHandler
close(stop)
<-c
<-shutdownHandler
os.Exit(1) // second signal. Exit directly.
}()
return stop
}
// RequestShutdown emulates a received event that is considered as shutdown signal (SIGTERM/SIGINT)
// This returns whether a handler was notified
func RequestShutdown() bool {
if shutdownHandler != nil {
select {
case shutdownHandler <- shutdownSignals[0]:
return true
default:
}
}
return false
}