@@ -43,6 +43,7 @@ import (
43
43
"k8s.io/klog/v2"
44
44
45
45
ksmtypes "k8s.io/kube-state-metrics/v2/pkg/builder/types"
46
+ "k8s.io/kube-state-metrics/v2/pkg/customresource"
46
47
generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator"
47
48
metricsstore "k8s.io/kube-state-metrics/v2/pkg/metrics_store"
48
49
"k8s.io/kube-state-metrics/v2/pkg/options"
@@ -57,21 +58,23 @@ var _ ksmtypes.BuilderInterface = &Builder{}
57
58
// Builder helps to build store. It follows the builder pattern
58
59
// (https://en.wikipedia.org/wiki/Builder_pattern).
59
60
type Builder struct {
60
- kubeClient clientset.Interface
61
- vpaClient vpaclientset.Interface
62
- namespaces options.NamespaceList
63
- namespaceFilter string
64
- ctx context.Context
65
- enabledResources []string
66
- familyGeneratorFilter generator.FamilyGeneratorFilter
67
- listWatchMetrics * watch.ListWatchMetrics
68
- shardingMetrics * sharding.Metrics
69
- shard int32
70
- totalShards int
71
- buildStoresFunc ksmtypes.BuildStoresFunc
72
- allowAnnotationsList map [string ][]string
73
- allowLabelsList map [string ][]string
74
- useAPIServerCache bool
61
+ kubeClient clientset.Interface
62
+ customResourceClients map [string ]interface {}
63
+ vpaClient vpaclientset.Interface
64
+ namespaces options.NamespaceList
65
+ namespaceFilter string
66
+ ctx context.Context
67
+ enabledResources []string
68
+ familyGeneratorFilter generator.FamilyGeneratorFilter
69
+ listWatchMetrics * watch.ListWatchMetrics
70
+ shardingMetrics * sharding.Metrics
71
+ shard int32
72
+ totalShards int
73
+ buildStoresFunc ksmtypes.BuildStoresFunc
74
+ buildCustomResourceStoresFunc ksmtypes.BuildCustomResourceStoresFunc
75
+ allowAnnotationsList map [string ][]string
76
+ allowLabelsList map [string ][]string
77
+ useAPIServerCache bool
75
78
}
76
79
77
80
// NewBuilder returns a new builder.
@@ -134,23 +137,61 @@ func (b *Builder) WithVPAClient(c vpaclientset.Interface) {
134
137
b .vpaClient = c
135
138
}
136
139
140
+ // WithCustomResourceClients sets the customResourceClients property of a Builder.
141
+ func (b * Builder ) WithCustomResourceClients (cs map [string ]interface {}) {
142
+ b .customResourceClients = cs
143
+ }
144
+
145
+ // WithUsingAPIServerCache configures whether using APIServer cache or not.
146
+ func (b * Builder ) WithUsingAPIServerCache (u bool ) {
147
+ b .useAPIServerCache = u
148
+ }
149
+
137
150
// WithFamilyGeneratorFilter configures the family generator filter which decides which
138
151
// metrics are to be exposed by the store build by the Builder.
139
152
func (b * Builder ) WithFamilyGeneratorFilter (l generator.FamilyGeneratorFilter ) {
140
153
b .familyGeneratorFilter = l
141
154
}
142
155
143
156
// WithGenerateStoresFunc configures a custom generate store function
144
- func (b * Builder ) WithGenerateStoresFunc (f ksmtypes.BuildStoresFunc , u bool ) {
157
+ func (b * Builder ) WithGenerateStoresFunc (f ksmtypes.BuildStoresFunc ) {
145
158
b .buildStoresFunc = f
146
- b .useAPIServerCache = u
159
+ }
160
+
161
+ // WithGenerateCustomResourceStoresFunc configures a custom generate custom resource store function
162
+ func (b * Builder ) WithGenerateCustomResourceStoresFunc (f ksmtypes.BuildCustomResourceStoresFunc ) {
163
+ b .buildCustomResourceStoresFunc = f
147
164
}
148
165
149
166
// DefaultGenerateStoresFunc returns default buildStores function
150
167
func (b * Builder ) DefaultGenerateStoresFunc () ksmtypes.BuildStoresFunc {
151
168
return b .buildStores
152
169
}
153
170
171
+ // DefaultGenerateCustomResourceStoresFunc returns default buildCustomResourceStores function
172
+ func (b * Builder ) DefaultGenerateCustomResourceStoresFunc () ksmtypes.BuildCustomResourceStoresFunc {
173
+ return b .buildCustomResourceStores
174
+ }
175
+
176
+ // WithCustomResourceStoreFactories returns configures a custom resource stores factory
177
+ func (b * Builder ) WithCustomResourceStoreFactories (fs ... customresource.RegistryFactory ) {
178
+ for i := range fs {
179
+ f := fs [i ]
180
+ if _ , ok := availableStores [f .Name ()]; ok {
181
+ klog .Warningf ("The internal resource store named %s already exists and is overridden by a custom resource store with the same name, please make sure it meets your expectation" , f .Name ())
182
+ }
183
+ availableStores [f .Name ()] = func (b * Builder ) []cache.Store {
184
+ return b .buildCustomResourceStoresFunc (
185
+ f .Name (),
186
+ f .MetricFamilyGenerators (b .allowAnnotationsList [f .Name ()], b .allowLabelsList [f .Name ()]),
187
+ f .ExpectedType (),
188
+ f .ListWatch ,
189
+ b .useAPIServerCache ,
190
+ )
191
+ }
192
+ }
193
+ }
194
+
154
195
// WithAllowAnnotations configures which annotations can be returned for metrics
155
196
func (b * Builder ) WithAllowAnnotations (annotations map [string ][]string ) {
156
197
if len (annotations ) > 0 {
@@ -414,6 +455,47 @@ func (b *Builder) buildStores(
414
455
return stores
415
456
}
416
457
458
+ // TODO(Garrybest): Merge `buildStores` and `buildCustomResourceStores`
459
+ func (b * Builder ) buildCustomResourceStores (resourceName string ,
460
+ metricFamilies []generator.FamilyGenerator ,
461
+ expectedType interface {},
462
+ listWatchFunc func (customResourceClient interface {}, ns string , fieldSelector string ) cache.ListerWatcher ,
463
+ useAPIServerCache bool ,
464
+ ) []cache.Store {
465
+ metricFamilies = generator .FilterFamilyGenerators (b .familyGeneratorFilter , metricFamilies )
466
+ composedMetricGenFuncs := generator .ComposeMetricGenFuncs (metricFamilies )
467
+ familyHeaders := generator .ExtractMetricFamilyHeaders (metricFamilies )
468
+
469
+ customResourceClient , ok := b .customResourceClients [resourceName ]
470
+ if ! ok {
471
+ klog .Warningf ("Custom resource client %s does not exist" , resourceName )
472
+ return []cache.Store {}
473
+ }
474
+
475
+ if b .namespaces .IsAllNamespaces () {
476
+ store := metricsstore .NewMetricsStore (
477
+ familyHeaders ,
478
+ composedMetricGenFuncs ,
479
+ )
480
+ listWatcher := listWatchFunc (customResourceClient , v1 .NamespaceAll , b .namespaceFilter )
481
+ b .startReflector (expectedType , store , listWatcher , useAPIServerCache )
482
+ return []cache.Store {store }
483
+ }
484
+
485
+ stores := make ([]cache.Store , 0 , len (b .namespaces ))
486
+ for _ , ns := range b .namespaces {
487
+ store := metricsstore .NewMetricsStore (
488
+ familyHeaders ,
489
+ composedMetricGenFuncs ,
490
+ )
491
+ listWatcher := listWatchFunc (customResourceClient , ns , b .namespaceFilter )
492
+ b .startReflector (expectedType , store , listWatcher , useAPIServerCache )
493
+ stores = append (stores , store )
494
+ }
495
+
496
+ return stores
497
+ }
498
+
417
499
// startReflector starts a Kubernetes client-go reflector with the given
418
500
// listWatcher and registers it with the given store.
419
501
func (b * Builder ) startReflector (
0 commit comments