Skip to content

Commit

Permalink
add new cache.Options field to customize transform
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander Zielenski committed Apr 1, 2022
1 parent 4270760 commit 603031f
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 11 deletions.
26 changes: 25 additions & 1 deletion pkg/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,14 @@ type Options struct {
// Be very careful with this, when enabled you must DeepCopy any object before mutating it,
// otherwise you will mutate the object in the cache.
UnsafeDisableDeepCopyByObject DisableDeepCopyByObject

// TransformFuncByObject is a map from GVKs to transformer functions which
// get applied when objects of the transformation are about to be committed
// to cache.
//
// This function is called both for new objects to enter the cache,
// and for updated objects.
TransformFuncByObject TransformFuncByObject
}

var defaultResyncTime = 10 * time.Hour
Expand All @@ -146,7 +154,11 @@ func New(config *rest.Config, opts Options) (Cache, error) {
if err != nil {
return nil, err
}
im := internal.NewInformersMap(config, opts.Scheme, opts.Mapper, *opts.Resync, opts.Namespace, selectorsByGVK, disableDeepCopyByGVK)
transformByObjectAndGVK, err := convertToTransformByKindAndGVK(opts.TransformFuncByObject, opts.Scheme)
if err != nil {
return nil, err
}
im := internal.NewInformersMap(config, opts.Scheme, opts.Mapper, *opts.Resync, opts.Namespace, selectorsByGVK, disableDeepCopyByGVK, transformByObjectAndGVK)
return &informerCache{InformersMap: im}, nil
}

Expand Down Expand Up @@ -241,3 +253,15 @@ func convertToDisableDeepCopyByGVK(disableDeepCopyByObject DisableDeepCopyByObje
}
return disableDeepCopyByGVK, nil
}

type TransformFuncByObject map[client.Object]toolscache.TransformFunc

func convertToTransformByKindAndGVK(t TransformFuncByObject, scheme *runtime.Scheme) (internal.TransformFuncByObject, error) {
result := internal.NewTransformFuncByObject()
for obj, transformation := range t {
if err := result.Set(obj, scheme, transformation); err != nil {
return nil, err
}
}
return result, nil
}
19 changes: 10 additions & 9 deletions pkg/cache/internal/deleg_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,12 @@ func NewInformersMap(config *rest.Config,
namespace string,
selectors SelectorsByGVK,
disableDeepCopy DisableDeepCopyByGVK,
transformers TransformFuncByObject,
) *InformersMap {
return &InformersMap{
structured: newStructuredInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy),
unstructured: newUnstructuredInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy),
metadata: newMetadataInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy),
structured: newStructuredInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, transformers.Get(runtimeObjectKindStructured)),
unstructured: newUnstructuredInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, transformers.Get(runtimeObjectKindUnstructured)),
metadata: newMetadataInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, transformers.Get(runtimeObjectKindMetadata)),

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

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

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

// newMetadataInformersMap creates a new InformersMap for metadata-only objects.
func newMetadataInformersMap(config *rest.Config, scheme *runtime.Scheme, mapper meta.RESTMapper, resync time.Duration,
namespace string, selectors SelectorsByGVK, disableDeepCopy DisableDeepCopyByGVK) *specificInformersMap {
return newSpecificInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, createMetadataListWatch)
namespace string, selectors SelectorsByGVK, disableDeepCopy DisableDeepCopyByGVK, transformers TransformFuncByGVK) *specificInformersMap {
return newSpecificInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, transformers, createMetadataListWatch)
}
11 changes: 10 additions & 1 deletion pkg/cache/internal/informers_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ func newSpecificInformersMap(config *rest.Config,
namespace string,
selectors SelectorsByGVK,
disableDeepCopy DisableDeepCopyByGVK,
createListWatcher createListWatcherFunc) *specificInformersMap {
transformers TransformFuncByGVK,
createListWatcher createListWatcherFunc,
) *specificInformersMap {
ip := &specificInformersMap{
config: config,
Scheme: scheme,
Expand Down Expand Up @@ -135,6 +137,9 @@ type specificInformersMap struct {

// disableDeepCopy indicates not to deep copy objects during get or list objects.
disableDeepCopy DisableDeepCopyByGVK

// transform funcs are applied to objects before they are committed to the cache
transformers TransformFuncByGVK
}

// Start calls Run on each of the informers and sets started to true. Blocks on the context.
Expand Down Expand Up @@ -227,6 +232,10 @@ func (ip *specificInformersMap) addInformerToMap(gvk schema.GroupVersionKind, ob
ni := cache.NewSharedIndexInformer(lw, obj, resyncPeriod(ip.resync)(), cache.Indexers{
cache.NamespaceIndex: cache.MetaNamespaceIndexFunc,
})

// Check to see if there is a transformer for this gvk
ni.SetTransform(ip.transformers.Get(gvk))

rm, err := ip.mapper.RESTMapping(gvk.GroupKind(), gvk.Version)
if err != nil {
return nil, false, err
Expand Down
72 changes: 72 additions & 0 deletions pkg/cache/internal/transformers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package internal

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/tools/cache"
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
)

type runtimeObjectKind int

const (
// prefixed names since there are packages with these names that conflict
runtimeObjectKindStructured runtimeObjectKind = iota
runtimeObjectKindUnstructured
runtimeObjectKindMetadata
)

func runtimeObjectKindForObject(obj runtime.Object) runtimeObjectKind {
switch obj.(type) {
case *unstructured.Unstructured:
return runtimeObjectKindUnstructured
case *unstructured.UnstructuredList:
return runtimeObjectKindUnstructured
case *metav1.PartialObjectMetadata:
return runtimeObjectKindMetadata
case *metav1.PartialObjectMetadataList:
return runtimeObjectKindMetadata
default:
return runtimeObjectKindStructured
}
}

type TransformFuncByObject map[runtimeObjectKind]map[schema.GroupVersionKind]cache.TransformFunc
type TransformFuncByGVK map[schema.GroupVersionKind]cache.TransformFunc

func NewTransformFuncByObject() TransformFuncByObject {
return TransformFuncByObject{}
}

func (t TransformFuncByObject) Set(obj runtime.Object, scheme *runtime.Scheme, transformer cache.TransformFunc) error {
kind := runtimeObjectKindForObject(obj)
existing, ok := t[kind]
if !ok {
existing = TransformFuncByGVK{}
t[kind] = existing
}

gvk, err := apiutil.GVKForObject(obj, nil)
if err != nil {
return err
}

existing[gvk] = transformer
return nil
}

func (t TransformFuncByObject) Get(kind runtimeObjectKind) TransformFuncByGVK {
if val, ok := t[kind]; ok {
return val
}
return nil
}

func (t TransformFuncByGVK) Get(gvk schema.GroupVersionKind) cache.TransformFunc {
if val, ok := t[gvk]; ok {
return val
}
return nil
}

0 comments on commit 603031f

Please sign in to comment.