Skip to content

Commit eaf18cd

Browse files
authored
Merge pull request #23 from nimishamehta5/add-list-selector
Add listSelector option to the list_resources tool
2 parents 990e0ce + 8e29c1e commit eaf18cd

File tree

3 files changed

+165
-85
lines changed

3 files changed

+165
-85
lines changed

pkg/k8s/client.go

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ type Client struct {
2929
getPodLogs PodLogsFunc
3030
kubeconfigPath string
3131
mu sync.RWMutex // Protects access to client components
32-
32+
3333
// For periodic refresh
34-
refreshCtx context.Context
35-
refreshCancel context.CancelFunc
36-
refreshInterval time.Duration
37-
refreshing bool
38-
refreshMu sync.Mutex // Protects refreshing state
34+
refreshCtx context.Context
35+
refreshCancel context.CancelFunc
36+
refreshInterval time.Duration
37+
refreshing bool
38+
refreshMu sync.Mutex // Protects refreshing state
3939
}
4040

4141
// NewClient creates a new Kubernetes client
@@ -69,10 +69,10 @@ func NewClient(kubeconfigPath string) (*Client, error) {
6969
clientset: clientset,
7070
kubeconfigPath: kubeconfigPath,
7171
}
72-
72+
7373
// Set the default implementation for getPodLogs
7474
client.getPodLogs = client.defaultGetPodLogs
75-
75+
7676
return client, nil
7777
}
7878

