// Run runs the specified APIServer. This should never exit. func Run(s *options.ServerRunOptions) error { // set defaults if err := s.GenericServerRunOptions.DefaultAdvertiseAddress(s.SecureServing, s.InsecureServing); err != nil { return err } if err := s.SecureServing.MaybeDefaultWithSelfSignedCerts(s.GenericServerRunOptions.AdvertiseAddress.String()); err != nil { return fmt.Errorf("error creating self-signed certificates: %v", err) } if err := s.GenericServerRunOptions.DefaultExternalHost(); err != nil { return fmt.Errorf("error setting the external host value: %v", err) } // validate options if errs := s.Validate(); len(errs) != 0 { return utilerrors.NewAggregate(errs) } // create config from options genericConfig := genericapiserver.NewConfig(). // create the new config ApplyOptions(s.GenericServerRunOptions). // apply the options selected ApplyInsecureServingOptions(s.InsecureServing) if _, err := genericConfig.ApplySecureServingOptions(s.SecureServing); err != nil { return fmt.Errorf("failed to configure https: %s", err) } if _, err := genericConfig.ApplyAuthenticationOptions(s.Authentication); err != nil { return fmt.Errorf("failed to configure authentication: %s", err) } // TODO: register cluster federation resources here. resourceConfig := genericapiserver.NewResourceConfig() if s.Etcd.StorageConfig.DeserializationCacheSize == 0 { // When size of cache is not explicitly set, set it to 50000 s.Etcd.StorageConfig.DeserializationCacheSize = 50000 } storageGroupsToEncodingVersion, err := s.GenericServerRunOptions.StorageGroupsToEncodingVersion() if err != nil { return fmt.Errorf("error generating storage version map: %s", err) } storageFactory, err := genericapiserver.BuildDefaultStorageFactory( s.Etcd.StorageConfig, s.GenericServerRunOptions.DefaultStorageMediaType, api.Codecs, genericapiserver.NewDefaultResourceEncodingConfig(), storageGroupsToEncodingVersion, []schema.GroupVersionResource{}, resourceConfig, s.GenericServerRunOptions.RuntimeConfig) if err != nil { return fmt.Errorf("error in initializing storage factory: %s", err) } for _, override := range s.Etcd.EtcdServersOverrides { tokens := strings.Split(override, "#") if len(tokens) != 2 { glog.Errorf("invalid value of etcd server overrides: %s", override) continue } apiresource := strings.Split(tokens[0], "/") if len(apiresource) != 2 { glog.Errorf("invalid resource definition: %s", tokens[0]) continue } group := apiresource[0] resource := apiresource[1] groupResource := schema.GroupResource{Group: group, Resource: resource} servers := strings.Split(tokens[1], ";") storageFactory.SetEtcdLocation(groupResource, servers) } apiAuthenticator, securityDefinitions, err := authenticator.New(s.Authentication.ToAuthenticationConfig()) if err != nil { return fmt.Errorf("invalid Authentication Config: %v", err) } privilegedLoopbackToken := uuid.NewRandom().String() selfClientConfig, err := genericapiserver.NewSelfClientConfig(genericConfig.SecureServingInfo, genericConfig.InsecureServingInfo, privilegedLoopbackToken) if err != nil { return fmt.Errorf("failed to create clientset: %v", err) } client, err := internalclientset.NewForConfig(selfClientConfig) if err != nil { return fmt.Errorf("failed to create clientset: %v", err) } sharedInformers := informers.NewSharedInformerFactory(nil, client, 10*time.Minute) authorizerconfig := s.Authorization.ToAuthorizationConfig(sharedInformers) apiAuthorizer, err := authorizer.NewAuthorizerFromAuthorizationConfig(authorizerconfig) if err != nil { return fmt.Errorf("invalid Authorization Config: %v", err) } admissionControlPluginNames := strings.Split(s.GenericServerRunOptions.AdmissionControl, ",") pluginInitializer := admission.NewPluginInitializer(sharedInformers, apiAuthorizer) admissionController, err := admission.NewFromPlugins(client, admissionControlPluginNames, s.GenericServerRunOptions.AdmissionControlConfigFile, pluginInitializer) if err != nil { return fmt.Errorf("failed to initialize plugins: %v", err) } kubeVersion := version.Get() genericConfig.Version = &kubeVersion genericConfig.LoopbackClientConfig = selfClientConfig genericConfig.Authenticator = apiAuthenticator genericConfig.Authorizer = apiAuthorizer genericConfig.AdmissionControl = admissionController genericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(openapi.OpenAPIDefinitions) genericConfig.OpenAPIConfig.SecurityDefinitions = securityDefinitions genericConfig.SwaggerConfig = genericapiserver.DefaultSwaggerConfig() genericConfig.LongRunningFunc = filters.BasicLongRunningRequestCheck( sets.NewString("watch", "proxy"), sets.NewString("attach", "exec", "proxy", "log", "portforward"), ) // TODO: Move this to generic api server (Need to move the command line flag). if s.GenericServerRunOptions.EnableWatchCache { cachesize.InitializeWatchCacheSizes(s.GenericServerRunOptions.TargetRAMMB) cachesize.SetWatchCacheSizes(s.GenericServerRunOptions.WatchCacheSizes) } m, err := genericConfig.Complete().New() if err != nil { return err } routes.UIRedirect{}.Install(m.HandlerContainer) routes.Logs{}.Install(m.HandlerContainer) // TODO: Refactor this code to share it with kube-apiserver rather than duplicating it here. restOptionsFactory := &restOptionsFactory{ storageFactory: storageFactory, enableGarbageCollection: s.GenericServerRunOptions.EnableGarbageCollection, deleteCollectionWorkers: s.GenericServerRunOptions.DeleteCollectionWorkers, } if s.GenericServerRunOptions.EnableWatchCache { restOptionsFactory.storageDecorator = genericregistry.StorageWithCacher } else { restOptionsFactory.storageDecorator = generic.UndecoratedStorage } installFederationAPIs(m, restOptionsFactory) installCoreAPIs(s, m, restOptionsFactory) installExtensionsAPIs(m, restOptionsFactory) sharedInformers.Start(wait.NeverStop) m.PrepareRun().Run(wait.NeverStop) return nil }