Files
grafana/pkg/services/apiserver/client/discovery.go
T
2025-12-02 09:59:46 -05:00

156 lines
4.9 KiB
Go

package client
import (
"context"
"fmt"
"strings"
"time"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/discovery"
"k8s.io/client-go/rest"
)
var (
defaultPollInterval = 500 * time.Millisecond
defaultAvailabilityTimeout = 30 * time.Second
)
type DiscoveryClient interface {
discovery.DiscoveryInterface
GetResourceForKind(gvk schema.GroupVersionKind) (schema.GroupVersionResource, error)
GetKindForResource(gvr schema.GroupVersionResource) (schema.GroupVersionKind, error)
GetPreferredVesion(gr schema.GroupResource) (schema.GroupVersionResource, schema.GroupVersionKind, error)
GetPreferredVersionForKind(gk schema.GroupKind) (schema.GroupVersionResource, schema.GroupVersionKind, error)
WaitForAvailability(ctx context.Context, gv schema.GroupVersion) error
}
type DiscoveryClientImpl struct {
restConfig *rest.Config
discovery.DiscoveryInterface
}
func NewDiscoveryClient(restConfig *rest.Config) (*DiscoveryClientImpl, error) {
discoveryClient, err := discovery.NewDiscoveryClientForConfig(restConfig)
if err != nil {
return nil, err
}
return &DiscoveryClientImpl{
restConfig: restConfig,
DiscoveryInterface: discoveryClient,
}, nil
}
func (d *DiscoveryClientImpl) GetResourceForKind(gvk schema.GroupVersionKind) (schema.GroupVersionResource, error) {
resourceList, err := d.ServerResourcesForGroupVersion(gvk.GroupVersion().String())
if err != nil {
return schema.GroupVersionResource{}, err
}
for _, resource := range resourceList.APIResources {
if resource.Kind == gvk.Kind {
return schema.GroupVersionResource{
Group: gvk.Group,
Version: gvk.Version,
Resource: resource.Name,
}, nil
}
}
return schema.GroupVersionResource{}, fmt.Errorf("resource not found for %s", gvk.String())
}
func (d *DiscoveryClientImpl) GetKindForResource(gvr schema.GroupVersionResource) (schema.GroupVersionKind, error) {
resourceList, err := d.ServerResourcesForGroupVersion(gvr.GroupVersion().String())
if err != nil {
return schema.GroupVersionKind{}, err
}
for _, resource := range resourceList.APIResources {
if resource.Name == gvr.Resource {
return schema.GroupVersionKind{
Group: gvr.Group,
Version: gvr.Version,
Kind: resource.Kind,
}, nil
}
}
return schema.GroupVersionKind{}, fmt.Errorf("kind not found for %s", gvr.String())
}
func (d *DiscoveryClientImpl) GetPreferredVesion(gr schema.GroupResource) (schema.GroupVersionResource, schema.GroupVersionKind, error) {
apiList, err := d.ServerPreferredResources()
if err != nil {
return schema.GroupVersionResource{}, schema.GroupVersionKind{}, fmt.Errorf("getting server's preferred resources: %w", err)
}
for _, apis := range apiList {
if !strings.HasPrefix(apis.GroupVersion, gr.Group) {
continue
}
gv := strings.Split(apis.GroupVersion, "/")
for _, resource := range apis.APIResources {
if resource.Name == gr.Resource {
return schema.GroupVersionResource{
Group: gv[0],
Version: gv[1],
Resource: resource.Name,
}, schema.GroupVersionKind{
Group: gv[0],
Version: gv[1],
Kind: resource.Kind,
}, nil
}
}
}
return schema.GroupVersionResource{}, schema.GroupVersionKind{}, fmt.Errorf("preferred version not found for %s", gr.String())
}
func (d *DiscoveryClientImpl) GetPreferredVersionForKind(gk schema.GroupKind) (schema.GroupVersionResource, schema.GroupVersionKind, error) {
apiList, err := d.ServerPreferredResources()
if err != nil {
return schema.GroupVersionResource{}, schema.GroupVersionKind{}, err
}
for _, apis := range apiList {
// Check if this API group matches our target group
if !strings.HasPrefix(apis.GroupVersion, gk.Group) {
continue
}
// Parse the group/version
var group, version string
if strings.Contains(apis.GroupVersion, "/") {
parts := strings.Split(apis.GroupVersion, "/")
group = parts[0]
version = parts[1]
} else {
// Core API group (e.g., "v1")
group = ""
version = apis.GroupVersion
}
// Look for our target kind in this API group version
for _, resource := range apis.APIResources {
if resource.Kind == gk.Kind {
return schema.GroupVersionResource{
Group: group,
Version: version,
Resource: resource.Name,
}, schema.GroupVersionKind{
Group: group,
Version: version,
Kind: resource.Kind,
}, nil
}
}
}
return schema.GroupVersionResource{}, schema.GroupVersionKind{}, fmt.Errorf("preferred version not found for kind %s in group %s", gk.Kind, gk.Group)
}
func (d *DiscoveryClientImpl) WaitForAvailability(ctx context.Context, gv schema.GroupVersion) error {
return wait.PollUntilContextTimeout(ctx, defaultPollInterval, defaultAvailabilityTimeout, true, func(ctx context.Context) (bool, error) {
_, err := d.ServerResourcesForGroupVersion(gv.String())
if err != nil {
return false, nil
}
return true, nil
})
}