mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Update admission control framework for quota
This commit is contained in:
parent
7f88e91892
commit
5b4ca14307
@ -506,11 +506,9 @@ func BuildAdmissionPluginInitializer(s *options.ServerRunOptions, client interna
|
||||
// TODO: use a dynamic restmapper. See https://github.com/kubernetes/kubernetes/pull/42615.
|
||||
restMapper := legacyscheme.Registry.RESTMapper()
|
||||
|
||||
// NOTE: we do not provide informers to the quota registry because admission level decisions
|
||||
// do not require us to open watches for all items tracked by quota.
|
||||
quotaRegistry := quotainstall.NewRegistry(nil, nil)
|
||||
quotaConfiguration := quotainstall.NewQuotaConfigurationForAdmission()
|
||||
|
||||
pluginInitializer := kubeapiserveradmission.NewPluginInitializer(client, sharedInformers, cloudConfig, restMapper, quotaRegistry, webhookAuthWrapper, serviceResolver)
|
||||
pluginInitializer := kubeapiserveradmission.NewPluginInitializer(client, sharedInformers, cloudConfig, restMapper, quotaConfiguration, webhookAuthWrapper, serviceResolver)
|
||||
|
||||
return pluginInitializer, nil
|
||||
}
|
||||
|
@ -53,9 +53,9 @@ type WantsRESTMapper interface {
|
||||
SetRESTMapper(meta.RESTMapper)
|
||||
}
|
||||
|
||||
// WantsQuotaRegistry defines a function which sets quota registry for admission plugins that need it.
|
||||
type WantsQuotaRegistry interface {
|
||||
SetQuotaRegistry(quota.Registry)
|
||||
// WantsQuotaConfiguration defines a function which sets quota configuration for admission plugins that need it.
|
||||
type WantsQuotaConfiguration interface {
|
||||
SetQuotaConfiguration(quota.Configuration)
|
||||
admission.Validator
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ type PluginInitializer struct {
|
||||
authorizer authorizer.Authorizer
|
||||
cloudConfig []byte
|
||||
restMapper meta.RESTMapper
|
||||
quotaRegistry quota.Registry
|
||||
quotaConfiguration quota.Configuration
|
||||
serviceResolver webhook.ServiceResolver
|
||||
authenticationInfoResolverWrapper webhook.AuthenticationInfoResolverWrapper
|
||||
}
|
||||
@ -100,7 +100,7 @@ func NewPluginInitializer(
|
||||
sharedInformers informers.SharedInformerFactory,
|
||||
cloudConfig []byte,
|
||||
restMapper meta.RESTMapper,
|
||||
quotaRegistry quota.Registry,
|
||||
quotaConfiguration quota.Configuration,
|
||||
authenticationInfoResolverWrapper webhook.AuthenticationInfoResolverWrapper,
|
||||
serviceResolver webhook.ServiceResolver,
|
||||
) *PluginInitializer {
|
||||
@ -109,7 +109,7 @@ func NewPluginInitializer(
|
||||
informers: sharedInformers,
|
||||
cloudConfig: cloudConfig,
|
||||
restMapper: restMapper,
|
||||
quotaRegistry: quotaRegistry,
|
||||
quotaConfiguration: quotaConfiguration,
|
||||
authenticationInfoResolverWrapper: authenticationInfoResolverWrapper,
|
||||
serviceResolver: serviceResolver,
|
||||
}
|
||||
@ -134,8 +134,8 @@ func (i *PluginInitializer) Initialize(plugin admission.Interface) {
|
||||
wants.SetRESTMapper(i.restMapper)
|
||||
}
|
||||
|
||||
if wants, ok := plugin.(WantsQuotaRegistry); ok {
|
||||
wants.SetQuotaRegistry(i.quotaRegistry)
|
||||
if wants, ok := plugin.(WantsQuotaConfiguration); ok {
|
||||
wants.SetQuotaConfiguration(i.quotaConfiguration)
|
||||
}
|
||||
|
||||
if wants, ok := plugin.(WantsServiceResolver); ok {
|
||||
|
@ -23,6 +23,7 @@ go_library(
|
||||
"//pkg/client/listers/core/internalversion:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//pkg/quota:go_default_library",
|
||||
"//pkg/quota/generic:go_default_library",
|
||||
"//pkg/util/reflector/prometheus:go_default_library",
|
||||
"//pkg/util/workqueue/prometheus:go_default_library",
|
||||
"//plugin/pkg/admission/resourcequota/apis/resourcequota:go_default_library",
|
||||
@ -58,14 +59,11 @@ go_test(
|
||||
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/controller:go_default_library",
|
||||
"//pkg/quota:go_default_library",
|
||||
"//pkg/quota/generic:go_default_library",
|
||||
"//pkg/quota/install:go_default_library",
|
||||
"//plugin/pkg/admission/resourcequota/apis/resourcequota:go_default_library",
|
||||
"//vendor/github.com/hashicorp/golang-lru:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
|
@ -53,16 +53,16 @@ func Register(plugins *admission.Plugins) {
|
||||
// quotaAdmission implements an admission controller that can enforce quota constraints
|
||||
type quotaAdmission struct {
|
||||
*admission.Handler
|
||||
config *resourcequotaapi.Configuration
|
||||
stopCh <-chan struct{}
|
||||
registry quota.Registry
|
||||
numEvaluators int
|
||||
quotaAccessor *quotaAccessor
|
||||
evaluator Evaluator
|
||||
config *resourcequotaapi.Configuration
|
||||
stopCh <-chan struct{}
|
||||
quotaConfiguration quota.Configuration
|
||||
numEvaluators int
|
||||
quotaAccessor *quotaAccessor
|
||||
evaluator Evaluator
|
||||
}
|
||||
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeClientSet("aAdmission{})
|
||||
var _ = kubeapiserveradmission.WantsQuotaRegistry("aAdmission{})
|
||||
var _ = kubeapiserveradmission.WantsQuotaConfiguration("aAdmission{})
|
||||
|
||||
type liveLookupEntry struct {
|
||||
expiry time.Time
|
||||
@ -95,9 +95,9 @@ func (a *quotaAdmission) SetInternalKubeInformerFactory(f informers.SharedInform
|
||||
a.quotaAccessor.lister = f.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
}
|
||||
|
||||
func (a *quotaAdmission) SetQuotaRegistry(r quota.Registry) {
|
||||
a.registry = r
|
||||
a.evaluator = NewQuotaEvaluator(a.quotaAccessor, a.registry, nil, a.config, a.numEvaluators, a.stopCh)
|
||||
func (a *quotaAdmission) SetQuotaConfiguration(c quota.Configuration) {
|
||||
a.quotaConfiguration = c
|
||||
a.evaluator = NewQuotaEvaluator(a.quotaAccessor, a.quotaConfiguration, nil, a.config, a.numEvaluators, a.stopCh)
|
||||
}
|
||||
|
||||
// Validate ensures an authorizer is set.
|
||||
@ -111,8 +111,8 @@ func (a *quotaAdmission) Validate() error {
|
||||
if a.quotaAccessor.lister == nil {
|
||||
return fmt.Errorf("missing quotaAccessor.lister")
|
||||
}
|
||||
if a.registry == nil {
|
||||
return fmt.Errorf("missing registry")
|
||||
if a.quotaConfiguration == nil {
|
||||
return fmt.Errorf("missing quotaConfiguration")
|
||||
}
|
||||
if a.evaluator == nil {
|
||||
return fmt.Errorf("missing evaluator")
|
||||
@ -126,5 +126,9 @@ func (a *quotaAdmission) Admit(attr admission.Attributes) (err error) {
|
||||
if attr.GetSubresource() != "" {
|
||||
return nil
|
||||
}
|
||||
// ignore all operations that are not namespaced
|
||||
if attr.GetNamespace() == "" {
|
||||
return nil
|
||||
}
|
||||
return a.evaluator.Evaluate(attr)
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ import (
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
@ -36,8 +35,6 @@ import (
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
"k8s.io/kubernetes/pkg/quota"
|
||||
"k8s.io/kubernetes/pkg/quota/generic"
|
||||
"k8s.io/kubernetes/pkg/quota/install"
|
||||
resourcequotaapi "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota"
|
||||
)
|
||||
@ -135,7 +132,8 @@ func TestAdmissionIgnoresDelete(t *testing.T) {
|
||||
quotaAccessor.client = kubeClient
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -170,7 +168,8 @@ func TestAdmissionIgnoresSubresources(t *testing.T) {
|
||||
quotaAccessor.client = kubeClient
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -214,7 +213,8 @@ func TestAdmitBelowQuotaLimit(t *testing.T) {
|
||||
quotaAccessor.client = kubeClient
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -297,7 +297,8 @@ func TestAdmitHandlesOldObjects(t *testing.T) {
|
||||
quotaAccessor.client = kubeClient
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -403,7 +404,8 @@ func TestAdmitHandlesNegativePVCUpdates(t *testing.T) {
|
||||
quotaAccessor.client = kubeClient
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -469,7 +471,8 @@ func TestAdmitHandlesPVCUpdates(t *testing.T) {
|
||||
quotaAccessor.client = kubeClient
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -567,7 +570,8 @@ func TestAdmitHandlesCreatingUpdates(t *testing.T) {
|
||||
quotaAccessor.client = kubeClient
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -661,7 +665,8 @@ func TestAdmitExceedQuotaLimit(t *testing.T) {
|
||||
quotaAccessor.client = kubeClient
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -705,7 +710,8 @@ func TestAdmitEnforceQuotaConstraints(t *testing.T) {
|
||||
quotaAccessor.client = kubeClient
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -759,7 +765,8 @@ func TestAdmitPodInNamespaceWithoutQuota(t *testing.T) {
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
quotaAccessor.liveLookupCache = liveLookupCache
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -825,7 +832,8 @@ func TestAdmitBelowTerminatingQuotaLimit(t *testing.T) {
|
||||
quotaAccessor.client = kubeClient
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -930,7 +938,8 @@ func TestAdmitBelowBestEffortQuotaLimit(t *testing.T) {
|
||||
quotaAccessor.client = kubeClient
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -1022,7 +1031,8 @@ func TestAdmitBestEffortQuotaLimitIgnoresBurstable(t *testing.T) {
|
||||
quotaAccessor.client = kubeClient
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -1098,17 +1108,6 @@ func TestAdmissionSetsMissingNamespace(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
// create a dummy evaluator so we can trigger quota
|
||||
podEvaluator := &generic.ObjectCountEvaluator{
|
||||
AllowCreateOnUpdate: false,
|
||||
InternalGroupKind: api.Kind("Pod"),
|
||||
ResourceName: api.ResourcePods,
|
||||
}
|
||||
registry := &generic.GenericRegistry{
|
||||
InternalEvaluators: map[schema.GroupKind]quota.Evaluator{
|
||||
podEvaluator.GroupKind(): podEvaluator,
|
||||
},
|
||||
}
|
||||
stopCh := make(chan struct{})
|
||||
defer close(stopCh)
|
||||
|
||||
@ -1118,8 +1117,8 @@ func TestAdmissionSetsMissingNamespace(t *testing.T) {
|
||||
quotaAccessor.client = kubeClient
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
evaluator.(*quotaEvaluator).registry = registry
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -1164,7 +1163,8 @@ func TestAdmitRejectsNegativeUsage(t *testing.T) {
|
||||
quotaAccessor.client = kubeClient
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -1210,7 +1210,8 @@ func TestAdmitWhenUnrelatedResourceExceedsQuota(t *testing.T) {
|
||||
quotaAccessor.client = kubeClient
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -1246,7 +1247,8 @@ func TestAdmitLimitedResourceNoQuota(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -1279,7 +1281,8 @@ func TestAdmitLimitedResourceNoQuotaIgnoresNonMatchingResources(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -1325,7 +1328,8 @@ func TestAdmitLimitedResourceWithQuota(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -1383,7 +1387,8 @@ func TestAdmitLimitedResourceWithMultipleQuota(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -1431,7 +1436,8 @@ func TestAdmitLimitedResourceWithQuotaThatDoesNotCover(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, install.NewRegistry(nil, nil), nil, config, 5, stopCh)
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
|
||||
handler := "aAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
|
@ -34,6 +34,7 @@ import (
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/quota"
|
||||
"k8s.io/kubernetes/pkg/quota/generic"
|
||||
_ "k8s.io/kubernetes/pkg/util/reflector/prometheus" // for reflector metric registration
|
||||
_ "k8s.io/kubernetes/pkg/util/workqueue/prometheus" // for workqueue metric registration
|
||||
resourcequotaapi "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota"
|
||||
@ -51,6 +52,9 @@ type quotaEvaluator struct {
|
||||
// lockAcquisitionFunc acquires any required locks and returns a cleanup method to defer
|
||||
lockAcquisitionFunc func([]api.ResourceQuota) func()
|
||||
|
||||
// how quota was configured
|
||||
quotaConfiguration quota.Configuration
|
||||
|
||||
// registry that knows how to measure usage for objects
|
||||
registry quota.Registry
|
||||
|
||||
@ -106,16 +110,18 @@ func newAdmissionWaiter(a admission.Attributes) *admissionWaiter {
|
||||
// NewQuotaEvaluator configures an admission controller that can enforce quota constraints
|
||||
// using the provided registry. The registry must have the capability to handle group/kinds that
|
||||
// are persisted by the server this admission controller is intercepting
|
||||
func NewQuotaEvaluator(quotaAccessor QuotaAccessor, registry quota.Registry, lockAcquisitionFunc func([]api.ResourceQuota) func(), config *resourcequotaapi.Configuration, workers int, stopCh <-chan struct{}) Evaluator {
|
||||
func NewQuotaEvaluator(quotaAccessor QuotaAccessor, quotaConfiguration quota.Configuration, lockAcquisitionFunc func([]api.ResourceQuota) func(), config *resourcequotaapi.Configuration, workers int, stopCh <-chan struct{}) Evaluator {
|
||||
// if we get a nil config, just create an empty default.
|
||||
if config == nil {
|
||||
config = &resourcequotaapi.Configuration{}
|
||||
}
|
||||
|
||||
return "aEvaluator{
|
||||
quotaAccessor: quotaAccessor,
|
||||
lockAcquisitionFunc: lockAcquisitionFunc,
|
||||
|
||||
registry: registry,
|
||||
quotaConfiguration: quotaConfiguration,
|
||||
registry: generic.NewRegistry(quotaConfiguration.Evaluators()),
|
||||
|
||||
queue: workqueue.NewNamed("admission_quota_controller"),
|
||||
work: map[string][]*admissionWaiter{},
|
||||
@ -365,9 +371,8 @@ func limitedByDefault(usage api.ResourceList, limitedResources []resourcequotaap
|
||||
// that capture what the usage would be if the request succeeded. It return an error if there is insufficient quota to satisfy the request
|
||||
func (e *quotaEvaluator) checkRequest(quotas []api.ResourceQuota, a admission.Attributes) ([]api.ResourceQuota, error) {
|
||||
namespace := a.GetNamespace()
|
||||
evaluators := e.registry.Evaluators()
|
||||
evaluator, found := evaluators[a.GetKind().GroupKind()]
|
||||
if !found {
|
||||
evaluator := e.registry.Get(a.GetResource().GroupResource())
|
||||
if evaluator == nil {
|
||||
return quotas, nil
|
||||
}
|
||||
|
||||
@ -516,18 +521,27 @@ func (e *quotaEvaluator) Evaluate(a admission.Attributes) error {
|
||||
go e.run()
|
||||
})
|
||||
|
||||
// if we do not know how to evaluate use for this kind, just ignore
|
||||
evaluators := e.registry.Evaluators()
|
||||
evaluator, found := evaluators[a.GetKind().GroupKind()]
|
||||
if !found {
|
||||
// is this resource ignored?
|
||||
gvr := a.GetResource()
|
||||
gr := gvr.GroupResource()
|
||||
if _, ok := e.quotaConfiguration.IgnoredResources()[gr]; ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
// if we do not know how to evaluate use for this resource, create an evaluator
|
||||
evaluator := e.registry.Get(gr)
|
||||
if evaluator == nil {
|
||||
// create an object count evaluator if no evaluator previously registered
|
||||
// note, we do not need aggregate usage here, so we pass a nil infomer func
|
||||
evaluator = generic.NewObjectCountEvaluator(false, gr, nil, "")
|
||||
e.registry.Add(evaluator)
|
||||
glog.Infof("quota admission added evaluator for: %s", gr)
|
||||
}
|
||||
// for this kind, check if the operation could mutate any quota resources
|
||||
// if no resources tracked by quota are impacted, then just return
|
||||
if !evaluator.Handles(a) {
|
||||
return nil
|
||||
}
|
||||
|
||||
waiter := newAdmissionWaiter(a)
|
||||
|
||||
e.addWork(waiter)
|
||||
|
Loading…
Reference in New Issue
Block a user