Skip to content

Commit bad30ba

Browse files
committed
Add Indexer plumbing, add kcp indexers by default
1 parent 44c7bee commit bad30ba

File tree

6 files changed

+76
-30
lines changed

6 files changed

+76
-30
lines changed

pkg/cache/cache.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ type Options struct {
113113
// Defaults to cache.MetaNamespaceKeyFunc from client-go
114114
KeyFunction cache.KeyFunc
115115

116+
// Indexers is the indexers that the informers will be configured to use.
117+
// Will always have the standard NamespaceIndex.
118+
Indexers cache.Indexers
119+
116120
// Namespace restricts the cache's ListWatch to the desired namespace
117121
// Default watches all namespaces
118122
Namespace string
@@ -151,7 +155,7 @@ func New(config *rest.Config, opts Options) (Cache, error) {
151155
if err != nil {
152156
return nil, err
153157
}
154-
im := internal.NewInformersMap(config, opts.Scheme, opts.Mapper, *opts.Resync, opts.Namespace, selectorsByGVK, disableDeepCopyByGVK, opts.KeyFunction)
158+
im := internal.NewInformersMap(config, opts.Scheme, opts.Mapper, *opts.Resync, opts.Namespace, selectorsByGVK, disableDeepCopyByGVK, opts.KeyFunction, opts.Indexers)
155159
return &informerCache{InformersMap: im}, nil
156160
}
157161

pkg/cache/internal/cache_reader.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222
"reflect"
2323

2424
kcpcache "github.com/kcp-dev/apimachinery/pkg/cache"
25+
kcpclient "github.com/kcp-dev/apimachinery/pkg/client"
26+
2527
apierrors "k8s.io/apimachinery/pkg/api/errors"
2628
apimeta "k8s.io/apimachinery/pkg/api/meta"
2729
"k8s.io/apimachinery/pkg/fields"
@@ -106,14 +108,24 @@ func (c *CacheReader) Get(_ context.Context, key client.ObjectKey, out client.Ob
106108
}
107109

108110
// List lists items out of the indexer and writes them to out.
109-
func (c *CacheReader) List(_ context.Context, out client.ObjectList, opts ...client.ListOption) error {
111+
func (c *CacheReader) List(ctx context.Context, out client.ObjectList, opts ...client.ListOption) error {
110112
var objs []interface{}
111113
var err error
112114

113115
listOpts := client.ListOptions{}
114116
listOpts.ApplyOptions(opts)
115117

118+
// TODO(kcp), should we just require people to pass in the cluster list option, or maybe provide
119+
// a wrapper that adds it from the context automatically rather than doing this?
120+
// It may also make more sense to just use the context and not bother provided a ListOption for it
121+
if listOpts.Cluster.Empty() {
122+
if cluster, ok := kcpclient.ClusterFromContext(ctx); ok {
123+
client.InCluster(cluster).ApplyToList(&listOpts)
124+
}
125+
}
126+
116127
switch {
128+
// TODO(kcp) add cluster to this case
117129
case listOpts.FieldSelector != nil:
118130
// TODO(directxman12): support more complicated field selectors by
119131
// combining multiple indices, GetIndexers, etc
@@ -125,10 +137,12 @@ func (c *CacheReader) List(_ context.Context, out client.ObjectList, opts ...cli
125137
// namespaced index key. Otherwise, ask for the non-namespaced variant by using the fake "all namespaces"
126138
// namespace.
127139
objs, err = c.indexer.ByIndex(FieldIndexName(field), KeyToNamespacedKey(listOpts.Namespace, val))
140+
case listOpts.Cluster.Empty():
141+
objs = c.indexer.List()
128142
case listOpts.Namespace != "":
129-
objs, err = c.indexer.ByIndex(cache.NamespaceIndex, listOpts.Namespace)
143+
objs, err = c.indexer.ByIndex(kcpcache.ClusterAndNamespaceIndexName, kcpcache.ToClusterAwareKey(listOpts.Cluster.String(), listOpts.Namespace, ""))
130144
default:
131-
objs = c.indexer.List()
145+
objs, err = c.indexer.ByIndex(kcpcache.ClusterIndexName, kcpcache.ToClusterAwareKey(listOpts.Cluster.String(), "", ""))
132146
}
133147
if err != nil {
134148
return err

pkg/cache/internal/deleg_map.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,12 @@ func NewInformersMap(config *rest.Config,
5353
selectors SelectorsByGVK,
5454
disableDeepCopy DisableDeepCopyByGVK,
5555
keyFunc cache.KeyFunc,
56+
indexers cache.Indexers,
5657
) *InformersMap {
5758
return &InformersMap{
58-
structured: newStructuredInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, keyFunc),
59-
unstructured: newUnstructuredInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, keyFunc),
60-
metadata: newMetadataInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, keyFunc),
59+
structured: newStructuredInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, keyFunc, indexers),
60+
unstructured: newUnstructuredInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, keyFunc, indexers),
61+
metadata: newMetadataInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, keyFunc, indexers),
6162

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

110111
// newStructuredInformersMap creates a new InformersMap for structured objects.
111112
func newStructuredInformersMap(config *rest.Config, scheme *runtime.Scheme, mapper meta.RESTMapper, resync time.Duration,
112-
namespace string, selectors SelectorsByGVK, disableDeepCopy DisableDeepCopyByGVK, keyFunc cache.KeyFunc) *specificInformersMap {
113-
return newSpecificInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, createStructuredListWatch, keyFunc)
113+
namespace string, selectors SelectorsByGVK, disableDeepCopy DisableDeepCopyByGVK, keyFunc cache.KeyFunc, indexers cache.Indexers) *specificInformersMap {
114+
return newSpecificInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, createStructuredListWatch, keyFunc, indexers)
114115
}
115116

