@@ -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
105105func (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
133137func (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
154157func (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
162165func (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
170173func (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
190193func (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
198201func (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)
206209func (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)
214217func (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)
222225func (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) {
231234func (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
239242func (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
247250func (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 {
294297func (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 {
334337func (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
350353func (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 {
359362func (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