Merge pull request #26709 from hodovska/master

Automatic merge from submit-queue

Allow shareable resources for admission control plugins.

Changes allow admission control plugins to share resources. This is done via new PluginInitialization structure. The structure can be extended for other resources, for now it is an shared informer for namespace plugins (NamespiceLifecycle, NamespaceAutoProvisioning, NamespaceExists).

If a plugins needs some kind of shared resource e.g. client, the client shall be added to PluginInitializer and Wants methods implemented to every plugin which will use it.
This commit is contained in:
k8s-merge-robot
2016-07-22 11:07:05 -07:00
committed by GitHub
11 changed files with 567 additions and 65 deletions

View File

@@ -0,0 +1,273 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package informers
import (
"reflect"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/cache"
"k8s.io/kubernetes/pkg/controller/framework"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/watch"
)
// PodInformer is type of SharedIndexInformer which watches and lists all pods.
// Interface provides constructor for informer and lister for pods
type PodInformer interface {
Informer() framework.SharedIndexInformer
Lister() *cache.StoreToPodLister
}
type podInformer struct {
*sharedInformerFactory
}
// Informer checks whether podInformer exists in sharedInformerFactory and if not, it creates new informer of type
// podInformer and connects it to sharedInformerFactory
func (f *podInformer) Informer() framework.SharedIndexInformer {
f.lock.Lock()
defer f.lock.Unlock()
informerObj := &api.Pod{}
informerType := reflect.TypeOf(informerObj)
informer, exists := f.informers[informerType]
if exists {
return informer
}
informer = framework.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
return f.client.Core().Pods(api.NamespaceAll).List(options)
},
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
return f.client.Core().Pods(api.NamespaceAll).Watch(options)
},
},
informerObj,
f.defaultResync,
cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc},
)
f.informers[informerType] = informer
return informer
}
// Lister returns lister for podInformer
func (f *podInformer) Lister() *cache.StoreToPodLister {
informer := f.Informer()
return &cache.StoreToPodLister{Indexer: informer.GetIndexer()}
}
//*****************************************************************************
// NamespaceInformer is type of SharedIndexInformer which watches and lists all namespaces.
// Interface provides constructor for informer and lister for namsespaces
type NamespaceInformer interface {
Informer() framework.SharedIndexInformer
Lister() *cache.IndexerToNamespaceLister
}
type namespaceInformer struct {
*sharedInformerFactory
}
// Informer checks whether namespaceInformer exists in sharedInformerFactory and if not, it creates new informer of type
// namespaceInformer and connects it to sharedInformerFactory
func (f *namespaceInformer) Informer() framework.SharedIndexInformer {
f.lock.Lock()
defer f.lock.Unlock()
informerObj := &api.Namespace{}
informerType := reflect.TypeOf(informerObj)
informer, exists := f.informers[informerType]
if exists {
return informer
}
informer = framework.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
return f.client.Core().Namespaces().List(options)
},
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
return f.client.Core().Namespaces().Watch(options)
},
},
informerObj,
f.defaultResync,
cache.Indexers{},
)
f.informers[informerType] = informer
return informer
}
// Lister returns lister for namespaceInformer
func (f *namespaceInformer) Lister() *cache.IndexerToNamespaceLister {
informer := f.Informer()
return &cache.IndexerToNamespaceLister{Indexer: informer.GetIndexer()}
}
//*****************************************************************************
// NodeInformer is type of SharedIndexInformer which watches and lists all nodes.
// Interface provides constructor for informer and lister for nodes
type NodeInformer interface {
Informer() framework.SharedIndexInformer
Lister() *cache.StoreToNodeLister
}
type nodeInformer struct {
*sharedInformerFactory
}
// Informer checks whether nodeInformer exists in sharedInformerFactory and if not, it creates new informer of type
// nodeInformer and connects it to sharedInformerFactory
func (f *nodeInformer) Informer() framework.SharedIndexInformer {
f.lock.Lock()
defer f.lock.Unlock()
informerObj := &api.Node{}
informerType := reflect.TypeOf(informerObj)
informer, exists := f.informers[informerType]
if exists {
return informer
}
informer = framework.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
return f.client.Core().Nodes().List(options)
},
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
return f.client.Core().Nodes().Watch(options)
},
},
informerObj,
f.defaultResync,
cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc},
)
f.informers[informerType] = informer
return informer
}
// Lister returns lister for nodeInformer
func (f *nodeInformer) Lister() *cache.StoreToNodeLister {
informer := f.Informer()
return &cache.StoreToNodeLister{Store: informer.GetStore()}
}
//*****************************************************************************
// PVCInformer is type of SharedIndexInformer which watches and lists all persistent volume claims.
// Interface provides constructor for informer and lister for persistent volume claims
type PVCInformer interface {
Informer() framework.SharedIndexInformer
Lister() *cache.StoreToPVCFetcher
}
type pvcInformer struct {
*sharedInformerFactory
}
// Informer checks whether pvcInformer exists in sharedInformerFactory and if not, it creates new informer of type
// pvcInformer and connects it to sharedInformerFactory
func (f *pvcInformer) Informer() framework.SharedIndexInformer {
f.lock.Lock()
defer f.lock.Unlock()
informerObj := &api.PersistentVolumeClaim{}
informerType := reflect.TypeOf(informerObj)
informer, exists := f.informers[informerType]
if exists {
return informer
}
informer = framework.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
return f.client.Core().PersistentVolumeClaims(api.NamespaceAll).List(options)
},
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
return f.client.Core().PersistentVolumeClaims(api.NamespaceAll).Watch(options)
},
},
informerObj,
f.defaultResync,
cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc},
)
f.informers[informerType] = informer
return informer
}
// Lister returns lister for pvcInformer
func (f *pvcInformer) Lister() *cache.StoreToPVCFetcher {
informer := f.Informer()
return &cache.StoreToPVCFetcher{Store: informer.GetStore()}
}
//*****************************************************************************
// PVInformer is type of SharedIndexInformer which watches and lists all persistent volumes.
// Interface provides constructor for informer and lister for persistent volumes
type PVInformer interface {
Informer() framework.SharedIndexInformer
Lister() *cache.StoreToPVFetcher
}
type pvInformer struct {
*sharedInformerFactory
}
// Informer checks whether pvInformer exists in sharedInformerFactory and if not, it creates new informer of type
// pvInformer and connects it to sharedInformerFactory
func (f *pvInformer) Informer() framework.SharedIndexInformer {
f.lock.Lock()
defer f.lock.Unlock()
informerObj := &api.PersistentVolume{}
informerType := reflect.TypeOf(informerObj)
informer, exists := f.informers[informerType]
if exists {
return informer
}
informer = framework.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
return f.client.Core().PersistentVolumes().List(options)
},
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
return f.client.Core().PersistentVolumes().Watch(options)
},
},
informerObj,
f.defaultResync,
cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc},
)
f.informers[informerType] = informer
return informer
}
// Lister returns lister for pvInformer
func (f *pvInformer) Lister() *cache.StoreToPVFetcher {
informer := f.Informer()
return &cache.StoreToPVFetcher{Store: informer.GetStore()}
}

