k3s/vendor/github.com/rancher/lasso/pkg/cache/cache.go

126 lines
3.0 KiB
Go
Raw Normal View History

package cache
import (
"context"
"fmt"
"time"
"github.com/rancher/lasso/pkg/client"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/tools/cache"
)
type Options struct {
Namespace string
Resync time.Duration
TweakList TweakListOptionsFunc
WaitHealthy func(ctx context.Context)
}
func NewCache(obj, listObj runtime.Object, client *client.Client, opts *Options) cache.SharedIndexInformer {
indexers := cache.Indexers{}
if client.Namespaced {
indexers[cache.NamespaceIndex] = cache.MetaNamespaceIndexFunc
}
opts = applyDefaultCacheOptions(opts)
lw := &deferredListWatcher{
client: client,
tweakList: opts.TweakList,
namespace: opts.Namespace,
listObj: listObj,
waitHealthy: opts.WaitHealthy,
}
return &deferredCache{
SharedIndexInformer: cache.NewSharedIndexInformer(
lw,
obj,
opts.Resync,
indexers,
),
deferredListWatcher: lw,
}
}
func applyDefaultCacheOptions(opts *Options) *Options {
var newOpts Options
if opts != nil {
newOpts = *opts
}
if newOpts.Resync == 0 {
newOpts.Resync = 10 * time.Hour
}
if newOpts.TweakList == nil {
newOpts.TweakList = func(*metav1.ListOptions) {}
}
return &newOpts
}
type deferredCache struct {
cache.SharedIndexInformer
deferredListWatcher *deferredListWatcher
}
type deferredListWatcher struct {
lw cache.ListerWatcher
client *client.Client
tweakList TweakListOptionsFunc
namespace string
listObj runtime.Object
waitHealthy func(ctx context.Context)
}
func (d *deferredListWatcher) List(options metav1.ListOptions) (runtime.Object, error) {
if d.lw == nil {
return nil, fmt.Errorf("cache not started")
}
return d.lw.List(options)
}
func (d *deferredListWatcher) Watch(options metav1.ListOptions) (watch.Interface, error) {
if d.lw == nil {
return nil, fmt.Errorf("cache not started")
}
return d.lw.Watch(options)
}
func (d *deferredListWatcher) run(stopCh <-chan struct{}) {
ctx, cancel := context.WithCancel(context.Background())
go func() {
<-stopCh
cancel()
}()
d.lw = &cache.ListWatch{
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
d.tweakList(&options)
// If ResourceVersion is set to 0 then the Limit is ignored on the API side. Usually
// that's not a problem, but with very large counts of a single object type the client will
// hit it's connection timeout
if options.ResourceVersion == "0" {
options.ResourceVersion = ""
}
listObj := d.listObj.DeepCopyObject()
err := d.client.List(ctx, d.namespace, listObj, options)
if err != nil && d.waitHealthy != nil {
d.waitHealthy(ctx)
}
return listObj, err
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
d.tweakList(&options)
return d.client.Watch(ctx, d.namespace, options)
},
}
}
func (d *deferredCache) Run(stopCh <-chan struct{}) {
d.deferredListWatcher.run(stopCh)
d.SharedIndexInformer.Run(stopCh)
}