190 lines
4.5 KiB
Go
190 lines
4.5 KiB
Go
package k8s
|
|
|
|
import (
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
"k8s.io/client-go/dynamic"
|
|
"k8s.io/client-go/kubernetes"
|
|
restclient "k8s.io/client-go/rest"
|
|
clientcmd "k8s.io/client-go/tools/clientcmd"
|
|
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
|
"k8s.io/kubernetes/pkg/kubectl/metricsutil"
|
|
metricsapi "k8s.io/metrics/pkg/apis/metrics"
|
|
versioned "k8s.io/metrics/pkg/client/clientset/versioned"
|
|
)
|
|
|
|
// NA Not available
|
|
const NA = "n/a"
|
|
|
|
var (
|
|
conn = &apiServer{}
|
|
supportedMetricsAPIVersions = []string{"v1beta1"}
|
|
)
|
|
|
|
type (
|
|
// APIGroup represents a K8s resource descriptor.
|
|
APIGroup struct {
|
|
Resource string
|
|
Group, Kind, Version string
|
|
Plural, Singular string
|
|
Aliases []string
|
|
}
|
|
|
|
// Collection of empty interfaces.
|
|
Collection []interface{}
|
|
|
|
// Res K8s api server calls.
|
|
Res interface {
|
|
Get(ns string, name string) (interface{}, error)
|
|
List(ns string) (Collection, error)
|
|
Delete(ns string, name string) error
|
|
}
|
|
|
|
// Connection represents a k8s api server connection.
|
|
connection interface {
|
|
configAccess() clientcmd.ConfigAccess
|
|
restConfigOrDie() *restclient.Config
|
|
apiConfigOrDie() clientcmdapi.Config
|
|
dialOrDie() kubernetes.Interface
|
|
dynDialOrDie() dynamic.Interface
|
|
nsDialOrDie() dynamic.NamespaceableResourceInterface
|
|
mxsDial() (*versioned.Clientset, error)
|
|
heapsterDial() (*metricsutil.HeapsterMetricsClient, error)
|
|
hasMetricsServer() bool
|
|
}
|
|
|
|
apiServer struct {
|
|
config *Config
|
|
client kubernetes.Interface
|
|
dClient dynamic.Interface
|
|
nsClient dynamic.NamespaceableResourceInterface
|
|
heapsterClient *metricsutil.HeapsterMetricsClient
|
|
mxsClient *versioned.Clientset
|
|
useMetricServer bool
|
|
}
|
|
)
|
|
|
|
// InitConnectionOrDie initialize connection from command line args.
|
|
// Checks for connectivity with the api server.
|
|
func InitConnectionOrDie(config *Config) {
|
|
conn = &apiServer{config: config}
|
|
conn.useMetricServer = conn.supportsMxServer()
|
|
}
|
|
|
|
func (a *apiServer) hasMetricsServer() bool {
|
|
return a.useMetricServer
|
|
}
|
|
|
|
// DialOrDie returns a handle to api server or die.
|
|
func (a *apiServer) dialOrDie() kubernetes.Interface {
|
|
if a.client != nil {
|
|
return a.client
|
|
}
|
|
|
|
var err error
|
|
if a.client, err = kubernetes.NewForConfig(a.restConfigOrDie()); err != nil {
|
|
panic(err)
|
|
}
|
|
return a.client
|
|
}
|
|
|
|
// DynDial returns a handle to the api server.
|
|
func (a *apiServer) dynDialOrDie() dynamic.Interface {
|
|
if a.dClient != nil {
|
|
return a.dClient
|
|
}
|
|
|
|
var err error
|
|
if a.dClient, err = dynamic.NewForConfig(a.restConfigOrDie()); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return a.dClient
|
|
}
|
|
|
|
func (a *apiServer) nsDialOrDie() dynamic.NamespaceableResourceInterface {
|
|
if a.nsClient != nil {
|
|
return a.nsClient
|
|
}
|
|
|
|
a.nsClient = a.dynDialOrDie().Resource(schema.GroupVersionResource{
|
|
Group: "apiextensions.k8s.io",
|
|
Version: "v1beta1",
|
|
Resource: "customresourcedefinitions",
|
|
})
|
|
return a.nsClient
|
|
}
|
|
|
|
func (a *apiServer) heapsterDial() (*metricsutil.HeapsterMetricsClient, error) {
|
|
if a.heapsterClient != nil {
|
|
return a.heapsterClient, nil
|
|
}
|
|
|
|
a.heapsterClient = metricsutil.NewHeapsterMetricsClient(
|
|
a.dialOrDie().CoreV1(),
|
|
metricsutil.DefaultHeapsterNamespace,
|
|
metricsutil.DefaultHeapsterScheme,
|
|
metricsutil.DefaultHeapsterService,
|
|
metricsutil.DefaultHeapsterPort,
|
|
)
|
|
return a.heapsterClient, nil
|
|
}
|
|
|
|
func (a *apiServer) mxsDial() (*versioned.Clientset, error) {
|
|
if a.mxsClient != nil {
|
|
return a.mxsClient, nil
|
|
}
|
|
|
|
var err error
|
|
a.mxsClient, err = versioned.NewForConfig(a.restConfigOrDie())
|
|
return a.mxsClient, err
|
|
}
|
|
|
|
func (a *apiServer) restConfigOrDie() *restclient.Config {
|
|
cfg, err := a.config.RESTConfig()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return cfg
|
|
}
|
|
|
|
func (a *apiServer) switchContextOrDie(ctx string) {
|
|
currentCtx, err := a.config.CurrentContextName()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
if currentCtx != ctx {
|
|
a.reset()
|
|
if err := a.config.SwitchContext(ctx); err != nil {
|
|
panic(err)
|
|
}
|
|
a.useMetricServer = a.supportsMxServer()
|
|
}
|
|
}
|
|
|
|
func (a *apiServer) reset() {
|
|
a.client, a.dClient, a.nsClient = nil, nil, nil
|
|
a.heapsterClient, a.mxsClient = nil, nil
|
|
}
|
|
|
|
func (a *apiServer) supportsMxServer() bool {
|
|
apiGroups, err := a.dialOrDie().Discovery().ServerGroups()
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
for _, discoveredAPIGroup := range apiGroups.Groups {
|
|
if discoveredAPIGroup.Name != metricsapi.GroupName {
|
|
continue
|
|
}
|
|
for _, version := range discoveredAPIGroup.Versions {
|
|
for _, supportedVersion := range supportedMetricsAPIVersions {
|
|
if version.Version == supportedVersion {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|