View File

@@ -17,6 +17,8 @@ limitations under the License.
package informers
import (
"reflect"
"sync"
"time"
"k8s.io/kubernetes/pkg/api"
@@ -27,6 +29,70 @@ import (
"k8s.io/kubernetes/pkg/watch"
)
// SharedInformerFactory provides interface which holds unique informers for pods, nodes, namespaces, persistent volume
// claims and persistent volumes
type SharedInformerFactory interface {
// Start starts informers that can start AFTER the API server and controllers have started
Start(stopCh <-chan struct{})
Pods() PodInformer
Nodes() NodeInformer
Namespaces() NamespaceInformer
PersistentVolumeClaims() PVCInformer
PersistentVolumes() PVInformer
}
type sharedInformerFactory struct {
client clientset.Interface
lock sync.Mutex
defaultResync time.Duration
informers map[reflect.Type]framework.SharedIndexInformer
}
// NewSharedInformerFactory constructs a new instance of sharedInformerFactory
func NewSharedInformerFactory(client clientset.Interface, defaultResync time.Duration) SharedInformerFactory {
return &sharedInformerFactory{
client: client,
defaultResync: defaultResync,
informers: make(map[reflect.Type]framework.SharedIndexInformer),
}
}
// Start initializes all requested informers.
func (s *sharedInformerFactory) Start(stopCh <-chan struct{}) {
s.lock.Lock()
defer s.lock.Unlock()
for _, informer := range s.informers {
go informer.Run(stopCh)
}
}
// Pods returns a SharedIndexInformer that lists and watches all pods
func (f *sharedInformerFactory) Pods() PodInformer {
return &podInformer{sharedInformerFactory: f}
}
// Nodes returns a SharedIndexInformer that lists and watches all nodes
func (f *sharedInformerFactory) Nodes() NodeInformer {
return &nodeInformer{sharedInformerFactory: f}
}
// Namespaces returns a SharedIndexInformer that lists and watches all namespaces
func (f *sharedInformerFactory) Namespaces() NamespaceInformer {
return &namespaceInformer{sharedInformerFactory: f}
}
// PersistentVolumeClaims returns a SharedIndexInformer that lists and watches all persistent volume claims
func (f *sharedInformerFactory) PersistentVolumeClaims() PVCInformer {
return &pvcInformer{sharedInformerFactory: f}
}
// PersistentVolumes returns a SharedIndexInformer that lists and watches all persistent volumes
func (f *sharedInformerFactory) PersistentVolumes() PVInformer {
return &pvInformer{sharedInformerFactory: f}
}
// CreateSharedPodInformer returns a SharedIndexInformer that lists and watches all pods
func CreateSharedPodInformer(client clientset.Interface, resyncPeriod time.Duration) framework.SharedIndexInformer {
sharedInformer := framework.NewSharedIndexInformer(
@@ -118,3 +184,21 @@ func CreateSharedPVIndexInformer(client clientset.Interface, resyncPeriod time.D
return sharedIndexInformer
}
// CreateSharedNamespaceIndexInformer returns a SharedIndexInformer that lists and watches namespaces
func CreateSharedNamespaceIndexInformer(client clientset.Interface, resyncPeriod time.Duration) framework.SharedIndexInformer {
sharedIndexInformer := framework.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
return client.Core().Namespaces().List(options)
},
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
return client.Core().Namespaces().Watch(options)
},
},
&api.Namespace{},
resyncPeriod,
cache.Indexers{})
return sharedIndexInformer
}