Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add LimitRange informer #33856

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 39 additions & 0 deletions pkg/client/cache/listers_core.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,42 @@ func (s *StoreToReplicationControllerLister) GetPodControllers(pod *api.Pod) (co
}
return
}

// StoreToLimitRangeLister helps list limit ranges
type StoreToLimitRangeLister struct {
Indexer Indexer
}

func (s *StoreToLimitRangeLister) List(selector labels.Selector) (ret []*api.LimitRange, err error) {
err = ListAll(s.Indexer, selector, func(m interface{}) {
ret = append(ret, m.(*api.LimitRange))
})
return ret, err
}

func (s *StoreToLimitRangeLister) LimitRanges(namespace string) storeLimitRangesNamespacer {
return storeLimitRangesNamespacer{s.Indexer, namespace}
}

type storeLimitRangesNamespacer struct {
indexer Indexer
namespace string
}

func (s storeLimitRangesNamespacer) List(selector labels.Selector) (ret []*api.LimitRange, err error) {
err = ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
ret = append(ret, m.(*api.LimitRange))
})
return ret, err
}

func (s storeLimitRangesNamespacer) Get(name string) (*api.LimitRange, error) {
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(api.Resource("limitrange"), name)
}
return obj.(*api.LimitRange), nil
}
54 changes: 54 additions & 0 deletions pkg/controller/informers/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,42 @@ func (f *pvInformer) Lister() *cache.StoreToPVFetcher {
return &cache.StoreToPVFetcher{Store: informer.GetStore()}
}

//*****************************************************************************

// LimitRangeInformer is type of SharedIndexInformer which watches and lists all limit ranges.
// Interface provides constructor for informer and lister for limit ranges.
type LimitRangeInformer interface {
Informer() cache.SharedIndexInformer
Lister() *cache.StoreToLimitRangeLister
}

type limitRangeInformer struct {
*sharedInformerFactory
}

// Informer checks whether pvcInformer exists in sharedInformerFactory and if not, it creates new informer of type
// limitRangeInformer and connects it to sharedInformerFactory
func (f *limitRangeInformer) Informer() cache.SharedIndexInformer {
f.lock.Lock()
defer f.lock.Unlock()

informerType := reflect.TypeOf(&api.LimitRange{})
informer, exists := f.informers[informerType]
if exists {
return informer
}
informer = NewLimitRangeInformer(f.client, f.defaultResync)
f.informers[informerType] = informer

return informer
}

// Lister returns lister for limitRangeInformer
func (f *limitRangeInformer) Lister() *cache.StoreToLimitRangeLister {
informer := f.Informer()
return &cache.StoreToLimitRangeLister{Indexer: informer.GetIndexer()}
}

// NewPodInformer returns a SharedIndexInformer that lists and watches all pods
func NewPodInformer(client clientset.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
sharedIndexInformer := cache.NewSharedIndexInformer(
Expand Down Expand Up @@ -295,3 +331,21 @@ func NewNamespaceInformer(client clientset.Interface, resyncPeriod time.Duration

return sharedIndexInformer
}

// NewLimitRangeInformer returns a SharedIndexInformer that lists and watches all LimitRanges
func NewLimitRangeInformer(client clientset.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to eliminate these methods and inline this in the Informer method.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i assume we can move everyone into their Informer in a single PR in a follow-on.

sharedIndexInformer := cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
return client.Core().LimitRanges(api.NamespaceAll).List(options)
},
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
return client.Core().LimitRanges(api.NamespaceAll).Watch(options)
},
},
&api.LimitRange{},
resyncPeriod,
cache.Indexers{})

return sharedIndexInformer
}
8 changes: 8 additions & 0 deletions pkg/controller/informers/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ type SharedInformerFactory interface {
ClusterRoleBindings() ClusterRoleBindingInformer
Roles() RoleInformer
RoleBindings() RoleBindingInformer

LimitRanges() LimitRangeInformer
}

