backend/config/config.go
package config
import (
"fmt"
"runtime"
"strings"
"time"
"k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/clientcmd/api"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
)
type Config struct {
KubeConfig string
KubeConfigs map[KubeConfigPath]*clientcmdapi.Config
DefaultKubeContext KubeContextName
KubeClusters map[KubeContextName]KubeCluster
Opts
}
type KubeConfigPath string
type KubeContextName string
func (k KubeContextName) String() string {
return string(k)
}
type KubeCluster struct {
KubeContext *api.Context
KubeCluster *api.Cluster
KubeClientSet *kubernetes.Clientset
KubeRestConfig *restclient.Config
}
type Opts struct {
Debug bool
}
type OptFunc func(*Opts)
func defaultOpts() Opts {
return Opts{
Debug: false,
}
}
func WithDebug(d bool) OptFunc {
return func(opts *Opts) {
opts.Debug = d
}
}
func (c Config) GetContext(name string) (*api.Context, error) {
kubeContext, ok := c.KubeClusters[KubeContextName(name)]
if !ok {
return nil, fmt.Errorf("context does not exist")
}
return kubeContext.KubeContext, nil
}
func (c Config) GetClientSet(contextName string) (*kubernetes.Clientset, error) {
kubeContext, ok := c.KubeClusters[KubeContextName(contextName)]
if !ok {
return &kubernetes.Clientset{}, fmt.Errorf("context does not exist")
}
return kubeContext.KubeClientSet, nil
}
func (c Config) GetRestConfig(contextName string) (*restclient.Config, error) {
kubeContext, ok := c.KubeClusters[KubeContextName(contextName)]
if !ok {
return &restclient.Config{}, fmt.Errorf("context does not exist")
}
return kubeContext.KubeRestConfig, nil
}
func (c Config) getKubeContext(s string) (*api.Context, bool) {
for _, apiConfig := range c.KubeConfigs {
for name, context := range apiConfig.Contexts {
if strings.ToLower(s) == name {
return context, true
}
}
}
return nil, false
}
func (c Config) getKubeCluster(s string) (*api.Cluster, bool) {
for _, apiConfig := range c.KubeConfigs {
for name, cluster := range apiConfig.Clusters {
if strings.ToLower(s) == name {
return cluster, true
}
}
}
return nil, false
}
func NewConfig(kubeConfig string, opts ...OptFunc) (Config, error) {
c := Config{
KubeClusters: map[KubeContextName]KubeCluster{},
}
o := defaultOpts()
for _, fn := range opts {
fn(&o)
}
c.Opts = o
kubeConfigs := map[KubeConfigPath]*clientcmdapi.Config{}
// NOTE(rene): on windows path may have : so only support single kubeconfig
kConfig := make([]string, 0)
switch runtime.GOOS {
case "windows":
kConfig = append(kConfig, kubeConfig)
default:
kConfig = strings.Split(kubeConfig, ":")
}
for _, i := range kConfig {
apiConfig, err := clientcmd.LoadFromFile(i)
if err != nil {
return c, err
}
kubeConfigs[KubeConfigPath(i)] = apiConfig
}
c.KubeConfigs = kubeConfigs
for _, apiConfig := range c.KubeConfigs {
for name, context := range apiConfig.Contexts {
cluster, ok := c.getKubeCluster(name)
if !ok {
continue
}
configOverrides := clientcmd.ConfigOverrides{
Context: api.Context{
Cluster: context.Cluster,
Namespace: context.Namespace,
AuthInfo: context.AuthInfo,
},
}
restConfig, err := clientcmd.NewNonInteractiveClientConfig(*apiConfig, name, &configOverrides, nil).ClientConfig()
if err != nil {
return c, err
}
restConfig.Timeout = 30 * time.Second
clientSet, err := kubernetes.NewForConfig(restConfig)
if err != nil {
return c, err
}
m := KubeCluster{
KubeContext: context,
KubeCluster: cluster,
KubeRestConfig: restConfig,
KubeClientSet: clientSet,
}
c.KubeClusters[KubeContextName(name)] = m
}
}
return c, nil
}