use istio client-go library instead of knative (#1661)
use istio client-go library instead of knative bump kubernetes dependency version change code coverage to codecov
This commit is contained in:
48
vendor/sigs.k8s.io/controller-runtime/pkg/cache/cache.go
generated
vendored
48
vendor/sigs.k8s.io/controller-runtime/pkg/cache/cache.go
generated
vendored
@@ -29,30 +29,33 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/cache/internal"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/internal/log"
|
||||
)
|
||||
|
||||
var log = logf.KBLog.WithName("object-cache")
|
||||
var log = logf.RuntimeLog.WithName("object-cache")
|
||||
|
||||
// Cache implements CacheReader by reading objects from a cache populated by InformersMap
|
||||
// Cache knows how to load Kubernetes objects, fetch informers to request
|
||||
// to receive events for Kubernetes objects (at a low-level),
|
||||
// and add indices to fields on the objects stored in the cache.
|
||||
type Cache interface {
|
||||
// Cache implements the client CacheReader
|
||||
// Cache acts as a client to objects stored in the cache.
|
||||
client.Reader
|
||||
|
||||
// Cache implements InformersMap
|
||||
// Cache loads informers and adds field indices.
|
||||
Informers
|
||||
}
|
||||
|
||||
// Informers knows how to create or fetch informers for different group-version-kinds.
|
||||
// It's safe to call GetInformer from multiple threads.
|
||||
// Informers knows how to create or fetch informers for different
|
||||
// group-version-kinds, and add indices to those informers. It's safe to call
|
||||
// GetInformer from multiple threads.
|
||||
type Informers interface {
|
||||
// GetInformer fetches or constructs an informer for the given object that corresponds to a single
|
||||
// API kind and resource.
|
||||
GetInformer(obj runtime.Object) (toolscache.SharedIndexInformer, error)
|
||||
GetInformer(obj runtime.Object) (Informer, error)
|
||||
|
||||
// GetInformerForKind is similar to GetInformer, except that it takes a group-version-kind, instead
|
||||
// of the underlying object.
|
||||
GetInformerForKind(gvk schema.GroupVersionKind) (toolscache.SharedIndexInformer, error)
|
||||
GetInformerForKind(gvk schema.GroupVersionKind) (Informer, error)
|
||||
|
||||
// Start runs all the informers known to this cache until the given channel is closed.
|
||||
// It blocks.
|
||||
@@ -61,12 +64,25 @@ type Informers interface {
|
||||
// WaitForCacheSync waits for all the caches to sync. Returns false if it could not sync a cache.
|
||||
WaitForCacheSync(stop <-chan struct{}) bool
|
||||
|
||||
// IndexField adds an index with the given field name on the given object type
|
||||
// by using the given function to extract the value for that field. If you want
|
||||
// compatibility with the Kubernetes API server, only return one key, and only use
|
||||
// fields that the API server supports. Otherwise, you can return multiple keys,
|
||||
// and "equality" in the field selector means that at least one key matches the value.
|
||||
IndexField(obj runtime.Object, field string, extractValue client.IndexerFunc) error
|
||||
// Informers knows how to add indices to the caches (informers) that it manages.
|
||||
client.FieldIndexer
|
||||
}
|
||||
|
||||
// Informer - informer allows you interact with the underlying informer
|
||||
type Informer interface {
|
||||
// AddEventHandler adds an event handler to the shared informer using the shared informer's resync
|
||||
// period. Events to a single handler are delivered sequentially, but there is no coordination
|
||||
// between different handlers.
|
||||
AddEventHandler(handler toolscache.ResourceEventHandler)
|
||||
// AddEventHandlerWithResyncPeriod adds an event handler to the shared informer using the
|
||||
// specified resync period. Events to a single handler are delivered sequentially, but there is
|
||||
// no coordination between different handlers.
|
||||
AddEventHandlerWithResyncPeriod(handler toolscache.ResourceEventHandler, resyncPeriod time.Duration)
|
||||
// AddIndexers adds more indexers to this store. If you call this after you already have data
|
||||
// in the store, the results are undefined.
|
||||
AddIndexers(indexers toolscache.Indexers) error
|
||||
//HasSynced return true if the informers underlying store has synced
|
||||
HasSynced() bool
|
||||
}
|
||||
|
||||
// Options are the optional arguments for creating a new InformersMap object
|
||||
@@ -87,7 +103,7 @@ type Options struct {
|
||||
|
||||
var defaultResyncTime = 10 * time.Hour
|
||||
|
||||
// New initializes and returns a new Cache
|
||||
// New initializes and returns a new Cache.
|
||||
func New(config *rest.Config, opts Options) (Cache, error) {
|
||||
opts, err := defaultOpts(config, opts)
|
||||
if err != nil {
|
||||
|
||||
19
vendor/sigs.k8s.io/controller-runtime/pkg/cache/doc.go
generated
vendored
Normal file
19
vendor/sigs.k8s.io/controller-runtime/pkg/cache/doc.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
Copyright 2019 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 cache provides object caches that act as caching client.Reader
|
||||
// instances and help drive Kubernetes-object-based event handlers.
|
||||
package cache
|
||||
41
vendor/sigs.k8s.io/controller-runtime/pkg/cache/informer_cache.go
generated
vendored
41
vendor/sigs.k8s.io/controller-runtime/pkg/cache/informer_cache.go
generated
vendored
@@ -38,6 +38,13 @@ var (
|
||||
_ Cache = &informerCache{}
|
||||
)
|
||||
|
||||
// ErrCacheNotStarted is returned when trying to read from the cache that wasn't started.
|
||||
type ErrCacheNotStarted struct{}
|
||||
|
||||
func (*ErrCacheNotStarted) Error() string {
|
||||
return "the cache is not started, can not read objects"
|
||||
}
|
||||
|
||||
// informerCache is a Kubernetes Object cache populated from InformersMap. informerCache wraps an InformersMap.
|
||||
type informerCache struct {
|
||||
*internal.InformersMap
|
||||
@@ -50,15 +57,19 @@ func (ip *informerCache) Get(ctx context.Context, key client.ObjectKey, out runt
|
||||
return err
|
||||
}
|
||||
|
||||
cache, err := ip.InformersMap.Get(gvk, out)
|
||||
started, cache, err := ip.InformersMap.Get(gvk, out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !started {
|
||||
return &ErrCacheNotStarted{}
|
||||
}
|
||||
return cache.Reader.Get(ctx, key, out)
|
||||
}
|
||||
|
||||
// List implements Reader
|
||||
func (ip *informerCache) List(ctx context.Context, opts *client.ListOptions, out runtime.Object) error {
|
||||
func (ip *informerCache) List(ctx context.Context, out runtime.Object, opts ...client.ListOption) error {
|
||||
gvk, err := apiutil.GVKForObject(out, ip.Scheme)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -90,22 +101,26 @@ func (ip *informerCache) List(ctx context.Context, opts *client.ListOptions, out
|
||||
}
|
||||
}
|
||||
|
||||
cache, err := ip.InformersMap.Get(gvk, cacheTypeObj)
|
||||
started, cache, err := ip.InformersMap.Get(gvk, cacheTypeObj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return cache.Reader.List(ctx, opts, out)
|
||||
if !started {
|
||||
return &ErrCacheNotStarted{}
|
||||
}
|
||||
|
||||
return cache.Reader.List(ctx, out, opts...)
|
||||
}
|
||||
|
||||
// GetInformerForKind returns the informer for the GroupVersionKind
|
||||
func (ip *informerCache) GetInformerForKind(gvk schema.GroupVersionKind) (cache.SharedIndexInformer, error) {
|
||||
func (ip *informerCache) GetInformerForKind(gvk schema.GroupVersionKind) (Informer, error) {
|
||||
// Map the gvk to an object
|
||||
obj, err := ip.Scheme.New(gvk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
i, err := ip.InformersMap.Get(gvk, obj)
|
||||
_, i, err := ip.InformersMap.Get(gvk, obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -113,18 +128,24 @@ func (ip *informerCache) GetInformerForKind(gvk schema.GroupVersionKind) (cache.
|
||||
}
|
||||
|
||||
// GetInformer returns the informer for the obj
|
||||
func (ip *informerCache) GetInformer(obj runtime.Object) (cache.SharedIndexInformer, error) {
|
||||
func (ip *informerCache) GetInformer(obj runtime.Object) (Informer, error) {
|
||||
gvk, err := apiutil.GVKForObject(obj, ip.Scheme)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
i, err := ip.InformersMap.Get(gvk, obj)
|
||||
_, i, err := ip.InformersMap.Get(gvk, obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return i.Informer, err
|
||||
}
|
||||
|
||||
// NeedLeaderElection implements the LeaderElectionRunnable interface
|
||||
// to indicate that this can be started without requiring the leader lock
|
||||
func (ip *informerCache) NeedLeaderElection() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IndexField adds an indexer to the underlying cache, using extraction function to get
|
||||
// value(s) from the given field. This index can then be used by passing a field selector
|
||||
// to List. For one-to-one compatibility with "normal" field selectors, only return one value.
|
||||
@@ -135,10 +156,10 @@ func (ip *informerCache) IndexField(obj runtime.Object, field string, extractVal
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return indexByField(informer.GetIndexer(), field, extractValue)
|
||||
return indexByField(informer, field, extractValue)
|
||||
}
|
||||
|
||||
func indexByField(indexer cache.Indexer, field string, extractor client.IndexerFunc) error {
|
||||
func indexByField(indexer Informer, field string, extractor client.IndexerFunc) error {
|
||||
indexFunc := func(objRaw interface{}) ([]string, error) {
|
||||
// TODO(directxman12): check if this is the correct type?
|
||||
obj, isObj := objRaw.(runtime.Object)
|
||||
|
||||
44
vendor/sigs.k8s.io/controller-runtime/pkg/cache/internal/cache_reader.go
generated
vendored
44
vendor/sigs.k8s.io/controller-runtime/pkg/cache/internal/cache_reader.go
generated
vendored
@@ -32,7 +32,7 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
// CacheReader is a CacheReader
|
||||
// CacheReader is a client.Reader
|
||||
var _ client.Reader = &CacheReader{}
|
||||
|
||||
// CacheReader wraps a cache.Index to implement the client.CacheReader interface for a single type
|
||||
@@ -87,23 +87,26 @@ func (c *CacheReader) Get(_ context.Context, key client.ObjectKey, out runtime.O
|
||||
}
|
||||
|
||||
// List lists items out of the indexer and writes them to out
|
||||
func (c *CacheReader) List(_ context.Context, opts *client.ListOptions, out runtime.Object) error {
|
||||
func (c *CacheReader) List(_ context.Context, out runtime.Object, opts ...client.ListOption) error {
|
||||
var objs []interface{}
|
||||
var err error
|
||||
|
||||
if opts != nil && opts.FieldSelector != nil {
|
||||
listOpts := client.ListOptions{}
|
||||
listOpts.ApplyOptions(opts)
|
||||
|
||||
if listOpts.FieldSelector != nil {
|
||||
// TODO(directxman12): support more complicated field selectors by
|
||||
// combining multiple indicies, GetIndexers, etc
|
||||
field, val, requiresExact := requiresExactMatch(opts.FieldSelector)
|
||||
// combining multiple indices, GetIndexers, etc
|
||||
field, val, requiresExact := requiresExactMatch(listOpts.FieldSelector)
|
||||
if !requiresExact {
|
||||
return fmt.Errorf("non-exact field matches are not supported by the cache")
|
||||
}
|
||||
// list all objects by the field selector. If this is namespaced and we have one, ask for the
|
||||
// namespaced index key. Otherwise, ask for the non-namespaced variant by using the fake "all namespaces"
|
||||
// namespace.
|
||||
objs, err = c.indexer.ByIndex(FieldIndexName(field), KeyToNamespacedKey(opts.Namespace, val))
|
||||
} else if opts != nil && opts.Namespace != "" {
|
||||
objs, err = c.indexer.ByIndex(cache.NamespaceIndex, opts.Namespace)
|
||||
objs, err = c.indexer.ByIndex(FieldIndexName(field), KeyToNamespacedKey(listOpts.Namespace, val))
|
||||
} else if listOpts.Namespace != "" {
|
||||
objs, err = c.indexer.ByIndex(cache.NamespaceIndex, listOpts.Namespace)
|
||||
} else {
|
||||
objs = c.indexer.List()
|
||||
}
|
||||
@@ -111,27 +114,19 @@ func (c *CacheReader) List(_ context.Context, opts *client.ListOptions, out runt
|
||||
return err
|
||||
}
|
||||
var labelSel labels.Selector
|
||||
if opts != nil && opts.LabelSelector != nil {
|
||||
labelSel = opts.LabelSelector
|
||||
if listOpts.LabelSelector != nil {
|
||||
labelSel = listOpts.LabelSelector
|
||||
}
|
||||
|
||||
outItems, err := c.getListItems(objs, labelSel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return apimeta.SetList(out, outItems)
|
||||
}
|
||||
|
||||
func (c *CacheReader) getListItems(objs []interface{}, labelSel labels.Selector) ([]runtime.Object, error) {
|
||||
outItems := make([]runtime.Object, 0, len(objs))
|
||||
runtimeObjs := make([]runtime.Object, 0, len(objs))
|
||||
for _, item := range objs {
|
||||
obj, isObj := item.(runtime.Object)
|
||||
if !isObj {
|
||||
return nil, fmt.Errorf("cache contained %T, which is not an Object", obj)
|
||||
return fmt.Errorf("cache contained %T, which is not an Object", obj)
|
||||
}
|
||||
meta, err := apimeta.Accessor(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
if labelSel != nil {
|
||||
lbls := labels.Set(meta.GetLabels())
|
||||
@@ -139,9 +134,12 @@ func (c *CacheReader) getListItems(objs []interface{}, labelSel labels.Selector)
|
||||
continue
|
||||
}
|
||||
}
|
||||
outItems = append(outItems, obj.DeepCopyObject())
|
||||
|
||||
outObj := obj.DeepCopyObject()
|
||||
outObj.GetObjectKind().SetGroupVersionKind(c.groupVersionKind)
|
||||
runtimeObjs = append(runtimeObjs, outObj)
|
||||
}
|
||||
return outItems, nil
|
||||
return apimeta.SetList(out, runtimeObjs)
|
||||
}
|
||||
|
||||
// objectKeyToStorageKey converts an object key to store key.
|
||||
|
||||
2
vendor/sigs.k8s.io/controller-runtime/pkg/cache/internal/deleg_map.go
generated
vendored
2
vendor/sigs.k8s.io/controller-runtime/pkg/cache/internal/deleg_map.go
generated
vendored
@@ -73,7 +73,7 @@ func (m *InformersMap) WaitForCacheSync(stop <-chan struct{}) bool {
|
||||
|
||||
// Get will create a new Informer and add it to the map of InformersMap if none exists. Returns
|
||||
// the Informer from the map.
|
||||
func (m *InformersMap) Get(gvk schema.GroupVersionKind, obj runtime.Object) (*MapEntry, error) {
|
||||
func (m *InformersMap) Get(gvk schema.GroupVersionKind, obj runtime.Object) (bool, *MapEntry, error) {
|
||||
_, isUnstructured := obj.(*unstructured.Unstructured)
|
||||
_, isUnstructuredList := obj.(*unstructured.UnstructuredList)
|
||||
isUnstructured = isUnstructured || isUnstructuredList
|
||||
|
||||
99
vendor/sigs.k8s.io/controller-runtime/pkg/cache/internal/informers_map.go
generated
vendored
99
vendor/sigs.k8s.io/controller-runtime/pkg/cache/internal/informers_map.go
generated
vendored
@@ -145,70 +145,65 @@ func (ip *specificInformersMap) HasSyncedFuncs() []cache.InformerSynced {
|
||||
|
||||
// Get will create a new Informer and add it to the map of specificInformersMap if none exists. Returns
|
||||
// the Informer from the map.
|
||||
func (ip *specificInformersMap) Get(gvk schema.GroupVersionKind, obj runtime.Object) (*MapEntry, error) {
|
||||
func (ip *specificInformersMap) Get(gvk schema.GroupVersionKind, obj runtime.Object) (bool, *MapEntry, error) {
|
||||
// Return the informer if it is found
|
||||
i, ok := func() (*MapEntry, bool) {
|
||||
i, started, ok := func() (*MapEntry, bool, bool) {
|
||||
ip.mu.RLock()
|
||||
defer ip.mu.RUnlock()
|
||||
i, ok := ip.informersByGVK[gvk]
|
||||
return i, ok
|
||||
return i, ip.started, ok
|
||||
}()
|
||||
if ok {
|
||||
return i, nil
|
||||
|
||||
if !ok {
|
||||
var err error
|
||||
if i, started, err = ip.addInformerToMap(gvk, obj); err != nil {
|
||||
return started, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Do the mutex part in its own function so we can use defer without blocking pieces that don't
|
||||
// need to be locked
|
||||
var sync bool
|
||||
i, err := func() (*MapEntry, error) {
|
||||
ip.mu.Lock()
|
||||
defer ip.mu.Unlock()
|
||||
|
||||
// Check the cache to see if we already have an Informer. If we do, return the Informer.
|
||||
// This is for the case where 2 routines tried to get the informer when it wasn't in the map
|
||||
// so neither returned early, but the first one created it.
|
||||
var ok bool
|
||||
i, ok := ip.informersByGVK[gvk]
|
||||
if ok {
|
||||
return i, nil
|
||||
}
|
||||
|
||||
// Create a NewSharedIndexInformer and add it to the map.
|
||||
var lw *cache.ListWatch
|
||||
lw, err := ip.createListWatcher(gvk, ip)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ni := cache.NewSharedIndexInformer(lw, obj, ip.resync, cache.Indexers{
|
||||
cache.NamespaceIndex: cache.MetaNamespaceIndexFunc,
|
||||
})
|
||||
i = &MapEntry{
|
||||
Informer: ni,
|
||||
Reader: CacheReader{indexer: ni.GetIndexer(), groupVersionKind: gvk},
|
||||
}
|
||||
ip.informersByGVK[gvk] = i
|
||||
|
||||
// Start the Informer if need by
|
||||
// TODO(seans): write thorough tests and document what happens here - can you add indexers?
|
||||
// can you add eventhandlers?
|
||||
if ip.started {
|
||||
sync = true
|
||||
go i.Informer.Run(ip.stop)
|
||||
}
|
||||
return i, nil
|
||||
}()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if sync {
|
||||
if started && !i.Informer.HasSynced() {
|
||||
// Wait for it to sync before returning the Informer so that folks don't read from a stale cache.
|
||||
if !cache.WaitForCacheSync(ip.stop, i.Informer.HasSynced) {
|
||||
return nil, fmt.Errorf("failed waiting for %T Informer to sync", obj)
|
||||
return started, nil, fmt.Errorf("failed waiting for %T Informer to sync", obj)
|
||||
}
|
||||
}
|
||||
|
||||
return i, err
|
||||
return started, i, nil
|
||||
}
|
||||
|
||||
func (ip *specificInformersMap) addInformerToMap(gvk schema.GroupVersionKind, obj runtime.Object) (*MapEntry, bool, error) {
|
||||
ip.mu.Lock()
|
||||
defer ip.mu.Unlock()
|
||||
|
||||
// Check the cache to see if we already have an Informer. If we do, return the Informer.
|
||||
// This is for the case where 2 routines tried to get the informer when it wasn't in the map
|
||||
// so neither returned early, but the first one created it.
|
||||
if i, ok := ip.informersByGVK[gvk]; ok {
|
||||
return i, ip.started, nil
|
||||
}
|
||||
|
||||
// Create a NewSharedIndexInformer and add it to the map.
|
||||
var lw *cache.ListWatch
|
||||
lw, err := ip.createListWatcher(gvk, ip)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
ni := cache.NewSharedIndexInformer(lw, obj, ip.resync, cache.Indexers{
|
||||
cache.NamespaceIndex: cache.MetaNamespaceIndexFunc,
|
||||
})
|
||||
i := &MapEntry{
|
||||
Informer: ni,
|
||||
Reader: CacheReader{indexer: ni.GetIndexer(), groupVersionKind: gvk},
|
||||
}
|
||||
ip.informersByGVK[gvk] = i
|
||||
|
||||
// Start the Informer if need by
|
||||
// TODO(seans): write thorough tests and document what happens here - can you add indexers?
|
||||
// can you add eventhandlers?
|
||||
if ip.started {
|
||||
go i.Informer.Run(ip.stop)
|
||||
}
|
||||
return i, ip.started, nil
|
||||
}
|
||||
|
||||
// newListWatch returns a new ListWatch object that can be used to create a SharedIndexInformer.
|
||||
|
||||
220
vendor/sigs.k8s.io/controller-runtime/pkg/cache/multi_namespace_cache.go
generated
vendored
Normal file
220
vendor/sigs.k8s.io/controller-runtime/pkg/cache/multi_namespace_cache.go
generated
vendored
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
Copyright 2019 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 cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
apimeta "k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/rest"
|
||||
toolscache "k8s.io/client-go/tools/cache"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
// NewCacheFunc - Function for creating a new cache from the options and a rest config
|
||||
type NewCacheFunc func(config *rest.Config, opts Options) (Cache, error)
|
||||
|
||||
// MultiNamespacedCacheBuilder - Builder function to create a new multi-namespaced cache.
|
||||
// This will scope the cache to a list of namespaces. Listing for all namespaces
|
||||
// will list for all the namespaces that this knows about.
|
||||
func MultiNamespacedCacheBuilder(namespaces []string) NewCacheFunc {
|
||||
return func(config *rest.Config, opts Options) (Cache, error) {
|
||||
opts, err := defaultOpts(config, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
caches := map[string]Cache{}
|
||||
for _, ns := range namespaces {
|
||||
opts.Namespace = ns
|
||||
c, err := New(config, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
caches[ns] = c
|
||||
}
|
||||
return &multiNamespaceCache{namespaceToCache: caches, Scheme: opts.Scheme}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// multiNamespaceCache knows how to handle multiple namespaced caches
|
||||
// Use this feature when scoping permissions for your
|
||||
// operator to a list of namespaces instead of watching every namespace
|
||||
// in the cluster.
|
||||
type multiNamespaceCache struct {
|
||||
namespaceToCache map[string]Cache
|
||||
Scheme *runtime.Scheme
|
||||
}
|
||||
|
||||
var _ Cache = &multiNamespaceCache{}
|
||||
|
||||
// Methods for multiNamespaceCache to conform to the Informers interface
|
||||
func (c *multiNamespaceCache) GetInformer(obj runtime.Object) (Informer, error) {
|
||||
informers := map[string]Informer{}
|
||||
for ns, cache := range c.namespaceToCache {
|
||||
informer, err := cache.GetInformer(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
informers[ns] = informer
|
||||
}
|
||||
return &multiNamespaceInformer{namespaceToInformer: informers}, nil
|
||||
}
|
||||
|
||||
func (c *multiNamespaceCache) GetInformerForKind(gvk schema.GroupVersionKind) (Informer, error) {
|
||||
informers := map[string]Informer{}
|
||||
for ns, cache := range c.namespaceToCache {
|
||||
informer, err := cache.GetInformerForKind(gvk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
informers[ns] = informer
|
||||
}
|
||||
return &multiNamespaceInformer{namespaceToInformer: informers}, nil
|
||||
}
|
||||
|
||||
func (c *multiNamespaceCache) Start(stopCh <-chan struct{}) error {
|
||||
for ns, cache := range c.namespaceToCache {
|
||||
go func(ns string, cache Cache) {
|
||||
err := cache.Start(stopCh)
|
||||
if err != nil {
|
||||
log.Error(err, "multinamespace cache failed to start namespaced informer", "namespace", ns)
|
||||
}
|
||||
}(ns, cache)
|
||||
}
|
||||
<-stopCh
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *multiNamespaceCache) WaitForCacheSync(stop <-chan struct{}) bool {
|
||||
synced := true
|
||||
for _, cache := range c.namespaceToCache {
|
||||
if s := cache.WaitForCacheSync(stop); !s {
|
||||
synced = s
|
||||
}
|
||||
}
|
||||
return synced
|
||||
}
|
||||
|
||||
func (c *multiNamespaceCache) IndexField(obj runtime.Object, field string, extractValue client.IndexerFunc) error {
|
||||
for _, cache := range c.namespaceToCache {
|
||||
if err := cache.IndexField(obj, field, extractValue); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *multiNamespaceCache) Get(ctx context.Context, key client.ObjectKey, obj runtime.Object) error {
|
||||
cache, ok := c.namespaceToCache[key.Namespace]
|
||||
if !ok {
|
||||
return fmt.Errorf("unable to get: %v because of unknown namespace for the cache", key)
|
||||
}
|
||||
return cache.Get(ctx, key, obj)
|
||||
}
|
||||
|
||||
// List multi namespace cache will get all the objects in the namespaces that the cache is watching if asked for all namespaces.
|
||||
func (c *multiNamespaceCache) List(ctx context.Context, list runtime.Object, opts ...client.ListOption) error {
|
||||
listOpts := client.ListOptions{}
|
||||
listOpts.ApplyOptions(opts)
|
||||
if listOpts.Namespace != corev1.NamespaceAll {
|
||||
cache, ok := c.namespaceToCache[listOpts.Namespace]
|
||||
if !ok {
|
||||
return fmt.Errorf("unable to get: %v because of unknown namespace for the cache", listOpts.Namespace)
|
||||
}
|
||||
return cache.List(ctx, list, opts...)
|
||||
}
|
||||
|
||||
listAccessor, err := meta.ListAccessor(list)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
allItems, err := apimeta.ExtractList(list)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var resourceVersion string
|
||||
for _, cache := range c.namespaceToCache {
|
||||
listObj := list.DeepCopyObject()
|
||||
err = cache.List(ctx, listObj, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
items, err := apimeta.ExtractList(listObj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
accessor, err := meta.ListAccessor(listObj)
|
||||
if err != nil {
|
||||
return fmt.Errorf("object: %T must be a list type", list)
|
||||
}
|
||||
allItems = append(allItems, items...)
|
||||
// The last list call should have the most correct resource version.
|
||||
resourceVersion = accessor.GetResourceVersion()
|
||||
}
|
||||
listAccessor.SetResourceVersion(resourceVersion)
|
||||
|
||||
return apimeta.SetList(list, allItems)
|
||||
}
|
||||
|
||||
// multiNamespaceInformer knows how to handle interacting with the underlying informer across multiple namespaces
|
||||
type multiNamespaceInformer struct {
|
||||
namespaceToInformer map[string]Informer
|
||||
}
|
||||
|
||||
var _ Informer = &multiNamespaceInformer{}
|
||||
|
||||
// AddEventHandler adds the handler to each namespaced informer
|
||||
func (i *multiNamespaceInformer) AddEventHandler(handler toolscache.ResourceEventHandler) {
|
||||
for _, informer := range i.namespaceToInformer {
|
||||
informer.AddEventHandler(handler)
|
||||
}
|
||||
}
|
||||
|
||||
// AddEventHandlerWithResyncPeriod adds the handler with a resync period to each namespaced informer
|
||||
func (i *multiNamespaceInformer) AddEventHandlerWithResyncPeriod(handler toolscache.ResourceEventHandler, resyncPeriod time.Duration) {
|
||||
for _, informer := range i.namespaceToInformer {
|
||||
informer.AddEventHandlerWithResyncPeriod(handler, resyncPeriod)
|
||||
}
|
||||
}
|
||||
|
||||
// AddIndexers adds the indexer for each namespaced informer
|
||||
func (i *multiNamespaceInformer) AddIndexers(indexers toolscache.Indexers) error {
|
||||
for _, informer := range i.namespaceToInformer {
|
||||
err := informer.AddIndexers(indexers)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// HasSynced checks if each namespaced informer has synced
|
||||
func (i *multiNamespaceInformer) HasSynced() bool {
|
||||
for _, informer := range i.namespaceToInformer {
|
||||
if ok := informer.HasSynced(); !ok {
|
||||
return ok
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
Reference in New Issue
Block a user