type sharedInformerFactory struct {
Expand Down Expand Up @@ -106,6 +108,7 @@ func (f *sharedInformerFactory) PersistentVolumes() PVInformer {
return &pvInformer{sharedInformerFactory: f}
}

// DaemonSets returns a SharedIndexInformer that lists and watches all daemon sets.
func (f *sharedInformerFactory) DaemonSets() DaemonSetInformer {
return &daemonSetInformer{sharedInformerFactory: f}
}
Expand Down Expand Up @@ -133,3 +136,8 @@ func (f *sharedInformerFactory) Roles() RoleInformer {
func (f *sharedInformerFactory) RoleBindings() RoleBindingInformer {
return &roleBindingInformer{sharedInformerFactory: f}
}

// LimitRanges returns a SharedIndexInformer that lists and watches all limit ranges.
func (f *sharedInformerFactory) LimitRanges() LimitRangeInformer {
return &limitRangeInformer{sharedInformerFactory: f}
}
40 changes: 18 additions & 22 deletions plugin/pkg/admission/limitranger/admission.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,16 @@ import (
lru "github.com/hashicorp/golang-lru"

clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/controller/informers"

"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/client/cache"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/runtime"
utilerrors "k8s.io/kubernetes/pkg/util/errors"
"k8s.io/kubernetes/pkg/watch"
)

const (
Expand All @@ -52,7 +53,7 @@ type limitRanger struct {
*admission.Handler
client clientset.Interface
actions LimitRangerActions
indexer cache.Indexer
lister *cache.StoreToLimitRangeLister

// 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.
Expand All @@ -66,6 +67,19 @@ type liveLookupEntry struct {
items []*api.LimitRange
}

func (l *limitRanger) SetInformerFactory(f informers.SharedInformerFactory) {
limitRangeInformer := f.LimitRanges().Informer()
l.SetReadyFunc(limitRangeInformer.HasSynced)
l.lister = f.LimitRanges().Lister()
}

func (l *limitRanger) Validate() error {
if l.lister == nil {
return fmt.Errorf("missing limitRange lister")
}
return nil
}

// Admit admits resources into cluster that do not violate any defined LimitRange in the namespace
func (l *limitRanger) Admit(a admission.Attributes) (err error) {
if !l.actions.SupportsAttributes(a) {
Expand All @@ -81,13 +95,7 @@ func (l *limitRanger) Admit(a admission.Attributes) (err error) {
}
}

key := &api.LimitRange{
ObjectMeta: api.ObjectMeta{
Namespace: a.GetNamespace(),
Name: "",
},
}
items, err := l.indexer.Index("namespace", key)
items, err := l.lister.LimitRanges(a.GetNamespace()).List(labels.Everything())
if err != nil {
return admission.NewForbidden(a, fmt.Errorf("unable to %s %v at this time because there was an error enforcing limit ranges", a.GetOperation(), a.GetResource()))
}
Expand Down Expand Up @@ -122,7 +130,7 @@ func (l *limitRanger) Admit(a admission.Attributes) (err error) {

// ensure it meets each prescribed min/max
for i := range items {
limitRange := items[i].(*api.LimitRange)
limitRange := items[i]

if !l.actions.SupportsLimit(limitRange) {
continue
Expand All @@ -143,17 +151,6 @@ func NewLimitRanger(client clientset.Interface, actions LimitRangerActions) (adm
return nil, err
}

lw := &cache.ListWatch{
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
return client.Core().LimitRanges(api.NamespaceAll).List(options)
},
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
return client.Core().LimitRanges(api.NamespaceAll).Watch(options)
},
}
indexer, reflector := cache.NewNamespaceKeyedIndexerAndReflector(lw, &api.LimitRange{}, 0)
reflector.Run()

if actions == nil {
actions = &DefaultLimitRangerActions{}
}
Expand All @@ -162,7 +159,6 @@ func NewLimitRanger(client clientset.Interface, actions LimitRangerActions) (adm
Handler: admission.NewHandler(admission.Create, admission.Update),
client: client,
actions: actions,
indexer: indexer,
liveLookupCache: liveLookupCache,
liveTTL: time.Duration(30 * time.Second),
}, nil
Expand Down