1 // Copyright 2019 The Operator-SDK Authors
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
20 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
22 "k8s.io/apimachinery/pkg/runtime"
23 "k8s.io/apimachinery/pkg/watch"
24 "k8s.io/client-go/dynamic"
25 "k8s.io/client-go/tools/cache"
26 kcollector "k8s.io/kube-state-metrics/pkg/collector"
27 "k8s.io/kube-state-metrics/pkg/metric"
28 metricsstore "k8s.io/kube-state-metrics/pkg/metrics_store"
31 // NewCollectors returns collections of metrics in the namespaces provided, per the api/kind resource.
32 // The metrics are registered in the custom generateStore function that needs to be defined.
33 func NewCollectors(dclient dynamic.NamespaceableResourceInterface, namespaces []string, api string, kind string, metricFamily []metric.FamilyGenerator) []kcollector.Collector {
34 namespaces = deduplicateNamespaces(namespaces)
35 var collectors []kcollector.Collector
36 // Generate collector per namespace.
37 for _, ns := range namespaces {
38 composedMetricGenFuncs := metric.ComposeMetricGenFuncs(metricFamily)
39 headers := metric.ExtractMetricFamilyHeaders(metricFamily)
40 store := metricsstore.NewMetricsStore(headers, composedMetricGenFuncs)
41 reflectorPerNamespace(context.TODO(), dclient, &unstructured.Unstructured{}, store, ns)
42 collector := kcollector.NewCollector(store)
43 collectors = append(collectors, *collector)
48 func deduplicateNamespaces(ns []string) (list []string) {
49 keys := make(map[string]struct{})
50 for _, entry := range ns {
51 if _, ok := keys[entry]; !ok {
52 keys[entry] = struct{}{}
53 list = append(list, entry)
59 func reflectorPerNamespace(
61 dynamicInterface dynamic.NamespaceableResourceInterface,
62 expectedType interface{},
66 lw := listWatchFunc(dynamicInterface, ns)
67 reflector := cache.NewReflector(&lw, expectedType, store, 0)
68 go reflector.Run(ctx.Done())
71 func listWatchFunc(dynamicInterface dynamic.NamespaceableResourceInterface, namespace string) cache.ListWatch {
72 return cache.ListWatch{
73 ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) {
74 return dynamicInterface.Namespace(namespace).List(opts)
76 WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
77 return dynamicInterface.Namespace(namespace).Watch(opts)