diff --git a/go.mod b/go.mod index 80c88e3b097a8..2e57f44d6e1ca 100644 --- a/go.mod +++ b/go.mod @@ -1074,3 +1074,6 @@ replace github.com/ProtonMail/go-crypto => github.com/ProtonMail/go-crypto v1.0. exclude go.opentelemetry.io/proto/otlp v1.1.0 replace github.com/google/gopacket v1.1.19 => github.com/DataDog/gopacket v0.0.0-20240626205202-4ac4cee31f14 + +// Remove once https://github.com/kubernetes/kube-state-metrics/pull/2553 is merged +replace k8s.io/kube-state-metrics/v2 v2.13.1-0.20241025121156-110f03d7331f => github.com/L3n41c/kube-state-metrics/v2 v2.13.1-0.20241108192007-8859a4289d92 diff --git a/go.sum b/go.sum index 2957241eed4ae..5a6d65c835aa9 100644 --- a/go.sum +++ b/go.sum @@ -197,6 +197,8 @@ github.com/Intevation/gval v1.3.0 h1:+Ze5sft5MmGbZrHj06NVUbcxCb67l9RaPTLMNr37mjw github.com/Intevation/gval v1.3.0/go.mod h1:xmGyGpP5be12EL0P12h+dqiYG8qn2j3PJxIgkoOHO5o= github.com/Intevation/jsonpath v0.2.1 h1:rINNQJ0Pts5XTFEG+zamtdL7l9uuE1z0FBA+r55Sw+A= github.com/Intevation/jsonpath v0.2.1/go.mod h1:WnZ8weMmwAx/fAO3SutjYFU+v7DFreNYnibV7CiaYIw= +github.com/L3n41c/kube-state-metrics/v2 v2.13.1-0.20241108192007-8859a4289d92 h1:l8Sk6DeEeAyCjjleYu6Kr/530dH7V2WDNaeJLB9CADE= +github.com/L3n41c/kube-state-metrics/v2 v2.13.1-0.20241108192007-8859a4289d92/go.mod h1:sGt/NFkZkA4hqb4cVd/xG2G17dzZ72TQXqSpHn8rF/U= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= @@ -2736,8 +2738,6 @@ k8s.io/kube-aggregator v0.31.2/go.mod h1:41/VIXH+/Qcg9ERNAY6bRF/WQR6xL1wFgYagdHa k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f h1:0LQagt0gDpKqvIkAMPaRGcXawNMouPECM1+F9BVxEaM= k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f/go.mod h1:S9tOR0FxgyusSNR+MboCuiDpVWkAifZvaYI1Q2ubgro= -k8s.io/kube-state-metrics/v2 v2.13.1-0.20241025121156-110f03d7331f h1:qgFTdM3vZhsVXp3psuvXnkD4JVMcNywBqAxIAER5gDE= -k8s.io/kube-state-metrics/v2 v2.13.1-0.20241025121156-110f03d7331f/go.mod h1:sGt/NFkZkA4hqb4cVd/xG2G17dzZ72TQXqSpHn8rF/U= k8s.io/kubectl v0.31.2 h1:gTxbvRkMBwvTSAlobiTVqsH6S8Aa1aGyBcu5xYLsn8M= k8s.io/kubectl v0.31.2/go.mod h1:EyASYVU6PY+032RrTh5ahtSOMgoDRIux9V1JLKtG5xM= k8s.io/kubelet v0.31.2 h1:6Hytyw4LqWqhgzoi7sPfpDGClu2UfxmPmaiXPC4FRgI= diff --git a/pkg/collector/corechecks/cluster/ksm/customresources/apiservice.go b/pkg/collector/corechecks/cluster/ksm/customresources/apiservice.go index 6098c746be052..c2076973aef3f 100644 --- a/pkg/collector/corechecks/cluster/ksm/customresources/apiservice.go +++ b/pkg/collector/corechecks/cluster/ksm/customresources/apiservice.go @@ -10,17 +10,15 @@ package customresources import ( "context" - "github.com/DataDog/datadog-agent/pkg/util/log" + "github.com/DataDog/datadog-agent/pkg/util/kubernetes/apiserver" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/dynamic" "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" basemetrics "k8s.io/component-base/metrics" v1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1" + apiregistrationclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1" "k8s.io/kube-state-metrics/v2/pkg/customresource" "k8s.io/kube-state-metrics/v2/pkg/metric" generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" @@ -35,22 +33,18 @@ var ( ) // NewAPIServiceFactory returns a new APIService metric family generator factory. -func NewAPIServiceFactory(client *dynamic.DynamicClient) customresource.RegistryFactory { +func NewAPIServiceFactory(client *apiserver.APIClient) customresource.RegistryFactory { return &apiserviceFactory{ - client: client, + client: client.APISInformerClient, } } type apiserviceFactory struct { - client *dynamic.DynamicClient + client apiregistrationclient.ApiregistrationV1Interface } func (f *apiserviceFactory) CreateClient(_ *rest.Config) (interface{}, error) { - return f.client.Resource(schema.GroupVersionResource{ - Group: v1.GroupName, - Version: v1.SchemeGroupVersion.Version, - Resource: "apiservices", - }), nil + return f.client, nil } func (f *apiserviceFactory) Name() string { @@ -126,33 +120,32 @@ func (f *apiserviceFactory) MetricFamilyGenerators() []generator.FamilyGenerator } func (f *apiserviceFactory) ExpectedType() interface{} { - u := unstructured.Unstructured{} - u.SetGroupVersionKind(v1.SchemeGroupVersion.WithKind("APIService")) - return &u + return &v1.APIService{ + TypeMeta: metav1.TypeMeta{ + Kind: "APIService", + APIVersion: v1.SchemeGroupVersion.String(), + }, + } } func (f *apiserviceFactory) ListWatch(customresourceClient interface{}, _ string, fieldSelector string) cache.ListerWatcher { - client := customresourceClient.(dynamic.ResourceInterface) + client := customresourceClient.(apiregistrationclient.ApiregistrationV1Interface) ctx := context.Background() return &cache.ListWatch{ ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { opts.FieldSelector = fieldSelector - return client.List(ctx, opts) + return client.APIServices().List(ctx, opts) }, WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { opts.FieldSelector = fieldSelector - return client.Watch(ctx, opts) + return client.APIServices().Watch(ctx, opts) }, } } func wrapAPIServiceFunc(f func(*v1.APIService) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { - apiservice := &v1.APIService{} - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.(*unstructured.Unstructured).Object, apiservice); err != nil { - log.Warnf("cannot decode object %q into v1.APIService, err=%s, skipping", obj.(*unstructured.Unstructured).Object["apiVersion"], err) - return nil - } + apiservice := obj.(*v1.APIService) metricFamily := f(apiservice) diff --git a/pkg/collector/corechecks/cluster/ksm/customresources/crd.go b/pkg/collector/corechecks/cluster/ksm/customresources/crd.go index d7c4a2fdeee98..3c85679e2abb2 100644 --- a/pkg/collector/corechecks/cluster/ksm/customresources/crd.go +++ b/pkg/collector/corechecks/cluster/ksm/customresources/crd.go @@ -10,14 +10,11 @@ package customresources import ( "context" - "github.com/DataDog/datadog-agent/pkg/util/log" + "github.com/DataDog/datadog-agent/pkg/util/kubernetes/apiserver" v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/dynamic" "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" basemetrics "k8s.io/component-base/metrics" @@ -25,6 +22,8 @@ import ( "k8s.io/kube-state-metrics/v2/pkg/customresource" "k8s.io/kube-state-metrics/v2/pkg/metric" generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" + + "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" ) var ( @@ -37,14 +36,14 @@ var ( // NewCustomResourceDefinitionFactory returns a new CustomResourceDefinition // metric family generator factory. -func NewCustomResourceDefinitionFactory(client *dynamic.DynamicClient) customresource.RegistryFactory { +func NewCustomResourceDefinitionFactory(client *apiserver.APIClient) customresource.RegistryFactory { return &crdFactory{ - client: client, + client: client.CRDInformerClient, } } type crdFactory struct { - client *dynamic.DynamicClient + client clientset.Interface } func (f *crdFactory) MetricFamilyGenerators() []generator.FamilyGenerator { @@ -120,41 +119,36 @@ func (f *crdFactory) Name() string { } func (f *crdFactory) CreateClient(_ *rest.Config) (interface{}, error) { - return f.client.Resource(schema.GroupVersionResource{ - Group: v1.GroupName, - Version: v1.SchemeGroupVersion.Version, - Resource: "customresourcedefinitions", - }), nil + return f.client, nil } func (f *crdFactory) ExpectedType() interface{} { - u := unstructured.Unstructured{} - u.SetGroupVersionKind(v1.SchemeGroupVersion.WithKind("CustomResourceDefinition")) - return &u + return &v1.CustomResourceDefinition{ + TypeMeta: metav1.TypeMeta{ + Kind: "CustomResourceDefinition", + APIVersion: v1.SchemeGroupVersion.String(), + }, + } } func (f *crdFactory) ListWatch(customResourceClient interface{}, _ string, fieldSelector string) cache.ListerWatcher { - client := customResourceClient.(dynamic.ResourceInterface) + client := customResourceClient.(clientset.Interface) ctx := context.Background() return &cache.ListWatch{ ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { opts.FieldSelector = fieldSelector - return client.List(ctx, opts) + return client.ApiextensionsV1().CustomResourceDefinitions().List(ctx, opts) }, WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { opts.FieldSelector = fieldSelector - return client.Watch(ctx, opts) + return client.ApiextensionsV1().CustomResourceDefinitions().Watch(ctx, opts) }, } } func wrapCustomResourceDefinition(f func(*v1.CustomResourceDefinition) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { - crd := &v1.CustomResourceDefinition{} - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.(*unstructured.Unstructured).Object, crd); err != nil { - log.Warnf("cannot decode object %q into v1.CustomResourceDefinition, err=%s, skipping", obj.(*unstructured.Unstructured).Object["apiVersion"], err) - return nil - } + crd := obj.(*v1.CustomResourceDefinition) metricFamily := f(crd) diff --git a/pkg/collector/corechecks/cluster/ksm/customresources/cronjob.go b/pkg/collector/corechecks/cluster/ksm/customresources/cronjob.go index 814be577ca706..84d87878bfd87 100644 --- a/pkg/collector/corechecks/cluster/ksm/customresources/cronjob.go +++ b/pkg/collector/corechecks/cluster/ksm/customresources/cronjob.go @@ -17,16 +17,14 @@ import ( "context" "time" - "github.com/DataDog/datadog-agent/pkg/util/log" + "github.com/DataDog/datadog-agent/pkg/util/kubernetes/apiserver" "github.com/pkg/errors" "github.com/robfig/cron/v3" batchv1beta1 "k8s.io/api/batch/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/dynamic" + "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" basemetrics "k8s.io/component-base/metrics" @@ -44,14 +42,14 @@ var ( ) // NewCronJobV1Beta1Factory returns a new CronJob metric family generator factory. -func NewCronJobV1Beta1Factory(client *dynamic.DynamicClient) customresource.RegistryFactory { +func NewCronJobV1Beta1Factory(client *apiserver.APIClient) customresource.RegistryFactory { return &cronjobv1beta1Factory{ - client: client, + client: client.Cl, } } type cronjobv1beta1Factory struct { - client *dynamic.DynamicClient + client kubernetes.Interface } func (f *cronjobv1beta1Factory) Name() string { @@ -59,11 +57,7 @@ func (f *cronjobv1beta1Factory) Name() string { } func (f *cronjobv1beta1Factory) CreateClient(_ *rest.Config) (interface{}, error) { - return f.client.Resource(schema.GroupVersionResource{ - Group: batchv1beta1.GroupName, - Version: batchv1beta1.SchemeGroupVersion.Version, - Resource: "cronjobs", - }), nil + return f.client, nil } func (f *cronjobv1beta1Factory) MetricFamilyGenerators() []generator.FamilyGenerator { @@ -317,11 +311,7 @@ func (f *cronjobv1beta1Factory) MetricFamilyGenerators() []generator.FamilyGener func wrapCronJobFunc(f func(*batchv1beta1.CronJob) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { - cronJob := &batchv1beta1.CronJob{} - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.(*unstructured.Unstructured).Object, cronJob); err != nil { - log.Warnf("cannot decode object %q into batchv1beta1.CronJob, err=%s, skipping", obj.(*unstructured.Unstructured).Object["apiVersion"], err) - return nil - } + cronJob := obj.(*batchv1beta1.CronJob) metricFamily := f(cronJob) @@ -334,22 +324,25 @@ func wrapCronJobFunc(f func(*batchv1beta1.CronJob) *metric.Family) func(interfac } func (f *cronjobv1beta1Factory) ExpectedType() interface{} { - u := unstructured.Unstructured{} - u.SetGroupVersionKind(batchv1beta1.SchemeGroupVersion.WithKind("CronJob")) - return &u + return &batchv1beta1.CronJob{ + TypeMeta: metav1.TypeMeta{ + Kind: "CronJob", + APIVersion: batchv1beta1.SchemeGroupVersion.String(), + }, + } } func (f *cronjobv1beta1Factory) ListWatch(customResourceClient interface{}, ns string, fieldSelector string) cache.ListerWatcher { - client := customResourceClient.(dynamic.NamespaceableResourceInterface).Namespace(ns) + client := customResourceClient.(kubernetes.Interface) ctx := context.Background() return &cache.ListWatch{ ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { opts.FieldSelector = fieldSelector - return client.List(ctx, opts) + return client.BatchV1beta1().CronJobs(ns).List(ctx, opts) }, WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { opts.FieldSelector = fieldSelector - return client.Watch(ctx, opts) + return client.BatchV1beta1().CronJobs(ns).Watch(ctx, opts) }, } } diff --git a/pkg/collector/corechecks/cluster/ksm/customresources/hpa.go b/pkg/collector/corechecks/cluster/ksm/customresources/hpa.go index 4d964f9b81e52..a20cfdf8ca05e 100644 --- a/pkg/collector/corechecks/cluster/ksm/customresources/hpa.go +++ b/pkg/collector/corechecks/cluster/ksm/customresources/hpa.go @@ -17,14 +17,12 @@ package customresources import ( "context" - "github.com/DataDog/datadog-agent/pkg/util/log" + "github.com/DataDog/datadog-agent/pkg/util/kubernetes/apiserver" autoscaling "k8s.io/api/autoscaling/v2beta2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/dynamic" + "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" basemetrics "k8s.io/component-base/metrics" @@ -60,14 +58,14 @@ var ( // NewHorizontalPodAutoscalerV2Beta2Factory returns a new // HorizontalPodAutoscaler metric family generator factory. -func NewHorizontalPodAutoscalerV2Beta2Factory(client *dynamic.DynamicClient) customresource.RegistryFactory { +func NewHorizontalPodAutoscalerV2Beta2Factory(client *apiserver.APIClient) customresource.RegistryFactory { return &hpav2Factory{ - client: client, + client: client.Cl, } } type hpav2Factory struct { - client *dynamic.DynamicClient + client kubernetes.Interface } func (f *hpav2Factory) Name() string { @@ -75,11 +73,7 @@ func (f *hpav2Factory) Name() string { } func (f *hpav2Factory) CreateClient(_ *rest.Config) (interface{}, error) { - return f.client.Resource(schema.GroupVersionResource{ - Group: autoscaling.GroupName, - Version: autoscaling.SchemeGroupVersion.Version, - Resource: "horizontalpodautoscalers", - }), nil + return f.client, nil } func (f *hpav2Factory) MetricFamilyGenerators() []generator.FamilyGenerator { @@ -374,33 +368,32 @@ func (f *hpav2Factory) MetricFamilyGenerators() []generator.FamilyGenerator { } func (f *hpav2Factory) ExpectedType() interface{} { - u := unstructured.Unstructured{} - u.SetGroupVersionKind(autoscaling.SchemeGroupVersion.WithKind("HorizontalPodAutoscaler")) - return &u + return &autoscaling.HorizontalPodAutoscaler{ + TypeMeta: metav1.TypeMeta{ + Kind: "HorizontalPodAutoscaler", + APIVersion: autoscaling.SchemeGroupVersion.String(), + }, + } } func (f *hpav2Factory) ListWatch(customResourceClient interface{}, ns string, fieldSelector string) cache.ListerWatcher { - client := customResourceClient.(dynamic.NamespaceableResourceInterface).Namespace(ns) + client := customResourceClient.(kubernetes.Interface) ctx := context.Background() return &cache.ListWatch{ ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { opts.FieldSelector = fieldSelector - return client.List(ctx, opts) + return client.AutoscalingV2beta2().HorizontalPodAutoscalers(ns).List(ctx, opts) }, WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { opts.FieldSelector = fieldSelector - return client.Watch(ctx, opts) + return client.AutoscalingV2beta2().HorizontalPodAutoscalers(ns).Watch(ctx, opts) }, } } func wrapHPAFunc(f func(*autoscaling.HorizontalPodAutoscaler) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { - hpa := &autoscaling.HorizontalPodAutoscaler{} - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.(*unstructured.Unstructured).Object, hpa); err != nil { - log.Warnf("cannot decode object %q into autoscaling/v2beta2.HorizontalPodAutoscaler, err=%s, skipping", obj.(*unstructured.Unstructured).Object["apiVersion"], err) - return nil - } + hpa := obj.(*autoscaling.HorizontalPodAutoscaler) metricFamily := f(hpa) diff --git a/pkg/collector/corechecks/cluster/ksm/customresources/job.go b/pkg/collector/corechecks/cluster/ksm/customresources/job.go index 47bd8ef195992..7af845b907b08 100644 --- a/pkg/collector/corechecks/cluster/ksm/customresources/job.go +++ b/pkg/collector/corechecks/cluster/ksm/customresources/job.go @@ -13,11 +13,9 @@ import ( batchv1 "k8s.io/api/batch/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/dynamic" + "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" basemetrics "k8s.io/component-base/metrics" @@ -25,20 +23,20 @@ import ( "k8s.io/kube-state-metrics/v2/pkg/metric" generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" - "github.com/DataDog/datadog-agent/pkg/util/log" + "github.com/DataDog/datadog-agent/pkg/util/kubernetes/apiserver" ) var descJobLabelsDefaultLabels = []string{"namespace", "job_name"} // NewExtendedJobFactory returns a new Job metric family generator factory. -func NewExtendedJobFactory(client *dynamic.DynamicClient) customresource.RegistryFactory { +func NewExtendedJobFactory(client *apiserver.APIClient) customresource.RegistryFactory { return &extendedJobFactory{ - client: client, + client: client.Cl, } } type extendedJobFactory struct { - client *dynamic.DynamicClient + client kubernetes.Interface } // Name is the name of the factory @@ -47,11 +45,7 @@ func (f *extendedJobFactory) Name() string { } func (f *extendedJobFactory) CreateClient(_ *rest.Config) (interface{}, error) { - return f.client.Resource(schema.GroupVersionResource{ - Group: batchv1.GroupName, - Version: batchv1.SchemeGroupVersion.Version, - Resource: "jobs", - }), nil + return f.client, nil } // MetricFamilyGenerators returns the extended job metric family generators @@ -89,11 +83,7 @@ func (f *extendedJobFactory) MetricFamilyGenerators() []generator.FamilyGenerato func wrapJobFunc(f func(*batchv1.Job) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { - job := &batchv1.Job{} - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.(*unstructured.Unstructured).Object, job); err != nil { - log.Warnf("cannot decode object %q into batchv1.Job, err=%s, skipping", obj.(*unstructured.Unstructured).Object["apiVersion"], err) - return nil - } + job := obj.(*batchv1.Job) metricFamily := f(job) @@ -107,23 +97,26 @@ func wrapJobFunc(f func(*batchv1.Job) *metric.Family) func(interface{}) *metric. // ExpectedType returns the type expected by the factory func (f *extendedJobFactory) ExpectedType() interface{} { - u := unstructured.Unstructured{} - u.SetGroupVersionKind(batchv1.SchemeGroupVersion.WithKind("Job")) - return &u + return &batchv1.Job{ + TypeMeta: metav1.TypeMeta{ + Kind: "Job", + APIVersion: batchv1.SchemeGroupVersion.String(), + }, + } } // ListWatch returns a ListerWatcher for batchv1.Job func (f *extendedJobFactory) ListWatch(customResourceClient interface{}, ns string, fieldSelector string) cache.ListerWatcher { - client := customResourceClient.(dynamic.NamespaceableResourceInterface).Namespace(ns) + client := customResourceClient.(kubernetes.Interface) ctx := context.Background() return &cache.ListWatch{ ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { opts.FieldSelector = fieldSelector - return client.List(ctx, opts) + return client.BatchV1().Jobs(ns).List(ctx, opts) }, WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { opts.FieldSelector = fieldSelector - return client.Watch(ctx, opts) + return client.BatchV1().Jobs(ns).Watch(ctx, opts) }, } } diff --git a/pkg/collector/corechecks/cluster/ksm/customresources/node.go b/pkg/collector/corechecks/cluster/ksm/customresources/node.go index 69b8682c4f23f..36ed198f92a74 100644 --- a/pkg/collector/corechecks/cluster/ksm/customresources/node.go +++ b/pkg/collector/corechecks/cluster/ksm/customresources/node.go @@ -10,14 +10,11 @@ package customresources import ( "context" - "github.com/DataDog/datadog-agent/pkg/util/log" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/dynamic" + clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" "k8s.io/component-base/metrics" @@ -25,19 +22,21 @@ import ( "k8s.io/kube-state-metrics/v2/pkg/customresource" "k8s.io/kube-state-metrics/v2/pkg/metric" generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" + + "github.com/DataDog/datadog-agent/pkg/util/kubernetes/apiserver" ) var descNodeLabelsDefaultLabels = []string{"node"} // NewExtendedNodeFactory returns a new Node metric family generator factory. -func NewExtendedNodeFactory(client *dynamic.DynamicClient) customresource.RegistryFactory { +func NewExtendedNodeFactory(client *apiserver.APIClient) customresource.RegistryFactory { return &extendedNodeFactory{ - client: client, + client: client.Cl, } } type extendedNodeFactory struct { - client *dynamic.DynamicClient + client clientset.Interface } // Name is the name of the factory @@ -46,11 +45,7 @@ func (f *extendedNodeFactory) Name() string { } func (f *extendedNodeFactory) CreateClient(_ *rest.Config) (interface{}, error) { - return f.client.Resource(schema.GroupVersionResource{ - Group: v1.GroupName, - Version: v1.SchemeGroupVersion.Version, - Resource: "nodes", - }), nil + return f.client, nil } // MetricFamilyGenerators returns the extended node metric family generators @@ -108,11 +103,7 @@ func (f *extendedNodeFactory) customResourceGenerator(resources v1.ResourceList) func wrapNodeFunc(f func(*v1.Node) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { - node := &v1.Node{} - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.(*unstructured.Unstructured).Object, node); err != nil { - log.Warnf("cannot decode object %q into v1.Node, err=%s, skipping", obj.(*unstructured.Unstructured).Object["apiVersion"], err) - return nil - } + node := obj.(*v1.Node) metricFamily := f(node) @@ -126,23 +117,26 @@ func wrapNodeFunc(f func(*v1.Node) *metric.Family) func(interface{}) *metric.Fam // ExpectedType returns the type expected by the factory func (f *extendedNodeFactory) ExpectedType() interface{} { - u := unstructured.Unstructured{} - u.SetGroupVersionKind(v1.SchemeGroupVersion.WithKind("Node")) - return &u + return &v1.Node{ + TypeMeta: metav1.TypeMeta{ + Kind: "Node", + APIVersion: v1.SchemeGroupVersion.String(), + }, + } } // ListWatch returns a ListerWatcher for v1.Node func (f *extendedNodeFactory) ListWatch(customResourceClient interface{}, _ string, fieldSelector string) cache.ListerWatcher { - client := customResourceClient.(dynamic.ResourceInterface) + client := customResourceClient.(clientset.Interface) ctx := context.Background() return &cache.ListWatch{ ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { opts.FieldSelector = fieldSelector - return client.List(ctx, opts) + return client.CoreV1().Nodes().List(ctx, opts) }, WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { opts.FieldSelector = fieldSelector - return client.Watch(ctx, opts) + return client.CoreV1().Nodes().Watch(ctx, opts) }, } } diff --git a/pkg/collector/corechecks/cluster/ksm/customresources/pdb.go b/pkg/collector/corechecks/cluster/ksm/customresources/pdb.go index 77c21f565ab63..51341704ff193 100644 --- a/pkg/collector/corechecks/cluster/ksm/customresources/pdb.go +++ b/pkg/collector/corechecks/cluster/ksm/customresources/pdb.go @@ -16,20 +16,19 @@ package customresources import ( "context" - "github.com/DataDog/datadog-agent/pkg/util/log" policyv1beta1 "k8s.io/api/policy/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/dynamic" + "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" "k8s.io/component-base/metrics" "k8s.io/kube-state-metrics/v2/pkg/customresource" "k8s.io/kube-state-metrics/v2/pkg/metric" generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" + + "github.com/DataDog/datadog-agent/pkg/util/kubernetes/apiserver" ) var ( @@ -41,14 +40,14 @@ var ( ) // NewPodDisruptionBudgetV1Beta1Factory returns a new PodDisruptionBudgets metric family generator factory. -func NewPodDisruptionBudgetV1Beta1Factory(client *dynamic.DynamicClient) customresource.RegistryFactory { +func NewPodDisruptionBudgetV1Beta1Factory(client *apiserver.APIClient) customresource.RegistryFactory { return &pdbv1beta1Factory{ - client: client, + client: client.Cl, } } type pdbv1beta1Factory struct { - client *dynamic.DynamicClient + client kubernetes.Interface } func (f *pdbv1beta1Factory) Name() string { @@ -56,11 +55,7 @@ func (f *pdbv1beta1Factory) Name() string { } func (f *pdbv1beta1Factory) CreateClient(_ *rest.Config) (interface{}, error) { - return f.client.Resource(schema.GroupVersionResource{ - Group: policyv1beta1.GroupName, - Version: policyv1beta1.SchemeGroupVersion.Version, - Resource: "poddisruptionbudgets", - }), nil + return f.client, nil } func (f *pdbv1beta1Factory) MetricFamilyGenerators() []generator.FamilyGenerator { @@ -207,33 +202,32 @@ func (f *pdbv1beta1Factory) MetricFamilyGenerators() []generator.FamilyGenerator } func (f *pdbv1beta1Factory) ExpectedType() interface{} { - u := unstructured.Unstructured{} - u.SetGroupVersionKind(policyv1beta1.SchemeGroupVersion.WithKind("PodDisruptionBudget")) - return &u + return &policyv1beta1.PodDisruptionBudget{ + TypeMeta: metav1.TypeMeta{ + Kind: "PodDisruptionBudget", + APIVersion: policyv1beta1.SchemeGroupVersion.String(), + }, + } } func (f *pdbv1beta1Factory) ListWatch(customResourceClient interface{}, ns string, fieldSelector string) cache.ListerWatcher { - client := customResourceClient.(dynamic.NamespaceableResourceInterface).Namespace(ns) + client := customResourceClient.(kubernetes.Interface) ctx := context.Background() return &cache.ListWatch{ ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { opts.FieldSelector = fieldSelector - return client.List(ctx, opts) + return client.PolicyV1beta1().PodDisruptionBudgets(ns).List(ctx, opts) }, WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { opts.FieldSelector = fieldSelector - return client.Watch(ctx, opts) + return client.PolicyV1beta1().PodDisruptionBudgets(ns).Watch(ctx, opts) }, } } func wrapPodDisruptionBudgetFunc(f func(*policyv1beta1.PodDisruptionBudget) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { - podDisruptionBudget := &policyv1beta1.PodDisruptionBudget{} - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.(*unstructured.Unstructured).Object, podDisruptionBudget); err != nil { - log.Warnf("cannot decode object %q into policyv1beta1.PodDisruptionBudget, err=%s, skipping", obj.(*unstructured.Unstructured).Object["apiVersion"], err) - return nil - } + podDisruptionBudget := obj.(*policyv1beta1.PodDisruptionBudget) metricFamily := f(podDisruptionBudget) diff --git a/pkg/collector/corechecks/cluster/ksm/customresources/pod.go b/pkg/collector/corechecks/cluster/ksm/customresources/pod.go index e6967641ee273..d15b757a88cf7 100644 --- a/pkg/collector/corechecks/cluster/ksm/customresources/pod.go +++ b/pkg/collector/corechecks/cluster/ksm/customresources/pod.go @@ -11,15 +11,14 @@ import ( "context" "github.com/DataDog/datadog-agent/pkg/util/kubernetes" + "github.com/DataDog/datadog-agent/pkg/util/kubernetes/apiserver" "github.com/DataDog/datadog-agent/pkg/util/log" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/dynamic" + clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" basemetrics "k8s.io/component-base/metrics" @@ -37,14 +36,14 @@ const ( var descPodLabelsDefaultLabels = []string{"namespace", "pod", "uid"} // NewExtendedPodFactory returns a new Pod metric family generator factory. -func NewExtendedPodFactory(client *dynamic.DynamicClient) customresource.RegistryFactory { +func NewExtendedPodFactory(client *apiserver.APIClient) customresource.RegistryFactory { return &extendedPodFactory{ - client: client, + client: client.Cl, } } type extendedPodFactory struct { - client *dynamic.DynamicClient + client clientset.Interface } // Name is the name of the factory @@ -53,11 +52,7 @@ func (f *extendedPodFactory) Name() string { } func (f *extendedPodFactory) CreateClient(_ *rest.Config) (interface{}, error) { - return f.client.Resource(schema.GroupVersionResource{ - Group: v1.GroupName, - Version: v1.SchemeGroupVersion.Version, - Resource: "pods", - }), nil + return f.client, nil } // MetricFamilyGenerators returns the extended pod metric family generators @@ -220,16 +215,7 @@ func (f *extendedPodFactory) customResourceGenerator(p *v1.Pod, resourceType str func wrapPodFunc(f func(*v1.Pod) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { - var pod *v1.Pod - if p, ok := obj.(*v1.Pod); ok { - pod = p - } else { - pod = &v1.Pod{} - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.(*unstructured.Unstructured).Object, pod); err != nil { - log.Warnf("cannot decode object %q into v1.Pod, err=%s, skipping", obj.(*unstructured.Unstructured).Object["apiVersion"], err) - return nil - } - } + pod := obj.(*v1.Pod) metricFamily := f(pod) @@ -243,23 +229,26 @@ func wrapPodFunc(f func(*v1.Pod) *metric.Family) func(interface{}) *metric.Famil // ExpectedType returns the type expected by the factory func (f *extendedPodFactory) ExpectedType() interface{} { - u := unstructured.Unstructured{} - u.SetGroupVersionKind(v1.SchemeGroupVersion.WithKind("Pod")) - return &u + return &v1.Pod{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: v1.SchemeGroupVersion.String(), + }, + } } // ListWatch returns a ListerWatcher for v1.Pod func (f *extendedPodFactory) ListWatch(customResourceClient interface{}, ns string, fieldSelector string) cache.ListerWatcher { - client := customResourceClient.(dynamic.NamespaceableResourceInterface).Namespace(ns) + client := customResourceClient.(clientset.Interface) ctx := context.Background() return &cache.ListWatch{ ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { opts.FieldSelector = fieldSelector - return client.List(ctx, opts) + return client.CoreV1().Pods(ns).List(ctx, opts) }, WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { opts.FieldSelector = fieldSelector - return client.Watch(ctx, opts) + return client.CoreV1().Pods(ns).Watch(ctx, opts) }, } } diff --git a/pkg/collector/corechecks/cluster/ksm/customresources/vpa.go b/pkg/collector/corechecks/cluster/ksm/customresources/vpa.go index bf5f32b08e738..b16080b4ef3ca 100644 --- a/pkg/collector/corechecks/cluster/ksm/customresources/vpa.go +++ b/pkg/collector/corechecks/cluster/ksm/customresources/vpa.go @@ -16,15 +16,14 @@ package customresources import ( "context" + "github.com/DataDog/datadog-agent/pkg/util/kubernetes/apiserver" autoscalingv1 "k8s.io/api/autoscaling/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/watch" v1 "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1" - "k8s.io/client-go/dynamic" + "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/client/clientset/versioned" "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" basemetrics "k8s.io/component-base/metrics" @@ -43,14 +42,14 @@ var ( ) // NewVerticalPodAutoscalerFactory returns a new VerticalPodAutoscalers metric family generator factory. -func NewVerticalPodAutoscalerFactory(client *dynamic.DynamicClient) customresource.RegistryFactory { +func NewVerticalPodAutoscalerFactory(client *apiserver.APIClient) customresource.RegistryFactory { return &vpaFactory{ - client: client, + client: &client.VPAInformerClient, } } type vpaFactory struct { - client *dynamic.DynamicClient + client *versioned.Interface } func (f *vpaFactory) Name() string { @@ -58,11 +57,7 @@ func (f *vpaFactory) Name() string { } func (f *vpaFactory) CreateClient(_ *rest.Config) (interface{}, error) { - return f.client.Resource(schema.GroupVersionResource{ - Group: v1.SchemeGroupVersion.Group, - Version: v1.SchemeGroupVersion.Version, - Resource: "verticalpodautoscalers", - }), nil + return f.client, nil } func (f *vpaFactory) MetricFamilyGenerators() []generator.FamilyGenerator { @@ -279,9 +274,12 @@ func (f *vpaFactory) MetricFamilyGenerators() []generator.FamilyGenerator { } func (f *vpaFactory) ExpectedType() interface{} { - u := unstructured.Unstructured{} - u.SetGroupVersionKind(v1.SchemeGroupVersion.WithKind("VerticalPodAutoscaler")) - return &u + return &v1.VerticalPodAutoscaler{ + TypeMeta: metav1.TypeMeta{ + Kind: "VerticalPodAutoscaler", + APIVersion: v1.SchemeGroupVersion.String(), + }, + } } func vpaResourcesToMetrics(containerName string, resources corev1.ResourceList) []*metric.Metric { @@ -334,16 +332,16 @@ func wrapVPAFunc(f func(*v1.VerticalPodAutoscaler) *metric.Family) func(interfac } func (f *vpaFactory) ListWatch(customResourceClient interface{}, ns string, fieldSelector string) cache.ListerWatcher { - client := customResourceClient.(dynamic.NamespaceableResourceInterface).Namespace(ns) + vpaClient := customResourceClient.(versioned.Clientset) ctx := context.Background() return &cache.ListWatch{ ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { opts.FieldSelector = fieldSelector - return client.List(ctx, opts) + return vpaClient.AutoscalingV1beta2().VerticalPodAutoscalers(ns).List(ctx, opts) }, WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { opts.FieldSelector = fieldSelector - return client.Watch(ctx, opts) + return vpaClient.AutoscalingV1beta2().VerticalPodAutoscalers(ns).Watch(ctx, opts) }, } } diff --git a/pkg/collector/corechecks/cluster/ksm/kubernetes_state.go b/pkg/collector/corechecks/cluster/ksm/kubernetes_state.go index 2a9b99f6ff4ad..79e2b46542693 100644 --- a/pkg/collector/corechecks/cluster/ksm/kubernetes_state.go +++ b/pkg/collector/corechecks/cluster/ksm/kubernetes_state.go @@ -40,7 +40,6 @@ import ( "gopkg.in/yaml.v2" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/discovery" - "k8s.io/client-go/dynamic" "k8s.io/client-go/tools/cache" "k8s.io/kube-state-metrics/v2/pkg/allowdenylist" "k8s.io/kube-state-metrics/v2/pkg/customresource" @@ -353,10 +352,7 @@ func (k *KSMCheck) Configure(senderManager sender.SenderManager, integrationConf // configure custom resources required for extended features and // compatibility across deprecated/removed versions of APIs - cr, err := k.discoverCustomResources(collectors, resources) - if err != nil { - return err - } + cr := k.discoverCustomResources(c, collectors, resources) builder.WithGenerateCustomResourceStoresFunc(builder.GenerateCustomResourceStoresFunc) builder.WithCustomResourceStoreFactories(cr.factories...) builder.WithCustomResourceClients(cr.clients) @@ -428,7 +424,7 @@ type customResources struct { clients map[string]interface{} } -func (k *KSMCheck) discoverCustomResources(collectors []string, resources []*v1.APIResourceList) (customResources, error) { +func (k *KSMCheck) discoverCustomResources(c *apiserver.APIClient, collectors []string, resources []*v1.APIResourceList) customResources { // automatically add extended collectors if their standard ones are // enabled for _, c := range collectors { @@ -437,16 +433,6 @@ func (k *KSMCheck) discoverCustomResources(collectors []string, resources []*v1. } } - clientConfig, err := apiserver.GetClientConfig(time.Duration(pkgconfigsetup.Datadog().GetInt64("kubernetes_apiserver_client_timeout")) * time.Second) - if err != nil { - return customResources{}, fmt.Errorf("Failed to get API server client config: %w", err) - } - - c, err := dynamic.NewForConfig(clientConfig) - if err != nil { - return customResources{}, fmt.Errorf("Failed to get dynamic client: %w", err) - } - // extended resource collectors always have a factory registered factories := []customresource.RegistryFactory{ customresources.NewExtendedJobFactory(c), @@ -461,10 +447,7 @@ func (k *KSMCheck) discoverCustomResources(collectors []string, resources []*v1. clients := make(map[string]interface{}, len(factories)) for _, f := range factories { - client, err := f.CreateClient(clientConfig) - if err != nil { - return customResources{}, err - } + client, _ := f.CreateClient(nil) clients[f.Name()] = client } @@ -472,14 +455,14 @@ func (k *KSMCheck) discoverCustomResources(collectors []string, resources []*v1. collectors: collectors, clients: clients, factories: factories, - }, nil + } } -func manageResourcesReplacement(c *dynamic.DynamicClient, factories []customresource.RegistryFactory, resources []*v1.APIResourceList) []customresource.RegistryFactory { +func manageResourcesReplacement(c *apiserver.APIClient, factories []customresource.RegistryFactory, resources []*v1.APIResourceList) []customresource.RegistryFactory { // backwards/forwards compatibility resource factories are only // registered if they're needed, otherwise they'd overwrite the default // ones that ship with ksm - resourceReplacements := map[string]map[string]func(c *dynamic.DynamicClient) customresource.RegistryFactory{ + resourceReplacements := map[string]map[string]func(c *apiserver.APIClient) customresource.RegistryFactory{ // support for older k8s versions where the resources are no // longer supported in KSM "batch/v1": {