@@ -105,7 +105,7 @@ var getConfig ConfigGetter = defaultConfigGetter
105105
func (c *Client) ListAPIResources(ctx context.Context) ([]*metav1.APIResourceList, error) {
106106
c.mu.RLock()
107107
defer c.mu.RUnlock()
108-
108+
109109
_, resourcesList, err := c.discoveryClient.ServerGroupsAndResources()
110110
if err != nil {
111111
return nil, fmt.Errorf("failed to get server resources: %w", err)
@@ -114,28 +114,32 @@ func (c *Client) ListAPIResources(ctx context.Context) ([]*metav1.APIResourceLis
114114
}
115115

116116
// ListClusteredResources returns all clustered resources of the specified group/version/kind
117-
func (c *Client) ListClusteredResources(ctx context.Context, gvr schema.GroupVersionResource) (*unstructured.UnstructuredList, error) {
117+
func (c *Client) ListClusteredResources(ctx context.Context, gvr schema.GroupVersionResource, labelSelector string) (*unstructured.UnstructuredList, error) {
118118
c.mu.RLock()
119119
defer c.mu.RUnlock()
120-
121-
return c.dynamicClient.Resource(gvr).List(ctx, metav1.ListOptions{})
120+
121+
return c.dynamicClient.Resource(gvr).List(ctx, metav1.ListOptions{
122+
LabelSelector: labelSelector,
123+
})
122124
}
123125

124126
// ListNamespacedResources returns all namespaced resources of the specified group/version/kind in the given namespace
125-
func (c *Client) ListNamespacedResources(ctx context.Context, gvr schema.GroupVersionResource, namespace string) (*unstructured.UnstructuredList, error) {
127+
func (c *Client) ListNamespacedResources(ctx context.Context, gvr schema.GroupVersionResource, namespace string, labelSelector string) (*unstructured.UnstructuredList, error) {
126128
c.mu.RLock()
127129
defer c.mu.RUnlock()
128-
129-
return c.dynamicClient.Resource(gvr).Namespace(namespace).List(ctx, metav1.ListOptions{})
130+
131+
return c.dynamicClient.Resource(gvr).Namespace(namespace).List(ctx, metav1.ListOptions{
132+
LabelSelector: labelSelector,
133+
})
130134
}
131135

132136
// ApplyClusteredResource creates or updates a clustered resource
133137
func (c *Client) ApplyClusteredResource(ctx context.Context, gvr schema.GroupVersionResource, obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
134138
c.mu.RLock()
135139
defer c.mu.RUnlock()
136-
140+
137141
name := obj.GetName()
138-
142+
139143
// Check if resource exists
140144
existing, err := c.dynamicClient.Resource(gvr).Get(ctx, name, metav1.GetOptions{})
141145
if err == nil {
@@ -144,8 +148,7 @@ func (c *Client) ApplyClusteredResource(ctx context.Context, gvr schema.GroupVer
144148
obj.SetResourceVersion(existing.GetResourceVersion())
145149
return c.dynamicClient.Resource(gvr).Update(ctx, obj, metav1.UpdateOptions{})
146150
}
147-
148-
151+
149152
// Resource doesn't exist or error occurred, create it
150153
return c.dynamicClient.Resource(gvr).Create(ctx, obj, metav1.CreateOptions{})
151154
}
@@ -154,25 +157,25 @@ func (c *Client) ApplyClusteredResource(ctx context.Context, gvr schema.GroupVer
154157
func (c *Client) GetClusteredResource(ctx context.Context, gvr schema.GroupVersionResource, name string) (interface{}, error) {
155158
c.mu.RLock()
156159
defer c.mu.RUnlock()
157-
160+
158161
return c.dynamicClient.Resource(gvr).Get(ctx, name, metav1.GetOptions{})
159162
}
160163

161164
// GetNamespacedResource gets a namespaced resource
162165
func (c *Client) GetNamespacedResource(ctx context.Context, gvr schema.GroupVersionResource, namespace, name string) (interface{}, error) {
163166
c.mu.RLock()
164167
defer c.mu.RUnlock()
165-
168+
166169
return c.dynamicClient.Resource(gvr).Namespace(namespace).Get(ctx, name, metav1.GetOptions{})
167170
}
168171

169172
// ApplyNamespacedResource creates or updates a namespaced resource
170173
func (c *Client) ApplyNamespacedResource(ctx context.Context, gvr schema.GroupVersionResource, namespace string, obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
171174
c.mu.RLock()
172175
defer c.mu.RUnlock()
173-
176+
174177
name := obj.GetName()
175-
178+
176179
// Check if resource exists
177180
existing, err := c.dynamicClient.Resource(gvr).Namespace(namespace).Get(ctx, name, metav1.GetOptions{})
178181
if err == nil {
@@ -181,7 +184,7 @@ func (c *Client) ApplyNamespacedResource(ctx context.Context, gvr schema.GroupVe
181184
obj.SetResourceVersion(existing.GetResourceVersion())
182185
return c.dynamicClient.Resource(gvr).Namespace(namespace).Update(ctx, obj, metav1.UpdateOptions{})
183186
}
184-
187+
185188
// Resource doesn't exist or error occurred, create it
186189
return c.dynamicClient.Resource(gvr).Namespace(namespace).Create(ctx, obj, metav1.CreateOptions{})
187190
}
@@ -190,39 +193,39 @@ func (c *Client) ApplyNamespacedResource(ctx context.Context, gvr schema.GroupVe
190193
func (c *Client) DeleteClusteredResource(ctx context.Context, gvr schema.GroupVersionResource, name string) error {
191194
c.mu.RLock()
192195
defer c.mu.RUnlock()
193-
196+
194197
return c.dynamicClient.Resource(gvr).Delete(ctx, name, metav1.DeleteOptions{})
195198
}
196199

197200
// DeleteNamespacedResource deletes a namespaced resource
198201
func (c *Client) DeleteNamespacedResource(ctx context.Context, gvr schema.GroupVersionResource, namespace, name string) error {
199202
c.mu.RLock()
200203
defer c.mu.RUnlock()
201-
204+
202205
return c.dynamicClient.Resource(gvr).Namespace(namespace).Delete(ctx, name, metav1.DeleteOptions{})
203206
}
204207

205208
// SetDynamicClient sets the dynamic client (for testing purposes)
206209
func (c *Client) SetDynamicClient(dynamicClient dynamic.Interface) {
207210
c.mu.Lock()
208211
defer c.mu.Unlock()
209-
212+
210213
c.dynamicClient = dynamicClient
211214
}
212215

213216
// SetDiscoveryClient sets the discovery client (for testing purposes)
214217
func (c *Client) SetDiscoveryClient(discoveryClient discovery.DiscoveryInterface) {
215218
c.mu.Lock()
216219
defer c.mu.Unlock()
217-
220+
218221
c.discoveryClient = discoveryClient
219222
}
220223

221224
// SetClientset sets the clientset (for testing purposes)
222225
func (c *Client) SetClientset(clientset kubernetes.Interface) {
223226
c.mu.Lock()
224227
defer c.mu.Unlock()
225-
228+
226229
// Store the interface directly, we'll use it through the interface methods
227230
c.clientset = clientset
228231
}
@@ -231,23 +234,23 @@ func (c *Client) SetClientset(clientset kubernetes.Interface) {
231234
func (c *Client) SetPodLogsFunc(getPodLogs PodLogsFunc) {
232235
c.mu.Lock()
233236
defer c.mu.Unlock()
234-
237+
235238
c.getPodLogs = getPodLogs
236239
}
237240

238241
// GetPodLogs returns the current pod logs function
239242
func (c *Client) GetPodLogs() PodLogsFunc {
240243
c.mu.RLock()
241244
defer c.mu.RUnlock()
242-
245+
243246
return c.getPodLogs
244247
}
245248

246249
// IsReady returns true if the client is ready to use
247250
func (c *Client) IsReady() bool {
248251
c.mu.RLock()
249252
defer c.mu.RUnlock()
250-
253+
251254
return c.discoveryClient != nil && c.dynamicClient != nil && c.clientset != nil
252255
}
253256

@@ -280,7 +283,7 @@ func (c *Client) RefreshClient() error {
280283
// Update the client's components with proper locking
281284
c.mu.Lock()
282285
defer c.mu.Unlock()
283-
286+
284287
c.discoveryClient = discoveryClient
285288
c.dynamicClient = dynamicClient
286289
c.clientset = clientset
@@ -294,23 +297,23 @@ func (c *Client) RefreshClient() error {
294297
func (c *Client) StartPeriodicRefresh(interval time.Duration) error {
295298
c.refreshMu.Lock()
296299
defer c.refreshMu.Unlock()
297-
300+
298301
if c.refreshing {
299302
return fmt.Errorf("periodic refresh is already running")
300303
}
301-
304+
302305
// Create a cancellable context for the refresh goroutine
303306
ctx, cancel := context.WithCancel(context.Background())
304307
c.refreshCtx = ctx
305308
c.refreshCancel = cancel
306309
c.refreshInterval = interval
307310
c.refreshing = true
308-
311+
309312
// Start the refresh goroutine
310313
go func() {
311314
ticker := time.NewTicker(interval)
312315
defer ticker.Stop()
313-
316+
314317
for {
315318
select {
316319
case <-ticker.C:
@@ -325,7 +328,7 @@ func (c *Client) StartPeriodicRefresh(interval time.Duration) error {
325328
}
326329
}
327330
}()
328-
331+
329332
return nil
330333
}
331334

@@ -334,23 +337,23 @@ func (c *Client) StartPeriodicRefresh(interval time.Duration) error {
334337
func (c *Client) StopPeriodicRefresh() error {
335338
c.refreshMu.Lock()
336339
defer c.refreshMu.Unlock()
337-
340+
338341
if !c.refreshing {
339342
return fmt.Errorf("periodic refresh is not running")
340343
}
341-
344+
342345
// Cancel the refresh context to stop the goroutine
343346
c.refreshCancel()
344347
c.refreshing = false
345-
348+
346349
return nil
347350
}
348351

349352
// IsRefreshing returns true if the client is periodically refreshing
350353
func (c *Client) IsRefreshing() bool {
351354
c.refreshMu.Lock()
352355
defer c.refreshMu.Unlock()
353-
356+
354357
return c.refreshing
355358
}
356359

@@ -359,10 +362,10 @@ func (c *Client) IsRefreshing() bool {
359362
func (c *Client) GetRefreshInterval() time.Duration {
360363
c.refreshMu.Lock()
361364
defer c.refreshMu.Unlock()
362-
365+
363366
if !c.refreshing {
364367
return 0
365368
}
366-
369+
367370
return c.refreshInterval
368-
}
371+
}

0 commit comments

Comments
 (0)