mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-01-29 21:29:24 +00:00
Make admission control plug-ins work from indexes
This commit is contained in:
@@ -23,10 +23,13 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/admission"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
apierrors "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/cache"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -39,6 +42,7 @@ func init() {
|
||||
type limitRanger struct {
|
||||
client client.Interface
|
||||
limitFunc LimitFunc
|
||||
indexer cache.Indexer
|
||||
}
|
||||
|
||||
// Admit admits resources into cluster that do not violate any defined LimitRange in the namespace
|
||||
@@ -48,16 +52,30 @@ func (l *limitRanger) Admit(a admission.Attributes) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// look for a limit range in current namespace that requires enforcement
|
||||
// TODO: Move to cache when issue is resolved: https://github.com/GoogleCloudPlatform/kubernetes/issues/2294
|
||||
items, err := l.client.LimitRanges(a.GetNamespace()).List(labels.Everything())
|
||||
obj := a.GetObject()
|
||||
resource := a.GetResource()
|
||||
name := "Unknown"
|
||||
if obj != nil {
|
||||
name, _ = meta.NewAccessor().Name(obj)
|
||||
}
|
||||
|
||||
key := &api.LimitRange{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Namespace: a.GetNamespace(),
|
||||
Name: "",
|
||||
},
|
||||
}
|
||||
items, err := l.indexer.Index("namespace", key)
|
||||
if err != nil {
|
||||
return err
|
||||
return apierrors.NewForbidden(a.GetResource(), name, fmt.Errorf("Unable to %s %s at this time because there was an error enforcing limit ranges", a.GetOperation(), resource))
|
||||
}
|
||||
if len(items) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ensure it meets each prescribed min/max
|
||||
for i := range items.Items {
|
||||
limitRange := &items.Items[i]
|
||||
for i := range items {
|
||||
limitRange := items[i].(*api.LimitRange)
|
||||
err = l.limitFunc(limitRange, a.GetResource(), a.GetObject())
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -68,7 +86,17 @@ func (l *limitRanger) Admit(a admission.Attributes) (err error) {
|
||||
|
||||
// NewLimitRanger returns an object that enforces limits based on the supplied limit function
|
||||
func NewLimitRanger(client client.Interface, limitFunc LimitFunc) admission.Interface {
|
||||
return &limitRanger{client: client, limitFunc: limitFunc}
|
||||
lw := &cache.ListWatch{
|
||||
ListFunc: func() (runtime.Object, error) {
|
||||
return client.LimitRanges(api.NamespaceAll).List(labels.Everything())
|
||||
},
|
||||
WatchFunc: func(resourceVersion string) (watch.Interface, error) {
|
||||
return client.LimitRanges(api.NamespaceAll).Watch(labels.Everything(), labels.Everything(), resourceVersion)
|
||||
},
|
||||
}
|
||||
indexer, reflector := cache.NewNamespaceKeyedIndexerAndReflector(lw, &api.LimitRange{}, 0)
|
||||
reflector.Run()
|
||||
return &limitRanger{client: client, limitFunc: limitFunc, indexer: indexer}
|
||||
}
|
||||
|
||||
func Min(a int64, b int64) int64 {
|
||||
|
||||
@@ -82,7 +82,6 @@ func (e *exists) Admit(a admission.Attributes) (err error) {
|
||||
|
||||
func NewExists(c client.Interface) admission.Interface {
|
||||
store := cache.NewStore(cache.MetaNamespaceKeyFunc)
|
||||
// TODO: look into a list/watch that can work with client.Interface, maybe pass it a ListFunc and a WatchFunc
|
||||
reflector := cache.NewReflector(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func() (runtime.Object, error) {
|
||||
|
||||
@@ -26,8 +26,11 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/cache"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/resourcequota"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -37,11 +40,22 @@ func init() {
|
||||
}
|
||||
|
||||
type quota struct {
|
||||
client client.Interface
|
||||
client client.Interface
|
||||
indexer cache.Indexer
|
||||
}
|
||||
|
||||
func NewResourceQuota(client client.Interface) admission.Interface {
|
||||
return "a{client: client}
|
||||
lw := &cache.ListWatch{
|
||||
ListFunc: func() (runtime.Object, error) {
|
||||
return client.ResourceQuotas(api.NamespaceAll).List(labels.Everything())
|
||||
},
|
||||
WatchFunc: func(resourceVersion string) (watch.Interface, error) {
|
||||
return client.ResourceQuotas(api.NamespaceAll).Watch(labels.Everything(), labels.Everything(), resourceVersion)
|
||||
},
|
||||
}
|
||||
indexer, reflector := cache.NewNamespaceKeyedIndexerAndReflector(lw, &api.ResourceQuota{}, 0)
|
||||
reflector.Run()
|
||||
return "a{client: client, indexer: indexer}
|
||||
}
|
||||
|
||||
var resourceToResourceName = map[string]api.ResourceName{
|
||||
@@ -63,18 +77,36 @@ func (q *quota) Admit(a admission.Attributes) (err error) {
|
||||
name, _ = meta.NewAccessor().Name(obj)
|
||||
}
|
||||
|
||||
list, err := q.client.ResourceQuotas(a.GetNamespace()).List(labels.Everything())
|
||||
key := &api.ResourceQuota{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Namespace: a.GetNamespace(),
|
||||
Name: "",
|
||||
},
|
||||
}
|
||||
items, err := q.indexer.Index("namespace", key)
|
||||
if err != nil {
|
||||
return apierrors.NewForbidden(a.GetResource(), name, fmt.Errorf("Unable to %s %s at this time because there was an error enforcing quota", a.GetOperation(), resource))
|
||||
}
|
||||
|
||||
if len(list.Items) == 0 {
|
||||
if len(items) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := range list.Items {
|
||||
quota := list.Items[i]
|
||||
dirty, err := IncrementUsage(a, "a.Status, q.client)
|
||||
for i := range items {
|
||||
quota := items[i].(*api.ResourceQuota)
|
||||
|
||||
// we cannot modify the value directly in the cache, so we copy
|
||||
status := &api.ResourceQuotaStatus{
|
||||
Hard: api.ResourceList{},
|
||||
Used: api.ResourceList{},
|
||||
}
|
||||
for k, v := range quota.Status.Hard {
|
||||
status.Hard[k] = *v.Copy()
|
||||
}
|
||||
for k, v := range quota.Status.Used {
|
||||
status.Used[k] = *v.Copy()
|
||||
}
|
||||
|
||||
dirty, err := IncrementUsage(a, status, q.client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -87,7 +119,7 @@ func (q *quota) Admit(a admission.Attributes) (err error) {
|
||||
Namespace: quota.Namespace,
|
||||
ResourceVersion: quota.ResourceVersion},
|
||||
}
|
||||
usage.Status = quota.Status
|
||||
usage.Status = *status
|
||||
err = q.client.ResourceQuotaUsages(usage.Namespace).Create(&usage)
|
||||
if err != nil {
|
||||
return apierrors.NewForbidden(a.GetResource(), name, fmt.Errorf("Unable to %s %s at this time because there was an error enforcing quota", a.GetOperation(), a.GetResource()))
|
||||
|
||||
Reference in New Issue
Block a user