// Package kube provides shared Kubernetes client bootstrapping for the tools in // benvin-utils: a single loader that works both in-cluster and from a local // kubeconfig, plus a helper that returns the core and metrics clients together. package kube import ( "fmt" "os" "path/filepath" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" metricsv "k8s.io/metrics/pkg/client/clientset/versioned" ) // LoadConfig resolves a *rest.Config, preferring in-cluster credentials, then // the explicit path, then $KUBECONFIG, then ~/.kube/config. func LoadConfig(explicit string) (*rest.Config, error) { if cfg, err := rest.InClusterConfig(); err == nil { return cfg, nil } path := explicit if path == "" { path = os.Getenv("KUBECONFIG") } if path == "" { if home, err := os.UserHomeDir(); err == nil { path = filepath.Join(home, ".kube", "config") } } cfg, err := clientcmd.BuildConfigFromFlags("", path) if err != nil { return nil, fmt.Errorf("load kubeconfig %q: %w", path, err) } return cfg, nil } // Clients returns the core and metrics clientsets for the resolved config. func Clients(explicit string) (kubernetes.Interface, metricsv.Interface, error) { cfg, err := LoadConfig(explicit) if err != nil { return nil, nil, err } core, err := kubernetes.NewForConfig(cfg) if err != nil { return nil, nil, fmt.Errorf("core client: %w", err) } mc, err := metricsv.NewForConfig(cfg) if err != nil { return nil, nil, fmt.Errorf("metrics client: %w", err) } return core, mc, nil }