Skip to content

Commit f622cca

Browse files
committed
Lazily create caches if they aren't present
1 parent cccff91 commit f622cca

File tree

4 files changed

+56
-10
lines changed

4 files changed

+56
-10
lines changed

pkg/cache/cache.go

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232

3333
"github.com/kubernetes-sigs/controller-runtime/pkg/client"
3434
logf "github.com/kubernetes-sigs/controller-runtime/pkg/runtime/log"
35+
toolscache "k8s.io/client-go/tools/cache"
3536
)
3637

3738
var log = logf.KBLog.WithName("object-cache")
@@ -43,6 +44,7 @@ var _ client.ReadInterface = &objectCache{}
4344
type objectCache struct {
4445
cachesByType map[reflect.Type]*singleObjectCache
4546
scheme *runtime.Scheme
47+
informers *informers
4648
}
4749

4850
var _ client.ReadInterface = &objectCache{}
@@ -54,7 +56,7 @@ func (o *objectCache) addInformer(gvk schema.GroupVersionKind, c cache.SharedInd
5456
log.Error(err, "could not register informer in objectCache for GVK", "GroupVersionKind", gvk)
5557
return
5658
}
57-
if _, found := o.cacheFor(obj); found {
59+
if o.has(obj) {
5860
return
5961
}
6062
o.registerCache(obj, gvk, c.GetIndexer())
@@ -68,18 +70,52 @@ func (o *objectCache) registerCache(obj runtime.Object, gvk schema.GroupVersionK
6870
}
6971
}
7072

71-
func (o *objectCache) cacheFor(obj runtime.Object) (*singleObjectCache, bool) {
73+
func (o *objectCache) has(obj runtime.Object) bool {
7274
objType := reflect.TypeOf(obj)
75+
_, found := o.cachesByType[objType]
76+
return found
77+
}
78+
79+
func (o *objectCache) init(obj runtime.Object) error {
80+
i, err := o.informers.GetInformer(obj)
81+
if err != nil {
82+
return err
83+
}
84+
log.Info("Waiting to sync cache for type.", "Type", fmt.Sprintf("%T", obj))
85+
toolscache.WaitForCacheSync(o.informers.stop, i.HasSynced)
86+
log.Info("Finished to syncing cache for type.", "Type", fmt.Sprintf("%T", obj))
87+
return nil
88+
}
89+
90+
func (o *objectCache) cacheFor(obj runtime.Object) (*singleObjectCache, error) {
91+
if !o.informers.started {
92+
return nil, fmt.Errorf("Must start Cache before calling Get or List %s %s",
93+
"Object", fmt.Sprintf("%T", obj))
94+
}
95+
objType := reflect.TypeOf(obj)
96+
7397
cache, isKnown := o.cachesByType[objType]
74-
return cache, isKnown
98+
if !isKnown {
99+
return nil, fmt.Errorf("No Cache found for %T. Must call GetInformer.", obj)
100+
}
101+
return cache, nil
75102
}
76103

77104
// Get implements populatingClient.ReadInterface
78105
func (o *objectCache) Get(ctx context.Context, key client.ObjectKey, out runtime.Object) error {
79-
cache, isKnown := o.cacheFor(out)
80-
if !isKnown {
81-
return fmt.Errorf("no cache for objects of type %T, must have asked for an watch/informer first", out)
106+
// Make sure there is a Cache for this type
107+
if !o.has(out) {
108+
err := o.init(out)
109+
if err != nil {
110+
return err
111+
}
112+
}
113+
114+
cache, err := o.cacheFor(out)
115+
if err != nil {
116+
return err
82117
}
118+
83119
return cache.Get(ctx, key, out)
84120
}
85121

@@ -89,6 +125,15 @@ func (o *objectCache) List(ctx context.Context, opts *client.ListOptions, out ru
89125
if err != nil {
90126
return nil
91127
}
128+
129+
ro, ok := itemsPtr.(runtime.Object)
130+
if ok && !o.has(ro) {
131+
err = o.init(ro)
132+
if err != nil {
133+
return err
134+
}
135+
}
136+
92137
// http://knowyourmeme.com/memes/this-is-fine
93138
outType := reflect.Indirect(reflect.ValueOf(itemsPtr)).Type().Elem()
94139
cache, isKnown := o.cachesByType[outType]

pkg/cache/cache_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,9 @@ var _ = Describe("Indexers", func() {
9090
var singleCache client.ReadInterface
9191

9292
BeforeEach(func() {
93-
var ok bool
94-
singleCache, ok = multiCache.cacheFor(&kapi.Pod{})
95-
Expect(ok).To(BeTrue())
93+
var err error
94+
singleCache, err = multiCache.cacheFor(&kapi.Pod{})
95+
Expect(err).NotTo(HaveOccurred())
9696
})
9797

9898
It("should be able to fetch a particular object by key", func() {

pkg/cache/informer.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ func New(config *rest.Config, opts Options) (Cache, error) {
9292
informersByGVK: make(map[schema.GroupVersionKind]cache.SharedIndexInformer),
9393
resync: *opts.Resync,
9494
}
95+
i.objectCache.informers = i
9596

9697
return i, nil
9798
}

pkg/source/source_suite_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ var stop chan struct{}
4343

4444
var _ = BeforeSuite(func(done Done) {
4545
stop = make(chan struct{})
46-
logf.SetLogger(logf.ZapLogger(false))
46+
logf.SetLogger(logf.ZapLogger(true))
4747

4848
testenv = &test.Environment{}
4949

0 commit comments

Comments
 (0)