diff --git a/pkg/genericapiserver/config.go b/pkg/genericapiserver/config.go index 433d89cea1d..b7f8d5d634f 100644 --- a/pkg/genericapiserver/config.go +++ b/pkg/genericapiserver/config.go @@ -210,8 +210,12 @@ func NewConfig(options *options.ServerRunOptions) *Config { } } +type completedConfig struct { + *Config +} + // Complete fills in any fields not set that are required to have valid data. It's mutating the receiver. -func (c *Config) Complete() *Config { +func (c *Config) Complete() completedConfig { if c.ServiceClusterIPRange == nil { defaultNet := "10.0.0.0/24" glog.Warningf("Network range for service cluster IPs is unspecified. Defaulting to %v.", defaultNet) @@ -264,7 +268,12 @@ func (c *Config) Complete() *Config { } c.ExternalHost = hostAndPort } - return c + return completedConfig{c} +} + +// SkipComplete provides a way to construct a server instance without config completion. +func (c *Config) SkipComplete() completedConfig { + return completedConfig{c} } // New returns a new instance of GenericAPIServer from the given config. @@ -289,7 +298,7 @@ func (c *Config) Complete() *Config { // 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 *Config) New() (*GenericAPIServer, error) { +func (c completedConfig) New() (*GenericAPIServer, error) { if c.Serializer == nil { return nil, fmt.Errorf("Genericapiserver.New() called with config.Serializer == nil") } @@ -341,8 +350,8 @@ func (c *Config) New() (*GenericAPIServer, error) { }) } - s.installAPI(c) - s.Handler, s.InsecureHandler = s.buildHandlerChains(c, http.Handler(s.Mux.BaseMux().(*http.ServeMux))) + s.installAPI(c.Config) + s.Handler, s.InsecureHandler = s.buildHandlerChains(c.Config, http.Handler(s.Mux.BaseMux().(*http.ServeMux))) return s, nil } diff --git a/pkg/master/master.go b/pkg/master/master.go index 7b5bfb6d0a1..aa906770b80 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -190,26 +190,35 @@ type RESTStorageProvider interface { NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (groupInfo genericapiserver.APIGroupInfo, enabled bool) } +type completedConfig struct { + *Config +} + // Complete fills in any fields not set that are required to have valid data. It's mutating the receiver. -func (c *Config) Complete() *Config { - c.Config.Complete() +func (c *Config) Complete() completedConfig { + c.GenericConfig.Complete() // enable swagger UI only if general UI support is on - c.Config.EnableSwaggerUI = c.Config.EnableSwaggerUI && c.EnableUISupport + c.GenericConfig.EnableSwaggerUI = c.GenericConfig.EnableSwaggerUI && c.EnableUISupport - return c + return completedConfig{c} +} + +// SkipComplete provides a way to construct a server instance without config completion. +func (c *Config) SkipComplete() completedConfig { + return completedConfig{c} } // New returns a new instance of Master from the given config. // Certain config fields will be set to a default value if unset. // Certain config fields must be specified, including: // KubeletClient -func (c *Config) New() (*Master, error) { +func (c completedConfig) New() (*Master, error) { if c.KubeletClient == nil { return nil, fmt.Errorf("Master.New() called with config.KubeletClient == nil") } - s, err := c.Config.New() + s, err := c.Config.GenericConfig.SkipComplete().New() // completion is done in Complete, no need for a second time if err != nil { return nil, err } @@ -259,7 +268,7 @@ func (c *Config) New() (*Master, error) { c.RESTStorageProviders[policy.GroupName] = policyrest.RESTStorageProvider{} c.RESTStorageProviders[rbac.GroupName] = &rbacrest.RESTStorageProvider{AuthorizerRBACSuperUser: c.GenericConfig.AuthorizerRBACSuperUser} c.RESTStorageProviders[storage.GroupName] = storagerest.RESTStorageProvider{} - m.InstallAPIs(c) + m.InstallAPIs(c.Config) // TODO: Attempt clean shutdown? if m.enableCoreControllers {