Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,29 @@ import (
corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/restmapper"
"k8s.io/client-go/tools/clientcmd"
metricsv1beta1 "k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1"
)

// AccessControlClientset is a limited clientset delegating interface to the standard kubernetes.Clientset
// Only a limited set of functions are implemented with a single point of access to the kubernetes API where
// apiVersion and kinds are checked for allowed access
type AccessControlClientset struct {
cfg *rest.Config
kubernetes.Interface
staticConfig *config.StaticConfig
clientCmdConfig clientcmd.ClientConfig
cfg *rest.Config
restMapper meta.ResettableRESTMapper
discoveryClient discovery.CachedDiscoveryInterface
dynamicClient dynamic.Interface
metricsV1beta1 *metricsv1beta1.MetricsV1beta1Client
}

func NewAccessControlClientset(staticConfig *config.StaticConfig, restConfig *rest.Config) (*AccessControlClientset, error) {
rest.CopyConfig(restConfig)
func NewAccessControlClientset(staticConfig *config.StaticConfig, clientCmdConfig clientcmd.ClientConfig, restConfig *rest.Config) (*AccessControlClientset, error) {
acc := &AccessControlClientset{
cfg: rest.CopyConfig(restConfig),
staticConfig: staticConfig,
clientCmdConfig: clientCmdConfig,
cfg: rest.CopyConfig(restConfig),
}
if acc.cfg.UserAgent == "" {
acc.cfg.UserAgent = rest.DefaultKubernetesUserAgent()
Expand Down Expand Up @@ -111,3 +115,8 @@ func (a *AccessControlClientset) SelfSubjectAccessReviews() (authorizationv1.Sel
func (a *AccessControlClientset) TokenReview() (authenticationv1.TokenReviewInterface, error) {
return a.AuthenticationV1().TokenReviews(), nil
}

// ToRawKubeConfigLoader returns the clientcmd.ClientConfig object (genericclioptions.RESTClientGetter)
func (a *AccessControlClientset) ToRawKubeConfigLoader() clientcmd.ClientConfig {
return a.clientCmdConfig
}
11 changes: 7 additions & 4 deletions pkg/kubernetes/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ func IsInCluster(cfg *config.StaticConfig) bool {
}

func (k *Kubernetes) NamespaceOrDefault(namespace string) string {
return k.manager.NamespaceOrDefault(namespace)
if namespace == "" {
return k.configuredNamespace()
}
return namespace
}

// ConfigurationContextsDefault returns the current context name
// TODO: Should be moved to the Provider level ?
func (k *Kubernetes) ConfigurationContextsDefault() (string, error) {
cfg, err := k.manager.clientCmdConfig.RawConfig()
cfg, err := k.ToRawKubeConfigLoader().RawConfig()
if err != nil {
return "", err
}
Expand All @@ -48,7 +51,7 @@ func (k *Kubernetes) ConfigurationContextsDefault() (string, error) {
// ConfigurationContextsList returns the list of available context names
// TODO: Should be moved to the Provider level ?
func (k *Kubernetes) ConfigurationContextsList() (map[string]string, error) {
cfg, err := k.manager.clientCmdConfig.RawConfig()
cfg, err := k.ToRawKubeConfigLoader().RawConfig()
if err != nil {
return nil, err
}
Expand All @@ -71,7 +74,7 @@ func (k *Kubernetes) ConfigurationContextsList() (map[string]string, error) {
func (k *Kubernetes) ConfigurationView(minify bool) (runtime.Object, error) {
var cfg clientcmdapi.Config
var err error
if cfg, err = k.manager.clientCmdConfig.RawConfig(); err != nil {
if cfg, err = k.ToRawKubeConfigLoader().RawConfig(); err != nil {
return nil, err
}
if minify {
Expand Down
44 changes: 37 additions & 7 deletions pkg/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package kubernetes

import (
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/discovery"
"k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth/oidc"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"

"github.com/containers/kubernetes-mcp-server/pkg/helm"
"github.com/containers/kubernetes-mcp-server/pkg/kiali"
Expand All @@ -20,26 +24,52 @@ const (

type CloseWatchKubeConfig func() error

var Scheme = scheme.Scheme
var ParameterCodec = runtime.NewParameterCodec(Scheme)

type Kubernetes struct {
manager *Manager
accessControlClientSet *AccessControlClientset
}

var _ helm.Kubernetes = (*Kubernetes)(nil)

// AccessControlClientset returns the access-controlled clientset
// This ensures that any denied resources configured in the system are properly enforced
func (k *Kubernetes) AccessControlClientset() *AccessControlClientset {
return k.manager.accessControlClientSet
return k.accessControlClientSet
}

var Scheme = scheme.Scheme
var ParameterCodec = runtime.NewParameterCodec(Scheme)

func (k *Kubernetes) NewHelm() *helm.Helm {
// This is a derived Kubernetes, so it already has the Helm initialized
return helm.NewHelm(k.manager)
return helm.NewHelm(k)
}

// NewKiali returns a Kiali client initialized with the same StaticConfig and bearer token
// as the underlying derived Kubernetes manager.
func (k *Kubernetes) NewKiali() *kiali.Kiali {
return kiali.NewKiali(k.manager.staticConfig, k.AccessControlClientset().cfg)
return kiali.NewKiali(k.AccessControlClientset().staticConfig, k.AccessControlClientset().cfg)
}

func (k *Kubernetes) configuredNamespace() string {
if ns, _, nsErr := k.AccessControlClientset().ToRawKubeConfigLoader().Namespace(); nsErr == nil {
return ns
}
return ""
}

func (k *Kubernetes) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) {
return k.AccessControlClientset().DiscoveryClient(), nil
}

func (k *Kubernetes) ToRESTMapper() (meta.RESTMapper, error) {
return k.AccessControlClientset().RESTMapper(), nil
}

// ToRESTConfig returns the rest.Config object (genericclioptions.RESTClientGetter)
func (k *Kubernetes) ToRESTConfig() (*rest.Config, error) {
return k.AccessControlClientset().cfg, nil
}

func (k *Kubernetes) ToRawKubeConfigLoader() clientcmd.ClientConfig {
return k.AccessControlClientset().ToRawKubeConfigLoader()
}
Loading