mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-04 18:00:08 +00:00
Merge pull request #23280 from pweil-/limitrange-supportsfunc
Auto commit by PR queue bot
This commit is contained in:
commit
6441e1fc33
@ -43,16 +43,16 @@ const (
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
admission.RegisterPlugin("LimitRanger", func(client clientset.Interface, config io.Reader) (admission.Interface, error) {
|
admission.RegisterPlugin("LimitRanger", func(client clientset.Interface, config io.Reader) (admission.Interface, error) {
|
||||||
return NewLimitRanger(client, Limit)
|
return NewLimitRanger(client, &DefaultLimitRangerActions{})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// limitRanger enforces usage limits on a per resource basis in the namespace
|
// limitRanger enforces usage limits on a per resource basis in the namespace
|
||||||
type limitRanger struct {
|
type limitRanger struct {
|
||||||
*admission.Handler
|
*admission.Handler
|
||||||
client clientset.Interface
|
client clientset.Interface
|
||||||
limitFunc LimitFunc
|
actions LimitRangerActions
|
||||||
indexer cache.Indexer
|
indexer cache.Indexer
|
||||||
|
|
||||||
// liveLookups holds the last few live lookups we've done to help ammortize cost on repeated lookup failures.
|
// liveLookups holds the last few live lookups we've done to help ammortize cost on repeated lookup failures.
|
||||||
// This let's us handle the case of latent caches, by looking up actual results for a namespace on cache miss/no results.
|
// This let's us handle the case of latent caches, by looking up actual results for a namespace on cache miss/no results.
|
||||||
@ -68,14 +68,7 @@ type liveLookupEntry struct {
|
|||||||
|
|
||||||
// Admit admits resources into cluster that do not violate any defined LimitRange in the namespace
|
// Admit admits resources into cluster that do not violate any defined LimitRange in the namespace
|
||||||
func (l *limitRanger) Admit(a admission.Attributes) (err error) {
|
func (l *limitRanger) Admit(a admission.Attributes) (err error) {
|
||||||
|
if !l.actions.SupportsAttributes(a) {
|
||||||
// Ignore all calls to subresources
|
|
||||||
if a.GetSubresource() != "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore all calls that do not deal with pod resources since that is all this supports now.
|
|
||||||
if a.GetKind() != api.Kind("Pod") {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +123,12 @@ func (l *limitRanger) Admit(a admission.Attributes) (err error) {
|
|||||||
// ensure it meets each prescribed min/max
|
// ensure it meets each prescribed min/max
|
||||||
for i := range items {
|
for i := range items {
|
||||||
limitRange := items[i].(*api.LimitRange)
|
limitRange := items[i].(*api.LimitRange)
|
||||||
err = l.limitFunc(limitRange, a.GetResource().Resource, a.GetObject())
|
|
||||||
|
if !l.actions.SupportsLimit(limitRange) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err = l.actions.Limit(limitRange, a.GetResource().Resource, a.GetObject())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return admission.NewForbidden(a, err)
|
return admission.NewForbidden(a, err)
|
||||||
}
|
}
|
||||||
@ -139,7 +137,7 @@ func (l *limitRanger) Admit(a admission.Attributes) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewLimitRanger returns an object that enforces limits based on the supplied limit function
|
// NewLimitRanger returns an object that enforces limits based on the supplied limit function
|
||||||
func NewLimitRanger(client clientset.Interface, limitFunc LimitFunc) (admission.Interface, error) {
|
func NewLimitRanger(client clientset.Interface, actions LimitRangerActions) (admission.Interface, error) {
|
||||||
liveLookupCache, err := lru.New(10000)
|
liveLookupCache, err := lru.New(10000)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -155,10 +153,15 @@ func NewLimitRanger(client clientset.Interface, limitFunc LimitFunc) (admission.
|
|||||||
}
|
}
|
||||||
indexer, reflector := cache.NewNamespaceKeyedIndexerAndReflector(lw, &api.LimitRange{}, 0)
|
indexer, reflector := cache.NewNamespaceKeyedIndexerAndReflector(lw, &api.LimitRange{}, 0)
|
||||||
reflector.Run()
|
reflector.Run()
|
||||||
|
|
||||||
|
if actions == nil {
|
||||||
|
actions = &DefaultLimitRangerActions{}
|
||||||
|
}
|
||||||
|
|
||||||
return &limitRanger{
|
return &limitRanger{
|
||||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||||
client: client,
|
client: client,
|
||||||
limitFunc: limitFunc,
|
actions: actions,
|
||||||
indexer: indexer,
|
indexer: indexer,
|
||||||
liveLookupCache: liveLookupCache,
|
liveLookupCache: liveLookupCache,
|
||||||
liveTTL: time.Duration(30 * time.Second),
|
liveTTL: time.Duration(30 * time.Second),
|
||||||
@ -181,17 +184,6 @@ func Max(a int64, b int64) int64 {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limit enforces resource requirements of incoming resources against enumerated constraints
|
|
||||||
// on the LimitRange. It may modify the incoming object to apply default resource requirements
|
|
||||||
// if not specified, and enumerated on the LimitRange
|
|
||||||
func Limit(limitRange *api.LimitRange, resourceName string, obj runtime.Object) error {
|
|
||||||
switch resourceName {
|
|
||||||
case "pods":
|
|
||||||
return PodLimitFunc(limitRange, obj.(*api.Pod))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// defaultContainerResourceRequirements returns the default requirements for a container
|
// defaultContainerResourceRequirements returns the default requirements for a container
|
||||||
// the requirement.Limits are taken from the LimitRange defaults (if specified)
|
// the requirement.Limits are taken from the LimitRange defaults (if specified)
|
||||||
// the requirement.Requests are taken from the LimitRange default request (if specified)
|
// the requirement.Requests are taken from the LimitRange default request (if specified)
|
||||||
@ -383,6 +375,38 @@ func sum(inputs []api.ResourceList) api.ResourceList {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultLimitRangerActions is the default implementatation of LimitRangerActions.
|
||||||
|
type DefaultLimitRangerActions struct{}
|
||||||
|
|
||||||
|
// ensure DefaultLimitRangerActions implements the LimitRangerActions interface.
|
||||||
|
var _ LimitRangerActions = &DefaultLimitRangerActions{}
|
||||||
|
|
||||||
|
// Limit enforces resource requirements of incoming resources against enumerated constraints
|
||||||
|
// on the LimitRange. It may modify the incoming object to apply default resource requirements
|
||||||
|
// if not specified, and enumerated on the LimitRange
|
||||||
|
func (d *DefaultLimitRangerActions) Limit(limitRange *api.LimitRange, resourceName string, obj runtime.Object) error {
|
||||||
|
switch resourceName {
|
||||||
|
case "pods":
|
||||||
|
return PodLimitFunc(limitRange, obj.(*api.Pod))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SupportsAttributes ignores all calls that do not deal with pod resources since that is
|
||||||
|
// all this supports now. Also ignores any call that has a subresource defined.
|
||||||
|
func (d *DefaultLimitRangerActions) SupportsAttributes(a admission.Attributes) bool {
|
||||||
|
if a.GetSubresource() != "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.GetKind() == api.Kind("Pod")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SupportsLimit always returns true.
|
||||||
|
func (d *DefaultLimitRangerActions) SupportsLimit(limitRange *api.LimitRange) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// PodLimitFunc enforces resource requirements enumerated by the pod against
|
// PodLimitFunc enforces resource requirements enumerated by the pod against
|
||||||
// the specified LimitRange. The pod may be modified to apply default resource
|
// the specified LimitRange. The pod may be modified to apply default resource
|
||||||
// requirements if not specified, and enumerated on the LimitRange
|
// requirements if not specified, and enumerated on the LimitRange
|
||||||
|
@ -435,10 +435,10 @@ func TestLimitRangerIgnoresSubresource(t *testing.T) {
|
|||||||
client := fake.NewSimpleClientset()
|
client := fake.NewSimpleClientset()
|
||||||
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc})
|
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc})
|
||||||
handler := &limitRanger{
|
handler := &limitRanger{
|
||||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||||
client: client,
|
client: client,
|
||||||
limitFunc: Limit,
|
actions: &DefaultLimitRangerActions{},
|
||||||
indexer: indexer,
|
indexer: indexer,
|
||||||
}
|
}
|
||||||
|
|
||||||
limitRange := validLimitRangeNoDefaults()
|
limitRange := validLimitRangeNoDefaults()
|
||||||
@ -468,7 +468,7 @@ func TestLimitRangerCacheMisses(t *testing.T) {
|
|||||||
handler := &limitRanger{
|
handler := &limitRanger{
|
||||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||||
client: client,
|
client: client,
|
||||||
limitFunc: Limit,
|
actions: &DefaultLimitRangerActions{},
|
||||||
indexer: indexer,
|
indexer: indexer,
|
||||||
liveLookupCache: liveLookupCache,
|
liveLookupCache: liveLookupCache,
|
||||||
}
|
}
|
||||||
@ -502,7 +502,7 @@ func TestLimitRangerCacheAndLRUMisses(t *testing.T) {
|
|||||||
handler := &limitRanger{
|
handler := &limitRanger{
|
||||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||||
client: client,
|
client: client,
|
||||||
limitFunc: Limit,
|
actions: &DefaultLimitRangerActions{},
|
||||||
indexer: indexer,
|
indexer: indexer,
|
||||||
liveLookupCache: liveLookupCache,
|
liveLookupCache: liveLookupCache,
|
||||||
}
|
}
|
||||||
@ -532,7 +532,7 @@ func TestLimitRangerCacheAndLRUExpiredMisses(t *testing.T) {
|
|||||||
handler := &limitRanger{
|
handler := &limitRanger{
|
||||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||||
client: client,
|
client: client,
|
||||||
limitFunc: Limit,
|
actions: &DefaultLimitRangerActions{},
|
||||||
indexer: indexer,
|
indexer: indexer,
|
||||||
liveLookupCache: liveLookupCache,
|
liveLookupCache: liveLookupCache,
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,18 @@ limitations under the License.
|
|||||||
package limitranger
|
package limitranger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"k8s.io/kubernetes/pkg/admission"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
// LimitFunc is a pluggable function to enforce limits on the object
|
type LimitRangerActions interface {
|
||||||
type LimitFunc func(limitRange *api.LimitRange, kind string, obj runtime.Object) error
|
// Limit is a pluggable function to enforce limits on the object.
|
||||||
|
Limit(limitRange *api.LimitRange, kind string, obj runtime.Object) error
|
||||||
|
// SupportsAttributes is a pluggable function to allow overridding what resources the limitranger
|
||||||
|
// supports.
|
||||||
|
SupportsAttributes(attr admission.Attributes) bool
|
||||||
|
// SupportsLimit is a pluggable function to allow ignoring limits that should not be applied
|
||||||
|
// for any reason.
|
||||||
|
SupportsLimit(limitRange *api.LimitRange) bool
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user