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.
This commit is contained in:
Clayton Coleman 2014-12-15 15:29:55 -05:00
parent e37e25807c
commit cd4135666e
3 changed files with 49 additions and 23 deletions

View File

@ -171,6 +171,7 @@ func main() {
PortalNet: &n, PortalNet: &n,
EnableLogsSupport: *enableLogsSupport, EnableLogsSupport: *enableLogsSupport,
EnableUISupport: true, EnableUISupport: true,
EnableSwaggerSupport: true,
APIPrefix: *apiPrefix, APIPrefix: *apiPrefix,
CorsAllowedOriginList: corsAllowedOriginList, CorsAllowedOriginList: corsAllowedOriginList,
ReadOnlyPort: *readOnlyPort, ReadOnlyPort: *readOnlyPort,

View File

@ -69,11 +69,15 @@ type Config struct {
PortalNet *net.IPNet PortalNet *net.IPNet
EnableLogsSupport bool EnableLogsSupport bool
EnableUISupport bool EnableUISupport bool
EnableSwaggerSupport bool
APIPrefix string APIPrefix string
CorsAllowedOriginList util.StringList CorsAllowedOriginList util.StringList
Authenticator authenticator.Request Authenticator authenticator.Request
Authorizer authorizer.Authorizer 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 // Number of masters running; all masters must be started with the
// same value for this field. (Numbers > 1 currently untested.) // same value for this field. (Numbers > 1 currently untested.)
MasterCount int MasterCount int
@ -102,11 +106,13 @@ type Master struct {
storage map[string]apiserver.RESTStorage storage map[string]apiserver.RESTStorage
client *client.Client client *client.Client
portalNet *net.IPNet portalNet *net.IPNet
mux apiserver.Mux mux apiserver.Mux
handlerContainer *restful.Container handlerContainer *restful.Container
rootWebService *restful.WebService rootWebService *restful.WebService
enableLogsSupport bool enableLogsSupport bool
enableUISupport bool enableUISupport bool
enableSwaggerSupport bool
apiPrefix string apiPrefix string
corsAllowedOriginList util.StringList corsAllowedOriginList util.StringList
authenticator authenticator.Request authenticator authenticator.Request
@ -222,7 +228,7 @@ func New(c *Config) *Master {
if c.KubeletClient == nil { if c.KubeletClient == nil {
glog.Fatalf("master.New() called with config.KubeletClient == nil") glog.Fatalf("master.New() called with config.KubeletClient == nil")
} }
mx := http.NewServeMux()
m := &Master{ m := &Master{
podRegistry: etcd.NewRegistry(c.EtcdHelper, boundPodFactory), podRegistry: etcd.NewRegistry(c.EtcdHelper, boundPodFactory),
controllerRegistry: etcd.NewRegistry(c.EtcdHelper, nil), controllerRegistry: etcd.NewRegistry(c.EtcdHelper, nil),
@ -233,11 +239,10 @@ func New(c *Config) *Master {
minionRegistry: minionRegistry, minionRegistry: minionRegistry,
client: c.Client, client: c.Client,
portalNet: c.PortalNet, portalNet: c.PortalNet,
mux: mx,
handlerContainer: NewHandlerContainer(mx),
rootWebService: new(restful.WebService), rootWebService: new(restful.WebService),
enableLogsSupport: c.EnableLogsSupport, enableLogsSupport: c.EnableLogsSupport,
enableUISupport: c.EnableUISupport, enableUISupport: c.EnableUISupport,
enableSwaggerSupport: c.EnableSwaggerSupport,
apiPrefix: c.APIPrefix, apiPrefix: c.APIPrefix,
corsAllowedOriginList: c.CorsAllowedOriginList, corsAllowedOriginList: c.CorsAllowedOriginList,
authenticator: c.Authenticator, authenticator: c.Authenticator,
@ -247,6 +252,16 @@ func New(c *Config) *Master {
readOnlyServer: net.JoinHostPort(c.PublicAddress, strconv.Itoa(int(c.ReadOnlyPort))), readOnlyServer: net.JoinHostPort(c.PublicAddress, strconv.Itoa(int(c.ReadOnlyPort))),
readWriteServer: net.JoinHostPort(c.PublicAddress, strconv.Itoa(int(c.ReadWritePort))), 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.masterServices = util.NewRunner(m.serviceWriterLoop, m.roServiceWriterLoop)
m.init(c) m.init(c)
return m return m
@ -377,7 +392,22 @@ func (m *Master) init(c *Config) {
// Install root web services // Install root web services
m.handlerContainer.Add(m.rootWebService) 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 // Enable swagger UI and discovery API
swaggerConfig := swagger.Config{ swaggerConfig := swagger.Config{
WebServices: m.handlerContainer.RegisteredWebServices(), WebServices: m.handlerContainer.RegisteredWebServices(),
@ -388,11 +418,6 @@ func (m *Master) init(c *Config) {
//SwaggerFilePath: "/srv/apiserver/swagger/dist" //SwaggerFilePath: "/srv/apiserver/swagger/dist"
} }
swagger.RegisterSwaggerService(swaggerConfig, m.handlerContainer) 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 { func (m *Master) getServersToValidate(c *Config) map[string]apiserver.Server {

View File

@ -88,6 +88,7 @@ func RunApiServer(cl *client.Client, etcdClient tools.EtcdClient, addr string, p
Port: 10250, Port: 10250,
}, },
EnableLogsSupport: false, EnableLogsSupport: false,
EnableSwaggerSupport: true,
APIPrefix: "/api", APIPrefix: "/api",
Authorizer: apiserver.NewAlwaysAllowAuthorizer(), Authorizer: apiserver.NewAlwaysAllowAuthorizer(),
@ -95,7 +96,6 @@ func RunApiServer(cl *client.Client, etcdClient tools.EtcdClient, addr string, p
ReadOnlyPort: port, ReadOnlyPort: port,
PublicAddress: addr, PublicAddress: addr,
}) })
handler.delegate = m.InsecureHandler handler.delegate = m.InsecureHandler
go http.ListenAndServe(fmt.Sprintf("%s:%d", addr, port), &handler) go http.ListenAndServe(fmt.Sprintf("%s:%d", addr, port), &handler)