Commit 4389f715 authored by deads2k's avatar deads2k

refactor names for the apiserver handling chain

parent 3a81a860
...@@ -82,7 +82,6 @@ go_library( ...@@ -82,7 +82,6 @@ go_library(
"//vendor/k8s.io/apiserver/pkg/server:go_default_library", "//vendor/k8s.io/apiserver/pkg/server:go_default_library",
"//vendor/k8s.io/apiserver/pkg/server/filters:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/filters:go_default_library",
"//vendor/k8s.io/apiserver/pkg/server/healthz:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/healthz:go_default_library",
"//vendor/k8s.io/apiserver/pkg/server/mux:go_default_library",
"//vendor/k8s.io/apiserver/pkg/server/options:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/options:go_default_library",
"//vendor/k8s.io/apiserver/pkg/server/storage:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/storage:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library",
......
...@@ -30,7 +30,6 @@ import ( ...@@ -30,7 +30,6 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
genericapiserver "k8s.io/apiserver/pkg/server" genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/apiserver/pkg/server/healthz" "k8s.io/apiserver/pkg/server/healthz"
"k8s.io/apiserver/pkg/server/mux"
genericoptions "k8s.io/apiserver/pkg/server/options" genericoptions "k8s.io/apiserver/pkg/server/options"
kubeclientset "k8s.io/client-go/kubernetes" kubeclientset "k8s.io/client-go/kubernetes"
"k8s.io/kube-aggregator/pkg/apis/apiregistration" "k8s.io/kube-aggregator/pkg/apis/apiregistration"
...@@ -46,7 +45,6 @@ func createAggregatorConfig(kubeAPIServerConfig genericapiserver.Config, command ...@@ -46,7 +45,6 @@ func createAggregatorConfig(kubeAPIServerConfig genericapiserver.Config, command
// make a shallow copy to let us twiddle a few things // make a shallow copy to let us twiddle a few things
// most of the config actually remains the same. We only need to mess with a couple items related to the particulars of the aggregator // most of the config actually remains the same. We only need to mess with a couple items related to the particulars of the aggregator
genericConfig := kubeAPIServerConfig genericConfig := kubeAPIServerConfig
genericConfig.FallThroughHandler = mux.NewPathRecorderMux()
// the aggregator doesn't wire these up. It just delegates them to the kubeapiserver // the aggregator doesn't wire these up. It just delegates them to the kubeapiserver
genericConfig.EnableSwaggerUI = false genericConfig.EnableSwaggerUI = false
......
...@@ -110,7 +110,7 @@ func Run(runOptions *options.ServerRunOptions, stopCh <-chan struct{}) error { ...@@ -110,7 +110,7 @@ func Run(runOptions *options.ServerRunOptions, stopCh <-chan struct{}) error {
// run the insecure server now, don't block. It doesn't have any aggregator goodies since authentication wouldn't work // run the insecure server now, don't block. It doesn't have any aggregator goodies since authentication wouldn't work
if insecureServingOptions != nil { if insecureServingOptions != nil {
insecureHandlerChain := kubeserver.BuildInsecureHandlerChain(kubeAPIServer.GenericAPIServer.HandlerContainer.ServeMux, kubeAPIServerConfig.GenericConfig) insecureHandlerChain := kubeserver.BuildInsecureHandlerChain(kubeAPIServer.GenericAPIServer.UnprotectedHandler(), kubeAPIServerConfig.GenericConfig)
if err := kubeserver.NonBlockingRun(insecureServingOptions, insecureHandlerChain, stopCh); err != nil { if err := kubeserver.NonBlockingRun(insecureServingOptions, insecureHandlerChain, stopCh); err != nil {
return err return err
} }
...@@ -139,7 +139,7 @@ func Run(runOptions *options.ServerRunOptions, stopCh <-chan struct{}) error { ...@@ -139,7 +139,7 @@ func Run(runOptions *options.ServerRunOptions, stopCh <-chan struct{}) error {
// CreateKubeAPIServer creates and wires a workable kube-apiserver // CreateKubeAPIServer creates and wires a workable kube-apiserver
func CreateKubeAPIServer(kubeAPIServerConfig *master.Config, sharedInformers informers.SharedInformerFactory, stopCh <-chan struct{}) (*master.Master, error) { func CreateKubeAPIServer(kubeAPIServerConfig *master.Config, sharedInformers informers.SharedInformerFactory, stopCh <-chan struct{}) (*master.Master, error) {
kubeAPIServer, err := kubeAPIServerConfig.Complete().New() kubeAPIServer, err := kubeAPIServerConfig.Complete().New(genericapiserver.EmptyDelegate)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -224,13 +224,13 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error { ...@@ -224,13 +224,13 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error {
cachesize.SetWatchCacheSizes(s.GenericServerRunOptions.WatchCacheSizes) cachesize.SetWatchCacheSizes(s.GenericServerRunOptions.WatchCacheSizes)
} }
m, err := genericConfig.Complete().New() m, err := genericConfig.Complete().New(genericapiserver.EmptyDelegate)
if err != nil { if err != nil {
return err return err
} }
routes.UIRedirect{}.Install(m.FallThroughHandler) routes.UIRedirect{}.Install(m.Handler.PostGoRestfulMux)
routes.Logs{}.Install(m.HandlerContainer) routes.Logs{}.Install(m.Handler.GoRestfulContainer)
apiResourceConfigSource := storageFactory.APIResourceConfigSource apiResourceConfigSource := storageFactory.APIResourceConfigSource
installFederationAPIs(m, genericConfig.RESTOptionsGetter, apiResourceConfigSource) installFederationAPIs(m, genericConfig.RESTOptionsGetter, apiResourceConfigSource)
...@@ -241,7 +241,7 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error { ...@@ -241,7 +241,7 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error {
// run the insecure server now // run the insecure server now
if insecureServingOptions != nil { if insecureServingOptions != nil {
insecureHandlerChain := kubeserver.BuildInsecureHandlerChain(m.HandlerContainer.ServeMux, genericConfig) insecureHandlerChain := kubeserver.BuildInsecureHandlerChain(m.UnprotectedHandler(), genericConfig)
if err := kubeserver.NonBlockingRun(insecureServingOptions, insecureHandlerChain, stopCh); err != nil { if err := kubeserver.NonBlockingRun(insecureServingOptions, insecureHandlerChain, stopCh); err != nil {
return err return err
} }
......
...@@ -206,21 +206,21 @@ func (c *Config) SkipComplete() completedConfig { ...@@ -206,21 +206,21 @@ func (c *Config) SkipComplete() completedConfig {
// Certain config fields will be set to a default value if unset. // Certain config fields will be set to a default value if unset.
// Certain config fields must be specified, including: // Certain config fields must be specified, including:
// KubeletClientConfig // KubeletClientConfig
func (c completedConfig) New() (*Master, error) { func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) (*Master, error) {
if reflect.DeepEqual(c.KubeletClientConfig, kubeletclient.KubeletClientConfig{}) { if reflect.DeepEqual(c.KubeletClientConfig, kubeletclient.KubeletClientConfig{}) {
return nil, fmt.Errorf("Master.New() called with empty config.KubeletClientConfig") return nil, fmt.Errorf("Master.New() called with empty config.KubeletClientConfig")
} }
s, err := c.Config.GenericConfig.SkipComplete().New() // completion is done in Complete, no need for a second time s, err := c.Config.GenericConfig.SkipComplete().New(delegationTarget) // completion is done in Complete, no need for a second time
if err != nil { if err != nil {
return nil, err return nil, err
} }
if c.EnableUISupport { if c.EnableUISupport {
routes.UIRedirect{}.Install(s.FallThroughHandler) routes.UIRedirect{}.Install(s.Handler.PostGoRestfulMux)
} }
if c.EnableLogsSupport { if c.EnableLogsSupport {
routes.Logs{}.Install(s.HandlerContainer) routes.Logs{}.Install(s.Handler.GoRestfulContainer)
} }
m := &Master{ m := &Master{
......
...@@ -53,13 +53,13 @@ func TestValidOpenAPISpec(t *testing.T) { ...@@ -53,13 +53,13 @@ func TestValidOpenAPISpec(t *testing.T) {
} }
config.GenericConfig.SwaggerConfig = genericapiserver.DefaultSwaggerConfig() config.GenericConfig.SwaggerConfig = genericapiserver.DefaultSwaggerConfig()
master, err := config.Complete().New() master, err := config.Complete().New(genericapiserver.EmptyDelegate)
if err != nil { if err != nil {
t.Fatalf("Error in bringing up the master: %v", err) t.Fatalf("Error in bringing up the master: %v", err)
} }
// make sure swagger.json is not registered before calling PrepareRun. // make sure swagger.json is not registered before calling PrepareRun.
server := httptest.NewServer(master.GenericAPIServer.HandlerContainer.ServeMux) server := httptest.NewServer(master.GenericAPIServer.Handler.GoRestfulContainer.ServeMux)
defer server.Close() defer server.Close()
resp, err := http.Get(server.URL + "/swagger.json") resp, err := http.Get(server.URL + "/swagger.json")
if !assert.NoError(err) { if !assert.NoError(err) {
......
...@@ -107,7 +107,7 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertion ...@@ -107,7 +107,7 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertion
func newMaster(t *testing.T) (*Master, *etcdtesting.EtcdTestServer, Config, *assert.Assertions) { func newMaster(t *testing.T) (*Master, *etcdtesting.EtcdTestServer, Config, *assert.Assertions) {
etcdserver, config, assert := setUp(t) etcdserver, config, assert := setUp(t)
master, err := config.Complete().New() master, err := config.Complete().New(genericapiserver.EmptyDelegate)
if err != nil { if err != nil {
t.Fatalf("Error in bringing up the master: %v", err) t.Fatalf("Error in bringing up the master: %v", err)
} }
...@@ -133,7 +133,7 @@ func limitedAPIResourceConfigSource() *serverstorage.ResourceConfig { ...@@ -133,7 +133,7 @@ func limitedAPIResourceConfigSource() *serverstorage.ResourceConfig {
func newLimitedMaster(t *testing.T) (*Master, *etcdtesting.EtcdTestServer, Config, *assert.Assertions) { func newLimitedMaster(t *testing.T) (*Master, *etcdtesting.EtcdTestServer, Config, *assert.Assertions) {
etcdserver, config, assert := setUp(t) etcdserver, config, assert := setUp(t)
config.APIResourceConfigSource = limitedAPIResourceConfigSource() config.APIResourceConfigSource = limitedAPIResourceConfigSource()
master, err := config.Complete().New() master, err := config.Complete().New(genericapiserver.EmptyDelegate)
if err != nil { if err != nil {
t.Fatalf("Error in bringing up the master: %v", err) t.Fatalf("Error in bringing up the master: %v", err)
} }
...@@ -226,7 +226,7 @@ func TestAPIVersionOfDiscoveryEndpoints(t *testing.T) { ...@@ -226,7 +226,7 @@ func TestAPIVersionOfDiscoveryEndpoints(t *testing.T) {
master, etcdserver, _, assert := newMaster(t) master, etcdserver, _, assert := newMaster(t)
defer etcdserver.Terminate(t) defer etcdserver.Terminate(t)
server := httptest.NewServer(master.GenericAPIServer.HandlerContainer.ServeMux) server := httptest.NewServer(master.GenericAPIServer.Handler.GoRestfulContainer.ServeMux)
// /api exists in release-1.1 // /api exists in release-1.1
resp, err := http.Get(server.URL + "/api") resp, err := http.Get(server.URL + "/api")
......
...@@ -156,11 +156,11 @@ func (m *ThirdPartyResourceServer) RemoveThirdPartyResource(path string) error { ...@@ -156,11 +156,11 @@ func (m *ThirdPartyResourceServer) RemoveThirdPartyResource(path string) error {
return err return err
} }
services := m.genericAPIServer.HandlerContainer.RegisteredWebServices() services := m.genericAPIServer.Handler.GoRestfulContainer.RegisteredWebServices()
for ix := range services { for ix := range services {
root := services[ix].RootPath() root := services[ix].RootPath()
if root == path || strings.HasPrefix(root, path+"/") { if root == path || strings.HasPrefix(root, path+"/") {
m.genericAPIServer.HandlerContainer.Remove(services[ix]) m.genericAPIServer.Handler.GoRestfulContainer.Remove(services[ix])
} }
} }
return nil return nil
...@@ -281,13 +281,13 @@ func (m *ThirdPartyResourceServer) InstallThirdPartyResource(rsrc *extensions.Th ...@@ -281,13 +281,13 @@ func (m *ThirdPartyResourceServer) InstallThirdPartyResource(rsrc *extensions.Th
// the group with the new API // the group with the new API
if m.hasThirdPartyGroupStorage(path) { if m.hasThirdPartyGroupStorage(path) {
m.addThirdPartyResourceStorage(path, plural.Resource, thirdparty.Storage[plural.Resource].(*thirdpartyresourcedatastore.REST), apiGroup) m.addThirdPartyResourceStorage(path, plural.Resource, thirdparty.Storage[plural.Resource].(*thirdpartyresourcedatastore.REST), apiGroup)
return thirdparty.UpdateREST(m.genericAPIServer.HandlerContainer.Container) return thirdparty.UpdateREST(m.genericAPIServer.Handler.GoRestfulContainer)
} }
if err := thirdparty.InstallREST(m.genericAPIServer.HandlerContainer.Container); err != nil { if err := thirdparty.InstallREST(m.genericAPIServer.Handler.GoRestfulContainer); err != nil {
glog.Errorf("Unable to setup thirdparty api: %v", err) glog.Errorf("Unable to setup thirdparty api: %v", err)
} }
m.genericAPIServer.HandlerContainer.Add(discovery.NewAPIGroupHandler(api.Codecs, apiGroup).WebService()) m.genericAPIServer.Handler.GoRestfulContainer.Add(discovery.NewAPIGroupHandler(api.Codecs, apiGroup).WebService())
m.addThirdPartyResourceStorage(path, plural.Resource, thirdparty.Storage[plural.Resource].(*thirdpartyresourcedatastore.REST), apiGroup) m.addThirdPartyResourceStorage(path, plural.Resource, thirdparty.Storage[plural.Resource].(*thirdpartyresourcedatastore.REST), apiGroup)
api.Registry.AddThirdPartyAPIGroupVersions(schema.GroupVersion{Group: group, Version: rsrc.Versions[0].Name}) api.Registry.AddThirdPartyAPIGroupVersions(schema.GroupVersion{Group: group, Version: rsrc.Versions[0].Name})
......
...@@ -21,14 +21,12 @@ import ( ...@@ -21,14 +21,12 @@ import (
"path" "path"
"github.com/emicklei/go-restful" "github.com/emicklei/go-restful"
"k8s.io/apiserver/pkg/server/mux"
) )
// Logs adds handlers for the /logs path serving log files from /var/log. // Logs adds handlers for the /logs path serving log files from /var/log.
type Logs struct{} type Logs struct{}
func (l Logs) Install(c *mux.APIContainer) { func (l Logs) Install(c *restful.Container) {
// use restful: ws.Route(ws.GET("/logs/{logpath:*}").To(fileHandler)) // use restful: ws.Route(ws.GET("/logs/{logpath:*}").To(fileHandler))
// See github.com/emicklei/go-restful/blob/master/examples/restful-serve-static.go // See github.com/emicklei/go-restful/blob/master/examples/restful-serve-static.go
ws := new(restful.WebService) ws := new(restful.WebService)
......
...@@ -35,7 +35,6 @@ go_test( ...@@ -35,7 +35,6 @@ go_test(
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
"//vendor/k8s.io/apiserver/pkg/server/healthz:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/healthz:go_default_library",
"//vendor/k8s.io/apiserver/pkg/server/mux:go_default_library",
"//vendor/k8s.io/apiserver/pkg/storage/etcd/testing:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/etcd/testing:go_default_library",
"//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library",
], ],
...@@ -48,6 +47,7 @@ go_library( ...@@ -48,6 +47,7 @@ go_library(
"config_selfclient.go", "config_selfclient.go",
"doc.go", "doc.go",
"genericapiserver.go", "genericapiserver.go",
"handler.go",
"healthz.go", "healthz.go",
"hooks.go", "hooks.go",
"serve.go", "serve.go",
...@@ -55,11 +55,13 @@ go_library( ...@@ -55,11 +55,13 @@ go_library(
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//vendor/github.com/coreos/go-systemd/daemon:go_default_library", "//vendor/github.com/coreos/go-systemd/daemon:go_default_library",
"//vendor/github.com/emicklei/go-restful:go_default_library",
"//vendor/github.com/emicklei/go-restful-swagger12:go_default_library", "//vendor/github.com/emicklei/go-restful-swagger12:go_default_library",
"//vendor/github.com/go-openapi/spec:go_default_library", "//vendor/github.com/go-openapi/spec:go_default_library",
"//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/pborman/uuid:go_default_library", "//vendor/github.com/pborman/uuid:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library", "//vendor/github.com/pkg/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apimachinery:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
...@@ -83,6 +85,7 @@ go_library( ...@@ -83,6 +85,7 @@ go_library(
"//vendor/k8s.io/apiserver/pkg/endpoints:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints:go_default_library",
"//vendor/k8s.io/apiserver/pkg/endpoints/discovery:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/discovery:go_default_library",
"//vendor/k8s.io/apiserver/pkg/endpoints/filters:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/filters:go_default_library",
"//vendor/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters:go_default_library",
"//vendor/k8s.io/apiserver/pkg/endpoints/openapi:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/openapi:go_default_library",
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library",
......
...@@ -53,7 +53,6 @@ import ( ...@@ -53,7 +53,6 @@ import (
genericregistry "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic"
genericfilters "k8s.io/apiserver/pkg/server/filters" genericfilters "k8s.io/apiserver/pkg/server/filters"
"k8s.io/apiserver/pkg/server/healthz" "k8s.io/apiserver/pkg/server/healthz"
"k8s.io/apiserver/pkg/server/mux"
"k8s.io/apiserver/pkg/server/routes" "k8s.io/apiserver/pkg/server/routes"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
certutil "k8s.io/client-go/util/cert" certutil "k8s.io/client-go/util/cert"
...@@ -110,10 +109,6 @@ type Config struct { ...@@ -110,10 +109,6 @@ type Config struct {
// Will default to a value based on secure serving info and available ipv4 IPs. // Will default to a value based on secure serving info and available ipv4 IPs.
ExternalAddress string ExternalAddress string
// FallThroughHandler is the final HTTP handler in the chain. If it is nil, one will be created for you.
// It comes after all filters and the API handling
FallThroughHandler *mux.PathRecorderMux
//=========================================================================== //===========================================================================
// Fields you probably don't care about changing // Fields you probably don't care about changing
//=========================================================================== //===========================================================================
...@@ -312,6 +307,17 @@ func (c *Config) Complete() completedConfig { ...@@ -312,6 +307,17 @@ func (c *Config) Complete() completedConfig {
}, },
} }
} }
if c.OpenAPIConfig.Info == nil {
c.OpenAPIConfig.Info = &spec.Info{}
}
if c.OpenAPIConfig.Info.Version == "" {
if c.Version != nil {
c.OpenAPIConfig.Info.Version = strings.Split(c.Version.String(), "-")[0]
} else {
c.OpenAPIConfig.Info.Version = "unversioned"
}
}
} }
if c.SwaggerConfig != nil && len(c.SwaggerConfig.WebServicesUrl) == 0 { if c.SwaggerConfig != nil && len(c.SwaggerConfig.WebServicesUrl) == 0 {
if c.SecureServingInfo != nil { if c.SecureServingInfo != nil {
...@@ -342,9 +348,6 @@ func (c *Config) Complete() completedConfig { ...@@ -342,9 +348,6 @@ func (c *Config) Complete() completedConfig {
tokenAuthorizer := authorizerfactory.NewPrivilegedGroups(user.SystemPrivilegedGroup) tokenAuthorizer := authorizerfactory.NewPrivilegedGroups(user.SystemPrivilegedGroup)
c.Authorizer = authorizerunion.New(tokenAuthorizer, c.Authorizer) c.Authorizer = authorizerunion.New(tokenAuthorizer, c.Authorizer)
} }
if c.FallThroughHandler == nil {
c.FallThroughHandler = mux.NewPathRecorderMux()
}
return completedConfig{c} return completedConfig{c}
} }
...@@ -354,38 +357,10 @@ func (c *Config) SkipComplete() completedConfig { ...@@ -354,38 +357,10 @@ func (c *Config) SkipComplete() completedConfig {
return completedConfig{c} return completedConfig{c}
} }
// New returns a new instance of GenericAPIServer from the given config. // New creates a new server which logically combines the handling chain with the passed server.
// Certain config fields will be set to a default value if unset, func (c completedConfig) New(delegationTarget DelegationTarget) (*GenericAPIServer, error) {
// including: // The delegationTarget and the config must agree on the RequestContextMapper
// ServiceClusterIPRange
// ServiceNodePortRange
// MasterCount
// ReadWritePort
// PublicAddress
// Public fields:
// Handler -- The returned GenericAPIServer has a field TopHandler which is an
// http.Handler which handles all the endpoints provided by the GenericAPIServer,
// including the API, the UI, and miscellaneous debugging endpoints. All
// these are subject to authorization and authentication.
// InsecureHandler -- an http.Handler which handles all the same
// endpoints as Handler, but no authorization and authentication is done.
// Public methods:
// HandleWithAuth -- Allows caller to add an http.Handler for an endpoint
// that uses the same authentication and authorization (if any is configured)
// as the GenericAPIServer's built-in endpoints.
// If the caller wants to add additional endpoints not using the GenericAPIServer's
// auth, then the caller should create a handler for those endpoints, which delegates the
// any unhandled paths to "Handler".
func (c completedConfig) New() (*GenericAPIServer, error) {
s, err := c.constructServer()
if err != nil {
return nil, err
}
return c.buildHandlers(s, nil)
}
func (c completedConfig) constructServer() (*GenericAPIServer, error) {
if c.Serializer == nil { if c.Serializer == nil {
return nil, fmt.Errorf("Genericapiserver.New() called with config.Serializer == nil") return nil, fmt.Errorf("Genericapiserver.New() called with config.Serializer == nil")
} }
...@@ -393,7 +368,10 @@ func (c completedConfig) constructServer() (*GenericAPIServer, error) { ...@@ -393,7 +368,10 @@ func (c completedConfig) constructServer() (*GenericAPIServer, error) {
return nil, fmt.Errorf("Genericapiserver.New() called with config.LoopbackClientConfig == nil") return nil, fmt.Errorf("Genericapiserver.New() called with config.LoopbackClientConfig == nil")
} }
handlerContainer := mux.NewAPIContainer(http.NewServeMux(), c.Serializer, c.FallThroughHandler) handlerChainBuilder := func(handler http.Handler) http.Handler {
return c.BuildHandlerChainFunc(handler, c.Config)
}
apiServerHandler := NewAPIServerHandler(c.Serializer, handlerChainBuilder, delegationTarget.UnprotectedHandler())
s := &GenericAPIServer{ s := &GenericAPIServer{
discoveryAddresses: c.DiscoveryAddresses, discoveryAddresses: c.DiscoveryAddresses,
...@@ -408,10 +386,9 @@ func (c completedConfig) constructServer() (*GenericAPIServer, error) { ...@@ -408,10 +386,9 @@ func (c completedConfig) constructServer() (*GenericAPIServer, error) {
SecureServingInfo: c.SecureServingInfo, SecureServingInfo: c.SecureServingInfo,
ExternalAddress: c.ExternalAddress, ExternalAddress: c.ExternalAddress,
HandlerContainer: handlerContainer, Handler: apiServerHandler,
FallThroughHandler: c.FallThroughHandler,
listedPathProvider: routes.ListedPathProviders{handlerContainer, c.FallThroughHandler}, listedPathProvider: apiServerHandler,
swaggerConfig: c.SwaggerConfig, swaggerConfig: c.SwaggerConfig,
openAPIConfig: c.OpenAPIConfig, openAPIConfig: c.OpenAPIConfig,
...@@ -424,20 +401,6 @@ func (c completedConfig) constructServer() (*GenericAPIServer, error) { ...@@ -424,20 +401,6 @@ func (c completedConfig) constructServer() (*GenericAPIServer, error) {
DiscoveryGroupManager: discovery.NewRootAPIsHandler(c.DiscoveryAddresses, c.Serializer), DiscoveryGroupManager: discovery.NewRootAPIsHandler(c.DiscoveryAddresses, c.Serializer),
} }
return s, nil
}
// NewWithDelegate creates a new server which logically combines the handling chain with the passed server.
func (c completedConfig) NewWithDelegate(delegationTarget DelegationTarget) (*GenericAPIServer, error) {
// some pieces of the delegationTarget take precendence. Callers should already have ensured that these
// were wired correctly. Documenting them here.
// c.RequestContextMapper = delegationTarget.RequestContextMapper()
s, err := c.constructServer()
if err != nil {
return nil, err
}
for k, v := range delegationTarget.PostStartHooks() { for k, v := range delegationTarget.PostStartHooks() {
s.postStartHooks[k] = v s.postStartHooks[k] = v
} }
...@@ -459,38 +422,17 @@ func (c completedConfig) NewWithDelegate(delegationTarget DelegationTarget) (*Ge ...@@ -459,38 +422,17 @@ func (c completedConfig) NewWithDelegate(delegationTarget DelegationTarget) (*Ge
s.listedPathProvider = routes.ListedPathProviders{s.listedPathProvider, delegationTarget} s.listedPathProvider = routes.ListedPathProviders{s.listedPathProvider, delegationTarget}
installAPI(s, c.Config)
// use the UnprotectedHandler from the delegation target to ensure that we don't attempt to double authenticator, authorize, // use the UnprotectedHandler from the delegation target to ensure that we don't attempt to double authenticator, authorize,
// or some other part of the filter chain in delegation cases. // or some other part of the filter chain in delegation cases.
return c.buildHandlers(s, delegationTarget.UnprotectedHandler()) if delegationTarget.UnprotectedHandler() == nil && c.EnableIndex {
} s.Handler.PostGoRestfulMux.NotFoundHandler(routes.IndexLister{
// buildHandlers builds our handling chain
func (c completedConfig) buildHandlers(s *GenericAPIServer, delegate http.Handler) (*GenericAPIServer, error) {
if s.openAPIConfig != nil {
if s.openAPIConfig.Info == nil {
s.openAPIConfig.Info = &spec.Info{}
}
if s.openAPIConfig.Info.Version == "" {
if c.Version != nil {
s.openAPIConfig.Info.Version = strings.Split(c.Version.String(), "-")[0]
} else {
s.openAPIConfig.Info.Version = "unversioned"
}
}
}
installAPI(s, c.Config)
if delegate != nil {
s.FallThroughHandler.NotFoundHandler(delegate)
} else if c.EnableIndex {
s.FallThroughHandler.NotFoundHandler(routes.IndexLister{
StatusCode: http.StatusNotFound, StatusCode: http.StatusNotFound,
PathProvider: s.listedPathProvider, PathProvider: s.listedPathProvider,
}) })
} }
s.Handler = c.BuildHandlerChainFunc(s.HandlerContainer.ServeMux, c.Config)
return s, nil return s, nil
} }
...@@ -510,28 +452,28 @@ func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler { ...@@ -510,28 +452,28 @@ func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler {
func installAPI(s *GenericAPIServer, c *Config) { func installAPI(s *GenericAPIServer, c *Config) {
if c.EnableIndex { if c.EnableIndex {
routes.Index{}.Install(s.listedPathProvider, c.FallThroughHandler) routes.Index{}.Install(s.listedPathProvider, s.Handler.PostGoRestfulMux)
} }
if c.SwaggerConfig != nil && c.EnableSwaggerUI { if c.SwaggerConfig != nil && c.EnableSwaggerUI {
routes.SwaggerUI{}.Install(s.FallThroughHandler) routes.SwaggerUI{}.Install(s.Handler.PostGoRestfulMux)
} }
if c.EnableProfiling { if c.EnableProfiling {
routes.Profiling{}.Install(s.FallThroughHandler) routes.Profiling{}.Install(s.Handler.PostGoRestfulMux)
if c.EnableContentionProfiling { if c.EnableContentionProfiling {
goruntime.SetBlockProfileRate(1) goruntime.SetBlockProfileRate(1)
} }
} }
if c.EnableMetrics { if c.EnableMetrics {
if c.EnableProfiling { if c.EnableProfiling {
routes.MetricsWithReset{}.Install(s.FallThroughHandler) routes.MetricsWithReset{}.Install(s.Handler.PostGoRestfulMux)
} else { } else {
routes.DefaultMetrics{}.Install(s.FallThroughHandler) routes.DefaultMetrics{}.Install(s.Handler.PostGoRestfulMux)
} }
} }
routes.Version{Version: c.Version}.Install(s.HandlerContainer) routes.Version{Version: c.Version}.Install(s.Handler.GoRestfulContainer)
if c.EnableDiscovery { if c.EnableDiscovery {
s.HandlerContainer.Add(s.DiscoveryGroupManager.WebService()) s.Handler.GoRestfulContainer.Add(s.DiscoveryGroupManager.WebService())
} }
} }
......
...@@ -28,7 +28,6 @@ import ( ...@@ -28,7 +28,6 @@ import (
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
genericapirequest "k8s.io/apiserver/pkg/endpoints/request" genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/server/healthz" "k8s.io/apiserver/pkg/server/healthz"
"k8s.io/apiserver/pkg/server/mux"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
) )
...@@ -38,7 +37,6 @@ func TestNewWithDelegate(t *testing.T) { ...@@ -38,7 +37,6 @@ func TestNewWithDelegate(t *testing.T) {
delegateConfig.RequestContextMapper = genericapirequest.NewRequestContextMapper() delegateConfig.RequestContextMapper = genericapirequest.NewRequestContextMapper()
delegateConfig.LegacyAPIGroupPrefixes = sets.NewString("/api") delegateConfig.LegacyAPIGroupPrefixes = sets.NewString("/api")
delegateConfig.LoopbackClientConfig = &rest.Config{} delegateConfig.LoopbackClientConfig = &rest.Config{}
delegateConfig.FallThroughHandler = mux.NewPathRecorderMux()
delegateConfig.SwaggerConfig = DefaultSwaggerConfig() delegateConfig.SwaggerConfig = DefaultSwaggerConfig()
delegateHealthzCalled := false delegateHealthzCalled := false
...@@ -47,14 +45,13 @@ func TestNewWithDelegate(t *testing.T) { ...@@ -47,14 +45,13 @@ func TestNewWithDelegate(t *testing.T) {
return fmt.Errorf("delegate failed healthcheck") return fmt.Errorf("delegate failed healthcheck")
})) }))
delegateConfig.FallThroughHandler.HandleFunc("/foo", func(w http.ResponseWriter, _ *http.Request) { delegateServer, err := delegateConfig.SkipComplete().New(EmptyDelegate)
w.WriteHeader(http.StatusForbidden)
})
delegateServer, err := delegateConfig.SkipComplete().New()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
delegateServer.Handler.PostGoRestfulMux.HandleFunc("/foo", func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusForbidden)
})
delegateServer.AddPostStartHook("delegate-post-start-hook", func(context PostStartHookContext) error { delegateServer.AddPostStartHook("delegate-post-start-hook", func(context PostStartHookContext) error {
return nil return nil
...@@ -68,7 +65,6 @@ func TestNewWithDelegate(t *testing.T) { ...@@ -68,7 +65,6 @@ func TestNewWithDelegate(t *testing.T) {
wrappingConfig.RequestContextMapper = genericapirequest.NewRequestContextMapper() wrappingConfig.RequestContextMapper = genericapirequest.NewRequestContextMapper()
wrappingConfig.LegacyAPIGroupPrefixes = sets.NewString("/api") wrappingConfig.LegacyAPIGroupPrefixes = sets.NewString("/api")
wrappingConfig.LoopbackClientConfig = &rest.Config{} wrappingConfig.LoopbackClientConfig = &rest.Config{}
wrappingConfig.FallThroughHandler = mux.NewPathRecorderMux()
wrappingConfig.SwaggerConfig = DefaultSwaggerConfig() wrappingConfig.SwaggerConfig = DefaultSwaggerConfig()
wrappingHealthzCalled := false wrappingHealthzCalled := false
...@@ -77,14 +73,13 @@ func TestNewWithDelegate(t *testing.T) { ...@@ -77,14 +73,13 @@ func TestNewWithDelegate(t *testing.T) {
return fmt.Errorf("wrapping failed healthcheck") return fmt.Errorf("wrapping failed healthcheck")
})) }))
wrappingConfig.FallThroughHandler.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) { wrappingServer, err := wrappingConfig.Complete().New(delegateServer)
w.WriteHeader(http.StatusUnauthorized)
})
wrappingServer, err := wrappingConfig.Complete().NewWithDelegate(delegateServer)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
wrappingServer.Handler.PostGoRestfulMux.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusUnauthorized)
})
wrappingServer.AddPostStartHook("wrapping-post-start-hook", func(context PostStartHookContext) error { wrappingServer.AddPostStartHook("wrapping-post-start-hook", func(context PostStartHookContext) error {
return nil return nil
......
...@@ -42,8 +42,6 @@ import ( ...@@ -42,8 +42,6 @@ import (
apirequest "k8s.io/apiserver/pkg/endpoints/request" apirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/server/healthz" "k8s.io/apiserver/pkg/server/healthz"
"k8s.io/apiserver/pkg/server/mux"
genericmux "k8s.io/apiserver/pkg/server/mux"
"k8s.io/apiserver/pkg/server/routes" "k8s.io/apiserver/pkg/server/routes"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
) )
...@@ -101,9 +99,6 @@ type GenericAPIServer struct { ...@@ -101,9 +99,6 @@ type GenericAPIServer struct {
// requestContextMapper provides a way to get the context for a request. It may be nil. // requestContextMapper provides a way to get the context for a request. It may be nil.
requestContextMapper apirequest.RequestContextMapper requestContextMapper apirequest.RequestContextMapper
// The registered APIs
HandlerContainer *genericmux.APIContainer
SecureServingInfo *SecureServingInfo SecureServingInfo *SecureServingInfo
// numerical ports, set after listening // numerical ports, set after listening
...@@ -121,10 +116,8 @@ type GenericAPIServer struct { ...@@ -121,10 +116,8 @@ type GenericAPIServer struct {
Serializer runtime.NegotiatedSerializer Serializer runtime.NegotiatedSerializer
// "Outputs" // "Outputs"
Handler http.Handler // Handler holdes the handlers being used by this API server
// FallThroughHandler is the final HTTP handler in the chain. Handler *APIServerHandler
// It comes after all filters and the API handling
FallThroughHandler *mux.PathRecorderMux
// listedPathProvider is a lister which provides the set of paths to show at / // listedPathProvider is a lister which provides the set of paths to show at /
listedPathProvider routes.ListedPathProvider listedPathProvider routes.ListedPathProvider
...@@ -171,7 +164,7 @@ type DelegationTarget interface { ...@@ -171,7 +164,7 @@ type DelegationTarget interface {
} }
func (s *GenericAPIServer) UnprotectedHandler() http.Handler { func (s *GenericAPIServer) UnprotectedHandler() http.Handler {
return s.HandlerContainer.ServeMux return s.Handler.GoRestfulContainer.ServeMux
} }
func (s *GenericAPIServer) PostStartHooks() map[string]postStartHookEntry { func (s *GenericAPIServer) PostStartHooks() map[string]postStartHookEntry {
return s.postStartHooks return s.postStartHooks
...@@ -233,12 +226,12 @@ type preparedGenericAPIServer struct { ...@@ -233,12 +226,12 @@ type preparedGenericAPIServer struct {
// PrepareRun does post API installation setup steps. // PrepareRun does post API installation setup steps.
func (s *GenericAPIServer) PrepareRun() preparedGenericAPIServer { func (s *GenericAPIServer) PrepareRun() preparedGenericAPIServer {
if s.swaggerConfig != nil { if s.swaggerConfig != nil {
routes.Swagger{Config: s.swaggerConfig}.Install(s.HandlerContainer) routes.Swagger{Config: s.swaggerConfig}.Install(s.Handler.GoRestfulContainer)
} }
if s.openAPIConfig != nil { if s.openAPIConfig != nil {
routes.OpenAPI{ routes.OpenAPI{
Config: s.openAPIConfig, Config: s.openAPIConfig,
}.Install(s.HandlerContainer, s.FallThroughHandler) }.Install(s.Handler.GoRestfulContainer, s.Handler.PostGoRestfulMux)
} }
s.installHealthz() s.installHealthz()
...@@ -306,7 +299,7 @@ func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *A ...@@ -306,7 +299,7 @@ func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *A
apiGroupVersion.OptionsExternalVersion = apiGroupInfo.OptionsExternalVersion apiGroupVersion.OptionsExternalVersion = apiGroupInfo.OptionsExternalVersion
} }
if err := apiGroupVersion.InstallREST(s.HandlerContainer.Container); err != nil { if err := apiGroupVersion.InstallREST(s.Handler.GoRestfulContainer); err != nil {
return fmt.Errorf("Unable to setup API %v: %v", apiGroupInfo, err) return fmt.Errorf("Unable to setup API %v: %v", apiGroupInfo, err)
} }
} }
...@@ -329,7 +322,7 @@ func (s *GenericAPIServer) InstallLegacyAPIGroup(apiPrefix string, apiGroupInfo ...@@ -329,7 +322,7 @@ func (s *GenericAPIServer) InstallLegacyAPIGroup(apiPrefix string, apiGroupInfo
} }
// Install the version handler. // Install the version handler.
// Add a handler at /<apiPrefix> to enumerate the supported api versions. // Add a handler at /<apiPrefix> to enumerate the supported api versions.
s.HandlerContainer.Add(discovery.NewLegacyRootAPIHandler(s.discoveryAddresses, s.Serializer, apiPrefix, apiVersions).WebService()) s.Handler.GoRestfulContainer.Add(discovery.NewLegacyRootAPIHandler(s.discoveryAddresses, s.Serializer, apiPrefix, apiVersions).WebService())
return nil return nil
} }
...@@ -373,7 +366,7 @@ func (s *GenericAPIServer) InstallAPIGroup(apiGroupInfo *APIGroupInfo) error { ...@@ -373,7 +366,7 @@ func (s *GenericAPIServer) InstallAPIGroup(apiGroupInfo *APIGroupInfo) error {
} }
s.DiscoveryGroupManager.AddGroup(apiGroup) s.DiscoveryGroupManager.AddGroup(apiGroup)
s.HandlerContainer.Add(discovery.NewAPIGroupHandler(s.Serializer, apiGroup).WebService()) s.Handler.GoRestfulContainer.Add(discovery.NewAPIGroupHandler(s.Serializer, apiGroup).WebService())
return nil return nil
} }
......
...@@ -47,7 +47,6 @@ import ( ...@@ -47,7 +47,6 @@ import (
"k8s.io/apiserver/pkg/endpoints/discovery" "k8s.io/apiserver/pkg/endpoints/discovery"
genericapirequest "k8s.io/apiserver/pkg/endpoints/request" genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/server/mux"
etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing" etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
) )
...@@ -90,7 +89,6 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertion ...@@ -90,7 +89,6 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertion
config.RequestContextMapper = genericapirequest.NewRequestContextMapper() config.RequestContextMapper = genericapirequest.NewRequestContextMapper()
config.LegacyAPIGroupPrefixes = sets.NewString("/api") config.LegacyAPIGroupPrefixes = sets.NewString("/api")
config.LoopbackClientConfig = &restclient.Config{} config.LoopbackClientConfig = &restclient.Config{}
config.FallThroughHandler = mux.NewPathRecorderMux()
// TODO restore this test, but right now, eliminate our cycle // TODO restore this test, but right now, eliminate our cycle
// config.OpenAPIConfig = DefaultOpenAPIConfig(testGetOpenAPIDefinitions, runtime.NewScheme()) // config.OpenAPIConfig = DefaultOpenAPIConfig(testGetOpenAPIDefinitions, runtime.NewScheme())
...@@ -108,7 +106,7 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertion ...@@ -108,7 +106,7 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertion
func newMaster(t *testing.T) (*GenericAPIServer, *etcdtesting.EtcdTestServer, Config, *assert.Assertions) { func newMaster(t *testing.T) (*GenericAPIServer, *etcdtesting.EtcdTestServer, Config, *assert.Assertions) {
etcdserver, config, assert := setUp(t) etcdserver, config, assert := setUp(t)
s, err := config.Complete().New() s, err := config.Complete().New(EmptyDelegate)
if err != nil { if err != nil {
t.Fatalf("Error in bringing up the server: %v", err) t.Fatalf("Error in bringing up the server: %v", err)
} }
...@@ -140,7 +138,7 @@ func TestInstallAPIGroups(t *testing.T) { ...@@ -140,7 +138,7 @@ func TestInstallAPIGroups(t *testing.T) {
config.LegacyAPIGroupPrefixes = sets.NewString("/apiPrefix") config.LegacyAPIGroupPrefixes = sets.NewString("/apiPrefix")
config.DiscoveryAddresses = discovery.DefaultAddresses{DefaultAddress: "ExternalAddress"} config.DiscoveryAddresses = discovery.DefaultAddresses{DefaultAddress: "ExternalAddress"}
s, err := config.SkipComplete().New() s, err := config.SkipComplete().New(EmptyDelegate)
if err != nil { if err != nil {
t.Fatalf("Error in bringing up the server: %v", err) t.Fatalf("Error in bringing up the server: %v", err)
} }
...@@ -304,7 +302,7 @@ func TestPrepareRun(t *testing.T) { ...@@ -304,7 +302,7 @@ func TestPrepareRun(t *testing.T) {
assert.NotNil(config.SwaggerConfig) assert.NotNil(config.SwaggerConfig)
// assert.NotNil(config.OpenAPIConfig) // assert.NotNil(config.OpenAPIConfig)
server := httptest.NewServer(s.HandlerContainer.ServeMux) server := httptest.NewServer(s.Handler.GoRestfulContainer.ServeMux)
defer server.Close() defer server.Close()
s.PrepareRun() s.PrepareRun()
...@@ -345,13 +343,13 @@ func TestCustomHandlerChain(t *testing.T) { ...@@ -345,13 +343,13 @@ func TestCustomHandlerChain(t *testing.T) {
called = true called = true
}) })
s, err := config.SkipComplete().New() s, err := config.SkipComplete().New(EmptyDelegate)
if err != nil { if err != nil {
t.Fatalf("Error in bringing up the server: %v", err) t.Fatalf("Error in bringing up the server: %v", err)
} }
s.FallThroughHandler.Handle("/nonswagger", handler) s.Handler.PostGoRestfulMux.Handle("/nonswagger", handler)
s.FallThroughHandler.Handle("/secret", handler) s.Handler.PostGoRestfulMux.Handle("/secret", handler)
type Test struct { type Test struct {
handler http.Handler handler http.Handler
...@@ -400,7 +398,7 @@ func TestNotRestRoutesHaveAuth(t *testing.T) { ...@@ -400,7 +398,7 @@ func TestNotRestRoutesHaveAuth(t *testing.T) {
kubeVersion := fakeVersion() kubeVersion := fakeVersion()
config.Version = &kubeVersion config.Version = &kubeVersion
s, err := config.SkipComplete().New() s, err := config.SkipComplete().New(EmptyDelegate)
if err != nil { if err != nil {
t.Fatalf("Error in bringing up the server: %v", err) t.Fatalf("Error in bringing up the server: %v", err)
} }
......
/* /*
Copyright 2016 The Kubernetes Authors. Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
...@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and ...@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package mux package server
import ( import (
"bytes" "bytes"
...@@ -30,42 +30,63 @@ import ( ...@@ -30,42 +30,63 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
"k8s.io/apiserver/pkg/server/mux"
genericmux "k8s.io/apiserver/pkg/server/mux"
) )
// APIContainer is a restful container which in addition support registering // APIServerHandlers holds the different http.Handlers used by the API server.
// handlers that do not show up in swagger or in / // This includes the full handler chain, the gorestful handler (used for the API) which falls through to the postGoRestful handler
type APIContainer struct { // and the postGoRestful handler (which can contain a fallthrough of its own)
*restful.Container type APIServerHandler struct {
// FullHandlerChain is the one that is eventually served with. It should include the full filter
// chain and then call the GoRestfulContainer.
FullHandlerChain http.Handler
// The registered APIs
GoRestfulContainer *restful.Container
// PostGoRestfulMux is the final HTTP handler in the chain.
// It comes after all filters and the API handling
PostGoRestfulMux *mux.PathRecorderMux
} }
// NewAPIContainer constructs a new container for APIs // HandlerChainBuilderFn is used to wrap the GoRestfulContainer handler using the provided handler chain.
func NewAPIContainer(mux *http.ServeMux, s runtime.NegotiatedSerializer, defaultMux http.Handler) *APIContainer { // It is normally used to apply filtering like authentication and authorization
c := APIContainer{ type HandlerChainBuilderFn func(apiHandler http.Handler) http.Handler
Container: restful.NewContainer(),
func NewAPIServerHandler(s runtime.NegotiatedSerializer, handlerChainBuilder HandlerChainBuilderFn, notFoundHandler http.Handler) *APIServerHandler {
postGoRestfulMux := genericmux.NewPathRecorderMux()
if notFoundHandler != nil {
postGoRestfulMux.NotFoundHandler(notFoundHandler)
} }
c.Container.ServeMux = mux
c.Container.Router(restful.CurlyRouter{}) // e.g. for proxy/{kind}/{name}/{*} gorestfulContainer := restful.NewContainer()
c.Container.RecoverHandler(func(panicReason interface{}, httpWriter http.ResponseWriter) { gorestfulContainer.ServeMux = http.NewServeMux()
gorestfulContainer.Router(restful.CurlyRouter{}) // e.g. for proxy/{kind}/{name}/{*}
gorestfulContainer.RecoverHandler(func(panicReason interface{}, httpWriter http.ResponseWriter) {
logStackOnRecover(s, panicReason, httpWriter) logStackOnRecover(s, panicReason, httpWriter)
}) })
c.Container.ServiceErrorHandler(func(serviceErr restful.ServiceError, request *restful.Request, response *restful.Response) { gorestfulContainer.ServiceErrorHandler(func(serviceErr restful.ServiceError, request *restful.Request, response *restful.Response) {
serviceErrorHandler(s, serviceErr, request, response) serviceErrorHandler(s, serviceErr, request, response)
}) })
// register the defaultHandler for everything. This will allow an unhandled request to fall through to another handler instead of // register the defaultHandler for everything. This will allow an unhandled request to fall through to another handler instead of
// ending up with a forced 404 // ending up with a forced 404
c.Container.Handle("/", defaultMux) gorestfulContainer.Handle("/", postGoRestfulMux)
return &c return &APIServerHandler{
FullHandlerChain: handlerChainBuilder(gorestfulContainer.ServeMux),
GoRestfulContainer: gorestfulContainer,
PostGoRestfulMux: postGoRestfulMux,
}
} }
// ListedPaths returns the paths of the webservices for listing on /. // ListedPaths returns the paths that should be shown under /
func (c *APIContainer) ListedPaths() []string { func (a *APIServerHandler) ListedPaths() []string {
var handledPaths []string var handledPaths []string
// Extract the paths handled using restful.WebService // Extract the paths handled using restful.WebService
for _, ws := range c.RegisteredWebServices() { for _, ws := range a.GoRestfulContainer.RegisteredWebServices() {
handledPaths = append(handledPaths, ws.RootPath()) handledPaths = append(handledPaths, ws.RootPath())
} }
handledPaths = append(handledPaths, a.PostGoRestfulMux.ListedPaths()...)
sort.Strings(handledPaths) sort.Strings(handledPaths)
return handledPaths return handledPaths
...@@ -100,3 +121,8 @@ func serviceErrorHandler(s runtime.NegotiatedSerializer, serviceErr restful.Serv ...@@ -100,3 +121,8 @@ func serviceErrorHandler(s runtime.NegotiatedSerializer, serviceErr restful.Serv
request.Request, request.Request,
) )
} }
// ServeHTTP makes it an http.Handler
func (a *APIServerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
a.FullHandlerChain.ServeHTTP(w, r)
}
...@@ -41,5 +41,5 @@ func (s *GenericAPIServer) installHealthz() { ...@@ -41,5 +41,5 @@ func (s *GenericAPIServer) installHealthz() {
defer s.healthzLock.Unlock() defer s.healthzLock.Unlock()
s.healthzCreated = true s.healthzCreated = true
healthz.InstallHandler(s.FallThroughHandler, s.healthzChecks...) healthz.InstallHandler(s.Handler.PostGoRestfulMux, s.healthzChecks...)
} }
...@@ -19,19 +19,12 @@ go_test( ...@@ -19,19 +19,12 @@ go_test(
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = [
"container.go",
"doc.go", "doc.go",
"pathrecorder.go", "pathrecorder.go",
], ],
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//vendor/github.com/emicklei/go-restful:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters:go_default_library",
], ],
) )
...@@ -475,7 +475,7 @@ NextTest: ...@@ -475,7 +475,7 @@ NextTest:
return return
} }
s, err := config.Complete().New() s, err := config.Complete().New(server.EmptyDelegate)
if err != nil { if err != nil {
t.Errorf("%q - failed creating the server: %v", title, err) t.Errorf("%q - failed creating the server: %v", title, err)
return return
......
...@@ -17,6 +17,8 @@ limitations under the License. ...@@ -17,6 +17,8 @@ limitations under the License.
package routes package routes
import ( import (
"github.com/emicklei/go-restful"
"k8s.io/apimachinery/pkg/openapi" "k8s.io/apimachinery/pkg/openapi"
"k8s.io/apiserver/pkg/server/mux" "k8s.io/apiserver/pkg/server/mux"
apiserveropenapi "k8s.io/apiserver/pkg/server/openapi" apiserveropenapi "k8s.io/apiserver/pkg/server/openapi"
...@@ -30,7 +32,7 @@ type OpenAPI struct { ...@@ -30,7 +32,7 @@ type OpenAPI struct {
} }
// Install adds the SwaggerUI webservice to the given mux. // Install adds the SwaggerUI webservice to the given mux.
func (oa OpenAPI) Install(c *mux.APIContainer, mux *mux.PathRecorderMux) { func (oa OpenAPI) Install(c *restful.Container, mux *mux.PathRecorderMux) {
err := apiserveropenapi.RegisterOpenAPIService("/swagger.json", c.RegisteredWebServices(), oa.Config, mux) err := apiserveropenapi.RegisterOpenAPIService("/swagger.json", c.RegisteredWebServices(), oa.Config, mux)
if err != nil { if err != nil {
glog.Fatalf("Failed to register open api spec for root: %v", err) glog.Fatalf("Failed to register open api spec for root: %v", err)
......
...@@ -17,8 +17,7 @@ limitations under the License. ...@@ -17,8 +17,7 @@ limitations under the License.
package routes package routes
import ( import (
"k8s.io/apiserver/pkg/server/mux" "github.com/emicklei/go-restful"
"github.com/emicklei/go-restful-swagger12" "github.com/emicklei/go-restful-swagger12"
) )
...@@ -31,7 +30,7 @@ type Swagger struct { ...@@ -31,7 +30,7 @@ type Swagger struct {
} }
// Install adds the SwaggerUI webservice to the given mux. // Install adds the SwaggerUI webservice to the given mux.
func (s Swagger) Install(c *mux.APIContainer) { func (s Swagger) Install(c *restful.Container) {
s.Config.WebServices = c.RegisteredWebServices() s.Config.WebServices = c.RegisteredWebServices()
swagger.RegisterSwaggerService(*s.Config, c.Container) swagger.RegisterSwaggerService(*s.Config, c)
} }
...@@ -23,7 +23,6 @@ import ( ...@@ -23,7 +23,6 @@ import (
"k8s.io/apimachinery/pkg/version" "k8s.io/apimachinery/pkg/version"
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
"k8s.io/apiserver/pkg/server/mux"
) )
// Version provides a webservice with version information. // Version provides a webservice with version information.
...@@ -32,7 +31,7 @@ type Version struct { ...@@ -32,7 +31,7 @@ type Version struct {
} }
// Install registers the APIServer's `/version` handler. // Install registers the APIServer's `/version` handler.
func (v Version) Install(c *mux.APIContainer) { func (v Version) Install(c *restful.Container) {
if v.Version == nil { if v.Version == nil {
return return
} }
......
...@@ -135,7 +135,7 @@ func (c *Config) SkipComplete() completedConfig { ...@@ -135,7 +135,7 @@ func (c *Config) SkipComplete() completedConfig {
// New returns a new instance of APIAggregator from the given config. // New returns a new instance of APIAggregator from the given config.
func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.DelegationTarget, stopCh <-chan struct{}) (*APIAggregator, error) { func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.DelegationTarget, stopCh <-chan struct{}) (*APIAggregator, error) {
genericServer, err := c.Config.GenericConfig.SkipComplete().NewWithDelegate(delegationTarget) // completion is done in Complete, no need for a second time genericServer, err := c.Config.GenericConfig.SkipComplete().New(delegationTarget) // completion is done in Complete, no need for a second time
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -176,8 +176,8 @@ func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.Deleg ...@@ -176,8 +176,8 @@ func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.Deleg
serviceLister: s.serviceLister, serviceLister: s.serviceLister,
endpointsLister: s.endpointsLister, endpointsLister: s.endpointsLister,
} }
s.GenericAPIServer.FallThroughHandler.Handle("/apis", apisHandler) s.GenericAPIServer.Handler.PostGoRestfulMux.Handle("/apis", apisHandler)
s.GenericAPIServer.FallThroughHandler.UnlistedHandle("/apis/", apisHandler) s.GenericAPIServer.Handler.PostGoRestfulMux.UnlistedHandle("/apis/", apisHandler)
apiserviceRegistrationController := NewAPIServiceRegistrationController(informerFactory.Apiregistration().InternalVersion().APIServices(), kubeInformers.Core().V1().Services(), s) apiserviceRegistrationController := NewAPIServiceRegistrationController(informerFactory.Apiregistration().InternalVersion().APIServices(), kubeInformers.Core().V1().Services(), s)
...@@ -219,8 +219,8 @@ func (s *APIAggregator) AddAPIService(apiService *apiregistration.APIService, de ...@@ -219,8 +219,8 @@ func (s *APIAggregator) AddAPIService(apiService *apiregistration.APIService, de
} }
proxyHandler.updateAPIService(apiService, destinationHost) proxyHandler.updateAPIService(apiService, destinationHost)
s.proxyHandlers[apiService.Name] = proxyHandler s.proxyHandlers[apiService.Name] = proxyHandler
s.GenericAPIServer.FallThroughHandler.Handle(proxyPath, proxyHandler) s.GenericAPIServer.Handler.PostGoRestfulMux.Handle(proxyPath, proxyHandler)
s.GenericAPIServer.FallThroughHandler.UnlistedHandle(proxyPath+"/", proxyHandler) s.GenericAPIServer.Handler.PostGoRestfulMux.UnlistedHandlePrefix(proxyPath+"/", proxyHandler)
// if we're dealing with the legacy group, we're done here // if we're dealing with the legacy group, we're done here
if apiService.Name == legacyAPIServiceName { if apiService.Name == legacyAPIServiceName {
...@@ -243,8 +243,8 @@ func (s *APIAggregator) AddAPIService(apiService *apiregistration.APIService, de ...@@ -243,8 +243,8 @@ func (s *APIAggregator) AddAPIService(apiService *apiregistration.APIService, de
delegate: s.delegateHandler, delegate: s.delegateHandler,
} }
// aggregation is protected // aggregation is protected
s.GenericAPIServer.FallThroughHandler.Handle(groupPath, groupDiscoveryHandler) s.GenericAPIServer.Handler.PostGoRestfulMux.Handle(groupPath, groupDiscoveryHandler)
s.GenericAPIServer.FallThroughHandler.UnlistedHandle(groupPath+"/", groupDiscoveryHandler) s.GenericAPIServer.Handler.PostGoRestfulMux.UnlistedHandle(groupPath+"/", groupDiscoveryHandler)
s.handledGroups.Insert(apiService.Spec.Group) s.handledGroups.Insert(apiService.Spec.Group)
} }
...@@ -258,8 +258,8 @@ func (s *APIAggregator) RemoveAPIService(apiServiceName string) { ...@@ -258,8 +258,8 @@ func (s *APIAggregator) RemoveAPIService(apiServiceName string) {
if apiServiceName == legacyAPIServiceName { if apiServiceName == legacyAPIServiceName {
proxyPath = "/api" proxyPath = "/api"
} }
s.GenericAPIServer.FallThroughHandler.Unregister(proxyPath) s.GenericAPIServer.Handler.PostGoRestfulMux.Unregister(proxyPath)
s.GenericAPIServer.FallThroughHandler.Unregister(proxyPath + "/") s.GenericAPIServer.Handler.PostGoRestfulMux.Unregister(proxyPath + "/")
delete(s.proxyHandlers, apiServiceName) delete(s.proxyHandlers, apiServiceName)
// TODO unregister group level discovery when there are no more versions for the group // TODO unregister group level discovery when there are no more versions for the group
......
...@@ -102,7 +102,7 @@ func (c *Config) SkipComplete() completedConfig { ...@@ -102,7 +102,7 @@ func (c *Config) SkipComplete() completedConfig {
// New returns a new instance of CustomResources from the given config. // New returns a new instance of CustomResources from the given config.
func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget, stopCh <-chan struct{}) (*CustomResources, error) { func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget, stopCh <-chan struct{}) (*CustomResources, error) {
genericServer, err := c.Config.GenericConfig.SkipComplete().New() // completion is done in Complete, no need for a second time genericServer, err := c.Config.GenericConfig.SkipComplete().New(genericapiserver.EmptyDelegate) // completion is done in Complete, no need for a second time
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -149,8 +149,8 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget, ...@@ -149,8 +149,8 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget,
c.CustomResourceRESTOptionsGetter, c.CustomResourceRESTOptionsGetter,
c.GenericConfig.AdmissionControl, c.GenericConfig.AdmissionControl,
) )
s.GenericAPIServer.FallThroughHandler.Handle("/apis", customResourceHandler) s.GenericAPIServer.Handler.PostGoRestfulMux.Handle("/apis", customResourceHandler)
s.GenericAPIServer.FallThroughHandler.HandlePrefix("/apis/", customResourceHandler) s.GenericAPIServer.Handler.PostGoRestfulMux.HandlePrefix("/apis/", customResourceHandler)
customResourceController := NewDiscoveryController(customResourceInformers.Apiextensions().InternalVersion().CustomResources(), versionDiscoveryHandler, groupDiscoveryHandler) customResourceController := NewDiscoveryController(customResourceInformers.Apiextensions().InternalVersion().CustomResources(), versionDiscoveryHandler, groupDiscoveryHandler)
......
...@@ -90,7 +90,7 @@ func (c *Config) SkipComplete() completedConfig { ...@@ -90,7 +90,7 @@ func (c *Config) SkipComplete() completedConfig {
// New returns a new instance of WardleServer from the given config. // New returns a new instance of WardleServer from the given config.
func (c completedConfig) New() (*WardleServer, error) { func (c completedConfig) New() (*WardleServer, error) {
genericServer, err := c.Config.GenericConfig.SkipComplete().New() // completion is done in Complete, no need for a second time genericServer, err := c.Config.GenericConfig.SkipComplete().New(genericapiserver.EmptyDelegate) // completion is done in Complete, no need for a second time
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -236,7 +236,7 @@ func startMasterOrDie(masterConfig *master.Config, incomingServer *httptest.Serv ...@@ -236,7 +236,7 @@ func startMasterOrDie(masterConfig *master.Config, incomingServer *httptest.Serv
masterConfig.GenericConfig.LoopbackClientConfig.BearerToken = privilegedLoopbackToken masterConfig.GenericConfig.LoopbackClientConfig.BearerToken = privilegedLoopbackToken
m, err := masterConfig.Complete().New() m, err := masterConfig.Complete().New(genericapiserver.EmptyDelegate)
if err != nil { if err != nil {
glog.Fatalf("error in bringing up the master: %v", err) glog.Fatalf("error in bringing up the master: %v", err)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment