From cd4135666ec39bc04230669eff83c89c490caab8 Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Mon, 15 Dec 2014 15:29:55 -0500 Subject: [PATCH] Make Swagger API support optional, so that consumers can define their own OpenShift would like to also enable swagger, but we need to register our services as swagger services prior to the SwaggerAPI being started. I've added a bool (default false) to master.Config to enable swagger, and split the method in master out so that a downstream consumer can call it. --- cmd/kube-apiserver/apiserver.go | 1 + pkg/master/master.go | 63 +++++++++++++++++++++++---------- pkg/standalone/standalone.go | 8 ++--- 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/cmd/kube-apiserver/apiserver.go b/cmd/kube-apiserver/apiserver.go index 6fc8562442c..ece895b736d 100644 --- a/cmd/kube-apiserver/apiserver.go +++ b/cmd/kube-apiserver/apiserver.go @@ -171,6 +171,7 @@ func main() { PortalNet: &n, EnableLogsSupport: *enableLogsSupport, EnableUISupport: true, + EnableSwaggerSupport: true, APIPrefix: *apiPrefix, CorsAllowedOriginList: corsAllowedOriginList, ReadOnlyPort: *readOnlyPort, diff --git a/pkg/master/master.go b/pkg/master/master.go index 63ec9a34ae3..2bfdaad3004 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -69,11 +69,15 @@ type Config struct { PortalNet *net.IPNet EnableLogsSupport bool EnableUISupport bool + EnableSwaggerSupport bool APIPrefix string CorsAllowedOriginList util.StringList Authenticator authenticator.Request Authorizer authorizer.Authorizer + // If specified, all web services will be registered into this container + RestfulContainer *restful.Container + // Number of masters running; all masters must be started with the // same value for this field. (Numbers > 1 currently untested.) MasterCount int @@ -92,21 +96,23 @@ type Config struct { // Master contains state for a Kubernetes cluster master/api server. type Master struct { // "Inputs", Copied from Config - podRegistry pod.Registry - controllerRegistry controller.Registry - serviceRegistry service.Registry - endpointRegistry endpoint.Registry - minionRegistry minion.Registry - bindingRegistry binding.Registry - eventRegistry generic.Registry - storage map[string]apiserver.RESTStorage - client *client.Client - portalNet *net.IPNet + podRegistry pod.Registry + controllerRegistry controller.Registry + serviceRegistry service.Registry + endpointRegistry endpoint.Registry + minionRegistry minion.Registry + bindingRegistry binding.Registry + eventRegistry generic.Registry + storage map[string]apiserver.RESTStorage + client *client.Client + portalNet *net.IPNet + mux apiserver.Mux handlerContainer *restful.Container rootWebService *restful.WebService enableLogsSupport bool enableUISupport bool + enableSwaggerSupport bool apiPrefix string corsAllowedOriginList util.StringList authenticator authenticator.Request @@ -222,7 +228,7 @@ func New(c *Config) *Master { if c.KubeletClient == nil { glog.Fatalf("master.New() called with config.KubeletClient == nil") } - mx := http.NewServeMux() + m := &Master{ podRegistry: etcd.NewRegistry(c.EtcdHelper, boundPodFactory), controllerRegistry: etcd.NewRegistry(c.EtcdHelper, nil), @@ -233,11 +239,10 @@ func New(c *Config) *Master { minionRegistry: minionRegistry, client: c.Client, portalNet: c.PortalNet, - mux: mx, - handlerContainer: NewHandlerContainer(mx), rootWebService: new(restful.WebService), enableLogsSupport: c.EnableLogsSupport, enableUISupport: c.EnableUISupport, + enableSwaggerSupport: c.EnableSwaggerSupport, apiPrefix: c.APIPrefix, corsAllowedOriginList: c.CorsAllowedOriginList, authenticator: c.Authenticator, @@ -247,6 +252,16 @@ func New(c *Config) *Master { readOnlyServer: net.JoinHostPort(c.PublicAddress, strconv.Itoa(int(c.ReadOnlyPort))), readWriteServer: net.JoinHostPort(c.PublicAddress, strconv.Itoa(int(c.ReadWritePort))), } + + if c.RestfulContainer != nil { + m.mux = c.RestfulContainer.ServeMux + m.handlerContainer = c.RestfulContainer + } else { + mux := http.NewServeMux() + m.mux = mux + m.handlerContainer = NewHandlerContainer(mux) + } + m.masterServices = util.NewRunner(m.serviceWriterLoop, m.roServiceWriterLoop) m.init(c) return m @@ -377,7 +392,22 @@ func (m *Master) init(c *Config) { // Install root web services m.handlerContainer.Add(m.rootWebService) - // TODO: Make this optional? + // TODO: Make this optional? Consumers of master depend on this currently. + m.Handler = handler + + if m.enableSwaggerSupport { + m.InstallSwaggerAPI() + } + + // TODO: Attempt clean shutdown? + m.masterServices.Start() +} + +// InstallSwaggerAPI installs the /swaggerapi/ endpoint to allow schema discovery +// and traversal. It is optional to allow consumers of the Kubernetes master to +// register their own web services into the Kubernetes mux prior to initialization +// of swagger, so that other resource types show up in the documentation. +func (m *Master) InstallSwaggerAPI() { // Enable swagger UI and discovery API swaggerConfig := swagger.Config{ WebServices: m.handlerContainer.RegisteredWebServices(), @@ -388,11 +418,6 @@ func (m *Master) init(c *Config) { //SwaggerFilePath: "/srv/apiserver/swagger/dist" } swagger.RegisterSwaggerService(swaggerConfig, m.handlerContainer) - - m.Handler = handler - - // TODO: Attempt clean shutdown? - m.masterServices.Start() } func (m *Master) getServersToValidate(c *Config) map[string]apiserver.Server { diff --git a/pkg/standalone/standalone.go b/pkg/standalone/standalone.go index 377162c87e1..7d2fcbd7bd5 100644 --- a/pkg/standalone/standalone.go +++ b/pkg/standalone/standalone.go @@ -87,15 +87,15 @@ func RunApiServer(cl *client.Client, etcdClient tools.EtcdClient, addr string, p Client: http.DefaultClient, Port: 10250, }, - EnableLogsSupport: false, - APIPrefix: "/api", - Authorizer: apiserver.NewAlwaysAllowAuthorizer(), + EnableLogsSupport: false, + EnableSwaggerSupport: true, + APIPrefix: "/api", + Authorizer: apiserver.NewAlwaysAllowAuthorizer(), ReadWritePort: port, ReadOnlyPort: port, PublicAddress: addr, }) - handler.delegate = m.InsecureHandler go http.ListenAndServe(fmt.Sprintf("%s:%d", addr, port), &handler)