diff --git a/internal/discovery/types.go b/internal/discovery/types.go index 7de4a6ca4a..9d31176ed9 100644 --- a/internal/discovery/types.go +++ b/internal/discovery/types.go @@ -15,93 +15,20 @@ package discovery import ( "fmt" - "sync" - "github.com/prometheus/client_golang/prometheus" "k8s.io/apimachinery/pkg/runtime/schema" ) -type groupVersionKindPlural struct { +type GroupVersionKindPlural struct { schema.GroupVersionKind Plural string } -func (g groupVersionKindPlural) String() string { +func (g GroupVersionKindPlural) String() string { return fmt.Sprintf("%s/%s, Kind=%s, Plural=%s", g.Group, g.Version, g.Kind, g.Plural) } -type kindPlural struct { +type KindPlural struct { Kind string Plural string } - -// CRDiscoverer provides a cache of the collected GVKs, along with helper utilities. -type CRDiscoverer struct { - // m is a mutex to protect the cache. - m sync.RWMutex - // Map is a cache of the collected GVKs. - Map map[string]map[string][]kindPlural - // ShouldUpdate is a flag that indicates whether the cache was updated. - WasUpdated bool - // CRDsAddEventsCounter tracks the number of times that the CRD informer triggered the "add" event. - CRDsAddEventsCounter prometheus.Counter - // CRDsDeleteEventsCounter tracks the number of times that the CRD informer triggered the "remove" event. - CRDsDeleteEventsCounter prometheus.Counter - // CRDsCacheCountGauge tracks the net amount of CRDs affecting the cache at this point. - CRDsCacheCountGauge prometheus.Gauge -} - -// SafeRead executes the given function while holding a read lock. -func (r *CRDiscoverer) SafeRead(f func()) { - r.m.RLock() - defer r.m.RUnlock() - f() -} - -// SafeWrite executes the given function while holding a write lock. -func (r *CRDiscoverer) SafeWrite(f func()) { - r.m.Lock() - defer r.m.Unlock() - f() -} - -// AppendToMap appends the given GVKs to the cache. -func (r *CRDiscoverer) AppendToMap(gvkps ...groupVersionKindPlural) { - if r.Map == nil { - r.Map = map[string]map[string][]kindPlural{} - } - for _, gvkp := range gvkps { - if _, ok := r.Map[gvkp.Group]; !ok { - r.Map[gvkp.Group] = map[string][]kindPlural{} - } - if _, ok := r.Map[gvkp.Group][gvkp.Version]; !ok { - r.Map[gvkp.Group][gvkp.Version] = []kindPlural{} - } - r.Map[gvkp.Group][gvkp.Version] = append(r.Map[gvkp.Group][gvkp.Version], kindPlural{Kind: gvkp.Kind, Plural: gvkp.Plural}) - } -} - -// RemoveFromMap removes the given GVKs from the cache. -func (r *CRDiscoverer) RemoveFromMap(gvkps ...groupVersionKindPlural) { - for _, gvkp := range gvkps { - if _, ok := r.Map[gvkp.Group]; !ok { - continue - } - if _, ok := r.Map[gvkp.Group][gvkp.Version]; !ok { - continue - } - for i, el := range r.Map[gvkp.Group][gvkp.Version] { - if el.Kind == gvkp.Kind { - if len(r.Map[gvkp.Group][gvkp.Version]) == 1 { - delete(r.Map[gvkp.Group], gvkp.Version) - if len(r.Map[gvkp.Group]) == 0 { - delete(r.Map, gvkp.Group) - } - break - } - r.Map[gvkp.Group][gvkp.Version] = append(r.Map[gvkp.Group][gvkp.Version][:i], r.Map[gvkp.Group][gvkp.Version][i+1:]...) - break - } - } - } -} diff --git a/internal/store/builder.go b/internal/store/builder.go index 837f8bc94d..7c4d4aaea4 100644 --- a/internal/store/builder.go +++ b/internal/store/builder.go @@ -48,7 +48,6 @@ import ( metricsstore "k8s.io/kube-state-metrics/v2/pkg/metrics_store" "k8s.io/kube-state-metrics/v2/pkg/options" "k8s.io/kube-state-metrics/v2/pkg/sharding" - "k8s.io/kube-state-metrics/v2/pkg/util" "k8s.io/kube-state-metrics/v2/pkg/watch" ) @@ -197,7 +196,7 @@ func (b *Builder) DefaultGenerateCustomResourceStoresFunc() ksmtypes.BuildCustom func (b *Builder) WithCustomResourceStoreFactories(fs ...customresource.RegistryFactory) { for i := range fs { f := fs[i] - gvr := util.GVRFromType(f.Name(), f.ExpectedType()) + gvr := customresource.GVRFromType(f.Name(), f.ExpectedType()) var gvrString string if gvr != nil { gvrString = gvr.String() @@ -542,7 +541,7 @@ func (b *Builder) buildCustomResourceStores(resourceName string, familyHeaders := generator.ExtractMetricFamilyHeaders(metricFamilies) - gvr := util.GVRFromType(resourceName, expectedType) + gvr := customresource.GVRFromType(resourceName, expectedType) var gvrString string if gvr != nil { gvrString = gvr.String() diff --git a/internal/discovery/discovery.go b/pkg/app/discovery.go similarity index 71% rename from internal/discovery/discovery.go rename to pkg/app/discovery.go index bd764ab701..60b73d5f51 100644 --- a/internal/discovery/discovery.go +++ b/pkg/app/discovery.go @@ -12,13 +12,15 @@ limitations under the License. */ // Package discovery provides a discovery and resolution logic for GVKs. -package discovery +package app import ( "context" "fmt" + "sync" "time" + "github.com/prometheus/client_golang/prometheus" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/dynamic" @@ -27,16 +29,87 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/klog/v2" + "k8s.io/kube-state-metrics/v2/internal/discovery" "k8s.io/kube-state-metrics/v2/internal/store" "k8s.io/kube-state-metrics/v2/pkg/customresource" "k8s.io/kube-state-metrics/v2/pkg/metricshandler" "k8s.io/kube-state-metrics/v2/pkg/options" - "k8s.io/kube-state-metrics/v2/pkg/util" ) // Interval is the time interval between two cache sync checks. const Interval = 3 * time.Second +// CRDiscoverer provides a cache of the collected GVKs, along with helper utilities. +type CRDiscoverer struct { + // m is a mutex to protect the cache. + m sync.RWMutex + // Map is a cache of the collected GVKs. + Map map[string]map[string][]discovery.KindPlural + // ShouldUpdate is a flag that indicates whether the cache was updated. + WasUpdated bool + // CRDsAddEventsCounter tracks the number of times that the CRD informer triggered the "add" event. + CRDsAddEventsCounter prometheus.Counter + // CRDsDeleteEventsCounter tracks the number of times that the CRD informer triggered the "remove" event. + CRDsDeleteEventsCounter prometheus.Counter + // CRDsCacheCountGauge tracks the net amount of CRDs affecting the cache at this point. + CRDsCacheCountGauge prometheus.Gauge +} + +// SafeRead executes the given function while holding a read lock. +func (r *CRDiscoverer) SafeRead(f func()) { + r.m.RLock() + defer r.m.RUnlock() + f() +} + +// SafeWrite executes the given function while holding a write lock. +func (r *CRDiscoverer) SafeWrite(f func()) { + r.m.Lock() + defer r.m.Unlock() + f() +} + +// AppendToMap appends the given GVKs to the cache. +func (r *CRDiscoverer) AppendToMap(gvkps ...discovery.GroupVersionKindPlural) { + if r.Map == nil { + r.Map = map[string]map[string][]discovery.KindPlural{} + } + for _, gvkp := range gvkps { + if _, ok := r.Map[gvkp.Group]; !ok { + r.Map[gvkp.Group] = map[string][]discovery.KindPlural{} + } + if _, ok := r.Map[gvkp.Group][gvkp.Version]; !ok { + r.Map[gvkp.Group][gvkp.Version] = []discovery.KindPlural{} + } + r.Map[gvkp.Group][gvkp.Version] = append(r.Map[gvkp.Group][gvkp.Version], discovery.KindPlural{Kind: gvkp.Kind, Plural: gvkp.Plural}) + } +} + +// RemoveFromMap removes the given GVKs from the cache. +func (r *CRDiscoverer) RemoveFromMap(gvkps ...discovery.GroupVersionKindPlural) { + for _, gvkp := range gvkps { + if _, ok := r.Map[gvkp.Group]; !ok { + continue + } + if _, ok := r.Map[gvkp.Group][gvkp.Version]; !ok { + continue + } + for i, el := range r.Map[gvkp.Group][gvkp.Version] { + if el.Kind == gvkp.Kind { + if len(r.Map[gvkp.Group][gvkp.Version]) == 1 { + delete(r.Map[gvkp.Group], gvkp.Version) + if len(r.Map[gvkp.Group]) == 0 { + delete(r.Map, gvkp.Group) + } + break + } + r.Map[gvkp.Group][gvkp.Version] = append(r.Map[gvkp.Group][gvkp.Version][:i], r.Map[gvkp.Group][gvkp.Version][i+1:]...) + break + } + } + } +} + // StartDiscovery starts the discovery process, fetching all the objects that can be listed from the apiserver, every `Interval` seconds. // resolveGVK needs to be called after StartDiscovery to generate factories. func (r *CRDiscoverer) StartDiscovery(ctx context.Context, config *rest.Config) error { @@ -56,7 +129,7 @@ func (r *CRDiscoverer) StartDiscovery(ctx context.Context, config *rest.Config) v := version.(map[string]interface{})["name"].(string) k := objSpec["names"].(map[string]interface{})["kind"].(string) p := objSpec["names"].(map[string]interface{})["plural"].(string) - gotGVKP := groupVersionKindPlural{ + gotGVKP := discovery.GroupVersionKindPlural{ GroupVersionKind: schema.GroupVersionKind{ Group: g, Version: v, @@ -81,7 +154,7 @@ func (r *CRDiscoverer) StartDiscovery(ctx context.Context, config *rest.Config) v := version.(map[string]interface{})["name"].(string) k := objSpec["names"].(map[string]interface{})["kind"].(string) p := objSpec["names"].(map[string]interface{})["plural"].(string) - gotGVKP := groupVersionKindPlural{ + gotGVKP := discovery.GroupVersionKindPlural{ GroupVersionKind: schema.GroupVersionKind{ Group: g, Version: v, @@ -116,7 +189,7 @@ func (r *CRDiscoverer) StartDiscovery(ctx context.Context, config *rest.Config) } // ResolveGVKToGVKPs resolves the variable VKs to a GVK list, based on the current cache. -func (r *CRDiscoverer) ResolveGVKToGVKPs(gvk schema.GroupVersionKind) (resolvedGVKPs []groupVersionKindPlural, err error) { // nolint:revive +func (r *CRDiscoverer) ResolveGVKToGVKPs(gvk schema.GroupVersionKind) (resolvedGVKPs []discovery.GroupVersionKindPlural, err error) { // nolint:revive g := gvk.Group v := gvk.Version k := gvk.Kind @@ -134,7 +207,7 @@ func (r *CRDiscoverer) ResolveGVKToGVKPs(gvk schema.GroupVersionKind) (resolvedG break } } - return []groupVersionKindPlural{ + return []discovery.GroupVersionKindPlural{ { GroupVersionKind: schema.GroupVersionKind{ Group: g, @@ -148,7 +221,7 @@ func (r *CRDiscoverer) ResolveGVKToGVKPs(gvk schema.GroupVersionKind) (resolvedG if hasVersion && !hasKind { kinds := r.Map[g][v] for _, el := range kinds { - resolvedGVKPs = append(resolvedGVKPs, groupVersionKindPlural{ + resolvedGVKPs = append(resolvedGVKPs, discovery.GroupVersionKindPlural{ GroupVersionKind: schema.GroupVersionKind{ Group: g, Version: v, @@ -163,7 +236,7 @@ func (r *CRDiscoverer) ResolveGVKToGVKPs(gvk schema.GroupVersionKind) (resolvedG for version, kinds := range versions { for _, el := range kinds { if el.Kind == k { - resolvedGVKPs = append(resolvedGVKPs, groupVersionKindPlural{ + resolvedGVKPs = append(resolvedGVKPs, discovery.GroupVersionKindPlural{ GroupVersionKind: schema.GroupVersionKind{ Group: g, Version: version, @@ -179,7 +252,7 @@ func (r *CRDiscoverer) ResolveGVKToGVKPs(gvk schema.GroupVersionKind) (resolvedG versions := r.Map[g] for version, kinds := range versions { for _, el := range kinds { - resolvedGVKPs = append(resolvedGVKPs, groupVersionKindPlural{ + resolvedGVKPs = append(resolvedGVKPs, discovery.GroupVersionKindPlural{ GroupVersionKind: schema.GroupVersionKind{ Group: g, Version: version, @@ -216,11 +289,11 @@ func (r *CRDiscoverer) PollForCacheUpdates( // Update the list of enabled custom resources. var enabledCustomResources []string for _, factory := range customFactories { - gvrString := util.GVRFromType(factory.Name(), factory.ExpectedType()).String() + gvrString := customresource.GVRFromType(factory.Name(), factory.ExpectedType()).String() enabledCustomResources = append(enabledCustomResources, gvrString) } // Create clients for discovered factories. - discoveredCustomResourceClients, err := util.CreateCustomResourceClients(opts.Apiserver, opts.Kubeconfig, customFactories...) + discoveredCustomResourceClients, err := customresource.CreateCustomResourceClients(opts.Apiserver, opts.Kubeconfig, customFactories...) if err != nil { klog.ErrorS(err, "failed to update custom resource stores") } diff --git a/internal/discovery/discovery_test.go b/pkg/app/discovery_test.go similarity index 82% rename from internal/discovery/discovery_test.go rename to pkg/app/discovery_test.go index 39d81aebe2..fed0ea79fc 100644 --- a/internal/discovery/discovery_test.go +++ b/pkg/app/discovery_test.go @@ -11,7 +11,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package discovery +package app import ( "reflect" @@ -19,6 +19,7 @@ import ( "testing" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/kube-state-metrics/v2/internal/discovery" ) func TestGVKMapsResolveGVK(t *testing.T) { @@ -26,21 +27,21 @@ func TestGVKMapsResolveGVK(t *testing.T) { desc string gvkmaps *CRDiscoverer gvk schema.GroupVersionKind - got []groupVersionKindPlural - want []groupVersionKindPlural + got []discovery.GroupVersionKindPlural + want []discovery.GroupVersionKindPlural } testcases := []testcase{ { desc: "variable version and kind", gvkmaps: &CRDiscoverer{ - Map: map[string]map[string][]kindPlural{ + Map: map[string]map[string][]discovery.KindPlural{ "apps": { "v1": { - kindPlural{ + discovery.KindPlural{ Kind: "Deployment", Plural: "deployments", }, - kindPlural{ + discovery.KindPlural{ Kind: "StatefulSet", Plural: "statefulsets", }, @@ -49,7 +50,7 @@ func TestGVKMapsResolveGVK(t *testing.T) { }, }, gvk: schema.GroupVersionKind{Group: "apps", Version: "*", Kind: "*"}, - want: []groupVersionKindPlural{ + want: []discovery.GroupVersionKindPlural{ { GroupVersionKind: schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"}, Plural: "deployments", @@ -63,20 +64,20 @@ func TestGVKMapsResolveGVK(t *testing.T) { { desc: "variable version", gvkmaps: &CRDiscoverer{ - Map: map[string]map[string][]kindPlural{ + Map: map[string]map[string][]discovery.KindPlural{ "testgroup": { "v1": { - kindPlural{ + discovery.KindPlural{ Kind: "TestObject1", Plural: "testobjects1", }, - kindPlural{ + discovery.KindPlural{ Kind: "TestObject2", Plural: "testobjects2", }, }, "v1alpha1": { - kindPlural{ + discovery.KindPlural{ Kind: "TestObject1", Plural: "testobjects1", }, @@ -85,7 +86,7 @@ func TestGVKMapsResolveGVK(t *testing.T) { }, }, gvk: schema.GroupVersionKind{Group: "testgroup", Version: "*", Kind: "TestObject1"}, - want: []groupVersionKindPlural{ + want: []discovery.GroupVersionKindPlural{ { GroupVersionKind: schema.GroupVersionKind{Group: "testgroup", Version: "v1", Kind: "TestObject1"}, Plural: "testobjects1", @@ -99,20 +100,20 @@ func TestGVKMapsResolveGVK(t *testing.T) { { desc: "variable kind", gvkmaps: &CRDiscoverer{ - Map: map[string]map[string][]kindPlural{ + Map: map[string]map[string][]discovery.KindPlural{ "testgroup": { "v1": { - kindPlural{ + discovery.KindPlural{ Kind: "TestObject1", Plural: "testobjects1", }, - kindPlural{ + discovery.KindPlural{ Kind: "TestObject2", Plural: "testobjects2", }, }, "v1alpha1": { - kindPlural{ + discovery.KindPlural{ Kind: "TestObject1", Plural: "testobjects1", }, @@ -121,7 +122,7 @@ func TestGVKMapsResolveGVK(t *testing.T) { }, }, gvk: schema.GroupVersionKind{Group: "testgroup", Version: "v1", Kind: "*"}, - want: []groupVersionKindPlural{ + want: []discovery.GroupVersionKindPlural{ { GroupVersionKind: schema.GroupVersionKind{Group: "testgroup", Version: "v1", Kind: "TestObject1"}, Plural: "testobjects1", @@ -135,20 +136,20 @@ func TestGVKMapsResolveGVK(t *testing.T) { { desc: "fixed version and kind", gvkmaps: &CRDiscoverer{ - Map: map[string]map[string][]kindPlural{ + Map: map[string]map[string][]discovery.KindPlural{ "testgroup": { "v1": { - kindPlural{ + discovery.KindPlural{ Kind: "TestObject1", Plural: "testobjects1", }, - kindPlural{ + discovery.KindPlural{ Kind: "TestObject2", Plural: "testobjects2", }, }, "v1alpha1": { - kindPlural{ + discovery.KindPlural{ Kind: "TestObject1", Plural: "testobjects1", }, @@ -157,7 +158,7 @@ func TestGVKMapsResolveGVK(t *testing.T) { }, }, gvk: schema.GroupVersionKind{Group: "testgroup", Version: "v1", Kind: "TestObject1"}, - want: []groupVersionKindPlural{ + want: []discovery.GroupVersionKindPlural{ { GroupVersionKind: schema.GroupVersionKind{Group: "testgroup", Version: "v1", Kind: "TestObject1"}, Plural: "testobjects1", diff --git a/pkg/app/server.go b/pkg/app/server.go index 09ce7cad82..3588648b07 100644 --- a/pkg/app/server.go +++ b/pkg/app/server.go @@ -26,10 +26,13 @@ import ( "net/http/pprof" "os" "path/filepath" + "runtime" "strconv" "strings" "time" + "k8s.io/client-go/rest" + "github.com/oklog/run" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/collectors" @@ -38,11 +41,11 @@ import ( "github.com/prometheus/common/version" "github.com/prometheus/exporter-toolkit/web" "gopkg.in/yaml.v3" + clientset "k8s.io/client-go/kubernetes" _ "k8s.io/client-go/plugin/pkg/client/auth" // Initialize common client auth plugins. "k8s.io/client-go/tools/clientcmd" "k8s.io/klog/v2" - "k8s.io/kube-state-metrics/v2/internal/discovery" "k8s.io/kube-state-metrics/v2/internal/store" "k8s.io/kube-state-metrics/v2/pkg/allowdenylist" "k8s.io/kube-state-metrics/v2/pkg/customresource" @@ -51,7 +54,7 @@ import ( "k8s.io/kube-state-metrics/v2/pkg/metricshandler" "k8s.io/kube-state-metrics/v2/pkg/optin" "k8s.io/kube-state-metrics/v2/pkg/options" - "k8s.io/kube-state-metrics/v2/pkg/util" + "k8s.io/kube-state-metrics/v2/pkg/util/proc" ) @@ -243,7 +246,8 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options) error { proc.StartReaper() storeBuilder.WithUtilOptions(opts) - kubeClient, err := util.CreateKubeClient(opts.Apiserver, opts.Kubeconfig) + kubeClient, err := createKubeClient(opts.Apiserver, opts.Kubeconfig) + if err != nil { return fmt.Errorf("failed to create client: %v", err) } @@ -282,7 +286,7 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options) error { // A nil CRS config implies that we need to hold off on all CRS operations. if config != nil { - discovererInstance := &discovery.CRDiscoverer{ + discovererInstance := &CRDiscoverer{ CRDsAddEventsCounter: crdsAddEventsCounter, CRDsDeleteEventsCounter: crdsDeleteEventsCounter, CRDsCacheCountGauge: crdsCacheCountGauge, @@ -453,3 +457,38 @@ func resolveCustomResourceConfig(opts *options.Options) (customresourcestate.Con } return nil, nil } + +func createKubeClient(apiserver string, kubeconfig string) (clientset.Interface, error) { + var config *rest.Config + + var err error + + if config == nil { + config, err = clientcmd.BuildConfigFromFlags(apiserver, kubeconfig) + if err != nil { + return nil, err + } + } + + config.UserAgent = fmt.Sprintf("%s/%s (%s/%s) kubernetes/%s", "kube-state-metrics", version.Version, runtime.GOOS, runtime.GOARCH, version.Revision) + config.AcceptContentTypes = "application/vnd.kubernetes.protobuf,application/json" + config.ContentType = "application/vnd.kubernetes.protobuf" + + kubeClient, err := clientset.NewForConfig(config) + if err != nil { + return nil, err + } + + // Informers don't seem to do a good job logging error messages when it + // can't reach the server, making debugging hard. This makes it easier to + // figure out if apiserver is configured incorrectly. + klog.InfoS("Tested communication with server") + v, err := kubeClient.Discovery().ServerVersion() + if err != nil { + return nil, fmt.Errorf("error while trying to communicate with apiserver: %w", err) + } + klog.InfoS("Run with Kubernetes cluster version", "major", v.Major, "minor", v.Minor, "gitVersion", v.GitVersion, "gitTreeState", v.GitTreeState, "gitCommit", v.GitCommit, "platform", v.Platform) + klog.InfoS("Communication with server successful") + + return kubeClient, nil +} diff --git a/pkg/util/utils.go b/pkg/customresource/utils.go similarity index 67% rename from pkg/util/utils.go rename to pkg/customresource/utils.go index 63e5aba650..2a77f7a18e 100644 --- a/pkg/util/utils.go +++ b/pkg/customresource/utils.go @@ -14,14 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -package util +package customresource import ( - "fmt" - "runtime" "strings" - "github.com/prometheus/common/version" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/discovery" @@ -29,10 +26,7 @@ import ( clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" - "k8s.io/klog/v2" testUnstructuredMock "k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1" - - "k8s.io/kube-state-metrics/v2/pkg/customresource" ) var config *rest.Config @@ -40,47 +34,8 @@ var currentKubeClient clientset.Interface var currentDiscoveryClient *discovery.DiscoveryClient var currentDynamicClient *dynamic.DynamicClient -// CreateKubeClient creates a Kubernetes clientset and a custom resource clientset. -func CreateKubeClient(apiserver string, kubeconfig string) (clientset.Interface, error) { - if currentKubeClient != nil { - return currentKubeClient, nil - } - - var err error - - if config == nil { - config, err = clientcmd.BuildConfigFromFlags(apiserver, kubeconfig) - if err != nil { - return nil, err - } - } - - config.UserAgent = fmt.Sprintf("%s/%s (%s/%s) kubernetes/%s", "kube-state-metrics", version.Version, runtime.GOOS, runtime.GOARCH, version.Revision) - config.AcceptContentTypes = "application/vnd.kubernetes.protobuf,application/json" - config.ContentType = "application/vnd.kubernetes.protobuf" - - kubeClient, err := clientset.NewForConfig(config) - if err != nil { - return nil, err - } - - // Informers don't seem to do a good job logging error messages when it - // can't reach the server, making debugging hard. This makes it easier to - // figure out if apiserver is configured incorrectly. - klog.InfoS("Tested communication with server") - v, err := kubeClient.Discovery().ServerVersion() - if err != nil { - return nil, fmt.Errorf("error while trying to communicate with apiserver: %w", err) - } - klog.InfoS("Run with Kubernetes cluster version", "major", v.Major, "minor", v.Minor, "gitVersion", v.GitVersion, "gitTreeState", v.GitTreeState, "gitCommit", v.GitCommit, "platform", v.Platform) - klog.InfoS("Communication with server successful") - - currentKubeClient = kubeClient - return kubeClient, nil -} - // CreateCustomResourceClients creates a custom resource clientset. -func CreateCustomResourceClients(apiserver string, kubeconfig string, factories ...customresource.RegistryFactory) (map[string]interface{}, error) { +func CreateCustomResourceClients(apiserver string, kubeconfig string, factories ...RegistryFactory) (map[string]interface{}, error) { // Not relying on memoized clients here because the factories are subject to change. var err error if config == nil { diff --git a/pkg/customresourcestate/config.go b/pkg/customresourcestate/config.go index 385858b8ba..174694c865 100644 --- a/pkg/customresourcestate/config.go +++ b/pkg/customresourcestate/config.go @@ -26,7 +26,6 @@ import ( "k8s.io/kube-state-metrics/v2/internal/discovery" "k8s.io/kube-state-metrics/v2/pkg/customresource" - "k8s.io/kube-state-metrics/v2/pkg/util" ) // customResourceState is used to prefix the auto-generated GVK labels as well as an appendix for the metric itself @@ -166,8 +165,12 @@ type ConfigDecoder interface { Decode(v interface{}) (err error) } +type GVKToGVKP interface { + ResolveGVKToGVKPs(gvk schema.GroupVersionKind) (resolvedGVKPs []discovery.GroupVersionKindPlural, err error) +} + // FromConfig decodes a configuration source into a slice of `customresource.RegistryFactory` that are ready to use. -func FromConfig(decoder ConfigDecoder, discovererInstance *discovery.CRDiscoverer) (func() ([]customresource.RegistryFactory, error), error) { +func FromConfig(decoder ConfigDecoder, discovererInstance GVKToGVKP) (func() ([]customresource.RegistryFactory, error), error) { var customResourceConfig Metrics factoriesIndex := map[string]bool{} if err := decoder.Decode(&customResourceConfig); err != nil { @@ -195,7 +198,7 @@ func FromConfig(decoder ConfigDecoder, discovererInstance *discovery.CRDiscovere if err != nil { return nil, fmt.Errorf("failed to create metrics factory for %s: %w", resource.GroupVersionKind, err) } - gvrString := util.GVRFromType(factory.Name(), factory.ExpectedType()).String() + gvrString := customresource.GVRFromType(factory.Name(), factory.ExpectedType()).String() if _, ok := factoriesIndex[gvrString]; ok { klog.InfoS("reloaded factory", "GVR", gvrString) } diff --git a/tests/e2e/discovery_test.go b/tests/e2e/discovery_test.go index 63f0878ff6..144e2c05d7 100644 --- a/tests/e2e/discovery_test.go +++ b/tests/e2e/discovery_test.go @@ -29,7 +29,7 @@ import ( "k8s.io/klog/v2" "k8s.io/kube-state-metrics/v2/internal" - "k8s.io/kube-state-metrics/v2/internal/discovery" + "k8s.io/kube-state-metrics/v2/pkg/customresourcestate" "k8s.io/kube-state-metrics/v2/pkg/options" ) @@ -140,7 +140,7 @@ func TestVariableVKsDiscoveryAndResolution(t *testing.T) { // Wait for the metric to be available. ch := make(chan bool, 1) klog.InfoS("waiting for metrics to become available") - err = wait.PollUntilContextTimeout(context.TODO(), discovery.Interval, PopulateTimeout, true, func(ctx context.Context) (bool, error) { + err = wait.PollUntilContextTimeout(context.TODO(), customresourcestate.Interval, PopulateTimeout, true, func(ctx context.Context) (bool, error) { out, err := exec.Command("curl", "localhost:8080/metrics").Output() if err != nil { return false, err