// RunApiServer starts an API server in a go routine. func RunApiServer(cl *client.Client, etcdClient tools.EtcdClient, addr string, port int) { handler := delegateHandler{} helper, err := master.NewEtcdHelper(etcdClient, "") if err != nil { glog.Fatalf("Unable to get etcd helper: %v", err) } // Create a master and install handlers into mux. m := master.New(&master.Config{ Client: cl, EtcdHelper: helper, KubeletClient: &client.HTTPKubeletClient{ Client: http.DefaultClient, Port: 10250, }, EnableLogsSupport: false, APIPrefix: "/api", Authorizer: apiserver.NewAlwaysAllowAuthorizer(), ReadWritePort: port, ReadOnlyPort: port, PublicAddress: addr, }) mux := http.NewServeMux() apiserver.NewAPIGroup(m.API_v1beta1()).InstallREST(mux, "/api/v1beta1") apiserver.NewAPIGroup(m.API_v1beta2()).InstallREST(mux, "/api/v1beta2") apiserver.InstallSupport(mux) handler.delegate = mux go http.ListenAndServe(fmt.Sprintf("%s:%d", addr, port), &handler) }
// init initializes master. func (m *Master) init(c *Config) { healthzChecks := []healthz.HealthzChecker{} m.clock = util.RealClock{} podStorage := podetcd.NewStorage(c.DatabaseStorage, c.KubeletClient) podRegistry := pod.NewRegistry(podStorage.Pod) podTemplateStorage := podtemplateetcd.NewREST(c.DatabaseStorage) eventRegistry := event.NewEtcdRegistry(c.DatabaseStorage, uint64(c.EventTTL.Seconds())) limitRangeRegistry := limitrange.NewEtcdRegistry(c.DatabaseStorage) resourceQuotaStorage, resourceQuotaStatusStorage := resourcequotaetcd.NewStorage(c.DatabaseStorage) secretStorage := secretetcd.NewStorage(c.DatabaseStorage) serviceAccountStorage := serviceaccountetcd.NewStorage(c.DatabaseStorage) persistentVolumeStorage, persistentVolumeStatusStorage := pvetcd.NewStorage(c.DatabaseStorage) persistentVolumeClaimStorage, persistentVolumeClaimStatusStorage := pvcetcd.NewStorage(c.DatabaseStorage) namespaceStorage, namespaceStatusStorage, namespaceFinalizeStorage := namespaceetcd.NewStorage(c.DatabaseStorage) m.namespaceRegistry = namespace.NewRegistry(namespaceStorage) endpointsStorage := endpointsetcd.NewStorage(c.DatabaseStorage) m.endpointRegistry = endpoint.NewRegistry(endpointsStorage) nodeStorage, nodeStatusStorage := nodeetcd.NewStorage(c.DatabaseStorage, c.KubeletClient) m.nodeRegistry = minion.NewRegistry(nodeStorage) // TODO: split me up into distinct storage registries registry := etcd.NewRegistry(c.DatabaseStorage, podRegistry, m.endpointRegistry) m.serviceRegistry = registry var serviceClusterIPRegistry service.RangeRegistry serviceClusterIPAllocator := ipallocator.NewAllocatorCIDRRange(m.serviceClusterIPRange, func(max int, rangeSpec string) allocator.Interface { mem := allocator.NewAllocationMap(max, rangeSpec) etcd := etcdallocator.NewEtcd(mem, "/ranges/serviceips", "serviceipallocation", c.DatabaseStorage) serviceClusterIPRegistry = etcd return etcd }) m.serviceClusterIPAllocator = serviceClusterIPRegistry var serviceNodePortRegistry service.RangeRegistry serviceNodePortAllocator := portallocator.NewPortAllocatorCustom(m.serviceNodePortRange, func(max int, rangeSpec string) allocator.Interface { mem := allocator.NewAllocationMap(max, rangeSpec) etcd := etcdallocator.NewEtcd(mem, "/ranges/servicenodeports", "servicenodeportallocation", c.DatabaseStorage) serviceNodePortRegistry = etcd return etcd }) m.serviceNodePortAllocator = serviceNodePortRegistry controllerStorage := controlleretcd.NewREST(c.DatabaseStorage) // TODO: Factor out the core API registration m.storage = map[string]rest.Storage{ "pods": podStorage.Pod, "pods/status": podStorage.Status, "pods/log": podStorage.Log, "pods/exec": podStorage.Exec, "pods/portforward": podStorage.PortForward, "pods/proxy": podStorage.Proxy, "pods/binding": podStorage.Binding, "bindings": podStorage.Binding, "podTemplates": podTemplateStorage, "replicationControllers": controllerStorage, "services": service.NewStorage(m.serviceRegistry, m.nodeRegistry, m.endpointRegistry, serviceClusterIPAllocator, serviceNodePortAllocator, c.ClusterName), "endpoints": endpointsStorage, "nodes": nodeStorage, "nodes/status": nodeStatusStorage, "events": event.NewStorage(eventRegistry), "limitRanges": limitrange.NewStorage(limitRangeRegistry), "resourceQuotas": resourceQuotaStorage, "resourceQuotas/status": resourceQuotaStatusStorage, "namespaces": namespaceStorage, "namespaces/status": namespaceStatusStorage, "namespaces/finalize": namespaceFinalizeStorage, "secrets": secretStorage, "serviceAccounts": serviceAccountStorage, "persistentVolumes": persistentVolumeStorage, "persistentVolumes/status": persistentVolumeStatusStorage, "persistentVolumeClaims": persistentVolumeClaimStorage, "persistentVolumeClaims/status": persistentVolumeClaimStatusStorage, "componentStatuses": componentstatus.NewStorage(func() map[string]apiserver.Server { return m.getServersToValidate(c) }), } // establish the node proxy dialer if len(c.SSHUser) > 0 { // Usernames are capped @ 32 if len(c.SSHUser) > 32 { glog.Warning("SSH User is too long, truncating to 32 chars") c.SSHUser = c.SSHUser[0:32] } glog.Infof("Setting up proxy: %s %s", c.SSHUser, c.SSHKeyfile) // public keyfile is written last, so check for that. publicKeyFile := c.SSHKeyfile + ".pub" exists, err := util.FileExists(publicKeyFile) if err != nil { glog.Errorf("Error detecting if key exists: %v", err) } else if !exists { glog.Infof("Key doesn't exist, attempting to create") err := m.generateSSHKey(c.SSHUser, c.SSHKeyfile, publicKeyFile) if err != nil { glog.Errorf("Failed to create key pair: %v", err) } } m.tunnels = &util.SSHTunnelList{} m.dialer = m.Dial m.setupSecureProxy(c.SSHUser, c.SSHKeyfile, publicKeyFile) m.lastSync = m.clock.Now().Unix() // This is pretty ugly. A better solution would be to pull this all the way up into the // server.go file. httpKubeletClient, ok := c.KubeletClient.(*client.HTTPKubeletClient) if ok { httpKubeletClient.Config.Dial = m.dialer transport, err := client.MakeTransport(httpKubeletClient.Config) if err != nil { glog.Errorf("Error setting up transport over SSH: %v", err) } else { httpKubeletClient.Client.Transport = transport } } else { glog.Errorf("Failed to cast %v to HTTPKubeletClient, skipping SSH tunnel.") } healthzChecks = append(healthzChecks, healthz.NamedCheck("SSH Tunnel Check", m.IsTunnelSyncHealthy)) m.lastSyncMetric = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ Name: "apiserver_proxy_tunnel_sync_latency_secs", Help: "The time since the last successful synchronization of the SSH tunnels for proxy requests.", }, func() float64 { return float64(m.secondsSinceSync()) }) } apiVersions := []string{} if m.v1 { if err := m.api_v1().InstallREST(m.handlerContainer); err != nil { glog.Fatalf("Unable to setup API v1: %v", err) } apiVersions = append(apiVersions, "v1") } apiserver.InstallSupport(m.muxHelper, m.rootWebService, c.EnableProfiling, healthzChecks...) apiserver.AddApiWebService(m.handlerContainer, c.APIPrefix, apiVersions) defaultVersion := m.defaultAPIGroupVersion() requestInfoResolver := &apiserver.APIRequestInfoResolver{util.NewStringSet(strings.TrimPrefix(defaultVersion.Root, "/")), defaultVersion.Mapper} apiserver.InstallServiceErrorHandler(m.handlerContainer, requestInfoResolver, apiVersions) // Register root handler. // We do not register this using restful Webservice since we do not want to surface this in api docs. // Allow master to be embedded in contexts which already have something registered at the root if c.EnableIndex { m.mux.HandleFunc("/", apiserver.IndexHandler(m.handlerContainer, m.muxHelper)) } if c.EnableLogsSupport { apiserver.InstallLogsSupport(m.muxHelper) } if c.EnableUISupport { ui.InstallSupport(m.muxHelper, m.enableSwaggerSupport) } if c.EnableProfiling { m.mux.HandleFunc("/debug/pprof/", pprof.Index) m.mux.HandleFunc("/debug/pprof/profile", pprof.Profile) m.mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) } handler := http.Handler(m.mux.(*http.ServeMux)) // TODO: handle CORS and auth using go-restful // See github.com/emicklei/go-restful/blob/master/examples/restful-CORS-filter.go, and // github.com/emicklei/go-restful/blob/master/examples/restful-basic-authentication.go if len(c.CorsAllowedOriginList) > 0 { allowedOriginRegexps, err := util.CompileRegexps(c.CorsAllowedOriginList) if err != nil { glog.Fatalf("Invalid CORS allowed origin, --cors_allowed_origins flag was set to %v - %v", strings.Join(c.CorsAllowedOriginList, ","), err) } handler = apiserver.CORS(handler, allowedOriginRegexps, nil, nil, "true") } m.InsecureHandler = handler attributeGetter := apiserver.NewRequestAttributeGetter(m.requestContextMapper, latest.RESTMapper, "api") handler = apiserver.WithAuthorizationCheck(handler, attributeGetter, m.authorizer) // Install Authenticator if c.Authenticator != nil { authenticatedHandler, err := handlers.NewRequestAuthenticator(m.requestContextMapper, c.Authenticator, handlers.Unauthorized(c.SupportsBasicAuth), handler) if err != nil { glog.Fatalf("Could not initialize authenticator: %v", err) } handler = authenticatedHandler } // Install root web services m.handlerContainer.Add(m.rootWebService) // TODO: Make this optional? Consumers of master depend on this currently. m.Handler = handler if m.enableSwaggerSupport { m.InstallSwaggerAPI() } // After all wrapping is done, put a context filter around both handlers if handler, err := api.NewRequestContextFilter(m.requestContextMapper, m.Handler); err != nil { glog.Fatalf("Could not initialize request context filter: %v", err) } else { m.Handler = handler } if handler, err := api.NewRequestContextFilter(m.requestContextMapper, m.InsecureHandler); err != nil { glog.Fatalf("Could not initialize request context filter: %v", err) } else { m.InsecureHandler = handler } // TODO: Attempt clean shutdown? if m.enableCoreControllers { m.NewBootstrapController().Start() } }
// init initializes master. func (m *Master) init(c *Config) { var userContexts = handlers.NewUserRequestContext() var authenticator = c.Authenticator nodeRESTStorage := minion.NewREST(m.minionRegistry) podCache := NewPodCache( m.nodeIPCache, c.KubeletClient, RESTStorageToNodes(nodeRESTStorage).Nodes(), m.podRegistry, ) go util.Forever(func() { podCache.UpdateAllContainers() }, time.Second*30) // TODO: Factor out the core API registration m.storage = map[string]apiserver.RESTStorage{ "pods": pod.NewREST(&pod.RESTConfig{ PodCache: podCache, Registry: m.podRegistry, }), "replicationControllers": controller.NewREST(m.controllerRegistry, m.podRegistry), "services": service.NewREST(m.serviceRegistry, c.Cloud, m.minionRegistry, m.portalNet), "endpoints": endpoint.NewREST(m.endpointRegistry), "minions": nodeRESTStorage, "nodes": nodeRESTStorage, "events": event.NewREST(m.eventRegistry), // TODO: should appear only in scheduler API group. "bindings": binding.NewREST(m.bindingRegistry), } apiVersions := []string{"v1beta1", "v1beta2"} if err := apiserver.NewAPIGroupVersion(m.api_v1beta1()).InstallREST(m.handlerContainer, c.APIPrefix, "v1beta1"); err != nil { glog.Fatalf("Unable to setup API v1beta1: %v", err) } if err := apiserver.NewAPIGroupVersion(m.api_v1beta2()).InstallREST(m.handlerContainer, c.APIPrefix, "v1beta2"); err != nil { glog.Fatalf("Unable to setup API v1beta2: %v", err) } if c.EnableV1Beta3 { if err := apiserver.NewAPIGroupVersion(m.api_v1beta3()).InstallREST(m.handlerContainer, c.APIPrefix, "v1beta3"); err != nil { glog.Fatalf("Unable to setup API v1beta3: %v", err) } apiVersions = []string{"v1beta1", "v1beta2", "v1beta3"} } apiserver.InstallSupport(m.handlerContainer, m.rootWebService) apiserver.AddApiWebService(m.handlerContainer, c.APIPrefix, apiVersions) // Register root handler. // We do not register this using restful Webservice since we do not want to surface this in api docs. m.mux.HandleFunc("/", apiserver.HandleIndex) // TODO: use go-restful apiserver.InstallValidator(m.mux, func() map[string]apiserver.Server { return m.getServersToValidate(c) }) if c.EnableLogsSupport { apiserver.InstallLogsSupport(m.mux) } if c.EnableUISupport { ui.InstallSupport(m.mux, m.enableSwaggerSupport) } // TODO: install runtime/pprof handler // See github.com/emicklei/go-restful/blob/master/examples/restful-cpuprofiler-service.go handler := http.Handler(m.mux.(*http.ServeMux)) // TODO: handle CORS and auth using go-restful // See github.com/emicklei/go-restful/blob/master/examples/restful-CORS-filter.go, and // github.com/emicklei/go-restful/blob/master/examples/restful-basic-authentication.go if len(c.CorsAllowedOriginList) > 0 { allowedOriginRegexps, err := util.CompileRegexps(c.CorsAllowedOriginList) if err != nil { glog.Fatalf("Invalid CORS allowed origin, --cors_allowed_origins flag was set to %v - %v", strings.Join(c.CorsAllowedOriginList, ","), err) } handler = apiserver.CORS(handler, allowedOriginRegexps, nil, nil, "true") } m.InsecureHandler = handler attributeGetter := apiserver.NewRequestAttributeGetter(userContexts) handler = apiserver.WithAuthorizationCheck(handler, attributeGetter, m.authorizer) // Install Authenticator if authenticator != nil { handler = handlers.NewRequestAuthenticator(userContexts, authenticator, handlers.Unauthorized, handler) } // Install root web services m.handlerContainer.Add(m.rootWebService) // 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() }
// init initializes master. func (m *Master) init(c *Config) { // TODO: make initialization of the helper part of the Master, and allow some storage // objects to have a newer storage version than the user's default. newerHelper, err := NewEtcdHelper(c.EtcdHelper.Client, "v1beta3", DefaultEtcdPathPrefix) if err != nil { glog.Fatalf("Unable to setup storage for v1beta3: %v", err) } podStorage := podetcd.NewStorage(c.EtcdHelper, c.KubeletClient) podRegistry := pod.NewRegistry(podStorage.Pod) podTemplateStorage := podtemplateetcd.NewREST(newerHelper) eventRegistry := event.NewEtcdRegistry(c.EtcdHelper, uint64(c.EventTTL.Seconds())) limitRangeRegistry := limitrange.NewEtcdRegistry(c.EtcdHelper) resourceQuotaStorage, resourceQuotaStatusStorage := resourcequotaetcd.NewStorage(c.EtcdHelper) secretStorage := secretetcd.NewStorage(c.EtcdHelper) serviceAccountStorage := serviceaccountetcd.NewStorage(c.EtcdHelper) persistentVolumeStorage, persistentVolumeStatusStorage := pvetcd.NewStorage(c.EtcdHelper) persistentVolumeClaimStorage, persistentVolumeClaimStatusStorage := pvcetcd.NewStorage(c.EtcdHelper) securityContextConstraintsStorage := sccetcd.NewStorage(c.EtcdHelper) namespaceStorage, namespaceStatusStorage, namespaceFinalizeStorage := namespaceetcd.NewStorage(c.EtcdHelper) m.namespaceRegistry = namespace.NewRegistry(namespaceStorage) endpointsStorage := endpointsetcd.NewStorage(c.EtcdHelper) m.endpointRegistry = endpoint.NewRegistry(endpointsStorage) nodeStorage, nodeStatusStorage := nodeetcd.NewStorage(c.EtcdHelper, c.KubeletClient) m.nodeRegistry = minion.NewRegistry(nodeStorage) // TODO: split me up into distinct storage registries registry := etcd.NewRegistry(c.EtcdHelper, podRegistry, m.endpointRegistry) m.serviceRegistry = registry var portalRangeRegistry service.RangeRegistry portalAllocator := ipallocator.NewAllocatorCIDRRange(m.portalNet, func(max int, rangeSpec string) allocator.Interface { mem := allocator.NewAllocationMap(max, rangeSpec) etcd := etcdallocator.NewEtcd(mem, "/ranges/serviceips", "serviceipallocation", c.EtcdHelper) portalRangeRegistry = etcd return etcd }) m.portalAllocator = portalRangeRegistry var serviceNodePortRegistry service.RangeRegistry serviceNodePortAllocator := portallocator.NewPortAllocatorCustom(m.serviceNodePorts, func(max int, rangeSpec string) allocator.Interface { mem := allocator.NewAllocationMap(max, rangeSpec) etcd := etcdallocator.NewEtcd(mem, "/ranges/servicenodeports", "servicenodeportallocation", c.EtcdHelper) serviceNodePortRegistry = etcd return etcd }) m.serviceNodePortAllocator = serviceNodePortRegistry controllerStorage := controlleretcd.NewREST(c.EtcdHelper) // TODO: Factor out the core API registration m.storage = map[string]rest.Storage{ "pods": podStorage.Pod, "pods/status": podStorage.Status, "pods/log": podStorage.Log, "pods/exec": podStorage.Exec, "pods/portforward": podStorage.PortForward, "pods/proxy": podStorage.Proxy, "pods/binding": podStorage.Binding, "bindings": podStorage.Binding, "podTemplates": podTemplateStorage, "replicationControllers": controllerStorage, "services": service.NewStorage(m.serviceRegistry, m.nodeRegistry, m.endpointRegistry, portalAllocator, serviceNodePortAllocator, c.ClusterName), "endpoints": endpointsStorage, "minions": nodeStorage, "minions/status": nodeStatusStorage, "nodes": nodeStorage, "nodes/status": nodeStatusStorage, "events": event.NewStorage(eventRegistry), "limitRanges": limitrange.NewStorage(limitRangeRegistry), "resourceQuotas": resourceQuotaStorage, "resourceQuotas/status": resourceQuotaStatusStorage, "namespaces": namespaceStorage, "namespaces/status": namespaceStatusStorage, "namespaces/finalize": namespaceFinalizeStorage, "secrets": secretStorage, "serviceAccounts": serviceAccountStorage, "securityContextConstraints": securityContextConstraintsStorage, "persistentVolumes": persistentVolumeStorage, "persistentVolumes/status": persistentVolumeStatusStorage, "persistentVolumeClaims": persistentVolumeClaimStorage, "persistentVolumeClaims/status": persistentVolumeClaimStatusStorage, "componentStatuses": componentstatus.NewStorage(func() map[string]apiserver.Server { return m.getServersToValidate(c, false) }), } apiVersions := []string{} if m.v1beta1 { if err := m.api_v1beta1().InstallREST(m.handlerContainer); err != nil { glog.Fatalf("Unable to setup API v1beta1: %v", err) } apiVersions = append(apiVersions, "v1beta1") } if m.v1beta2 { if err := m.api_v1beta2().InstallREST(m.handlerContainer); err != nil { glog.Fatalf("Unable to setup API v1beta2: %v", err) } apiVersions = append(apiVersions, "v1beta2") } if m.v1beta3 { if err := m.api_v1beta3().InstallREST(m.handlerContainer); err != nil { glog.Fatalf("Unable to setup API v1beta3: %v", err) } apiVersions = append(apiVersions, "v1beta3") } if m.v1 { if err := m.api_v1().InstallREST(m.handlerContainer); err != nil { glog.Fatalf("Unable to setup API v1: %v", err) } apiVersions = append(apiVersions, "v1") } apiserver.InstallSupport(m.muxHelper, m.rootWebService) apiserver.AddApiWebService(m.handlerContainer, c.APIPrefix, apiVersions) defaultVersion := m.defaultAPIGroupVersion() requestInfoResolver := &apiserver.APIRequestInfoResolver{util.NewStringSet(strings.TrimPrefix(defaultVersion.Root, "/")), defaultVersion.Mapper} apiserver.InstallServiceErrorHandler(m.handlerContainer, requestInfoResolver, apiVersions) // Register root handler. // We do not register this using restful Webservice since we do not want to surface this in api docs. // Allow master to be embedded in contexts which already have something registered at the root if c.EnableIndex { m.mux.HandleFunc("/", apiserver.IndexHandler(m.handlerContainer, m.muxHelper)) } // TODO: This is now deprecated. Should be removed once client dependencies are gone. apiserver.InstallValidator(m.muxHelper, func() map[string]apiserver.Server { return m.getServersToValidate(c, true) }) if c.EnableLogsSupport { apiserver.InstallLogsSupport(m.muxHelper) } if c.EnableUISupport { ui.InstallSupport(m.muxHelper, m.enableSwaggerSupport) } if c.EnableProfiling { m.mux.HandleFunc("/debug/pprof/", pprof.Index) m.mux.HandleFunc("/debug/pprof/profile", pprof.Profile) m.mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) } handler := http.Handler(m.mux.(*http.ServeMux)) // TODO: handle CORS and auth using go-restful // See github.com/emicklei/go-restful/blob/master/examples/restful-CORS-filter.go, and // github.com/emicklei/go-restful/blob/master/examples/restful-basic-authentication.go if len(c.CorsAllowedOriginList) > 0 { allowedOriginRegexps, err := util.CompileRegexps(c.CorsAllowedOriginList) if err != nil { glog.Fatalf("Invalid CORS allowed origin, --cors_allowed_origins flag was set to %v - %v", strings.Join(c.CorsAllowedOriginList, ","), err) } handler = apiserver.CORS(handler, allowedOriginRegexps, nil, nil, "true") } m.InsecureHandler = handler attributeGetter := apiserver.NewRequestAttributeGetter(m.requestContextMapper, latest.RESTMapper, "api") handler = apiserver.WithAuthorizationCheck(handler, attributeGetter, m.authorizer) // Install Authenticator if c.Authenticator != nil { authenticatedHandler, err := handlers.NewRequestAuthenticator(m.requestContextMapper, c.Authenticator, handlers.Unauthorized(c.SupportsBasicAuth), handler) if err != nil { glog.Fatalf("Could not initialize authenticator: %v", err) } handler = authenticatedHandler } // Install root web services m.handlerContainer.Add(m.rootWebService) // TODO: Make this optional? Consumers of master depend on this currently. m.Handler = handler if m.enableSwaggerSupport { m.InstallSwaggerAPI() } // After all wrapping is done, put a context filter around both handlers if handler, err := api.NewRequestContextFilter(m.requestContextMapper, m.Handler); err != nil { glog.Fatalf("Could not initialize request context filter: %v", err) } else { m.Handler = handler } if handler, err := api.NewRequestContextFilter(m.requestContextMapper, m.InsecureHandler); err != nil { glog.Fatalf("Could not initialize request context filter: %v", err) } else { m.InsecureHandler = handler } // TODO: Attempt clean shutdown? if m.enableCoreControllers { m.NewBootstrapController().Start() } }
func TestBuildConfigClient(t *testing.T) { etcdClient := newEtcdClient() m := master.New(&master.Config{ EtcdServers: etcdClient.GetCluster(), }) osMux := http.NewServeMux() storage := map[string]apiserver.RESTStorage{ "builds": buildregistry.NewStorage(build.NewEtcdRegistry(etcdClient)), "buildConfigs": buildconfigregistry.NewStorage(build.NewEtcdRegistry(etcdClient)), } apiserver.NewAPIGroup(m.API_v1beta1()).InstallREST(osMux, "/api/v1beta1") apiserver.NewAPIGroup(storage, runtime.Codec).InstallREST(osMux, "/osapi/v1beta1") apiserver.InstallSupport(osMux) s := httptest.NewServer(osMux) kubeclient := client.NewOrDie(s.URL, nil) osclient, _ := osclient.New(s.URL, nil) info, err := kubeclient.ServerVersion() if err != nil { t.Fatalf("unexpected error: %v", err) } if e, a := version.Get(), *info; !reflect.DeepEqual(e, a) { t.Errorf("expected %#v, got %#v", e, a) } buildConfigs, err := osclient.ListBuildConfigs(labels.Everything()) if err != nil { t.Fatalf("unexpected error %v", err) } if len(buildConfigs.Items) != 0 { t.Errorf("expected no buildConfigs, got %#v", buildConfigs) } // get a validation error buildConfig := &api.BuildConfig{ Labels: map[string]string{ "label1": "value1", "label2": "value2", }, DesiredInput: api.BuildInput{ Type: api.DockerBuildType, SourceURI: "http://my.docker/build", ImageTag: "namespace/builtimage", BuilderImage: "anImage", }, } got, err := osclient.CreateBuildConfig(buildConfig) if err == nil { t.Fatalf("unexpected non-error: %v", err) } // get a created buildConfig buildConfig.DesiredInput.BuilderImage = "" got, err = osclient.CreateBuildConfig(buildConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } if got.ID == "" { t.Errorf("unexpected empty buildConfig ID %v", got) } // get a list of buildConfigs buildConfigs, err = osclient.ListBuildConfigs(labels.Everything()) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(buildConfigs.Items) != 1 { t.Errorf("expected one buildConfig, got %#v", buildConfigs) } actual := buildConfigs.Items[0] if actual.ID != got.ID { t.Errorf("expected buildConfig %#v, got %#v", got, actual) } // delete a buildConfig err = osclient.DeleteBuildConfig(got.ID) if err != nil { t.Fatalf("unexpected error %v", err) } buildConfigs, err = osclient.ListBuildConfigs(labels.Everything()) if err != nil { t.Fatalf("unexpected error %v", err) } if len(buildConfigs.Items) != 0 { t.Errorf("expected no buildConfigs, got %#v", buildConfigs) } }
// init initializes master. func (m *Master) init(c *Config) { podCache := NewPodCache(c.KubeletClient, m.podRegistry) go util.Forever(func() { podCache.UpdateAllContainers() }, time.Second*30) var userContexts = handlers.NewUserRequestContext() var authenticator authenticator.Request if len(c.TokenAuthFile) != 0 { tokenAuthenticator, err := tokenfile.New(c.TokenAuthFile) if err != nil { glog.Fatalf("Unable to load the token authentication file '%s': %v", c.TokenAuthFile, err) } authenticator = bearertoken.New(tokenAuthenticator) } m.storage = map[string]apiserver.RESTStorage{ "pods": pod.NewREST(&pod.RESTConfig{ CloudProvider: c.Cloud, PodCache: podCache, PodInfoGetter: c.KubeletClient, Registry: m.podRegistry, Minions: m.client.Minions(), }), "replicationControllers": controller.NewREST(m.controllerRegistry, m.podRegistry), "services": service.NewREST(m.serviceRegistry, c.Cloud, m.minionRegistry, m.portalNet), "endpoints": endpoint.NewREST(m.endpointRegistry), "minions": minion.NewREST(m.minionRegistry), "events": event.NewREST(m.eventRegistry), // TODO: should appear only in scheduler API group. "bindings": binding.NewREST(m.bindingRegistry), } apiserver.NewAPIGroup(m.API_v1beta1()).InstallREST(m.mux, c.APIPrefix+"/v1beta1") apiserver.NewAPIGroup(m.API_v1beta2()).InstallREST(m.mux, c.APIPrefix+"/v1beta2") versionHandler := apiserver.APIVersionHandler("v1beta1", "v1beta2") m.mux.Handle(c.APIPrefix, versionHandler) apiserver.InstallSupport(m.mux) serversToValidate := m.getServersToValidate(c) apiserver.InstallValidator(m.mux, serversToValidate) if c.EnableLogsSupport { apiserver.InstallLogsSupport(m.mux) } if c.EnableUISupport { ui.InstallSupport(m.mux) } handler := http.Handler(m.mux.(*http.ServeMux)) if len(c.CorsAllowedOriginList) > 0 { allowedOriginRegexps, err := util.CompileRegexps(c.CorsAllowedOriginList) if err != nil { glog.Fatalf("Invalid CORS allowed origin, --cors_allowed_origins flag was set to %v - %v", strings.Join(c.CorsAllowedOriginList, ","), err) } handler = apiserver.CORS(handler, allowedOriginRegexps, nil, nil, "true") } m.InsecureHandler = handler attributeGetter := apiserver.NewRequestAttributeGetter(userContexts) handler = apiserver.WithAuthorizationCheck(handler, attributeGetter, m.authorizer) // Install Authenticator if authenticator != nil { handler = handlers.NewRequestAuthenticator(userContexts, authenticator, handlers.Unauthorized, handler) } m.mux.HandleFunc("/_whoami", handleWhoAmI(authenticator)) m.Handler = handler // TODO: Attempt clean shutdown? m.masterServices.Start() }
// init initializes master. func (m *Master) init(c *Config) { var userContexts = handlers.NewUserRequestContext() var authenticator = c.Authenticator ipCache := NewIPCache(c.Cloud, util.RealClock{}, 30*time.Second) podCache := NewPodCache( ipCache, c.KubeletClient, m.client.Minions(), m.podRegistry, ) go util.Forever(func() { podCache.UpdateAllContainers() }, time.Second*30) // TODO: Factor out the core API registration m.storage = map[string]apiserver.RESTStorage{ "pods": pod.NewREST(&pod.RESTConfig{ PodCache: podCache, Registry: m.podRegistry, }), "replicationControllers": controller.NewREST(m.controllerRegistry, m.podRegistry), "services": service.NewREST(m.serviceRegistry, c.Cloud, m.minionRegistry, m.portalNet), "endpoints": endpoint.NewREST(m.endpointRegistry), "minions": minion.NewREST(m.minionRegistry), "events": event.NewREST(m.eventRegistry), // TODO: should appear only in scheduler API group. "bindings": binding.NewREST(m.bindingRegistry), } apiserver.NewAPIGroupVersion(m.API_v1beta1()).InstallREST(m.handlerContainer, c.APIPrefix, "v1beta1") apiserver.NewAPIGroupVersion(m.API_v1beta2()).InstallREST(m.handlerContainer, c.APIPrefix, "v1beta2") // TODO: InstallREST should register each version automatically versionHandler := apiserver.APIVersionHandler("v1beta1", "v1beta2") m.rootWebService.Route(m.rootWebService.GET(c.APIPrefix).To(versionHandler)) apiserver.InstallSupport(m.handlerContainer, m.rootWebService) // TODO: use go-restful serversToValidate := m.getServersToValidate(c) apiserver.InstallValidator(m.mux, serversToValidate) if c.EnableLogsSupport { apiserver.InstallLogsSupport(m.mux) } if c.EnableUISupport { ui.InstallSupport(m.mux) } // TODO: install runtime/pprof handler // See github.com/emicklei/go-restful/blob/master/examples/restful-cpuprofiler-service.go handler := http.Handler(m.mux.(*http.ServeMux)) // TODO: handle CORS and auth using go-restful // See github.com/emicklei/go-restful/blob/master/examples/restful-CORS-filter.go, and // github.com/emicklei/go-restful/blob/master/examples/restful-basic-authentication.go if len(c.CorsAllowedOriginList) > 0 { allowedOriginRegexps, err := util.CompileRegexps(c.CorsAllowedOriginList) if err != nil { glog.Fatalf("Invalid CORS allowed origin, --cors_allowed_origins flag was set to %v - %v", strings.Join(c.CorsAllowedOriginList, ","), err) } handler = apiserver.CORS(handler, allowedOriginRegexps, nil, nil, "true") } m.InsecureHandler = handler attributeGetter := apiserver.NewRequestAttributeGetter(userContexts) handler = apiserver.WithAuthorizationCheck(handler, attributeGetter, m.authorizer) // Install Authenticator if authenticator != nil { handler = handlers.NewRequestAuthenticator(userContexts, authenticator, handlers.Unauthorized, handler) } // TODO: Remove temporary _whoami handler m.rootWebService.Route(m.rootWebService.GET("/_whoami").To(handleWhoAmI(authenticator))) // Install root web services m.handlerContainer.Add(m.rootWebService) // TODO: Make this optional? // Enable swagger UI and discovery API swaggerConfig := swagger.Config{ WebServices: m.handlerContainer.RegisteredWebServices(), // TODO: Parameterize the path? ApiPath: "/swaggerapi/", // TODO: Distribute UI javascript and enable the UI //SwaggerPath: "/swaggerui/", //SwaggerFilePath: "/srv/apiserver/swagger/dist" } swagger.RegisterSwaggerService(swaggerConfig, m.handlerContainer) m.Handler = handler // TODO: Attempt clean shutdown? m.masterServices.Start() }
func (c *config) startAllInOne() { minionHost := "127.0.0.1" minionPort := 10250 rootDirectory := path.Clean("/var/lib/openshift") osAddr := c.ListenAddr osPrefix := "/osapi/v1beta1" kubePrefix := "/api/v1beta1" kubeClient, err := kubeclient.New("http://"+osAddr, nil) if err != nil { glog.Fatalf("Unable to configure client - bad URL: %v", err) } osClient, err := osclient.New("http://"+osAddr, nil) if err != nil { glog.Fatalf("Unable to configure client - bad URL: %v", err) } etcdAddr := "127.0.0.1:4001" etcdServers := []string{} // default etcdConfig := etcdconfig.New() etcdConfig.BindAddr = etcdAddr etcdConfig.DataDir = "openshift.local.etcd" etcdConfig.Name = "openshift.local" // check docker connection dockerClient, dockerAddr := c.Docker.GetClientOrExit() if err := dockerClient.Ping(); err != nil { glog.Errorf("WARNING: Docker could not be reached at %s. Docker must be installed and running to start containers.\n%v", dockerAddr, err) } else { glog.Infof("Connecting to Docker at %s", dockerAddr) } cadvisorClient, err := cadvisor.NewClient("http://127.0.0.1:4194") if err != nil { glog.Errorf("Error on creating cadvisor client: %v", err) } // initialize etcd etcdServer := etcd.New(etcdConfig) go util.Forever(func() { glog.Infof("Started etcd at http://%s", etcdAddr) etcdServer.Run() }, 0) etcdClient := etcdclient.NewClient(etcdServers) for i := 0; ; i += 1 { _, err := etcdClient.Get("/", false, false) if err == nil || tools.IsEtcdNotFound(err) { break } if i > 100 { glog.Fatal("Could not reach etcd: %v", err) } time.Sleep(50 * time.Millisecond) } // initialize Kubelet os.MkdirAll(rootDirectory, 0750) cfg := kconfig.NewPodConfig(kconfig.PodConfigNotificationSnapshotAndUpdates) kconfig.NewSourceEtcd(kconfig.EtcdKeyForHost(minionHost), etcdClient, cfg.Channel("etcd")) k := kubelet.NewMainKubelet( minionHost, dockerClient, cadvisorClient, etcdClient, rootDirectory, 30*time.Second) go util.Forever(func() { k.Run(cfg.Updates()) }, 0) go util.Forever(func() { kubelet.ListenAndServeKubeletServer(k, cfg.Channel("http"), minionHost, uint(minionPort)) }, 0) imageRegistry := image.NewEtcdRegistry(etcdClient) // initialize OpenShift API storage := map[string]apiserver.RESTStorage{ "builds": buildregistry.NewStorage(build.NewEtcdRegistry(etcdClient)), "buildConfigs": buildconfigregistry.NewStorage(build.NewEtcdRegistry(etcdClient)), "images": image.NewImageStorage(imageRegistry), "imageRepositories": image.NewImageRepositoryStorage(imageRegistry), "imageRepositoryMappings": image.NewImageRepositoryMappingStorage(imageRegistry, imageRegistry), "templateConfigs": template.NewStorage(), } osMux := http.NewServeMux() // initialize Kubernetes API podInfoGetter := &kubeclient.HTTPPodInfoGetter{ Client: http.DefaultClient, Port: uint(minionPort), } masterConfig := &master.Config{ Client: kubeClient, EtcdServers: etcdServers, HealthCheckMinions: true, Minions: []string{minionHost}, PodInfoGetter: podInfoGetter, } m := master.New(masterConfig) apiserver.NewAPIGroup(m.API_v1beta1()).InstallREST(osMux, kubePrefix) apiserver.NewAPIGroup(storage, runtime.Codec).InstallREST(osMux, osPrefix) apiserver.InstallSupport(osMux) osApi := &http.Server{ Addr: osAddr, Handler: apiserver.RecoverPanics(osMux), ReadTimeout: 5 * time.Minute, WriteTimeout: 5 * time.Minute, MaxHeaderBytes: 1 << 20, } go util.Forever(func() { glog.Infof("Started Kubernetes API at http://%s%s", osAddr, kubePrefix) glog.Infof("Started OpenShift API at http://%s%s", osAddr, osPrefix) glog.Fatal(osApi.ListenAndServe()) }, 0) // initialize kube proxy serviceConfig := pconfig.NewServiceConfig() endpointsConfig := pconfig.NewEndpointsConfig() pconfig.NewConfigSourceEtcd(etcdClient, serviceConfig.Channel("etcd"), endpointsConfig.Channel("etcd")) loadBalancer := proxy.NewLoadBalancerRR() proxier := proxy.NewProxier(loadBalancer) serviceConfig.RegisterHandler(proxier) endpointsConfig.RegisterHandler(loadBalancer) glog.Infof("Started Kubernetes Proxy") // initialize replication manager controllerManager := controller.NewReplicationManager(kubeClient) controllerManager.Run(10 * time.Second) glog.Infof("Started Kubernetes Replication Manager") // initialize scheduler configFactory := &factory.ConfigFactory{Client: kubeClient} config := configFactory.Create() s := scheduler.New(config) s.Run() glog.Infof("Started Kubernetes Scheduler") // initialize build controller dockerBuilderImage := env("OPENSHIFT_DOCKER_BUILDER_IMAGE", "openshift/docker-builder") useHostDockerSocket := len(env("USE_HOST_DOCKER_SOCKET", "")) > 0 stiBuilderImage := env("OPENSHIFT_STI_BUILDER_IMAGE", "openshift/sti-builder") dockerRegistry := env("DOCKER_REGISTRY", "") buildStrategies := map[buildapi.BuildType]build.BuildJobStrategy{ buildapi.DockerBuildType: strategy.NewDockerBuildStrategy(dockerBuilderImage, useHostDockerSocket), buildapi.STIBuildType: strategy.NewSTIBuildStrategy(stiBuilderImage, useHostDockerSocket), } buildController := build.NewBuildController(kubeClient, osClient, buildStrategies, dockerRegistry, 1200) buildController.Run(10 * time.Second) select {} }
func TestWebhookGithubPush(t *testing.T) { etcdClient := newEtcdClient() m := master.New(&master.Config{ EtcdServers: etcdClient.GetCluster(), }) osMux := http.NewServeMux() storage := map[string]apiserver.RESTStorage{ "builds": buildregistry.NewStorage(build.NewEtcdRegistry(etcdClient)), "buildConfigs": buildconfigregistry.NewStorage(build.NewEtcdRegistry(etcdClient)), } apiserver.NewAPIGroup(m.API_v1beta1()).InstallREST(osMux, "/api/v1beta1") osPrefix := "/osapi/v1beta1" apiserver.NewAPIGroup(storage, runtime.Codec).InstallREST(osMux, osPrefix) apiserver.InstallSupport(osMux) s := httptest.NewServer(osMux) kubeclient := client.NewOrDie(s.URL, nil) osClient, _ := osclient.New(s.URL, nil) whPrefix := osPrefix + "/buildConfigHooks/" osMux.Handle(whPrefix, http.StripPrefix(whPrefix, webhook.NewController(osClient, map[string]webhook.Plugin{ "github": github.New(), }))) info, err := kubeclient.ServerVersion() if err != nil { t.Fatalf("Unexpected error: %v", err) } if e, a := version.Get(), *info; !reflect.DeepEqual(e, a) { t.Errorf("Expected %#v, got %#v", e, a) } // create buildconfig buildConfig := &buildapi.BuildConfig{ JSONBase: kubeapi.JSONBase{ ID: "build100", }, DesiredInput: buildapi.BuildInput{ Type: buildapi.DockerBuildType, SourceURI: "http://my.docker/build", ImageTag: "namespace/builtimage", }, Secret: "secret101", } if _, err := osClient.CreateBuildConfig(buildConfig); err != nil { t.Fatalf("Unexpected error: %v", err) } // trigger build event sending push notification client := &http.Client{} data, err := ioutil.ReadFile("../../pkg/build/webhook/github/fixtures/pushevent.json") if err != nil { t.Fatalf("Failed to open pushevent.json: %v", err) } req, err := http.NewRequest("POST", s.URL+whPrefix+"build100/secret101/github", bytes.NewReader(data)) if err != nil { t.Fatalf("Error creating POST request: %v", err) } req.Header.Add("Content-Type", "application/json") req.Header.Add("User-Agent", "GitHub-Hookshot/github") req.Header.Add("X-Github-Event", "push") resp, err := client.Do(req) if err != nil { t.Fatalf("Failed posting webhook: %v", err) } body, _ := ioutil.ReadAll(resp.Body) if resp.StatusCode != http.StatusOK { t.Errorf("Wrong response code, expecting 200, got %s: %s!", resp.Status, string(body)) } // get a list of builds builds, err := osClient.ListBuilds(labels.Everything()) if err != nil { t.Fatalf("Unexpected error: %v", err) } if len(builds.Items) != 1 { t.Fatalf("Expected one build, got %#v", builds) } actual := builds.Items[0] if actual.Status != buildapi.BuildNew { t.Errorf("Expected %s, got %s", buildapi.BuildNew, actual.Status) } if !reflect.DeepEqual(actual.Input, buildConfig.DesiredInput) { t.Errorf("Expected %#v, got %#v", buildConfig.DesiredInput, actual.Input) } }
func (c *config) runApiserver() { minionPort := 10250 osAddr := c.ListenAddr kubePrefix := "/api/v1beta1" osPrefix := "/osapi/v1beta1" kubeClient := c.getKubeClient() osClient := c.getOsClient() etcdClient, etcdServers := c.getEtcdClient() imageRegistry := imageetcd.NewEtcd(etcdClient) // initialize OpenShift API storage := map[string]apiserver.RESTStorage{ "builds": buildregistry.NewStorage(build.NewEtcdRegistry(etcdClient)), "buildConfigs": buildconfigregistry.NewStorage(build.NewEtcdRegistry(etcdClient)), "images": image.NewREST(imageRegistry), "imageRepositories": imagerepository.NewREST(imageRegistry), "imageRepositoryMappings": imagerepositorymapping.NewREST(imageRegistry, imageRegistry), "templateConfigs": template.NewStorage(), } osMux := http.NewServeMux() // initialize webhooks whPrefix := osPrefix + "/buildConfigHooks/" osMux.Handle(whPrefix, http.StripPrefix(whPrefix, webhook.NewController(osClient, map[string]webhook.Plugin{ "github": github.New(), }))) // initialize Kubernetes API podInfoGetter := &kubeclient.HTTPPodInfoGetter{ Client: http.DefaultClient, Port: uint(minionPort), } masterConfig := &master.Config{ Client: kubeClient, EtcdServers: etcdServers, HealthCheckMinions: true, Minions: c.nodeHosts, PodInfoGetter: podInfoGetter, } m := master.New(masterConfig) apiserver.NewAPIGroup(m.API_v1beta1()).InstallREST(osMux, kubePrefix) apiserver.NewAPIGroup(storage, runtime.Codec).InstallREST(osMux, osPrefix) apiserver.InstallSupport(osMux) osApi := &http.Server{ Addr: osAddr, Handler: apiserver.RecoverPanics(osMux), ReadTimeout: 5 * time.Minute, WriteTimeout: 5 * time.Minute, MaxHeaderBytes: 1 << 20, } go util.Forever(func() { glog.Infof("Started Kubernetes API at http://%s%s", osAddr, kubePrefix) glog.Infof("Started OpenShift API at http://%s%s", osAddr, osPrefix) glog.Fatal(osApi.ListenAndServe()) }, 0) }
// init initializes master. func (m *Master) init(c *Config) { podStorage, bindingStorage, podStatusStorage := podetcd.NewREST(c.EtcdHelper) podRegistry := pod.NewRegistry(podStorage) eventRegistry := event.NewEtcdRegistry(c.EtcdHelper, uint64(c.EventTTL.Seconds())) limitRangeRegistry := limitrange.NewEtcdRegistry(c.EtcdHelper) resourceQuotaStorage, resourceQuotaStatusStorage := resourcequotaetcd.NewREST(c.EtcdHelper) secretRegistry := secret.NewEtcdRegistry(c.EtcdHelper) namespaceStorage := namespaceetcd.NewREST(c.EtcdHelper) m.namespaceRegistry = namespace.NewRegistry(namespaceStorage) // TODO: split me up into distinct storage registries registry := etcd.NewRegistry(c.EtcdHelper, podRegistry) m.serviceRegistry = registry m.endpointRegistry = registry m.nodeRegistry = registry nodeStorage := minion.NewREST(m.nodeRegistry) // TODO: unify the storage -> registry and storage -> client patterns nodeStorageClient := RESTStorageToNodes(nodeStorage) podCache := NewPodCache( c.KubeletClient, nodeStorageClient.Nodes(), podRegistry, ) if c.SyncPodStatus { go util.Forever(podCache.UpdateAllContainers, m.cacheTimeout) go util.Forever(podCache.GarbageCollectPodStatus, time.Minute*30) podStorage = podStorage.WithPodStatus(podCache) } // TODO: Factor out the core API registration m.storage = map[string]apiserver.RESTStorage{ "pods": podStorage, "pods/status": podStatusStorage, "pods/binding": bindingStorage, "bindings": bindingStorage, "replicationControllers": controller.NewREST(registry, podRegistry), "services": service.NewREST(m.serviceRegistry, c.Cloud, m.nodeRegistry, m.portalNet, c.ClusterName), "endpoints": endpoint.NewREST(m.endpointRegistry), "minions": nodeStorage, "nodes": nodeStorage, "events": event.NewREST(eventRegistry), "limitRanges": limitrange.NewREST(limitRangeRegistry), "resourceQuotas": resourceQuotaStorage, "resourceQuotas/status": resourceQuotaStatusStorage, "namespaces": namespaceStorage, "secrets": secret.NewREST(secretRegistry), } apiVersions := []string{"v1beta1", "v1beta2"} if err := m.api_v1beta1().InstallREST(m.handlerContainer); err != nil { glog.Fatalf("Unable to setup API v1beta1: %v", err) } if err := m.api_v1beta2().InstallREST(m.handlerContainer); err != nil { glog.Fatalf("Unable to setup API v1beta2: %v", err) } if c.EnableV1Beta3 { if err := m.api_v1beta3().InstallREST(m.handlerContainer); err != nil { glog.Fatalf("Unable to setup API v1beta3: %v", err) } apiVersions = []string{"v1beta1", "v1beta2", "v1beta3"} } apiserver.InstallSupport(m.muxHelper, m.rootWebService) apiserver.AddApiWebService(m.handlerContainer, c.APIPrefix, apiVersions) // Register root handler. // We do not register this using restful Webservice since we do not want to surface this in api docs. // Allow master to be embedded in contexts which already have something registered at the root if c.EnableIndex { m.mux.HandleFunc("/", apiserver.IndexHandler(m.handlerContainer, m.muxHelper)) } // TODO: use go-restful apiserver.InstallValidator(m.muxHelper, func() map[string]apiserver.Server { return m.getServersToValidate(c) }) if c.EnableLogsSupport { apiserver.InstallLogsSupport(m.muxHelper) } if c.EnableUISupport { ui.InstallSupport(m.muxHelper, m.enableSwaggerSupport) } if c.EnableProfiling { m.mux.HandleFunc("/debug/pprof/", pprof.Index) m.mux.HandleFunc("/debug/pprof/profile", pprof.Profile) m.mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) } handler := http.Handler(m.mux.(*http.ServeMux)) // TODO: handle CORS and auth using go-restful // See github.com/emicklei/go-restful/blob/master/examples/restful-CORS-filter.go, and // github.com/emicklei/go-restful/blob/master/examples/restful-basic-authentication.go if len(c.CorsAllowedOriginList) > 0 { allowedOriginRegexps, err := util.CompileRegexps(c.CorsAllowedOriginList) if err != nil { glog.Fatalf("Invalid CORS allowed origin, --cors_allowed_origins flag was set to %v - %v", strings.Join(c.CorsAllowedOriginList, ","), err) } handler = apiserver.CORS(handler, allowedOriginRegexps, nil, nil, "true") } m.InsecureHandler = handler attributeGetter := apiserver.NewRequestAttributeGetter(m.requestContextMapper, latest.RESTMapper, "api") handler = apiserver.WithAuthorizationCheck(handler, attributeGetter, m.authorizer) // Install Authenticator if c.Authenticator != nil { authenticatedHandler, err := handlers.NewRequestAuthenticator(m.requestContextMapper, c.Authenticator, handlers.Unauthorized, handler) if err != nil { glog.Fatalf("Could not initialize authenticator: %v", err) } handler = authenticatedHandler } // Install root web services m.handlerContainer.Add(m.rootWebService) // TODO: Make this optional? Consumers of master depend on this currently. m.Handler = handler if m.enableSwaggerSupport { m.InstallSwaggerAPI() } // After all wrapping is done, put a context filter around both handlers if handler, err := api.NewRequestContextFilter(m.requestContextMapper, m.Handler); err != nil { glog.Fatalf("Could not initialize request context filter: %v", err) } else { m.Handler = handler } if handler, err := api.NewRequestContextFilter(m.requestContextMapper, m.InsecureHandler); err != nil { glog.Fatalf("Could not initialize request context filter: %v", err) } else { m.InsecureHandler = handler } // TODO: Attempt clean shutdown? m.masterServices.Start() }