@@ -27,24 +27,31 @@ import (
27
27
"k8s.io/apimachinery/pkg/runtime/schema"
28
28
"k8s.io/apimachinery/pkg/runtime/serializer"
29
29
"k8s.io/apimachinery/pkg/watch"
30
+ "k8s.io/client-go/dynamic"
30
31
"k8s.io/client-go/rest"
31
32
"k8s.io/client-go/tools/cache"
33
+
32
34
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
33
35
)
34
36
35
- // NewInformersMap returns a new InformersMap
36
- func NewInformersMap (config * rest.Config ,
37
+ // clientListWatcherFunc knows how to create a ListWatcher
38
+ type createListWatcherFunc func (gvk schema.GroupVersionKind , ip * specificInformersMap ) (* cache.ListWatch , error )
39
+
40
+ // newSpecificInformersMap returns a new specificInformersMap (like
41
+ // the generical InformersMap, except that it doesn't implement WaitForCacheSync).
42
+ func newSpecificInformersMap (config * rest.Config ,
37
43
scheme * runtime.Scheme ,
38
44
mapper meta.RESTMapper ,
39
- resync time.Duration ) * InformersMap {
40
- ip := & InformersMap {
41
- config : config ,
42
- Scheme : scheme ,
43
- mapper : mapper ,
44
- informersByGVK : make (map [schema.GroupVersionKind ]* MapEntry ),
45
- codecs : serializer .NewCodecFactory (scheme ),
46
- paramCodec : runtime .NewParameterCodec (scheme ),
47
- resync : resync ,
45
+ resync time.Duration , createListWatcher createListWatcherFunc ) * specificInformersMap {
46
+ ip := & specificInformersMap {
47
+ config : config ,
48
+ Scheme : scheme ,
49
+ mapper : mapper ,
50
+ informersByGVK : make (map [schema.GroupVersionKind ]* MapEntry ),
51
+ codecs : serializer .NewCodecFactory (scheme ),
52
+ paramCodec : runtime .NewParameterCodec (scheme ),
53
+ resync : resync ,
54
+ createListWatcher : createListWatcher ,
48
55
}
49
56
return ip
50
57
}
@@ -58,9 +65,9 @@ type MapEntry struct {
58
65
Reader CacheReader
59
66
}
60
67
61
- // InformersMap create and caches Informers for (runtime.Object, schema.GroupVersionKind) pairs.
62
- //It uses a standard parameter codec constructed based on the given generated Scheme.
63
- type InformersMap struct {
68
+ // specificInformersMap create and caches Informers for (runtime.Object, schema.GroupVersionKind) pairs.
69
+ // It uses a standard parameter codec constructed based on the given generated Scheme.
70
+ type specificInformersMap struct {
64
71
// Scheme maps runtime.Objects to GroupVersionKinds
65
72
Scheme * runtime.Scheme
66
73
@@ -90,10 +97,16 @@ type InformersMap struct {
90
97
91
98
// start is true if the informers have been started
92
99
started bool
100
+
101
+ // createClient knows how to create a client and a list object,
102
+ // and allows for abstracting over the particulars of structured vs
103
+ // unstructured objects.
104
+ createListWatcher createListWatcherFunc
93
105
}
94
106
95
107
// Start calls Run on each of the informers and sets started to true. Blocks on the stop channel.
96
- func (ip * InformersMap ) Start (stop <- chan struct {}) error {
108
+ // It doesn't return start because it can't return an error, and it's not a runnable directly.
109
+ func (ip * specificInformersMap ) Start (stop <- chan struct {}) {
97
110
func () {
98
111
ip .mu .Lock ()
99
112
defer ip .mu .Unlock ()
@@ -110,21 +123,20 @@ func (ip *InformersMap) Start(stop <-chan struct{}) error {
110
123
ip .started = true
111
124
}()
112
125
<- stop
113
- return nil
114
126
}
115
127
116
- // WaitForCacheSync waits until all the caches have been synced
117
- func (ip * InformersMap ) WaitForCacheSync ( stop <- chan struct {}) bool {
128
+ // HasSyncedFuncs returns all the HasSynced functions for the informers in this map.
129
+ func (ip * specificInformersMap ) HasSyncedFuncs () []cache. InformerSynced {
118
130
syncedFuncs := make ([]cache.InformerSynced , 0 , len (ip .informersByGVK ))
119
131
for _ , informer := range ip .informersByGVK {
120
132
syncedFuncs = append (syncedFuncs , informer .Informer .HasSynced )
121
133
}
122
- return cache . WaitForCacheSync ( stop , syncedFuncs ... )
134
+ return syncedFuncs
123
135
}
124
136
125
- // Get will create a new Informer and add it to the map of InformersMap if none exists. Returns
137
+ // Get will create a new Informer and add it to the map of specificInformersMap if none exists. Returns
126
138
// the Informer from the map.
127
- func (ip * InformersMap ) Get (gvk schema.GroupVersionKind , obj runtime.Object ) (* MapEntry , error ) {
139
+ func (ip * specificInformersMap ) Get (gvk schema.GroupVersionKind , obj runtime.Object ) (* MapEntry , error ) {
128
140
// Return the informer if it is found
129
141
i , ok := func () (* MapEntry , bool ) {
130
142
ip .mu .RLock ()
@@ -154,7 +166,7 @@ func (ip *InformersMap) Get(gvk schema.GroupVersionKind, obj runtime.Object) (*M
154
166
155
167
// Create a NewSharedIndexInformer and add it to the map.
156
168
var lw * cache.ListWatch
157
- lw , err := ip .newListWatch (gvk )
169
+ lw , err := ip .createListWatcher (gvk , ip )
158
170
if err != nil {
159
171
return nil , err
160
172
}
@@ -191,22 +203,18 @@ func (ip *InformersMap) Get(gvk schema.GroupVersionKind, obj runtime.Object) (*M
191
203
}
192
204
193
205
// newListWatch returns a new ListWatch object that can be used to create a SharedIndexInformer.
194
- func (ip * InformersMap ) newListWatch (gvk schema.GroupVersionKind ) (* cache.ListWatch , error ) {
195
- // Construct a RESTClient for the groupVersionKind that we will use to
196
- // talk to the apiserver.
197
- client , err := apiutil .RESTClientForGVK (gvk , ip .config , ip .codecs )
198
- if err != nil {
199
- return nil , err
200
- }
201
-
206
+ func createStructuredListWatch (gvk schema.GroupVersionKind , ip * specificInformersMap ) (* cache.ListWatch , error ) {
202
207
// Kubernetes APIs work against Resources, not GroupVersionKinds. Map the
203
208
// groupVersionKind to the Resource API we will use.
204
209
mapping , err := ip .mapper .RESTMapping (gvk .GroupKind (), gvk .Version )
205
210
if err != nil {
206
211
return nil , err
207
212
}
208
213
209
- // Get a listObject for listing that the ListWatch can DeepCopy
214
+ client , err := apiutil .RESTClientForGVK (gvk , ip .config , ip .codecs )
215
+ if err != nil {
216
+ return nil , err
217
+ }
210
218
listGVK := gvk .GroupVersion ().WithKind (gvk .Kind + "List" )
211
219
listObj , err := ip .Scheme .New (listGVK )
212
220
if err != nil {
@@ -228,3 +236,29 @@ func (ip *InformersMap) newListWatch(gvk schema.GroupVersionKind) (*cache.ListWa
228
236
},
229
237
}, nil
230
238
}
239
+
240
+ func createUnstructuredListWatch (gvk schema.GroupVersionKind , ip * specificInformersMap ) (* cache.ListWatch , error ) {
241
+ // Kubernetes APIs work against Resources, not GroupVersionKinds. Map the
242
+ // groupVersionKind to the Resource API we will use.
243
+ mapping , err := ip .mapper .RESTMapping (gvk .GroupKind (), gvk .Version )
244
+ if err != nil {
245
+ return nil , err
246
+ }
247
+ dynamicClient , err := dynamic .NewForConfig (ip .config )
248
+ if err != nil {
249
+ return nil , err
250
+ }
251
+
252
+ // Create a new ListWatch for the obj
253
+ return & cache.ListWatch {
254
+ ListFunc : func (opts metav1.ListOptions ) (runtime.Object , error ) {
255
+ return dynamicClient .Resource (mapping .Resource ).List (opts )
256
+ },
257
+ // Setup the watch function
258
+ WatchFunc : func (opts metav1.ListOptions ) (watch.Interface , error ) {
259
+ // Watch needs to be set to true separately
260
+ opts .Watch = true
261
+ return dynamicClient .Resource (mapping .Resource ).Watch (opts )
262
+ },
263
+ }, nil
264
+ }
0 commit comments