Skip to content

Commit 6a3965a

Browse files
committed
feat: add LabelMatchMode to AppDetails and implement intersection label matching for pod selection
Signed-off-by: XploY04 <[email protected]>
1 parent 3a9a539 commit 6a3965a

File tree

2 files changed

+105
-10
lines changed

2 files changed

+105
-10
lines changed

pkg/types/types.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,11 @@ type ProbeContext struct {
156156

157157
// AppDetails contains all the application related envs
158158
type AppDetails struct {
159-
Namespace string
160-
Labels []string
161-
Kind string
162-
Names []string
159+
Namespace string
160+
Labels []string
161+
Kind string
162+
Names []string
163+
LabelMatchMode string
163164
}
164165

165166
func GetTargets(targets string) []AppDetails {
@@ -171,9 +172,18 @@ func GetTargets(targets string) []AppDetails {
171172
for _, k := range t {
172173
val := strings.Split(strings.TrimSpace(k), ":")
173174
data := AppDetails{
174-
Kind: val[0],
175-
Namespace: val[1],
175+
Kind: val[0],
176+
Namespace: val[1],
177+
LabelMatchMode: "union",
178+
}
179+
180+
if len(val) > 3 {
181+
mode := strings.TrimSpace(val[3])
182+
if mode == "intersection" || mode == "union" {
183+
data.LabelMatchMode = mode
184+
}
176185
}
186+
177187
if strings.Contains(val[2], "=") {
178188
data.Labels = parse(val[2])
179189
} else {

pkg/utils/common/pods.go

Lines changed: 89 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
334419
func 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

Comments
 (0)