// setDefaults fills in any fields not set that are required to have valid data. func setDefaults(c *Config) { if c.ServiceClusterIPRange == nil { defaultNet := "10.0.0.0/24" glog.Warningf("Network range for service cluster IPs is unspecified. Defaulting to %v.", defaultNet) _, serviceClusterIPRange, err := net.ParseCIDR(defaultNet) if err != nil { glog.Fatalf("Unable to parse CIDR: %v", err) } if size := ipallocator.RangeSize(serviceClusterIPRange); size < 8 { glog.Fatalf("The service cluster IP range must be at least %d IP addresses", 8) } c.ServiceClusterIPRange = serviceClusterIPRange } if c.ServiceReadWriteIP == nil { // Select the first valid IP from ServiceClusterIPRange to use as the master service IP. serviceReadWriteIP, err := ipallocator.GetIndexedIP(c.ServiceClusterIPRange, 1) if err != nil { glog.Fatalf("Failed to generate service read-write IP for master service: %v", err) } glog.V(4).Infof("Setting master service IP to %q (read-write).", serviceReadWriteIP) c.ServiceReadWriteIP = serviceReadWriteIP } if c.ServiceNodePortRange.Size == 0 { // TODO: Currently no way to specify an empty range (do we need to allow this?) // We should probably allow this for clouds that don't require NodePort to do load-balancing (GCE) // but then that breaks the strict nestedness of ServiceType. // Review post-v1 defaultServiceNodePortRange := util.PortRange{Base: 30000, Size: 2768} c.ServiceNodePortRange = defaultServiceNodePortRange glog.Infof("Node port range unspecified. Defaulting to %v.", c.ServiceNodePortRange) } if c.MasterCount == 0 { // Clearly, there will be at least one master. c.MasterCount = 1 } if c.ReadWritePort == 0 { c.ReadWritePort = 6443 } if c.CacheTimeout == 0 { c.CacheTimeout = 5 * time.Second } for c.PublicAddress == nil || c.PublicAddress.IsUnspecified() { // TODO: This should be done in the caller and just require a // valid value to be passed in. hostIP, err := util.ChooseHostInterface() if err != nil { glog.Fatalf("Unable to find suitable network address.error='%v' . "+ "Will try again in 5 seconds. Set the public address directly to avoid this wait.", err) time.Sleep(5 * time.Second) } c.PublicAddress = hostIP glog.Infof("Will report %v as public IP address.", c.PublicAddress) } if c.RequestContextMapper == nil { c.RequestContextMapper = api.NewRequestContextMapper() } }
// New returns a new instance of Master from the given config. // Certain config fields will be set to a default value if unset, // including: // ServiceClusterIPRange // ServiceNodePortRange // MasterCount // ReadWritePort // PublicAddress // Certain config fields must be specified, including: // KubeletClient // Public fields: // Handler -- The returned master has a field TopHandler which is an // http.Handler which handles all the endpoints provided by the master, // including the API, the UI, and miscelaneous 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 master's built-in endpoints. // If the caller wants to add additional endpoints not using the master's // auth, then the caller should create a handler for those endpoints, which delegates the // any unhandled paths to "Handler". func New(c *Config) *Master { setDefaults(c) if c.KubeletClient == nil { glog.Fatalf("master.New() called with config.KubeletClient == nil") } // Select the first valid IP from serviceClusterIPRange to use as the master service IP. serviceReadWriteIP, err := ipallocator.GetIndexedIP(c.ServiceClusterIPRange, 1) if err != nil { glog.Fatalf("Failed to generate service read-write IP for master service: %v", err) } glog.V(4).Infof("Setting master service IP to %q (read-write).", serviceReadWriteIP) m := &Master{ serviceClusterIPRange: c.ServiceClusterIPRange, serviceNodePortRange: c.ServiceNodePortRange, rootWebService: new(restful.WebService), enableCoreControllers: c.EnableCoreControllers, enableLogsSupport: c.EnableLogsSupport, enableUISupport: c.EnableUISupport, enableSwaggerSupport: c.EnableSwaggerSupport, enableProfiling: c.EnableProfiling, apiPrefix: c.APIPrefix, corsAllowedOriginList: c.CorsAllowedOriginList, authenticator: c.Authenticator, authorizer: c.Authorizer, admissionControl: c.AdmissionControl, v1beta3: !c.DisableV1Beta3, v1: !c.DisableV1, requestContextMapper: c.RequestContextMapper, cacheTimeout: c.CacheTimeout, minRequestTimeout: time.Duration(c.MinRequestTimeout) * time.Second, masterCount: c.MasterCount, externalHost: c.ExternalHost, clusterIP: c.PublicAddress, publicReadWritePort: c.ReadWritePort, serviceReadWriteIP: serviceReadWriteIP, // TODO: serviceReadWritePort should be passed in as an argument, it may not always be 443 serviceReadWritePort: 443, installSSHKey: c.InstallSSHKey, } var handlerContainer *restful.Container if c.RestfulContainer != nil { m.mux = c.RestfulContainer.ServeMux handlerContainer = c.RestfulContainer } else { mux := http.NewServeMux() m.mux = mux handlerContainer = NewHandlerContainer(mux) } m.handlerContainer = handlerContainer // Use CurlyRouter to be able to use regular expressions in paths. Regular expressions are required in paths for example for proxy (where the path is proxy/{kind}/{name}/{*}) m.handlerContainer.Router(restful.CurlyRouter{}) m.muxHelper = &apiserver.MuxHelper{m.mux, []string{}} m.init(c) return m }