Skip to content

Commit b897b2f

Browse files
author
Alexander Zielenski
committed
add new cache.Options field to customize transform
1 parent 3f75399 commit b897b2f

File tree

4 files changed

+117
-11
lines changed

4 files changed

+117
-11
lines changed

pkg/cache/cache.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,14 @@ type Options struct {
128128
// Be very careful with this, when enabled you must DeepCopy any object before mutating it,
129129
// otherwise you will mutate the object in the cache.
130130
UnsafeDisableDeepCopyByObject DisableDeepCopyByObject
131+
132+
// TransformFuncByObject is a map from GVKs to transformer functions which
133+
// get applied when objects of the transformation are about to be committed
134+
// to cache.
135+
//
136+
// This function is called both for new objects to enter the cache,
137+
// and for updated objects.
138+
TransformFuncByObject TransformFuncByObject
131139
}
132140

133141
var defaultResyncTime = 10 * time.Hour
@@ -146,7 +154,11 @@ func New(config *rest.Config, opts Options) (Cache, error) {
146154
if err != nil {
147155
return nil, err
148156
}
149-
im := internal.NewInformersMap(config, opts.Scheme, opts.Mapper, *opts.Resync, opts.Namespace, selectorsByGVK, disableDeepCopyByGVK)
157+
transformByObjectAndGVK, err := convertToTransformByKindAndGVK(opts.TransformFuncByObject, opts.Scheme)
158+
if err != nil {
159+
return nil, err
160+
}
161+
im := internal.NewInformersMap(config, opts.Scheme, opts.Mapper, *opts.Resync, opts.Namespace, selectorsByGVK, disableDeepCopyByGVK, transformByObjectAndGVK)
150162
return &informerCache{InformersMap: im}, nil
151163
}
152164

@@ -241,3 +253,15 @@ func convertToDisableDeepCopyByGVK(disableDeepCopyByObject DisableDeepCopyByObje
241253
}
242254
return disableDeepCopyByGVK, nil
243255
}
256+
257+
type TransformFuncByObject map[client.Object]toolscache.TransformFunc
258+
259+
func convertToTransformByKindAndGVK(t TransformFuncByObject, scheme *runtime.Scheme) (internal.TransformFuncByObject, error) {
260+
result := internal.NewTransformFuncByObject()
261+
for obj, transformation := range t {
262+
if err := result.Set(obj, scheme, transformation); err != nil {
263+
return nil, err
264+
}
265+
}
266+
return result, nil
267+
}

pkg/cache/internal/deleg_map.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,12 @@ func NewInformersMap(config *rest.Config,
5252
namespace string,
5353
selectors SelectorsByGVK,
5454
disableDeepCopy DisableDeepCopyByGVK,
55+
transformers TransformFuncByObject,
5556
) *InformersMap {
5657
return &InformersMap{
57-
structured: newStructuredInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy),
58-
unstructured: newUnstructuredInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy),
59-
metadata: newMetadataInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy),
58+
structured: newStructuredInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, transformers.Get(runtimeObjectKindStructured)),
59+
unstructured: newUnstructuredInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, transformers.Get(runtimeObjectKindUnstructured)),
60+
metadata: newMetadataInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, transformers.Get(runtimeObjectKindMetadata)),
6061

6162
Scheme: scheme,
6263
}
@@ -108,18 +109,18 @@ func (m *InformersMap) Get(ctx context.Context, gvk schema.GroupVersionKind, obj
108109

109110
// newStructuredInformersMap creates a new InformersMap for structured objects.
110111
func newStructuredInformersMap(config *rest.Config, scheme *runtime.Scheme, mapper meta.RESTMapper, resync time.Duration,
111-
namespace string, selectors SelectorsByGVK, disableDeepCopy DisableDeepCopyByGVK) *specificInformersMap {
112-
return newSpecificInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, createStructuredListWatch)
112+
namespace string, selectors SelectorsByGVK, disableDeepCopy DisableDeepCopyByGVK, transformers TransformFuncByGVK) *specificInformersMap {
113+
return newSpecificInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, transformers, createStructuredListWatch)
113114
}
114115

115116
// newUnstructuredInformersMap creates a new InformersMap for unstructured objects.
116117
func newUnstructuredInformersMap(config *rest.Config, scheme *runtime.Scheme, mapper meta.RESTMapper, resync time.Duration,
117-
namespace string, selectors SelectorsByGVK, disableDeepCopy DisableDeepCopyByGVK) *specificInformersMap {
118-
return newSpecificInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, createUnstructuredListWatch)
118+
namespace string, selectors SelectorsByGVK, disableDeepCopy DisableDeepCopyByGVK, transformers TransformFuncByGVK) *specificInformersMap {
119+
return newSpecificInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, transformers, createUnstructuredListWatch)
119120
}
120121

