@@ -27,15 +27,16 @@ import (
27
27
"time"
28
28
29
29
"github.com/go-logr/logr"
30
+ certificatesv1alpha1 "k8s.io/api/certificates/v1alpha1"
30
31
certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
31
32
k8serrors "k8s.io/apimachinery/pkg/api/errors"
32
33
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
34
+ "k8s.io/apimachinery/pkg/labels"
35
+ "k8s.io/apimachinery/pkg/runtime/schema"
33
36
lrucache "k8s.io/apimachinery/pkg/util/cache"
34
37
"k8s.io/apimachinery/pkg/util/sets"
35
38
"k8s.io/client-go/informers"
36
- certinformersv1beta1 "k8s.io/client-go/informers/certificates/v1beta1"
37
39
clientset "k8s.io/client-go/kubernetes"
38
- certlistersv1beta1 "k8s.io/client-go/listers/certificates/v1beta1"
39
40
"k8s.io/client-go/tools/cache"
40
41
"k8s.io/klog/v2"
41
42
)
@@ -44,6 +45,51 @@ const (
44
45
maxLabelSelectorLength = 100 * 1024
45
46
)
46
47
48
+ // clusterTrustBundle is a type constraint for version-independent ClusterTrustBundle API
49
+ type clusterTrustBundle interface {
50
+ certificatesv1alpha1.ClusterTrustBundle | certificatesv1beta1.ClusterTrustBundle
51
+ }
52
+
53
+ // clusterTrustBundlesLister is an API-verion independent ClusterTrustBundles lister
54
+ type clusterTrustBundlesLister [T clusterTrustBundle ] interface {
55
+ Get (string ) (* T , error )
56
+ List (labels.Selector ) ([]* T , error )
57
+ }
58
+
59
+ type clusterTrustBundleHandlers [T clusterTrustBundle ] interface {
60
+ GetName (* T ) string
61
+ GetSignerName (* T ) string
62
+ GetTrustBundle (* T ) string
63
+ }
64
+
65
+ type alphaClusterTrustBundleHandlers struct {}
66
+
67
+ type betaClusterTrustBundleHandlers struct {}
68
+
69
+ func (b * alphaClusterTrustBundleHandlers ) GetName (ctb * certificatesv1alpha1.ClusterTrustBundle ) string {
70
+ return ctb .Name
71
+ }
72
+
73
+ func (b * alphaClusterTrustBundleHandlers ) GetSignerName (ctb * certificatesv1alpha1.ClusterTrustBundle ) string {
74
+ return ctb .Spec .SignerName
75
+ }
76
+
77
+ func (b * alphaClusterTrustBundleHandlers ) GetTrustBundle (ctb * certificatesv1alpha1.ClusterTrustBundle ) string {
78
+ return ctb .Spec .TrustBundle
79
+ }
80
+
81
+ func (b betaClusterTrustBundleHandlers ) GetName (ctb * certificatesv1beta1.ClusterTrustBundle ) string {
82
+ return ctb .Name
83
+ }
84
+
85
+ func (b * betaClusterTrustBundleHandlers ) GetSignerName (ctb * certificatesv1beta1.ClusterTrustBundle ) string {
86
+ return ctb .Spec .SignerName
87
+ }
88
+
89
+ func (b * betaClusterTrustBundleHandlers ) GetTrustBundle (ctb * certificatesv1beta1.ClusterTrustBundle ) string {
90
+ return ctb .Spec .TrustBundle
91
+ }
92
+
47
93
// Manager abstracts over the ability to get trust anchors.
48
94
type Manager interface {
49
95
GetTrustAnchorsByName (name string , allowMissing bool ) ([]byte , error )
@@ -52,23 +98,44 @@ type Manager interface {
52
98
53
99
// InformerManager is the "real" manager. It uses informers to track
54
100
// ClusterTrustBundle objects.
55
- type InformerManager struct {
101
+ type InformerManager [ T clusterTrustBundle ] struct {
56
102
ctbInformer cache.SharedIndexInformer
57
- ctbLister certlistersv1beta1.ClusterTrustBundleLister
103
+ ctbLister clusterTrustBundlesLister [T ]
104
+
105
+ ctbHandlers clusterTrustBundleHandlers [T ]
58
106
59
107
normalizationCache * lrucache.LRUExpireCache
60
108
cacheTTL time.Duration
61
109
}
62
110
63
- var _ Manager = (* InformerManager )(nil )
111
+ var _ Manager = (* InformerManager [certificatesv1beta1.ClusterTrustBundle ])(nil )
112
+
113
+ func NewAlphaInformerManager (
114
+ ctx context.Context , informerFactory informers.SharedInformerFactory , cacheSize int , cacheTTL time.Duration ,
115
+ ) (Manager , error ) {
116
+ bundlesInformer := informerFactory .Certificates ().V1alpha1 ().ClusterTrustBundles ()
117
+ return newInformerManager (
118
+ ctx , & alphaClusterTrustBundleHandlers {}, bundlesInformer .Informer (), bundlesInformer .Lister (), cacheSize , cacheTTL ,
119
+ )
120
+ }
121
+
122
+ func NewBetaInformerManager (
123
+ ctx context.Context , informerFactory informers.SharedInformerFactory , cacheSize int , cacheTTL time.Duration ,
124
+ ) (Manager , error ) {
125
+ bundlesInformer := informerFactory .Certificates ().V1beta1 ().ClusterTrustBundles ()
126
+ return newInformerManager (
127
+ ctx , & betaClusterTrustBundleHandlers {}, bundlesInformer .Informer (), bundlesInformer .Lister (), cacheSize , cacheTTL ,
128
+ )
129
+ }
64
130
65
- // NewInformerManager returns an initialized InformerManager.
66
- func NewInformerManager (ctx context.Context , bundles certinformersv1beta1. ClusterTrustBundleInformer , cacheSize int , cacheTTL time.Duration ) (* InformerManager , error ) {
131
+ // newInformerManager returns an initialized InformerManager.
132
+ func newInformerManager [ T clusterTrustBundle ] (ctx context.Context , handlers clusterTrustBundleHandlers [ T ], informer cache. SharedIndexInformer , lister clusterTrustBundlesLister [ T ], cacheSize int , cacheTTL time.Duration ) (Manager , error ) {
67
133
// We need to call Informer() before calling start on the shared informer
68
134
// factory, or the informer won't be registered to be started.
69
- m := & InformerManager {
70
- ctbInformer : bundles .Informer (),
71
- ctbLister : bundles .Lister (),
135
+ m := & InformerManager [T ]{
136
+ ctbInformer : informer ,
137
+ ctbLister : lister ,
138
+ ctbHandlers : handlers ,
72
139
normalizationCache : lrucache .NewLRUExpireCache (cacheSize ),
73
140
cacheTTL : cacheTTL ,
74
141
}
@@ -78,34 +145,34 @@ func NewInformerManager(ctx context.Context, bundles certinformersv1beta1.Cluste
78
145
// apply to them.
79
146
_ , err := m .ctbInformer .AddEventHandler (cache.ResourceEventHandlerFuncs {
80
147
AddFunc : func (obj any ) {
81
- ctb , ok := obj .(* certificatesv1beta1. ClusterTrustBundle )
148
+ ctb , ok := obj .(* T )
82
149
if ! ok {
83
150
return
84
151
}
85
- logger .Info ("Dropping all cache entries for signer" , "signerName" , ctb . Spec . SignerName )
152
+ logger .Info ("Dropping all cache entries for signer" , "signerName" , m . ctbHandlers . GetSignerName ( ctb ) )
86
153
m .dropCacheFor (ctb )
87
154
},
88
155
UpdateFunc : func (old , new any ) {
89
- ctb , ok := new .(* certificatesv1beta1. ClusterTrustBundle )
156
+ ctb , ok := new .(* T )
90
157
if ! ok {
91
158
return
92
159
}
93
- logger .Info ("Dropping cache for ClusterTrustBundle" , "signerName" , ctb . Spec . SignerName )
94
- m .dropCacheFor (new .(* certificatesv1beta1. ClusterTrustBundle ))
160
+ logger .Info ("Dropping cache for ClusterTrustBundle" , "signerName" , m . ctbHandlers . GetSignerName ( ctb ) )
161
+ m .dropCacheFor (new .(* T ))
95
162
},
96
163
DeleteFunc : func (obj any ) {
97
- ctb , ok := obj .(* certificatesv1beta1. ClusterTrustBundle )
164
+ ctb , ok := obj .(* T )
98
165
if ! ok {
99
166
tombstone , ok := obj .(cache.DeletedFinalStateUnknown )
100
167
if ! ok {
101
168
return
102
169
}
103
- ctb , ok = tombstone .Obj .(* certificatesv1beta1. ClusterTrustBundle )
170
+ ctb , ok = tombstone .Obj .(* T )
104
171
if ! ok {
105
172
return
106
173
}
107
174
}
108
- logger .Info ("Dropping cache for ClusterTrustBundle" , "signerName" , ctb . Spec . SignerName )
175
+ logger .Info ("Dropping cache for ClusterTrustBundle" , "signerName" , m . ctbHandlers . GetSignerName ( ctb ) )
109
176
m .dropCacheFor (ctb )
110
177
},
111
178
})
@@ -116,21 +183,21 @@ func NewInformerManager(ctx context.Context, bundles certinformersv1beta1.Cluste
116
183
return m , nil
117
184
}
118
185
119
- func (m * InformerManager ) dropCacheFor (ctb * certificatesv1beta1. ClusterTrustBundle ) {
120
- if ctb . Spec . SignerName != "" {
186
+ func (m * InformerManager [ T ] ) dropCacheFor (ctb * T ) {
187
+ if ctbSignerName := m . ctbHandlers . GetSignerName ( ctb ); ctbSignerName != "" {
121
188
m .normalizationCache .RemoveAll (func (key any ) bool {
122
- return key .(cacheKeyType ).signerName == ctb . Spec . SignerName
189
+ return key .(cacheKeyType ).signerName == ctbSignerName
123
190
})
124
191
} else {
125
192
m .normalizationCache .RemoveAll (func (key any ) bool {
126
- return key .(cacheKeyType ).ctbName == ctb . ObjectMeta . Name
193
+ return key .(cacheKeyType ).ctbName == m . ctbHandlers . GetName ( ctb )
127
194
})
128
195
}
129
196
}
130
197
131
198
// GetTrustAnchorsByName returns normalized and deduplicated trust anchors from
132
199
// a single named ClusterTrustBundle.
133
- func (m * InformerManager ) GetTrustAnchorsByName (name string , allowMissing bool ) ([]byte , error ) {
200
+ func (m * InformerManager [ T ] ) GetTrustAnchorsByName (name string , allowMissing bool ) ([]byte , error ) {
134
201
if ! m .ctbInformer .HasSynced () {
135
202
return nil , fmt .Errorf ("ClusterTrustBundle informer has not yet synced" )
136
203
}
@@ -149,7 +216,7 @@ func (m *InformerManager) GetTrustAnchorsByName(name string, allowMissing bool)
149
216
return nil , fmt .Errorf ("while getting ClusterTrustBundle: %w" , err )
150
217
}
151
218
152
- pemTrustAnchors , err := m .normalizeTrustAnchors ([]* certificatesv1beta1. ClusterTrustBundle {ctb })
219
+ pemTrustAnchors , err := m .normalizeTrustAnchors ([]* T {ctb })
153
220
if err != nil {
154
221
return nil , fmt .Errorf ("while normalizing trust anchors: %w" , err )
155
222
}
@@ -161,7 +228,7 @@ func (m *InformerManager) GetTrustAnchorsByName(name string, allowMissing bool)
161
228
162
229
// GetTrustAnchorsBySigner returns normalized and deduplicated trust anchors
163
230
// from a set of selected ClusterTrustBundles.
164
- func (m * InformerManager ) GetTrustAnchorsBySigner (signerName string , labelSelector * metav1.LabelSelector , allowMissing bool ) ([]byte , error ) {
231
+ func (m * InformerManager [ T ] ) GetTrustAnchorsBySigner (signerName string , labelSelector * metav1.LabelSelector , allowMissing bool ) ([]byte , error ) {
165
232
if ! m .ctbInformer .HasSynced () {
166
233
return nil , fmt .Errorf ("ClusterTrustBundle informer has not yet synced" )
167
234
}
@@ -188,9 +255,9 @@ func (m *InformerManager) GetTrustAnchorsBySigner(signerName string, labelSelect
188
255
return nil , fmt .Errorf ("while listing ClusterTrustBundles matching label selector %v: %w" , labelSelector , err )
189
256
}
190
257
191
- ctbList := []* certificatesv1beta1. ClusterTrustBundle {}
258
+ ctbList := []* T {}
192
259
for _ , ctb := range rawCTBList {
193
- if ctb . Spec . SignerName == signerName {
260
+ if m . ctbHandlers . GetSignerName ( ctb ) == signerName {
194
261
ctbList = append (ctbList , ctb )
195
262
}
196
263
}
@@ -212,11 +279,11 @@ func (m *InformerManager) GetTrustAnchorsBySigner(signerName string, labelSelect
212
279
return pemTrustAnchors , nil
213
280
}
214
281
215
- func (m * InformerManager ) normalizeTrustAnchors (ctbList []* certificatesv1beta1. ClusterTrustBundle ) ([]byte , error ) {
282
+ func (m * InformerManager [ T ] ) normalizeTrustAnchors (ctbList []* T ) ([]byte , error ) {
216
283
// Deduplicate trust anchors from all ClusterTrustBundles.
217
284
trustAnchorSet := sets.Set [string ]{}
218
285
for _ , ctb := range ctbList {
219
- rest := []byte (ctb . Spec . TrustBundle )
286
+ rest := []byte (m . ctbHandlers . GetTrustBundle ( ctb ) )
220
287
var b * pem.Block
221
288
for {
222
289
b , rest = pem .Decode (rest )
@@ -309,6 +376,8 @@ func (m *LazyInformerManager) isManagerSet() bool {
309
376
return m .manager != nil
310
377
}
311
378
379
+ type managerConstructor func (ctx context.Context , informerFactory informers.SharedInformerFactory , cacheSize int , cacheTTL time.Duration ) (Manager , error )
380
+
312
381
func (m * LazyInformerManager ) ensureManagerSet () error {
313
382
if m .isManagerSet () {
314
383
return nil
@@ -321,24 +390,42 @@ func (m *LazyInformerManager) ensureManagerSet() error {
321
390
return nil
322
391
}
323
392
324
- ctbAPIAvailable , err := clusterTrustBundlesAvailable ( m . client )
325
- if err != nil {
326
- return fmt . Errorf ( "failed to determine which informer manager to choose: %w" , err )
393
+ managerSchema := map [schema. GroupVersion ] managerConstructor {
394
+ certificatesv1alpha1 . SchemeGroupVersion : NewAlphaInformerManager ,
395
+ certificatesv1beta1 . SchemeGroupVersion : NewBetaInformerManager ,
327
396
}
328
397
329
- if ! ctbAPIAvailable {
398
+ kubeInformers := informers .NewSharedInformerFactoryWithOptions (m .client , 0 )
399
+
400
+ var clusterTrustBundleManager Manager
401
+ var foundGV string
402
+ for _ , gv := range []schema.GroupVersion {certificatesv1beta1 .SchemeGroupVersion , certificatesv1alpha1 .SchemeGroupVersion } {
403
+ ctbAPIAvailable , err := clusterTrustBundlesAvailable (m .client , gv )
404
+ if err != nil {
405
+ return fmt .Errorf ("failed to determine which informer manager to choose: %w" , err )
406
+ }
407
+
408
+ if ! ctbAPIAvailable {
409
+ continue
410
+ }
411
+
412
+ clusterTrustBundleManager , err = managerSchema [gv ](m .contextWithLogger , kubeInformers , m .cacheSize , 5 * time .Minute )
413
+ if err != nil {
414
+ return fmt .Errorf ("error starting informer-based ClusterTrustBundle manager: %w" , err )
415
+ }
416
+ foundGV = gv .String ()
417
+ break
418
+ }
419
+
420
+ if clusterTrustBundleManager == nil {
330
421
m .manager = & NoopManager {}
422
+ m .logger .Info ("No version of the ClusterTrustBundle API was found, the ClusterTrustBundle informer won't be started" )
331
423
return nil
332
424
}
333
425
334
- kubeInformers := informers .NewSharedInformerFactoryWithOptions (m .client , 0 )
335
- clusterTrustBundleManager , err := NewInformerManager (m .contextWithLogger , kubeInformers .Certificates ().V1beta1 ().ClusterTrustBundles (), m .cacheSize , 5 * time .Minute )
336
- if err != nil {
337
- return fmt .Errorf ("error starting informer-based ClusterTrustBundle manager: %w" , err )
338
- }
339
426
m .manager = clusterTrustBundleManager
340
427
kubeInformers .Start (m .contextWithLogger .Done ())
341
- m .logger .Info ("Started ClusterTrustBundle informer" )
428
+ m .logger .Info ("Started ClusterTrustBundle informer" , "apiGroup" , foundGV )
342
429
343
430
// a cache fetch will likely follow right after, wait for the freshly started
344
431
// informers to sync
@@ -358,8 +445,8 @@ func (m *LazyInformerManager) ensureManagerSet() error {
358
445
return nil
359
446
}
360
447
361
- func clusterTrustBundlesAvailable (client clientset.Interface ) (bool , error ) {
362
- resList , err := client .Discovery ().ServerResourcesForGroupVersion (certificatesv1beta1 . SchemeGroupVersion .String ())
448
+ func clusterTrustBundlesAvailable (client clientset.Interface , gv schema. GroupVersion ) (bool , error ) {
449
+ resList , err := client .Discovery ().ServerResourcesForGroupVersion (gv .String ())
363
450
if k8serrors .IsNotFound (err ) {
364
451
return false , nil
365
452
}
0 commit comments