func DefaultAPIResourceConfigSource() *genericapiserver.ResourceConfig { ret := genericapiserver.NewResourceConfig() ret.EnableVersions( apiv1.SchemeGroupVersion, extensionsapiv1beta1.SchemeGroupVersion, batchapiv1.SchemeGroupVersion, authenticationv1beta1.SchemeGroupVersion, autoscalingapiv1.SchemeGroupVersion, appsapi.SchemeGroupVersion, policyapiv1beta1.SchemeGroupVersion, rbacv1beta1.SchemeGroupVersion, rbacapi.SchemeGroupVersion, storageapiv1beta1.SchemeGroupVersion, certificatesapiv1beta1.SchemeGroupVersion, authorizationapiv1beta1.SchemeGroupVersion, ) // all extensions resources except these are disabled by default ret.EnableResources( extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"), extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"), extensionsapiv1beta1.SchemeGroupVersion.WithResource("horizontalpodautoscalers"), extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"), extensionsapiv1beta1.SchemeGroupVersion.WithResource("networkpolicies"), extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"), extensionsapiv1beta1.SchemeGroupVersion.WithResource("thirdpartyresources"), extensionsapiv1beta1.SchemeGroupVersion.WithResource("podsecuritypolicies"), ) return ret }
// limitedAPIResourceConfigSource only enables the core group, the extensions group, the batch group, and the autoscaling group. func limitedAPIResourceConfigSource() *genericapiserver.ResourceConfig { ret := genericapiserver.NewResourceConfig() ret.EnableVersions( apiv1.SchemeGroupVersion, extensionsapiv1beta1.SchemeGroupVersion, batchapiv1.SchemeGroupVersion, batchapiv2alpha1.SchemeGroupVersion, appsapiv1beta1.SchemeGroupVersion, autoscalingapiv1.SchemeGroupVersion, ) return ret }
func newStorageFactory() genericapiserver.StorageFactory { config := storagebackend.Config{ Prefix: genericoptions.DefaultEtcdPathPrefix, ServerList: []string{"http://127.0.0.1:2379"}, } storageFactory := genericapiserver.NewDefaultStorageFactory(config, "application/json", api.Codecs, genericapiserver.NewDefaultResourceEncodingConfig(), genericapiserver.NewResourceConfig()) return storageFactory }
// 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.CloudProvider.DefaultExternalHost(s.GenericServerRunOptions); err != nil { return fmt.Errorf("error setting the external host value: %v", err) } s.Authentication.ApplyAuthorization(s.Authorization) // validate options if errs := s.Validate(); len(errs) != 0 { return utilerrors.NewAggregate(errs) } 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 := s.Authentication.Apply(genericConfig); 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 := kubeapiserver.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 := s.Authentication.ToAuthenticationConfig().New() 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) authorizationConfig := s.Authorization.ToAuthorizationConfig(sharedInformers) apiAuthorizer, err := authorizationConfig.New() if err != nil { return fmt.Errorf("invalid Authorization Config: %v", err) } admissionControlPluginNames := strings.Split(s.GenericServerRunOptions.AdmissionControl, ",") pluginInitializer := kubeapiserveradmission.NewPluginInitializer(client, sharedInformers, apiAuthorizer) admissionConfigProvider, err := kubeapiserveradmission.ReadAdmissionConfiguration(admissionControlPluginNames, s.GenericServerRunOptions.AdmissionControlConfigFile) if err != nil { return fmt.Errorf("failed to read plugin config: %v", err) } admissionController, err := admission.NewFromPlugins(admissionControlPluginNames, admissionConfigProvider, 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) installBatchAPIs(m, restOptionsFactory) sharedInformers.Start(wait.NeverStop) m.PrepareRun().Run(wait.NeverStop) return nil }
func TestParseRuntimeConfig(t *testing.T) { extensionsGroupVersion := extensionsapiv1beta1.SchemeGroupVersion apiv1GroupVersion := apiv1.SchemeGroupVersion testCases := []struct { runtimeConfig map[string]string defaultResourceConfig func() *genericapiserver.ResourceConfig expectedAPIConfig func() *genericapiserver.ResourceConfig err bool }{ { // everything default value. runtimeConfig: map[string]string{}, defaultResourceConfig: func() *genericapiserver.ResourceConfig { return genericapiserver.NewResourceConfig() }, expectedAPIConfig: func() *genericapiserver.ResourceConfig { return genericapiserver.NewResourceConfig() }, err: false, }, { // no runtimeConfig override. runtimeConfig: map[string]string{}, defaultResourceConfig: func() *genericapiserver.ResourceConfig { config := genericapiserver.NewResourceConfig() config.DisableVersions(extensionsapiv1beta1.SchemeGroupVersion) return config }, expectedAPIConfig: func() *genericapiserver.ResourceConfig { config := genericapiserver.NewResourceConfig() config.DisableVersions(extensionsapiv1beta1.SchemeGroupVersion) return config }, err: false, }, { // version enabled by runtimeConfig override. runtimeConfig: map[string]string{ "extensions/v1beta1": "", }, defaultResourceConfig: func() *genericapiserver.ResourceConfig { config := genericapiserver.NewResourceConfig() config.DisableVersions(extensionsapiv1beta1.SchemeGroupVersion) return config }, expectedAPIConfig: func() *genericapiserver.ResourceConfig { config := genericapiserver.NewResourceConfig() config.EnableVersions(extensionsapiv1beta1.SchemeGroupVersion) return config }, err: false, }, { // disable resource runtimeConfig: map[string]string{ "api/v1/pods": "false", }, defaultResourceConfig: func() *genericapiserver.ResourceConfig { config := genericapiserver.NewResourceConfig() config.EnableVersions(apiv1GroupVersion) return config }, expectedAPIConfig: func() *genericapiserver.ResourceConfig { config := genericapiserver.NewResourceConfig() config.EnableVersions(apiv1GroupVersion) config.DisableResources(apiv1GroupVersion.WithResource("pods")) return config }, err: false, }, { // Disable v1. runtimeConfig: map[string]string{ "api/v1": "false", }, defaultResourceConfig: func() *genericapiserver.ResourceConfig { return genericapiserver.NewResourceConfig() }, expectedAPIConfig: func() *genericapiserver.ResourceConfig { config := genericapiserver.NewResourceConfig() config.DisableVersions(apiv1GroupVersion) return config }, err: false, }, { // Enable deployments and disable daemonsets. runtimeConfig: map[string]string{ "extensions/v1beta1/anything": "true", "extensions/v1beta1/daemonsets": "false", }, defaultResourceConfig: func() *genericapiserver.ResourceConfig { config := genericapiserver.NewResourceConfig() config.EnableVersions(extensionsGroupVersion) return config }, expectedAPIConfig: func() *genericapiserver.ResourceConfig { config := genericapiserver.NewResourceConfig() config.EnableVersions(extensionsGroupVersion) config.DisableResources(extensionsGroupVersion.WithResource("daemonsets")) config.EnableResources(extensionsGroupVersion.WithResource("anything")) return config }, err: false, }, { // invalid runtime config runtimeConfig: map[string]string{ "invalidgroup/version": "false", }, defaultResourceConfig: func() *genericapiserver.ResourceConfig { return genericapiserver.NewResourceConfig() }, expectedAPIConfig: func() *genericapiserver.ResourceConfig { return genericapiserver.NewResourceConfig() }, err: true, }, { // cannot disable individual resource when version is not enabled. runtimeConfig: map[string]string{ "api/v1/pods": "false", }, defaultResourceConfig: func() *genericapiserver.ResourceConfig { return genericapiserver.NewResourceConfig() }, expectedAPIConfig: func() *genericapiserver.ResourceConfig { config := genericapiserver.NewResourceConfig() config.DisableResources(schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}) return config }, err: true, }, { // enable all runtimeConfig: map[string]string{ "api/all": "true", }, defaultResourceConfig: func() *genericapiserver.ResourceConfig { return genericapiserver.NewResourceConfig() }, expectedAPIConfig: func() *genericapiserver.ResourceConfig { config := genericapiserver.NewResourceConfig() config.EnableVersions(api.Registry.RegisteredGroupVersions()...) return config }, err: false, }, { // disable all runtimeConfig: map[string]string{ "api/all": "false", }, defaultResourceConfig: func() *genericapiserver.ResourceConfig { return genericapiserver.NewResourceConfig() }, expectedAPIConfig: func() *genericapiserver.ResourceConfig { config := genericapiserver.NewResourceConfig() config.DisableVersions(api.Registry.RegisteredGroupVersions()...) return config }, err: false, }, } for _, test := range testCases { actualDisablers, err := mergeAPIResourceConfigs(test.defaultResourceConfig(), test.runtimeConfig) if err == nil && test.err { t.Fatalf("expected error for test: %v", test) } else if err != nil && !test.err { t.Fatalf("unexpected error: %s, for test: %v", err, test) } expectedConfig := test.expectedAPIConfig() if err == nil && !reflect.DeepEqual(actualDisablers, expectedConfig) { t.Fatalf("%v: unexpected apiResourceDisablers. Actual: %v\n expected: %v", test.runtimeConfig, actualDisablers, expectedConfig) } } }