Skip to content

Commit

Permalink
🌱 Cleanup internal cache/informers map impl
Browse files Browse the repository at this point in the history
Signed-off-by: Vince Prignano <vince@prigna.com>
  • Loading branch information
vincepri committed Dec 21, 2022
1 parent 92234b3 commit 67c79f0
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 71 deletions.
16 changes: 14 additions & 2 deletions pkg/cache/cache.go
Expand Up @@ -181,8 +181,20 @@ func New(config *rest.Config, opts Options) (Cache, error) {
internalSelectorsByGVK[gvk] = internal.Selector(selector)
}

im := internal.NewInformersMap(config, opts.Scheme, opts.Mapper, *opts.Resync, opts.Namespace, internalSelectorsByGVK, disableDeepCopyByGVK, transformByObj)
return &informerCache{InformersMap: im}, nil
return &informerCache{
scheme: opts.Scheme,
InformersMap: internal.NewInformersMap(config, &internal.InformersMapOptions{
Scheme: opts.Scheme,
Mapper: opts.Mapper,
ResyncPeriod: *opts.Resync,
Namespace: opts.Namespace,
ByGVK: internal.InformersMapOptionsByGVK{
Selectors: internalSelectorsByGVK,
DisableDeepCopy: disableDeepCopyByGVK,
Transformers: transformByObj,
},
}),
}, nil
}