121122
// newMetadataInformersMap creates a new InformersMap for metadata-only objects.
122123
func newMetadataInformersMap(config *rest.Config, scheme *runtime.Scheme, mapper meta.RESTMapper, resync time.Duration,
123-
namespace string, selectors SelectorsByGVK, disableDeepCopy DisableDeepCopyByGVK) *specificInformersMap {
124-
return newSpecificInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, createMetadataListWatch)
124+
namespace string, selectors SelectorsByGVK, disableDeepCopy DisableDeepCopyByGVK, transformers TransformFuncByGVK) *specificInformersMap {
125+
return newSpecificInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, transformers, createMetadataListWatch)
125126
}

pkg/cache/internal/informers_map.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ func newSpecificInformersMap(config *rest.Config,
5454
namespace string,
5555
selectors SelectorsByGVK,
5656
disableDeepCopy DisableDeepCopyByGVK,
57-
createListWatcher createListWatcherFunc) *specificInformersMap {
57+
transformers TransformFuncByGVK,
58+
createListWatcher createListWatcherFunc,
59+
) *specificInformersMap {
5860
ip := &specificInformersMap{
5961
config: config,
6062
Scheme: scheme,
@@ -135,6 +137,9 @@ type specificInformersMap struct {
135137

136138
// disableDeepCopy indicates not to deep copy objects during get or list objects.
137139
disableDeepCopy DisableDeepCopyByGVK
140+
141+
// transform funcs are applied to objects before they are committed to the cache
142+
transformers TransformFuncByGVK
138143
}
139144

140145
// Start calls Run on each of the informers and sets started to true. Blocks on the context.
@@ -227,6 +232,10 @@ func (ip *specificInformersMap) addInformerToMap(gvk schema.GroupVersionKind, ob
227232
ni := cache.NewSharedIndexInformer(lw, obj, resyncPeriod(ip.resync)(), cache.Indexers{
228233
cache.NamespaceIndex: cache.MetaNamespaceIndexFunc,
229234
})
235+
236+
// Check to see if there is a transformer for this gvk
237+
ni.SetTransform(ip.transformers.Get(gvk))
238+
230239
rm, err := ip.mapper.RESTMapping(gvk.GroupKind(), gvk.Version)
231240
if err != nil {
232241
return nil, false, err

pkg/cache/internal/transformers.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package internal
2+
3+
import (
4+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
5+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
6+
"k8s.io/apimachinery/pkg/runtime"
7+
"k8s.io/apimachinery/pkg/runtime/schema"
8+
"k8s.io/client-go/tools/cache"
9+
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
10+
)
11+
12+
type runtimeObjectKind int
13+
14+
const (
15+
// prefixed names since there are packages with these names that conflict
16+
runtimeObjectKindStructured runtimeObjectKind = iota
17+
runtimeObjectKindUnstructured
18+
runtimeObjectKindMetadata
19+
)
20+
21+
func runtimeObjectKindForObject(obj runtime.Object) runtimeObjectKind {
22+
switch obj.(type) {
23+
case *unstructured.Unstructured:
24+
return runtimeObjectKindUnstructured
25+
case *unstructured.UnstructuredList:
26+
return runtimeObjectKindUnstructured
27+
case *metav1.PartialObjectMetadata:
28+
return runtimeObjectKindMetadata
29+
case *metav1.PartialObjectMetadataList:
30+
return runtimeObjectKindMetadata
31+
default:
32+
return runtimeObjectKindStructured
33+
}
34+
}
35+
36+
type TransformFuncByObject map[runtimeObjectKind]map[schema.GroupVersionKind]cache.TransformFunc
37+
type TransformFuncByGVK map[schema.GroupVersionKind]cache.TransformFunc
38+
39+
func NewTransformFuncByObject() TransformFuncByObject {
40+
return TransformFuncByObject{}
41+
}
42+
43+
func (t TransformFuncByObject) Set(obj runtime.Object, scheme *runtime.Scheme, transformer cache.TransformFunc) error {
44+
kind := runtimeObjectKindForObject(obj)
45+
existing, ok := t[kind]
46+
if !ok {
47+
existing = TransformFuncByGVK{}
48+
t[kind] = existing
49+
}
50+
51+
gvk, err := apiutil.GVKForObject(obj, nil)
52+
if err != nil {
53+
return err
54+
}
55+
56+
existing[gvk] = transformer
57+
return nil
58+
}
59+
60+
func (t TransformFuncByObject) Get(kind runtimeObjectKind) TransformFuncByGVK {
61+
if val, ok := t[kind]; ok {
62+
return val
63+
}
64+
return nil
65+
}
66+
67+
func (t TransformFuncByGVK) Get(gvk schema.GroupVersionKind) cache.TransformFunc {
68+
if val, ok := t[gvk]; ok {
69+
return val
70+
}
71+
return nil
72+
}

0 commit comments

Comments
 (0)