116117
// newUnstructuredInformersMap creates a new InformersMap for unstructured objects.
117118
func newUnstructuredInformersMap(config *rest.Config, scheme *runtime.Scheme, mapper meta.RESTMapper, resync time.Duration,
118-
namespace string, selectors SelectorsByGVK, disableDeepCopy DisableDeepCopyByGVK, keyFunc cache.KeyFunc) *specificInformersMap {
119-
return newSpecificInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, createUnstructuredListWatch, keyFunc)
119+
namespace string, selectors SelectorsByGVK, disableDeepCopy DisableDeepCopyByGVK, keyFunc cache.KeyFunc, indexers cache.Indexers) *specificInformersMap {
120+
return newSpecificInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, createUnstructuredListWatch, keyFunc, indexers)
120121
}
121122

122123
// newMetadataInformersMap creates a new InformersMap for metadata-only objects.
123124
func newMetadataInformersMap(config *rest.Config, scheme *runtime.Scheme, mapper meta.RESTMapper, resync time.Duration,
124-
namespace string, selectors SelectorsByGVK, disableDeepCopy DisableDeepCopyByGVK, keyFunc cache.KeyFunc) *specificInformersMap {
125-
return newSpecificInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, createMetadataListWatch, keyFunc)
125+
namespace string, selectors SelectorsByGVK, disableDeepCopy DisableDeepCopyByGVK, keyFunc cache.KeyFunc, indexers cache.Indexers) *specificInformersMap {
126+
return newSpecificInformersMap(config, scheme, mapper, resync, namespace, selectors, disableDeepCopy, createMetadataListWatch, keyFunc, indexers)
126127
}

pkg/cache/internal/informers_map.go

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -55,22 +55,24 @@ func newSpecificInformersMap(config *rest.Config,
5555
selectors SelectorsByGVK,
5656
disableDeepCopy DisableDeepCopyByGVK,
5757
createListWatcher createListWatcherFunc,
58-
keyFunction cache.KeyFunc) *specificInformersMap {
58+
keyFunction cache.KeyFunc,
59+
indexers cache.Indexers) *specificInformersMap {
5960

6061
ip := &specificInformersMap{
61-
config: config,
62-
Scheme: scheme,
63-
mapper: mapper,
64-
informersByGVK: make(map[schema.GroupVersionKind]*MapEntry),
65-
codecs: serializer.NewCodecFactory(scheme),
66-
paramCodec: runtime.NewParameterCodec(scheme),
67-
resync: resync,
68-
startWait: make(chan struct{}),
69-
createListWatcher: createListWatcher,
70-
namespace: namespace,
71-
selectors: selectors.forGVK,
72-
disableDeepCopy: disableDeepCopy,
73-
keyFunction: keyFunction,
62+
config: config,
63+
Scheme: scheme,
64+
mapper: mapper,
65+
informersByGVK: make(map[schema.GroupVersionKind]*MapEntry),
66+
codecs: serializer.NewCodecFactory(scheme),
67+
paramCodec: runtime.NewParameterCodec(scheme),
68+
resync: resync,
69+
startWait: make(chan struct{}),
70+
createListWatcher: createListWatcher,
71+
namespace: namespace,
72+
selectors: selectors.forGVK,
73+
disableDeepCopy: disableDeepCopy,
74+
keyFunction: keyFunction,
75+
additionalIndexers: indexers,
7476
}
7577
return ip
7678
}
@@ -141,6 +143,10 @@ type specificInformersMap struct {
141143

142144
// keyFunction is the cache.KeyFunc informers will be configured to use
143145
keyFunction cache.KeyFunc
146+
147+
// additionalIndexers is the indexers that the informers will be configured to use.
148+
// Will not allow overwriting the standard NamespaceIndex.
149+
additionalIndexers cache.Indexers
144150
}
145151