// BuilderWithOptions returns a Cache constructor that will build a cache
Expand Down
9 changes: 5 additions & 4 deletions pkg/cache/informer_cache.go
Expand Up @@ -47,12 +47,13 @@ func (*ErrCacheNotStarted) Error() string {

// informerCache is a Kubernetes Object cache populated from InformersMap. informerCache wraps an InformersMap.
type informerCache struct {
scheme *runtime.Scheme
*internal.InformersMap
}

// Get implements Reader.
func (ip *informerCache) Get(ctx context.Context, key client.ObjectKey, out client.Object, opts ...client.GetOption) error {
gvk, err := apiutil.GVKForObject(out, ip.Scheme)
gvk, err := apiutil.GVKForObject(out, ip.scheme)
if err != nil {
return err
}
Expand Down Expand Up @@ -91,7 +92,7 @@ func (ip *informerCache) List(ctx context.Context, out client.ObjectList, opts .
// for a single object corresponding to the passed-in list type. We need them
// because they are used as cache map key.
func (ip *informerCache) objectTypeForListObject(list client.ObjectList) (*schema.GroupVersionKind, runtime.Object, error) {
gvk, err := apiutil.GVKForObject(list, ip.Scheme)
gvk, err := apiutil.GVKForObject(list, ip.scheme)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -132,7 +133,7 @@ func (ip *informerCache) objectTypeForListObject(list client.ObjectList) (*schem
// GetInformerForKind returns the informer for the GroupVersionKind.
func (ip *informerCache) GetInformerForKind(ctx context.Context, gvk schema.GroupVersionKind) (Informer, error) {
// Map the gvk to an object
obj, err := ip.Scheme.New(gvk)
obj, err := ip.scheme.New(gvk)
if err != nil {
return nil, err
}
Expand All @@ -146,7 +147,7 @@ func (ip *informerCache) GetInformerForKind(ctx context.Context, gvk schema.Grou

// GetInformer returns the informer for the obj.
func (ip *informerCache) GetInformer(ctx context.Context, obj client.Object) (Informer, error) {
gvk, err := apiutil.GVKForObject(obj, ip.Scheme)
gvk, err := apiutil.GVKForObject(obj, ip.scheme)
if err != nil {
return nil, err
}
Expand Down
7 changes: 4 additions & 3 deletions pkg/cache/informer_cache_unit_test.go
Expand Up @@ -38,7 +38,8 @@ const (

var _ = Describe("ip.objectTypeForListObject", func() {
ip := &informerCache{
InformersMap: &internal.InformersMap{Scheme: scheme.Scheme},
scheme: scheme.Scheme,
InformersMap: &internal.InformersMap{},
}

It("should find the object type for unstructured lists", func() {
Expand Down Expand Up @@ -70,14 +71,14 @@ var _ = Describe("ip.objectTypeForListObject", func() {

It("should find the object type of a list with a slice of pointers items field", func() {
By("registering the type", func() {
ip.Scheme = runtime.NewScheme()
ip.scheme = runtime.NewScheme()
err := (&crscheme.Builder{
GroupVersion: schema.GroupVersion{Group: itemPointerSliceTypeGroupName, Version: itemPointerSliceTypeVersion},
}).
Register(
&controllertest.UnconventionalListType{},
&controllertest.UnconventionalListTypeList{},
).AddToScheme(ip.Scheme)
).AddToScheme(ip.scheme)
Expect(err).To(BeNil())
})

Expand Down
66 changes: 32 additions & 34 deletions pkg/cache/internal/deleg_map.go
Expand Up @@ -34,32 +34,48 @@ import (
type InformersMap struct {
// we abstract over the details of structured/unstructured/metadata with the specificInformerMaps
// TODO(directxman12): genericize this over different projections now that we have 3 different maps
// TODO(vincepri): A different structure of the specific informer map is possible, although it requires
// a large refactoring that takes into account that there may be different kind of informers, in this case
// 3 of those: structured, unstructured, and metadata.

structured *specificInformersMap
unstructured *specificInformersMap
metadata *specificInformersMap
}

// InformersMapOptions configures an InformerMap.
type InformersMapOptions struct {
Scheme *runtime.Scheme
Mapper meta.RESTMapper
ResyncPeriod time.Duration
Namespace string
ByGVK InformersMapOptionsByGVK
}

// Scheme maps runtime.Objects to GroupVersionKinds
Scheme *runtime.Scheme
// InformersMapOptionsByGVK configured additional by group version kind (or object)
// in an InformerMap.
type InformersMapOptionsByGVK struct {
Selectors SelectorsByGVK
Transformers TransformFuncByObject // TODO(vincepri): Why is this by object and not GVK?
DisableDeepCopy DisableDeepCopyByGVK
}

// NewInformersMap creates a new InformersMap that can create informers for
// both structured and unstructured objects.
func NewInformersMap(config *rest.Config,
scheme *runtime.Scheme,
mapper meta.RESTMapper,
resync time.Duration,
namespace string,
selectors SelectorsByGVK,
disableDeepCopy DisableDeepCopyByGVK,
transformers TransformFuncByObject,
) *InformersMap {
func NewInformersMap(config *rest.Config, options *InformersMapOptions) *InformersMap {
return &InformersMap{
structured: newStructuredInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, transformers),
unstructured: newUnstructuredInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, transformers),
metadata: newMetadataInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, transformers),

Scheme: scheme,
structured: newSpecificInformersMap(config, &specificInformerMapOptions{
InformersMapOptions: options,
ListWatcherFunc: structuredListWatch,
}),
unstructured: newSpecificInformersMap(config, &specificInformerMapOptions{
InformersMapOptions: options,
ListWatcherFunc: unstructuredListWatch,
}),
metadata: newSpecificInformersMap(config, &specificInformerMapOptions{
InformersMapOptions: options,
ListWatcherFunc: metadataListWatch,
}),
}
}

Expand Down Expand Up @@ -106,21 +122,3 @@ func (m *InformersMap) Get(ctx context.Context, gvk schema.GroupVersionKind, obj
return m.structured.Get(ctx, gvk, 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, transformers TransformFuncByObject) *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, transformers TransformFuncByObject) *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, transformers TransformFuncByObject) *specificInformersMap {
return newSpecificInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, transformers, createMetadataListWatch)
}
52 changes: 24 additions & 28 deletions pkg/cache/internal/informers_map.go
Expand Up @@ -45,34 +45,30 @@ func init() {
// clientListWatcherFunc knows how to create a ListWatcher.
type createListWatcherFunc func(gvk schema.GroupVersionKind, ip *specificInformersMap) (*cache.ListWatch, error)

// specificInformerMapOptions contains options to create a new specific informer map.
type specificInformerMapOptions struct {
*InformersMapOptions
ListWatcherFunc createListWatcherFunc
}

// newSpecificInformersMap returns a new specificInformersMap (like
// the generical InformersMap, except that it doesn't implement WaitForCacheSync).
func newSpecificInformersMap(config *rest.Config,
scheme *runtime.Scheme,
mapper meta.RESTMapper,
resync time.Duration,
namespace string,
selectors SelectorsByGVK,
disableDeepCopy DisableDeepCopyByGVK,
transformers TransformFuncByObject,
createListWatcher createListWatcherFunc,
) *specificInformersMap {
ip := &specificInformersMap{
func newSpecificInformersMap(config *rest.Config, options *specificInformerMapOptions) *specificInformersMap {
return &specificInformersMap{
config: config,
Scheme: scheme,
mapper: mapper,
scheme: options.Scheme,
mapper: options.Mapper,
informersByGVK: make(map[schema.GroupVersionKind]*MapEntry),
codecs: serializer.NewCodecFactory(scheme),
paramCodec: runtime.NewParameterCodec(scheme),
resync: resync,
codecs: serializer.NewCodecFactory(options.Scheme),
paramCodec: runtime.NewParameterCodec(options.Scheme),
resync: options.ResyncPeriod,
startWait: make(chan struct{}),
createListWatcher: createListWatcher,
namespace: namespace,
selectors: selectors.forGVK,
disableDeepCopy: disableDeepCopy,
transformers: transformers,
createListWatcher: options.ListWatcherFunc,
namespace: options.Namespace,
selectors: options.ByGVK.Selectors.forGVK,
disableDeepCopy: options.ByGVK.DisableDeepCopy,
transformers: options.ByGVK.Transformers,
}
return ip
}

// MapEntry contains the cached data for an Informer.
Expand All @@ -87,8 +83,8 @@ type MapEntry struct {
// specificInformersMap create and caches Informers for (runtime.Object, schema.GroupVersionKind) pairs.
// It uses a standard parameter codec constructed based on the given generated Scheme.
type specificInformersMap struct {
// Scheme maps runtime.Objects to GroupVersionKinds
Scheme *runtime.Scheme
// scheme maps runtime.Objects to GroupVersionKinds
scheme *runtime.Scheme

// config is used to talk to the apiserver
config *rest.Config
Expand Down Expand Up @@ -265,7 +261,7 @@ func (ip *specificInformersMap) addInformerToMap(gvk schema.GroupVersionKind, ob
}

// newListWatch returns a new ListWatch object that can be used to create a SharedIndexInformer.
func createStructuredListWatch(gvk schema.GroupVersionKind, ip *specificInformersMap) (*cache.ListWatch, error) {
func structuredListWatch(gvk schema.GroupVersionKind, ip *specificInformersMap) (*cache.ListWatch, error) {
// Kubernetes APIs work against Resources, not GroupVersionKinds. Map the
// groupVersionKind to the Resource API we will use.
mapping, err := ip.mapper.RESTMapping(gvk.GroupKind(), gvk.Version)
Expand All @@ -278,7 +274,7 @@ func createStructuredListWatch(gvk schema.GroupVersionKind, ip *specificInformer
return nil, err
}
listGVK := gvk.GroupVersion().WithKind(gvk.Kind + "List")
listObj, err := ip.Scheme.New(listGVK)
listObj, err := ip.scheme.New(listGVK)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -308,7 +304,7 @@ func createStructuredListWatch(gvk schema.GroupVersionKind, ip *specificInformer
}, nil
}

func createUnstructuredListWatch(gvk schema.GroupVersionKind, ip *specificInformersMap) (*cache.ListWatch, error) {
func unstructuredListWatch(gvk schema.GroupVersionKind, ip *specificInformersMap) (*cache.ListWatch, error) {
// Kubernetes APIs work against Resources, not GroupVersionKinds. Map the
// groupVersionKind to the Resource API we will use.
mapping, err := ip.mapper.RESTMapping(gvk.GroupKind(), gvk.Version)
Expand Down Expand Up @@ -352,7 +348,7 @@ func createUnstructuredListWatch(gvk schema.GroupVersionKind, ip *specificInform
}, nil
}

func createMetadataListWatch(gvk schema.GroupVersionKind, ip *specificInformersMap) (*cache.ListWatch, error) {
func metadataListWatch(gvk schema.GroupVersionKind, ip *specificInformersMap) (*cache.ListWatch, error) {
// Kubernetes APIs work against Resources, not GroupVersionKinds. Map the
// groupVersionKind to the Resource API we will use.
mapping, err := ip.mapper.RESTMapping(gvk.GroupKind(), gvk.Version)
Expand Down

0 comments on commit 67c79f0

Please sign in to comment.