245 lines
5.6 KiB
Go
245 lines
5.6 KiB
Go
package k8s
|
|
|
|
import (
|
|
"io/ioutil"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
"k8s.io/client-go/dynamic"
|
|
"k8s.io/client-go/kubernetes"
|
|
"k8s.io/client-go/rest"
|
|
restclient "k8s.io/client-go/rest"
|
|
"k8s.io/client-go/tools/clientcmd"
|
|
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
|
"k8s.io/kubernetes/pkg/kubectl/metricsutil"
|
|
"k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
|
metricsapi "k8s.io/metrics/pkg/apis/metrics"
|
|
versioned "k8s.io/metrics/pkg/client/clientset/versioned"
|
|
)
|
|
|
|
// NA Not available
|
|
const NA = "n/a"
|
|
|
|
var (
|
|
conn connection
|
|
supportedMetricsAPIVersions = []string{"v1beta1"}
|
|
)
|
|
|
|
func init() {
|
|
conn = &apiServer{}
|
|
}
|
|
|
|
type (
|
|
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 interface {
|
|
configOrDie() *restclient.Config
|
|
dialConfigOrDie() *clientcmdapi.Config
|
|
dialOrDie() kubernetes.Interface
|
|
dynDialOrDie() dynamic.Interface
|
|
nsDialOrDie() dynamic.NamespaceableResourceInterface
|
|
mxsDial() (*versioned.Clientset, error)
|
|
heapsterDial() (*metricsutil.HeapsterMetricsClient, error)
|
|
getClusterName() string
|
|
setClusterName(n string)
|
|
hasMetricsServer() bool
|
|
}
|
|
|
|
apiServer struct {
|
|
client kubernetes.Interface
|
|
dClient dynamic.Interface
|
|
csClient *clientset.Clientset
|
|
nsClient dynamic.NamespaceableResourceInterface
|
|
heapsterClient *metricsutil.HeapsterMetricsClient
|
|
mxsClient *versioned.Clientset
|
|
cluster string
|
|
useMetricServer bool
|
|
}
|
|
)
|
|
|
|
func (a *apiServer) getClusterName() string {
|
|
return a.cluster
|
|
}
|
|
|
|
func (a *apiServer) setClusterName(n string) {
|
|
a.cluster = n
|
|
}
|
|
|
|
func (a *apiServer) hasMetricsServer() bool {
|
|
return a.useMetricServer
|
|
}
|
|
|
|
func (a *apiServer) dialConfigOrDie() *clientcmdapi.Config {
|
|
c, err := clientcmd.NewDefaultPathOptions().GetStartingConfig()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
return c
|
|
}
|
|
|
|
// DialOrDie returns a handle to api server or die.
|
|
func (a *apiServer) dialOrDie() kubernetes.Interface {
|
|
a.checkCurrentConfig()
|
|
if a.client != nil {
|
|
return a.client
|
|
}
|
|
|
|
var err error
|
|
if a.client, err = kubernetes.NewForConfig(a.configOrDie()); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
return a.client
|
|
}
|
|
|
|
func (a *apiServer) csDialOrDie() *clientset.Clientset {
|
|
a.checkCurrentConfig()
|
|
if a.csClient != nil {
|
|
return a.csClient
|
|
}
|
|
|
|
var cfg *rest.Config
|
|
// cfg := clientcmd.NewNonInteractiveClientConfig(config, contextName, overrides, configAccess)
|
|
var err error
|
|
if a.csClient, err = clientset.NewForConfig(cfg); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
return a.csClient
|
|
}
|
|
|
|
// DynDial returns a handle to the api server.
|
|
func (a *apiServer) dynDialOrDie() dynamic.Interface {
|
|
a.checkCurrentConfig()
|
|
if a.dClient != nil {
|
|
return a.dClient
|
|
}
|
|
|
|
var err error
|
|
if a.dClient, err = dynamic.NewForConfig(a.configOrDie()); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
return a.dClient
|
|
}
|
|
|
|
func (a *apiServer) nsDialOrDie() dynamic.NamespaceableResourceInterface {
|
|
a.checkCurrentConfig()
|
|
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) {
|
|
a.checkCurrentConfig()
|
|
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) {
|
|
a.checkCurrentConfig()
|
|
if a.mxsClient != nil {
|
|
return a.mxsClient, nil
|
|
}
|
|
|
|
opts := clientcmd.NewDefaultPathOptions()
|
|
dat, err := ioutil.ReadFile(opts.GetDefaultFilename())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
rc, err := clientcmd.RESTConfigFromKubeConfig(dat)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
a.mxsClient, err = versioned.NewForConfig(rc)
|
|
return a.mxsClient, err
|
|
}
|
|
|
|
func (*apiServer) configOrDie() *restclient.Config {
|
|
opts := clientcmd.NewDefaultPathOptions()
|
|
cfg, err := clientcmd.BuildConfigFromFlags("", opts.GetDefaultFilename())
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
return cfg
|
|
}
|
|
|
|
func (a *apiServer) checkCurrentConfig() {
|
|
cfg, err := clientcmd.NewDefaultPathOptions().GetStartingConfig()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
if len(a.getClusterName()) == 0 {
|
|
a.setClusterName(cfg.CurrentContext)
|
|
a.useMetricServer = a.supportsMxServer()
|
|
return
|
|
}
|
|
|
|
if a.getClusterName() != cfg.CurrentContext {
|
|
a.reset()
|
|
a.setClusterName(cfg.CurrentContext)
|
|
a.useMetricServer = a.supportsMxServer()
|
|
}
|
|
}
|
|
|
|
func (a *apiServer) reset() {
|
|
a.client, a.dClient, a.nsClient = nil, nil, nil
|
|
a.heapsterClient, a.mxsClient = nil, nil
|
|
a.setClusterName("")
|
|
}
|
|
|
|
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
|
|
}
|