@@ -27,6 +27,10 @@ const (
2727type CloseWatchKubeConfig func () error
2828
2929type Kubernetes struct {
30+ manager * Manager
31+ }
32+
33+ type Manager struct {
3034 // Kubeconfig path override
3135 Kubeconfig string
3236 cfg * rest.Config
@@ -38,11 +42,10 @@ type Kubernetes struct {
3842 discoveryClient discovery.CachedDiscoveryInterface
3943 deferredDiscoveryRESTMapper * restmapper.DeferredDiscoveryRESTMapper
4044 dynamicClient * dynamic.DynamicClient
41- Helm * helm.Helm
4245}
4346
44- func NewKubernetes (kubeconfig string ) (* Kubernetes , error ) {
45- k8s := & Kubernetes {
47+ func NewManager (kubeconfig string ) (* Manager , error ) {
48+ k8s := & Manager {
4649 Kubeconfig : kubeconfig ,
4750 }
4851 if err := resolveKubernetesConfigurations (k8s ); err != nil {
@@ -68,15 +71,14 @@ func NewKubernetes(kubeconfig string) (*Kubernetes, error) {
6871 return nil , err
6972 }
7073 k8s .parameterCodec = runtime .NewParameterCodec (k8s .scheme )
71- k8s .Helm = helm .NewHelm (k8s )
7274 return k8s , nil
7375}
7476
75- func (k * Kubernetes ) WatchKubeConfig (onKubeConfigChange func () error ) {
76- if k .clientCmdConfig == nil {
77+ func (m * Manager ) WatchKubeConfig (onKubeConfigChange func () error ) {
78+ if m .clientCmdConfig == nil {
7779 return
7880 }
79- kubeConfigFiles := k .clientCmdConfig .ConfigAccess ().GetLoadingPrecedence ()
81+ kubeConfigFiles := m .clientCmdConfig .ConfigAccess ().GetLoadingPrecedence ()
8082 if len (kubeConfigFiles ) == 0 {
8183 return
8284 }
@@ -102,33 +104,33 @@ func (k *Kubernetes) WatchKubeConfig(onKubeConfigChange func() error) {
102104 }
103105 }
104106 }()
105- if k .CloseWatchKubeConfig != nil {
106- _ = k .CloseWatchKubeConfig ()
107+ if m .CloseWatchKubeConfig != nil {
108+ _ = m .CloseWatchKubeConfig ()
107109 }
108- k .CloseWatchKubeConfig = watcher .Close
110+ m .CloseWatchKubeConfig = watcher .Close
109111}
110112
111- func (k * Kubernetes ) Close () {
112- if k .CloseWatchKubeConfig != nil {
113- _ = k .CloseWatchKubeConfig ()
113+ func (m * Manager ) Close () {
114+ if m .CloseWatchKubeConfig != nil {
115+ _ = m .CloseWatchKubeConfig ()
114116 }
115117}
116118
117- func (k * Kubernetes ) ToDiscoveryClient () (discovery.CachedDiscoveryInterface , error ) {
118- return k .discoveryClient , nil
119+ func (m * Manager ) ToDiscoveryClient () (discovery.CachedDiscoveryInterface , error ) {
120+ return m .discoveryClient , nil
119121}
120122
121- func (k * Kubernetes ) ToRESTMapper () (meta.RESTMapper , error ) {
122- return k .deferredDiscoveryRESTMapper , nil
123+ func (m * Manager ) ToRESTMapper () (meta.RESTMapper , error ) {
124+ return m .deferredDiscoveryRESTMapper , nil
123125}
124126
125- func (k * Kubernetes ) Derived (ctx context.Context ) * Kubernetes {
127+ func (m * Manager ) Derived (ctx context.Context ) * Kubernetes {
126128 authorization , ok := ctx .Value (AuthorizationHeader ).(string )
127129 if ! ok || ! strings .HasPrefix (authorization , "Bearer " ) {
128- return k
130+ return & Kubernetes { manager : m }
129131 }
130132 klog .V (5 ).Infof ("%s header found (Bearer), using provided bearer token" , AuthorizationHeader )
131- derivedCfg := rest .CopyConfig (k .cfg )
133+ derivedCfg := rest .CopyConfig (m .cfg )
132134 derivedCfg .BearerToken = strings .TrimPrefix (authorization , "Bearer " )
133135 derivedCfg .BearerTokenFile = ""
134136 derivedCfg .Username = ""
@@ -137,28 +139,42 @@ func (k *Kubernetes) Derived(ctx context.Context) *Kubernetes {
137139 derivedCfg .AuthConfigPersister = nil
138140 derivedCfg .ExecProvider = nil
139141 derivedCfg .Impersonate = rest.ImpersonationConfig {}
140- clientCmdApiConfig , err := k .clientCmdConfig .RawConfig ()
142+ clientCmdApiConfig , err := m .clientCmdConfig .RawConfig ()
141143 if err != nil {
142- return k
144+ return & Kubernetes { manager : m }
143145 }
144146 clientCmdApiConfig .AuthInfos = make (map [string ]* clientcmdapi.AuthInfo )
145- derived := & Kubernetes {
146- Kubeconfig : k .Kubeconfig ,
147+ derived := & Kubernetes {manager : & Manager {
148+ Kubeconfig : m .Kubeconfig ,
147149 clientCmdConfig : clientcmd .NewDefaultClientConfig (clientCmdApiConfig , nil ),
148150 cfg : derivedCfg ,
149- scheme : k .scheme ,
150- parameterCodec : k .parameterCodec ,
151- }
152- derived .clientSet , err = kubernetes .NewForConfig (derived .cfg )
151+ scheme : m .scheme ,
152+ parameterCodec : m .parameterCodec ,
153+ }}
154+ derived .manager . clientSet , err = kubernetes .NewForConfig (derived . manager .cfg )
153155 if err != nil {
154- return k
156+ return & Kubernetes { manager : m }
155157 }
156- derived .discoveryClient = memory .NewMemCacheClient (discovery .NewDiscoveryClient (derived .clientSet .CoreV1 ().RESTClient ()))
157- derived .deferredDiscoveryRESTMapper = restmapper .NewDeferredDiscoveryRESTMapper (derived .discoveryClient )
158- derived .dynamicClient , err = dynamic .NewForConfig (derived .cfg )
158+ derived .manager . discoveryClient = memory .NewMemCacheClient (discovery .NewDiscoveryClient (derived . manager .clientSet .CoreV1 ().RESTClient ()))
159+ derived .manager . deferredDiscoveryRESTMapper = restmapper .NewDeferredDiscoveryRESTMapper (derived . manager .discoveryClient )
160+ derived .manager . dynamicClient , err = dynamic .NewForConfig (derived . manager .cfg )
159161 if err != nil {
160- return k
162+ return & Kubernetes { manager : m }
161163 }
162- derived .Helm = helm .NewHelm (derived )
163164 return derived
164165}
166+
167+ // TODO: check test to see why cache isn't getting invalidated automatically https://github.com/manusa/kubernetes-mcp-server/pull/125#discussion_r2152194784
168+ func (k * Kubernetes ) CacheInvalidate () {
169+ if k .manager .discoveryClient != nil {
170+ k .manager .discoveryClient .Invalidate ()
171+ }
172+ if k .manager .deferredDiscoveryRESTMapper != nil {
173+ k .manager .deferredDiscoveryRESTMapper .Reset ()
174+ }
175+ }
176+
177+ func (k * Kubernetes ) NewHelm () * helm.Helm {
178+ // This is a derived Kubernetes, so it already has the Helm initialized
179+ return helm .NewHelm (k .manager )
180+ }
0 commit comments