146152
// Start calls Run on each of the informers and sets started to true. Blocks on the context.
@@ -230,12 +236,16 @@ func (ip *specificInformersMap) addInformerToMap(gvk schema.GroupVersionKind, ob
230236
if err != nil {
231237
return nil, false, err
232238
}
239+
indexers := cache.Indexers{}
240+
for indexName, indexer := range ip.additionalIndexers {
241+
indexers[indexName] = indexer
242+
}
243+
indexers[cache.NamespaceIndex] = cache.MetaNamespaceIndexFunc
244+
233245
ni := cache.NewSharedIndexInformerWithOptions(lw, obj,
234246
cache.WithResyncPeriod(resyncPeriod(ip.resync)()),
235247
cache.WithKeyFunction(ip.keyFunction),
236-
cache.WithIndexers(cache.Indexers{
237-
cache.NamespaceIndex: cache.MetaNamespaceIndexFunc,
238-
}))
248+
cache.WithIndexers(indexers))
239249
rm, err := ip.mapper.RESTMapping(gvk.GroupKind(), gvk.Version)
240250
if err != nil {
241251
return nil, false, err

pkg/client/options.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package client
1818

1919
import (
20+
"github.com/kcp-dev/logicalcluster"
2021
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2122
"k8s.io/apimachinery/pkg/fields"
2223
"k8s.io/apimachinery/pkg/labels"
@@ -330,6 +331,9 @@ type ListOptions struct {
330331
// non-namespaced objects, or to list across all namespaces.
331332
Namespace string
332333

334+
// Cluster represents the cluster to list for, or empty to list across all clusters.
335+
Cluster logicalcluster.Name
336+
333337
// Limit specifies the maximum number of results to return from the server. The server may
334338
// not support this field on all resource types, but if it does and more results remain it
335339
// will set the continue field on the returned list object. This field is not supported if watch
@@ -488,6 +492,14 @@ func (m MatchingFieldsSelector) ApplyToDeleteAllOf(opts *DeleteAllOfOptions) {
488492
m.ApplyToList(&opts.ListOptions)
489493
}
490494

495+
// InCluster restricts the list/delete operation to the given cluster.
496+
type InCluster logicalcluster.Name
497+
498+
// ApplyToList applies this configuration to the given list options.
499+
func (n InCluster) ApplyToList(opts *ListOptions) {
500+
opts.Cluster = logicalcluster.Name(n)
501+
}
502+
491503
// InNamespace restricts the list/delete operation to the given namespace.
492504
type InNamespace string
493505

pkg/kcp/wrappers.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"net/http"
2121

2222
"k8s.io/client-go/rest"
23+
k8scache "k8s.io/client-go/tools/cache"
2324

2425
kcpcache "github.com/kcp-dev/apimachinery/pkg/cache"
2526
kcpclient "github.com/kcp-dev/apimachinery/pkg/client"
@@ -49,6 +50,10 @@ func NewClusterAwareCache(config *rest.Config, opts cache.Options) (cache.Cache,
4950
c := rest.CopyConfig(config)
5051
c.Host += "/clusters/*"
5152
opts.KeyFunction = kcpcache.ClusterAwareKeyFunc
53+
opts.Indexers = k8scache.Indexers{
54+
kcpcache.ClusterIndexName: kcpcache.ClusterIndexFunc,
55+
kcpcache.ClusterAndNamespaceIndexName: kcpcache.ClusterAndNamespaceIndexFunc,
56+
}
5257
return cache.New(c, opts)
5358
}
5459

0 commit comments

Comments
 (0)