Skip to main content
Glama
provider_kubeconfig.go4.37 kB
package kubernetes import ( "context" "errors" "fmt" "reflect" "github.com/containers/kubernetes-mcp-server/pkg/api" "github.com/containers/kubernetes-mcp-server/pkg/kubernetes/watcher" authenticationv1api "k8s.io/api/authentication/v1" ) // KubeConfigTargetParameterName is the parameter name used to specify // the kubeconfig context when using the kubeconfig cluster provider strategy. const KubeConfigTargetParameterName = "context" // kubeConfigClusterProvider implements Provider for managing multiple // Kubernetes clusters using different contexts from a kubeconfig file. // It lazily initializes managers for each context as they are requested. type kubeConfigClusterProvider struct { config api.BaseConfig defaultContext string managers map[string]*Manager kubeconfigWatcher *watcher.Kubeconfig clusterStateWatcher *watcher.ClusterState } var _ Provider = &kubeConfigClusterProvider{} func init() { RegisterProvider(api.ClusterProviderKubeConfig, newKubeConfigClusterProvider) } // newKubeConfigClusterProvider creates a provider that manages multiple clusters // via kubeconfig contexts. // Internally, it leverages a KubeconfigManager for each context, initializing them // lazily when requested. func newKubeConfigClusterProvider(cfg api.BaseConfig) (Provider, error) { ret := &kubeConfigClusterProvider{config: cfg} if err := ret.reset(); err != nil { return nil, err } return ret, nil } func (p *kubeConfigClusterProvider) reset() error { m, err := NewKubeconfigManager(p.config, "") if err != nil { if errors.Is(err, ErrorKubeconfigInClusterNotAllowed) { return fmt.Errorf("kubeconfig ClusterProviderStrategy is invalid for in-cluster deployments: %v", err) } return err } rawConfig, err := m.accessControlClientset.clientCmdConfig.RawConfig() if err != nil { return err } p.managers = map[string]*Manager{ rawConfig.CurrentContext: m, // we already initialized a manager for the default context, let's use it } for name := range rawConfig.Contexts { if name == rawConfig.CurrentContext { continue // already initialized this, don't want to set it to nil } p.managers[name] = nil } p.Close() p.kubeconfigWatcher = watcher.NewKubeconfig(m.accessControlClientset.clientCmdConfig) p.clusterStateWatcher = watcher.NewClusterState(m.accessControlClientset.DiscoveryClient()) p.defaultContext = rawConfig.CurrentContext return nil } func (p *kubeConfigClusterProvider) managerForContext(context string) (*Manager, error) { m, ok := p.managers[context] if ok && m != nil { return m, nil } baseManager := p.managers[p.defaultContext] m, err := NewKubeconfigManager(baseManager.config, context) if err != nil { return nil, err } p.managers[context] = m return m, nil } func (p *kubeConfigClusterProvider) IsOpenShift(ctx context.Context) bool { return p.managers[p.defaultContext].IsOpenShift(ctx) } func (p *kubeConfigClusterProvider) VerifyToken(ctx context.Context, context, token, audience string) (*authenticationv1api.UserInfo, []string, error) { m, err := p.managerForContext(context) if err != nil { return nil, nil, err } return m.VerifyToken(ctx, token, audience) } func (p *kubeConfigClusterProvider) GetTargets(_ context.Context) ([]string, error) { contextNames := make([]string, 0, len(p.managers)) for contextName := range p.managers { contextNames = append(contextNames, contextName) } return contextNames, nil } func (p *kubeConfigClusterProvider) GetTargetParameterName() string { return KubeConfigTargetParameterName } func (p *kubeConfigClusterProvider) GetDerivedKubernetes(ctx context.Context, context string) (*Kubernetes, error) { m, err := p.managerForContext(context) if err != nil { return nil, err } return m.Derived(ctx) } func (p *kubeConfigClusterProvider) GetDefaultTarget() string { return p.defaultContext } func (p *kubeConfigClusterProvider) WatchTargets(reload McpReload) { reloadWithReset := func() error { if err := p.reset(); err != nil { return err } p.WatchTargets(reload) return reload() } p.kubeconfigWatcher.Watch(reloadWithReset) p.clusterStateWatcher.Watch(reload) } func (p *kubeConfigClusterProvider) Close() { for _, w := range []watcher.Watcher{p.kubeconfigWatcher, p.clusterStateWatcher} { if !reflect.ValueOf(w).IsNil() { w.Close() } } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/containers/kubernetes-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server