@@ -306,16 +306,30 @@ func GetTargetPodsWhenTargetPodsENVNotSet(podAffPerc int, clients clients.Client
306306 }
307307 finalPods .Items = append (finalPods .Items , pods .Items ... )
308308 } else {
309- for _ , label := range target .Labels {
310- pods , err := clients .KubeClient .CoreV1 ().Pods (target .Namespace ).List (context .Background (), v1.ListOptions {LabelSelector : label })
309+ // Check label match mode to determine union vs intersection
310+ if target .LabelMatchMode == "intersection" {
311+ // INTERSECTION: Get pods matching ALL labels
312+ pods , err := getPodsWithIntersectionLabels (target , clients )
311313 if err != nil {
312- return finalPods , cerrors. Error { ErrorCode : cerrors . ErrorTypeTargetSelection , Target : fmt . Sprintf ( "{podLabel: %s, namespace: %s}" , label , target . Namespace ), Reason : err . Error ()}
314+ return finalPods , err
313315 }
314- filteredPods , err := filterPodsByOwnerKind (pods . Items , target , clients )
316+ filteredPods , err := filterPodsByOwnerKind (pods , target , clients )
315317 if err != nil {
316318 return finalPods , stacktrace .Propagate (err , "could not identify parent type from pod" )
317319 }
318320 finalPods .Items = append (finalPods .Items , filteredPods ... )
321+ } else {
322+ for _ , label := range target .Labels {
323+ pods , err := clients .KubeClient .CoreV1 ().Pods (target .Namespace ).List (context .Background (), v1.ListOptions {LabelSelector : label })
324+ if err != nil {
325+ return finalPods , cerrors.Error {ErrorCode : cerrors .ErrorTypeTargetSelection , Target : fmt .Sprintf ("{podLabel: %s, namespace: %s}" , label , target .Namespace ), Reason : err .Error ()}
326+ }
327+ filteredPods , err := filterPodsByOwnerKind (pods .Items , target , clients )
328+ if err != nil {
329+ return finalPods , stacktrace .Propagate (err , "could not identify parent type from pod" )
330+ }
331+ finalPods .Items = append (finalPods .Items , filteredPods ... )
332+ }
319333 }
320334 }
321335 }
@@ -331,6 +345,77 @@ func GetTargetPodsWhenTargetPodsENVNotSet(podAffPerc int, clients clients.Client
331345 return filterPodsByPercentage (finalPods , podAffPerc ), nil
332346}
333347
348+ // getPodsWithIntersectionLabels returns pods that match ALL the provided labels (intersection)
349+ func getPodsWithIntersectionLabels (target types.AppDetails , clients clients.ClientSets ) ([]core_v1.Pod , error ) {
350+ if len (target .Labels ) == 0 {
351+ return nil , cerrors.Error {
352+ ErrorCode : cerrors .ErrorTypeTargetSelection ,
353+ Target : fmt .Sprintf ("{namespace: %s, kind: %s}" , target .Namespace , target .Kind ),
354+ Reason : "no labels provided for intersection" ,
355+ }
356+ }
357+
358+ // Start with pods matching first label
359+ pods , err := clients .KubeClient .CoreV1 ().Pods (target .Namespace ).List (context .Background (), v1.ListOptions {LabelSelector : target .Labels [0 ]})
360+ if err != nil {
361+ return nil , cerrors.Error {
362+ ErrorCode : cerrors .ErrorTypeTargetSelection ,
363+ Target : fmt .Sprintf ("{podLabel: %s, namespace: %s}" , target .Labels [0 ], target .Namespace ),
364+ Reason : err .Error (),
365+ }
366+ }
367+
368+ // If only one label, return the pods
369+ if len (target .Labels ) == 1 {
370+ return pods .Items , nil
371+ }
372+
373+ // Create map for fast lookup using pod name as key
374+ podMap := make (map [string ]core_v1.Pod )
375+ for _ , pod := range pods .Items {
376+ podMap [pod .Name ] = pod
377+ }
378+
379+ // Intersect with each subsequent label
380+ for i := 1 ; i < len (target .Labels ); i ++ {
381+ label := target .Labels [i ]
382+ pods , err := clients .KubeClient .CoreV1 ().Pods (target .Namespace ).List (context .Background (), v1.ListOptions {LabelSelector : label })
383+ if err != nil {
384+ return nil , cerrors.Error {
385+ ErrorCode : cerrors .ErrorTypeTargetSelection ,
386+ Target : fmt .Sprintf ("{podLabel: %s, namespace: %s}" , label , target .Namespace ),
387+ Reason : err .Error (),
388+ }
389+ }
390+
391+ // Keep only pods that exist in both the current map and the new query result
392+ newPodMap := make (map [string ]core_v1.Pod )
393+ for _ , pod := range pods .Items {
394+ if _ , exists := podMap [pod .Name ]; exists {
395+ newPodMap [pod .Name ] = pod
396+ }
397+ }
398+ podMap = newPodMap
399+
400+ // Early exit if no intersection found
401+ if len (podMap ) == 0 {
402+ return nil , cerrors.Error {
403+ ErrorCode : cerrors .ErrorTypeTargetSelection ,
404+ Target : fmt .Sprintf ("{labels: %v, namespace: %s}" , target .Labels , target .Namespace ),
405+ Reason : fmt .Sprintf ("no pods found matching all labels after checking: %s" , label ),
406+ }
407+ }
408+ }
409+
410+ // Convert map back to slice
411+ var result []core_v1.Pod
412+ for _ , pod := range podMap {
413+ result = append (result , pod )
414+ }
415+
416+ return result , nil
417+ }
418+
334419func filterPodsByOwnerKind (pods []core_v1.Pod , target types.AppDetails , clients clients.ClientSets ) ([]core_v1.Pod , error ) {
335420 var filteredPods []core_v1.Pod
336421 for _ , pod := range pods {
0 commit comments