diff --git a/cmd/kube-controller-manager/app/controllermanager.go b/cmd/kube-controller-manager/app/controllermanager.go index fe7d7b6f67..8be587684e 100644 --- a/cmd/kube-controller-manager/app/controllermanager.go +++ b/cmd/kube-controller-manager/app/controllermanager.go @@ -323,7 +323,7 @@ func StartControllers(s *options.CMServer, kubeconfig *restclient.Config, rootCl } resourceQuotaControllerClient := client("resourcequota-controller") - resourceQuotaRegistry := quotainstall.NewRegistry(resourceQuotaControllerClient) + resourceQuotaRegistry := quotainstall.NewRegistry(resourceQuotaControllerClient, sharedInformers) groupKindsToReplenish := []unversioned.GroupKind{ api.Kind("Pod"), api.Kind("Service"), @@ -336,7 +336,7 @@ func StartControllers(s *options.CMServer, kubeconfig *restclient.Config, rootCl KubeClient: resourceQuotaControllerClient, ResyncPeriod: controller.StaticResyncPeriodFunc(s.ResourceQuotaSyncPeriod.Duration), Registry: resourceQuotaRegistry, - ControllerFactory: resourcequotacontroller.NewReplenishmentControllerFactory(sharedInformers.Pods().Informer(), resourceQuotaControllerClient), + ControllerFactory: resourcequotacontroller.NewReplenishmentControllerFactory(sharedInformers, resourceQuotaControllerClient), ReplenishmentResyncPeriod: ResyncPeriod(s), GroupKindsToReplenish: groupKindsToReplenish, } diff --git a/pkg/controller/resourcequota/replenishment_controller.go b/pkg/controller/resourcequota/replenishment_controller.go index 1e99588866..bf090026f1 100644 --- a/pkg/controller/resourcequota/replenishment_controller.go +++ b/pkg/controller/resourcequota/replenishment_controller.go @@ -94,19 +94,21 @@ type ReplenishmentControllerFactory interface { // replenishmentControllerFactory implements ReplenishmentControllerFactory type replenishmentControllerFactory struct { - kubeClient clientset.Interface - podInformer cache.SharedInformer + kubeClient clientset.Interface + sharedInformerFactory informers.SharedInformerFactory } // NewReplenishmentControllerFactory returns a factory that knows how to build controllers // to replenish resources when updated or deleted -func NewReplenishmentControllerFactory(podInformer cache.SharedInformer, kubeClient clientset.Interface) ReplenishmentControllerFactory { +func NewReplenishmentControllerFactory(f informers.SharedInformerFactory, kubeClient clientset.Interface) ReplenishmentControllerFactory { return &replenishmentControllerFactory{ - kubeClient: kubeClient, - podInformer: podInformer, + kubeClient: kubeClient, + sharedInformerFactory: f, } } +// NewReplenishmentControllerFactoryFromClient returns a factory that knows how to build controllers to replenish resources +// when updated or deleted using the specified client. func NewReplenishmentControllerFactoryFromClient(kubeClient clientset.Interface) ReplenishmentControllerFactory { return NewReplenishmentControllerFactory(nil, kubeClient) } @@ -119,18 +121,16 @@ func (r *replenishmentControllerFactory) NewController(options *ReplenishmentCon switch options.GroupKind { case api.Kind("Pod"): - if r.podInformer != nil { - r.podInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ + if r.sharedInformerFactory != nil { + podInformer := r.sharedInformerFactory.Pods().Informer() + podInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ UpdateFunc: PodReplenishmentUpdateFunc(options), DeleteFunc: ObjectReplenishmentDeleteFunc(options), }) - result = r.podInformer.GetController() + result = podInformer.GetController() break } - - r.podInformer = informers.NewPodInformer(r.kubeClient, options.ResyncPeriod()) - result = r.podInformer - + result = informers.NewPodInformer(r.kubeClient, options.ResyncPeriod()) case api.Kind("Service"): _, result = cache.NewInformer( &cache.ListWatch{ diff --git a/pkg/controller/resourcequota/resource_quota_controller_test.go b/pkg/controller/resourcequota/resource_quota_controller_test.go index f62bae9e64..0221448a22 100644 --- a/pkg/controller/resourcequota/resource_quota_controller_test.go +++ b/pkg/controller/resourcequota/resource_quota_controller_test.go @@ -107,7 +107,7 @@ func TestSyncResourceQuota(t *testing.T) { resourceQuotaControllerOptions := &ResourceQuotaControllerOptions{ KubeClient: kubeClient, ResyncPeriod: controller.NoResyncPeriodFunc, - Registry: install.NewRegistry(kubeClient), + Registry: install.NewRegistry(kubeClient, nil), GroupKindsToReplenish: []unversioned.GroupKind{ api.Kind("Pod"), api.Kind("Service"), @@ -192,7 +192,7 @@ func TestSyncResourceQuotaSpecChange(t *testing.T) { resourceQuotaControllerOptions := &ResourceQuotaControllerOptions{ KubeClient: kubeClient, ResyncPeriod: controller.NoResyncPeriodFunc, - Registry: install.NewRegistry(kubeClient), + Registry: install.NewRegistry(kubeClient, nil), GroupKindsToReplenish: []unversioned.GroupKind{ api.Kind("Pod"), api.Kind("Service"), @@ -280,7 +280,7 @@ func TestSyncResourceQuotaSpecHardChange(t *testing.T) { resourceQuotaControllerOptions := &ResourceQuotaControllerOptions{ KubeClient: kubeClient, ResyncPeriod: controller.NoResyncPeriodFunc, - Registry: install.NewRegistry(kubeClient), + Registry: install.NewRegistry(kubeClient, nil), GroupKindsToReplenish: []unversioned.GroupKind{ api.Kind("Pod"), api.Kind("Service"), @@ -368,7 +368,7 @@ func TestSyncResourceQuotaNoChange(t *testing.T) { resourceQuotaControllerOptions := &ResourceQuotaControllerOptions{ KubeClient: kubeClient, ResyncPeriod: controller.NoResyncPeriodFunc, - Registry: install.NewRegistry(kubeClient), + Registry: install.NewRegistry(kubeClient, nil), GroupKindsToReplenish: []unversioned.GroupKind{ api.Kind("Pod"), api.Kind("Service"), @@ -400,7 +400,7 @@ func TestAddQuota(t *testing.T) { resourceQuotaControllerOptions := &ResourceQuotaControllerOptions{ KubeClient: kubeClient, ResyncPeriod: controller.NoResyncPeriodFunc, - Registry: install.NewRegistry(kubeClient), + Registry: install.NewRegistry(kubeClient, nil), GroupKindsToReplenish: []unversioned.GroupKind{ api.Kind("Pod"), api.Kind("ReplicationController"), diff --git a/pkg/quota/evaluator/core/BUILD b/pkg/quota/evaluator/core/BUILD index 7a846d8bdd..26cd8d9ade 100644 --- a/pkg/quota/evaluator/core/BUILD +++ b/pkg/quota/evaluator/core/BUILD @@ -31,6 +31,7 @@ go_library( "//pkg/api/unversioned:go_default_library", "//pkg/api/validation:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", + "//pkg/controller/informers:go_default_library", "//pkg/kubelet/qos:go_default_library", "//pkg/quota:go_default_library", "//pkg/quota/generic:go_default_library", diff --git a/pkg/quota/evaluator/core/configmap.go b/pkg/quota/evaluator/core/configmap.go index 46ee974292..3358df60f3 100644 --- a/pkg/quota/evaluator/core/configmap.go +++ b/pkg/quota/evaluator/core/configmap.go @@ -38,8 +38,16 @@ func NewConfigMapEvaluator(kubeClient clientset.Interface) quota.Evaluator { MatchesScopeFunc: generic.MatchesNoScopeFunc, ConstraintsFunc: generic.ObjectCountConstraintsFunc(api.ResourceConfigMaps), UsageFunc: generic.ObjectCountUsageFunc(api.ResourceConfigMaps), - ListFuncByNamespace: func(namespace string, options api.ListOptions) (runtime.Object, error) { - return kubeClient.Core().ConfigMaps(namespace).List(options) + ListFuncByNamespace: func(namespace string, options api.ListOptions) ([]runtime.Object, error) { + itemList, err := kubeClient.Core().ConfigMaps(namespace).List(options) + if err != nil { + return nil, err + } + results := make([]runtime.Object, 0, len(itemList.Items)) + for i := range itemList.Items { + results = append(results, &itemList.Items[i]) + } + return results, nil }, } } diff --git a/pkg/quota/evaluator/core/persistent_volume_claims.go b/pkg/quota/evaluator/core/persistent_volume_claims.go index d6a58a756c..20945d3978 100644 --- a/pkg/quota/evaluator/core/persistent_volume_claims.go +++ b/pkg/quota/evaluator/core/persistent_volume_claims.go @@ -43,8 +43,16 @@ func NewPersistentVolumeClaimEvaluator(kubeClient clientset.Interface) quota.Eva MatchesScopeFunc: generic.MatchesNoScopeFunc, ConstraintsFunc: PersistentVolumeClaimConstraintsFunc, UsageFunc: PersistentVolumeClaimUsageFunc, - ListFuncByNamespace: func(namespace string, options api.ListOptions) (runtime.Object, error) { - return kubeClient.Core().PersistentVolumeClaims(namespace).List(options) + ListFuncByNamespace: func(namespace string, options api.ListOptions) ([]runtime.Object, error) { + itemList, err := kubeClient.Core().PersistentVolumeClaims(namespace).List(options) + if err != nil { + return nil, err + } + results := make([]runtime.Object, 0, len(itemList.Items)) + for i := range itemList.Items { + results = append(results, &itemList.Items[i]) + } + return results, nil }, } } diff --git a/pkg/quota/evaluator/core/pods.go b/pkg/quota/evaluator/core/pods.go index abad5950f7..4d5d8ea75d 100644 --- a/pkg/quota/evaluator/core/pods.go +++ b/pkg/quota/evaluator/core/pods.go @@ -23,8 +23,10 @@ import ( "k8s.io/kubernetes/pkg/admission" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/resource" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/validation" clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" + "k8s.io/kubernetes/pkg/controller/informers" "k8s.io/kubernetes/pkg/kubelet/qos" "k8s.io/kubernetes/pkg/quota" "k8s.io/kubernetes/pkg/quota/generic" @@ -33,8 +35,27 @@ import ( "k8s.io/kubernetes/pkg/util/validation/field" ) +// listPodsByNamespaceFuncUsingClient returns a pod listing function based on the provided client. +func listPodsByNamespaceFuncUsingClient(kubeClient clientset.Interface) generic.ListFuncByNamespace { + // TODO: ideally, we could pass dynamic client pool down into this code, and have one way of doing this. + // unfortunately, dynamic client works with Unstructured objects, and when we calculate Usage, we require + // structured objects. + return func(namespace string, options api.ListOptions) ([]runtime.Object, error) { + itemList, err := kubeClient.Core().Pods(namespace).List(options) + if err != nil { + return nil, err + } + results := make([]runtime.Object, 0, len(itemList.Items)) + for i := range itemList.Items { + results = append(results, &itemList.Items[i]) + } + return results, nil + } +} + // NewPodEvaluator returns an evaluator that can evaluate pods -func NewPodEvaluator(kubeClient clientset.Interface) quota.Evaluator { +// if the specified shared informer factory is not nil, evaluator may use it to support listing functions. +func NewPodEvaluator(kubeClient clientset.Interface, f informers.SharedInformerFactory) quota.Evaluator { computeResources := []api.ResourceName{ api.ResourceCPU, api.ResourceMemory, @@ -44,6 +65,10 @@ func NewPodEvaluator(kubeClient clientset.Interface) quota.Evaluator { api.ResourceLimitsMemory, } allResources := append(computeResources, api.ResourcePods) + listFuncByNamespace := listPodsByNamespaceFuncUsingClient(kubeClient) + if f != nil { + listFuncByNamespace = generic.ListResourceUsingInformerFunc(f, unversioned.GroupResource{Resource: "pods"}) + } return &generic.GenericEvaluator{ Name: "Evaluator.Pod", InternalGroupKind: api.Kind("Pod"), @@ -59,9 +84,7 @@ func NewPodEvaluator(kubeClient clientset.Interface) quota.Evaluator { MatchedResourceNames: allResources, MatchesScopeFunc: PodMatchesScopeFunc, UsageFunc: PodUsageFunc, - ListFuncByNamespace: func(namespace string, options api.ListOptions) (runtime.Object, error) { - return kubeClient.Core().Pods(namespace).List(options) - }, + ListFuncByNamespace: listFuncByNamespace, } } diff --git a/pkg/quota/evaluator/core/pods_test.go b/pkg/quota/evaluator/core/pods_test.go index fc056431dd..32c454fb4d 100644 --- a/pkg/quota/evaluator/core/pods_test.go +++ b/pkg/quota/evaluator/core/pods_test.go @@ -99,7 +99,7 @@ func TestPodConstraintsFunc(t *testing.T) { func TestPodEvaluatorUsage(t *testing.T) { kubeClient := fake.NewSimpleClientset() - evaluator := NewPodEvaluator(kubeClient) + evaluator := NewPodEvaluator(kubeClient, nil) testCases := map[string]struct { pod *api.Pod usage api.ResourceList diff --git a/pkg/quota/evaluator/core/registry.go b/pkg/quota/evaluator/core/registry.go index 814e9d4737..511b4d08f0 100644 --- a/pkg/quota/evaluator/core/registry.go +++ b/pkg/quota/evaluator/core/registry.go @@ -19,13 +19,15 @@ package core import ( "k8s.io/kubernetes/pkg/api/unversioned" clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" + "k8s.io/kubernetes/pkg/controller/informers" "k8s.io/kubernetes/pkg/quota" "k8s.io/kubernetes/pkg/quota/generic" ) // NewRegistry returns a registry that knows how to deal with core kubernetes resources -func NewRegistry(kubeClient clientset.Interface) quota.Registry { - pod := NewPodEvaluator(kubeClient) +// If an informer factory is provided, evaluators will use them. +func NewRegistry(kubeClient clientset.Interface, f informers.SharedInformerFactory) quota.Registry { + pod := NewPodEvaluator(kubeClient, f) service := NewServiceEvaluator(kubeClient) replicationController := NewReplicationControllerEvaluator(kubeClient) resourceQuota := NewResourceQuotaEvaluator(kubeClient) diff --git a/pkg/quota/evaluator/core/replication_controllers.go b/pkg/quota/evaluator/core/replication_controllers.go index c99f33d25d..c95da8c34d 100644 --- a/pkg/quota/evaluator/core/replication_controllers.go +++ b/pkg/quota/evaluator/core/replication_controllers.go @@ -38,8 +38,16 @@ func NewReplicationControllerEvaluator(kubeClient clientset.Interface) quota.Eva MatchesScopeFunc: generic.MatchesNoScopeFunc, ConstraintsFunc: generic.ObjectCountConstraintsFunc(api.ResourceReplicationControllers), UsageFunc: generic.ObjectCountUsageFunc(api.ResourceReplicationControllers), - ListFuncByNamespace: func(namespace string, options api.ListOptions) (runtime.Object, error) { - return kubeClient.Core().ReplicationControllers(namespace).List(options) + ListFuncByNamespace: func(namespace string, options api.ListOptions) ([]runtime.Object, error) { + itemList, err := kubeClient.Core().ReplicationControllers(namespace).List(options) + if err != nil { + return nil, err + } + results := make([]runtime.Object, 0, len(itemList.Items)) + for i := range itemList.Items { + results = append(results, &itemList.Items[i]) + } + return results, nil }, } } diff --git a/pkg/quota/evaluator/core/resource_quotas.go b/pkg/quota/evaluator/core/resource_quotas.go index 51bc04c9dd..5652ea5b54 100644 --- a/pkg/quota/evaluator/core/resource_quotas.go +++ b/pkg/quota/evaluator/core/resource_quotas.go @@ -38,8 +38,16 @@ func NewResourceQuotaEvaluator(kubeClient clientset.Interface) quota.Evaluator { MatchesScopeFunc: generic.MatchesNoScopeFunc, ConstraintsFunc: generic.ObjectCountConstraintsFunc(api.ResourceQuotas), UsageFunc: generic.ObjectCountUsageFunc(api.ResourceQuotas), - ListFuncByNamespace: func(namespace string, options api.ListOptions) (runtime.Object, error) { - return kubeClient.Core().ResourceQuotas(namespace).List(options) + ListFuncByNamespace: func(namespace string, options api.ListOptions) ([]runtime.Object, error) { + itemList, err := kubeClient.Core().ResourceQuotas(namespace).List(options) + if err != nil { + return nil, err + } + results := make([]runtime.Object, 0, len(itemList.Items)) + for i := range itemList.Items { + results = append(results, &itemList.Items[i]) + } + return results, nil }, } } diff --git a/pkg/quota/evaluator/core/secrets.go b/pkg/quota/evaluator/core/secrets.go index c378597324..48676f35ab 100644 --- a/pkg/quota/evaluator/core/secrets.go +++ b/pkg/quota/evaluator/core/secrets.go @@ -38,8 +38,16 @@ func NewSecretEvaluator(kubeClient clientset.Interface) quota.Evaluator { MatchesScopeFunc: generic.MatchesNoScopeFunc, ConstraintsFunc: generic.ObjectCountConstraintsFunc(api.ResourceSecrets), UsageFunc: generic.ObjectCountUsageFunc(api.ResourceSecrets), - ListFuncByNamespace: func(namespace string, options api.ListOptions) (runtime.Object, error) { - return kubeClient.Core().Secrets(namespace).List(options) + ListFuncByNamespace: func(namespace string, options api.ListOptions) ([]runtime.Object, error) { + itemList, err := kubeClient.Core().Secrets(namespace).List(options) + if err != nil { + return nil, err + } + results := make([]runtime.Object, 0, len(itemList.Items)) + for i := range itemList.Items { + results = append(results, &itemList.Items[i]) + } + return results, nil }, } } diff --git a/pkg/quota/evaluator/core/services.go b/pkg/quota/evaluator/core/services.go index d5d83e551f..3d07335f9f 100644 --- a/pkg/quota/evaluator/core/services.go +++ b/pkg/quota/evaluator/core/services.go @@ -48,8 +48,16 @@ func NewServiceEvaluator(kubeClient clientset.Interface) quota.Evaluator { MatchesScopeFunc: generic.MatchesNoScopeFunc, ConstraintsFunc: ServiceConstraintsFunc, UsageFunc: ServiceUsageFunc, - ListFuncByNamespace: func(namespace string, options api.ListOptions) (runtime.Object, error) { - return kubeClient.Core().Services(namespace).List(options) + ListFuncByNamespace: func(namespace string, options api.ListOptions) ([]runtime.Object, error) { + itemList, err := kubeClient.Core().Services(namespace).List(options) + if err != nil { + return nil, err + } + results := make([]runtime.Object, 0, len(itemList.Items)) + for i := range itemList.Items { + results = append(results, &itemList.Items[i]) + } + return results, nil }, } } diff --git a/pkg/quota/generic/BUILD b/pkg/quota/generic/BUILD index 2c2fe856c1..7bad635e23 100644 --- a/pkg/quota/generic/BUILD +++ b/pkg/quota/generic/BUILD @@ -20,9 +20,10 @@ go_library( deps = [ "//pkg/admission:go_default_library", "//pkg/api:go_default_library", - "//pkg/api/meta:go_default_library", "//pkg/api/resource:go_default_library", "//pkg/api/unversioned:go_default_library", + "//pkg/controller/informers:go_default_library", + "//pkg/labels:go_default_library", "//pkg/quota:go_default_library", "//pkg/runtime:go_default_library", ], diff --git a/pkg/quota/generic/evaluator.go b/pkg/quota/generic/evaluator.go index 96dc4878f3..9c8bda66d3 100644 --- a/pkg/quota/generic/evaluator.go +++ b/pkg/quota/generic/evaluator.go @@ -21,13 +21,25 @@ import ( "k8s.io/kubernetes/pkg/admission" "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/api/unversioned" + "k8s.io/kubernetes/pkg/controller/informers" + "k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/quota" "k8s.io/kubernetes/pkg/runtime" ) +// ListResourceUsingInformerFunc returns a listing function based on the shared informer factory for the specified resource. +func ListResourceUsingInformerFunc(f informers.SharedInformerFactory, groupResource unversioned.GroupResource) ListFuncByNamespace { + return func(namespace string, options api.ListOptions) ([]runtime.Object, error) { + informer, err := f.ForResource(groupResource) + if err != nil { + return nil, err + } + return informer.Lister().ByNamespace(namespace).List(options.LabelSelector) + } +} + // ConstraintsFunc takes a list of required resources that must match on the input item type ConstraintsFunc func(required []api.ResourceName, item runtime.Object) error @@ -35,7 +47,7 @@ type ConstraintsFunc func(required []api.ResourceName, item runtime.Object) erro type GetFuncByNamespace func(namespace, name string) (runtime.Object, error) // ListFuncByNamespace knows how to list resources in a namespace -type ListFuncByNamespace func(namespace string, options api.ListOptions) (runtime.Object, error) +type ListFuncByNamespace func(namespace string, options api.ListOptions) ([]runtime.Object, error) // MatchesScopeFunc knows how to evaluate if an object matches a scope type MatchesScopeFunc func(scope api.ResourceQuotaScope, object runtime.Object) bool @@ -171,18 +183,12 @@ func (g *GenericEvaluator) UsageStats(options quota.UsageStatsOptions) (quota.Us for _, resourceName := range g.MatchedResourceNames { result.Used[resourceName] = resource.MustParse("0") } - list, err := g.ListFuncByNamespace(options.Namespace, api.ListOptions{}) + items, err := g.ListFuncByNamespace(options.Namespace, api.ListOptions{ + LabelSelector: labels.Everything(), + }) if err != nil { return result, fmt.Errorf("%s: Failed to list %v: %v", g.Name, g.GroupKind(), err) } - _, err = meta.ListAccessor(list) - if err != nil { - return result, fmt.Errorf("%s: Unable to understand list result, does not appear to be a list %#v", g.Name, list) - } - items, err := meta.ExtractList(list) - if err != nil { - return result, fmt.Errorf("%s: Unable to understand list result %#v (%v)", g.Name, list, err) - } for _, item := range items { // need to verify that the item matches the set of scopes matchesScopes := true diff --git a/pkg/quota/install/BUILD b/pkg/quota/install/BUILD index 3df571704c..8055b14fa0 100644 --- a/pkg/quota/install/BUILD +++ b/pkg/quota/install/BUILD @@ -16,6 +16,7 @@ go_library( tags = ["automanaged"], deps = [ "//pkg/client/clientset_generated/internalclientset:go_default_library", + "//pkg/controller/informers:go_default_library", "//pkg/quota:go_default_library", "//pkg/quota/evaluator/core:go_default_library", ], diff --git a/pkg/quota/install/registry.go b/pkg/quota/install/registry.go index 46c46dd878..563702b441 100644 --- a/pkg/quota/install/registry.go +++ b/pkg/quota/install/registry.go @@ -18,13 +18,14 @@ package install import ( clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" + "k8s.io/kubernetes/pkg/controller/informers" "k8s.io/kubernetes/pkg/quota" "k8s.io/kubernetes/pkg/quota/evaluator/core" ) -// NewRegistry returns a registry that knows how to deal kubernetes resources -// across API groups -func NewRegistry(kubeClient clientset.Interface) quota.Registry { +// NewRegistry returns a registry of quota evaluators. +// If a shared informer factory is provided, it is used by evaluators rather than performing direct queries. +func NewRegistry(kubeClient clientset.Interface, f informers.SharedInformerFactory) quota.Registry { // TODO: when quota supports resources in other api groups, we will need to merge - return core.NewRegistry(kubeClient) + return core.NewRegistry(kubeClient, f) } diff --git a/plugin/pkg/admission/resourcequota/admission.go b/plugin/pkg/admission/resourcequota/admission.go index 244d338eef..b5c00b81ba 100644 --- a/plugin/pkg/admission/resourcequota/admission.go +++ b/plugin/pkg/admission/resourcequota/admission.go @@ -31,8 +31,9 @@ import ( func init() { admission.RegisterPlugin("ResourceQuota", func(client clientset.Interface, config io.Reader) (admission.Interface, error) { - registry := install.NewRegistry(client) - // TODO: expose a stop channel in admission factory + // NOTE: we do not provide informers to the registry because admission level decisions + // does not require us to open watches for all items tracked by quota. + registry := install.NewRegistry(client, nil) return NewResourceQuota(client, registry, 5, make(chan struct{})) }) } diff --git a/plugin/pkg/admission/resourcequota/admission_test.go b/plugin/pkg/admission/resourcequota/admission_test.go index 7138fd2da4..ed8c415a74 100644 --- a/plugin/pkg/admission/resourcequota/admission_test.go +++ b/plugin/pkg/admission/resourcequota/admission_test.go @@ -126,7 +126,7 @@ func TestAdmissionIgnoresDelete(t *testing.T) { kubeClient := fake.NewSimpleClientset() stopCh := make(chan struct{}) defer close(stopCh) - handler, err := NewResourceQuota(kubeClient, install.NewRegistry(kubeClient), 5, stopCh) + handler, err := NewResourceQuota(kubeClient, install.NewRegistry(kubeClient, nil), 5, stopCh) if err != nil { t.Errorf("Unexpected error %v", err) } @@ -158,7 +158,7 @@ func TestAdmissionIgnoresSubresources(t *testing.T) { quotaAccessor, _ := newQuotaAccessor(kubeClient) quotaAccessor.indexer = indexer go quotaAccessor.Run(stopCh) - evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient), nil, 5, stopCh) + evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient, nil), nil, 5, stopCh) handler := "aAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), @@ -201,7 +201,7 @@ func TestAdmitBelowQuotaLimit(t *testing.T) { quotaAccessor, _ := newQuotaAccessor(kubeClient) quotaAccessor.indexer = indexer go quotaAccessor.Run(stopCh) - evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient), nil, 5, stopCh) + evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient, nil), nil, 5, stopCh) handler := "aAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), @@ -283,7 +283,7 @@ func TestAdmitHandlesOldObjects(t *testing.T) { quotaAccessor, _ := newQuotaAccessor(kubeClient) quotaAccessor.indexer = indexer go quotaAccessor.Run(stopCh) - evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient), nil, 5, stopCh) + evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient, nil), nil, 5, stopCh) handler := "aAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), @@ -379,7 +379,7 @@ func TestAdmitHandlesCreatingUpdates(t *testing.T) { quotaAccessor, _ := newQuotaAccessor(kubeClient) quotaAccessor.indexer = indexer go quotaAccessor.Run(stopCh) - evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient), nil, 5, stopCh) + evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient, nil), nil, 5, stopCh) handler := "aAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), @@ -472,7 +472,7 @@ func TestAdmitExceedQuotaLimit(t *testing.T) { quotaAccessor, _ := newQuotaAccessor(kubeClient) quotaAccessor.indexer = indexer go quotaAccessor.Run(stopCh) - evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient), nil, 5, stopCh) + evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient, nil), nil, 5, stopCh) handler := "aAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), @@ -515,7 +515,7 @@ func TestAdmitEnforceQuotaConstraints(t *testing.T) { quotaAccessor, _ := newQuotaAccessor(kubeClient) quotaAccessor.indexer = indexer go quotaAccessor.Run(stopCh) - evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient), nil, 5, stopCh) + evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient, nil), nil, 5, stopCh) handler := "aAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), @@ -568,7 +568,7 @@ func TestAdmitPodInNamespaceWithoutQuota(t *testing.T) { quotaAccessor.indexer = indexer quotaAccessor.liveLookupCache = liveLookupCache go quotaAccessor.Run(stopCh) - evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient), nil, 5, stopCh) + evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient, nil), nil, 5, stopCh) handler := "aAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), @@ -633,7 +633,7 @@ func TestAdmitBelowTerminatingQuotaLimit(t *testing.T) { quotaAccessor, _ := newQuotaAccessor(kubeClient) quotaAccessor.indexer = indexer go quotaAccessor.Run(stopCh) - evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient), nil, 5, stopCh) + evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient, nil), nil, 5, stopCh) handler := "aAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), @@ -737,7 +737,7 @@ func TestAdmitBelowBestEffortQuotaLimit(t *testing.T) { quotaAccessor, _ := newQuotaAccessor(kubeClient) quotaAccessor.indexer = indexer go quotaAccessor.Run(stopCh) - evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient), nil, 5, stopCh) + evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient, nil), nil, 5, stopCh) handler := "aAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), @@ -828,7 +828,7 @@ func TestAdmitBestEffortQuotaLimitIgnoresBurstable(t *testing.T) { quotaAccessor, _ := newQuotaAccessor(kubeClient) quotaAccessor.indexer = indexer go quotaAccessor.Run(stopCh) - evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient), nil, 5, stopCh) + evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient, nil), nil, 5, stopCh) handler := "aAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), @@ -945,7 +945,7 @@ func TestAdmissionSetsMissingNamespace(t *testing.T) { quotaAccessor, _ := newQuotaAccessor(kubeClient) quotaAccessor.indexer = indexer go quotaAccessor.Run(stopCh) - evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient), nil, 5, stopCh) + evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient, nil), nil, 5, stopCh) evaluator.(*quotaEvaluator).registry = registry handler := "aAdmission{ @@ -990,7 +990,7 @@ func TestAdmitRejectsNegativeUsage(t *testing.T) { quotaAccessor, _ := newQuotaAccessor(kubeClient) quotaAccessor.indexer = indexer go quotaAccessor.Run(stopCh) - evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient), nil, 5, stopCh) + evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient, nil), nil, 5, stopCh) handler := "aAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), @@ -1035,7 +1035,7 @@ func TestAdmitWhenUnrelatedResourceExceedsQuota(t *testing.T) { quotaAccessor, _ := newQuotaAccessor(kubeClient) quotaAccessor.indexer = indexer go quotaAccessor.Run(stopCh) - evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient), nil, 5, stopCh) + evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(kubeClient, nil), nil, 5, stopCh) handler := "aAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), diff --git a/test/integration/quota/quota_test.go b/test/integration/quota/quota_test.go index 7ddd4240f5..0811c6fe8a 100644 --- a/test/integration/quota/quota_test.go +++ b/test/integration/quota/quota_test.go @@ -64,7 +64,7 @@ func TestQuota(t *testing.T) { admissionCh := make(chan struct{}) clientset := clientset.NewForConfigOrDie(&restclient.Config{QPS: -1, Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: ®istered.GroupOrDie(api.GroupName).GroupVersion}}) - admission, err := resourcequota.NewResourceQuota(clientset, quotainstall.NewRegistry(clientset), 5, admissionCh) + admission, err := resourcequota.NewResourceQuota(clientset, quotainstall.NewRegistry(clientset, nil), 5, admissionCh) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -85,7 +85,7 @@ func TestQuota(t *testing.T) { go replicationcontroller.NewReplicationManagerFromClientForIntegration(clientset, controller.NoResyncPeriodFunc, replicationcontroller.BurstReplicas, 4096). Run(3, controllerCh) - resourceQuotaRegistry := quotainstall.NewRegistry(clientset) + resourceQuotaRegistry := quotainstall.NewRegistry(clientset, nil) groupKindsToReplenish := []unversioned.GroupKind{ api.Kind("Pod"), }