mirror of
https://github.com/kubernetes-sigs/descheduler.git
synced 2026-01-26 05:14:13 +01:00
PodsListing: Add WithLabelSelector option.
This commit is contained in:
@@ -31,6 +31,7 @@ type Options struct {
|
|||||||
filter func(pod *v1.Pod) bool
|
filter func(pod *v1.Pod) bool
|
||||||
includedNamespaces []string
|
includedNamespaces []string
|
||||||
excludedNamespaces []string
|
excludedNamespaces []string
|
||||||
|
labelSelector *metav1.LabelSelector
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithFilter sets a pod filter.
|
// WithFilter sets a pod filter.
|
||||||
@@ -55,6 +56,13 @@ func WithoutNamespaces(namespaces []string) func(opts *Options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithLabelSelector sets a pod label selector
|
||||||
|
func WithLabelSelector(labelSelector *metav1.LabelSelector) func(opts *Options) {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.labelSelector = labelSelector
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ListPodsOnANode lists all of the pods on a node
|
// ListPodsOnANode lists all of the pods on a node
|
||||||
// It also accepts an optional "filter" function which can be used to further limit the pods that are returned.
|
// It also accepts an optional "filter" function which can be used to further limit the pods that are returned.
|
||||||
// (Usually this is podEvictor.Evictable().IsEvictable, in order to only list the evictable pods on a node, but can
|
// (Usually this is podEvictor.Evictable().IsEvictable, in order to only list the evictable pods on a node, but can
|
||||||
@@ -74,6 +82,15 @@ func ListPodsOnANode(
|
|||||||
|
|
||||||
fieldSelectorString := "spec.nodeName=" + node.Name + ",status.phase!=" + string(v1.PodSucceeded) + ",status.phase!=" + string(v1.PodFailed)
|
fieldSelectorString := "spec.nodeName=" + node.Name + ",status.phase!=" + string(v1.PodSucceeded) + ",status.phase!=" + string(v1.PodFailed)
|
||||||
|
|
||||||
|
labelSelectorString := ""
|
||||||
|
if options.labelSelector != nil {
|
||||||
|
selector, err := metav1.LabelSelectorAsSelector(options.labelSelector)
|
||||||
|
if err != nil {
|
||||||
|
return []*v1.Pod{}, err
|
||||||
|
}
|
||||||
|
labelSelectorString = selector.String()
|
||||||
|
}
|
||||||
|
|
||||||
if len(options.includedNamespaces) > 0 {
|
if len(options.includedNamespaces) > 0 {
|
||||||
fieldSelector, err := fields.ParseSelector(fieldSelectorString)
|
fieldSelector, err := fields.ParseSelector(fieldSelectorString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -82,7 +99,10 @@ func ListPodsOnANode(
|
|||||||
|
|
||||||
for _, namespace := range options.includedNamespaces {
|
for _, namespace := range options.includedNamespaces {
|
||||||
podList, err := client.CoreV1().Pods(namespace).List(ctx,
|
podList, err := client.CoreV1().Pods(namespace).List(ctx,
|
||||||
metav1.ListOptions{FieldSelector: fieldSelector.String()})
|
metav1.ListOptions{
|
||||||
|
FieldSelector: fieldSelector.String(),
|
||||||
|
LabelSelector: labelSelectorString,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []*v1.Pod{}, err
|
return []*v1.Pod{}, err
|
||||||
}
|
}
|
||||||
@@ -111,7 +131,10 @@ func ListPodsOnANode(
|
|||||||
// Once the descheduler switches to pod listers (through informers),
|
// Once the descheduler switches to pod listers (through informers),
|
||||||
// We need to flip to client-side filtering.
|
// We need to flip to client-side filtering.
|
||||||
podList, err := client.CoreV1().Pods(v1.NamespaceAll).List(ctx,
|
podList, err := client.CoreV1().Pods(v1.NamespaceAll).List(ctx,
|
||||||
metav1.ListOptions{FieldSelector: fieldSelector.String()})
|
metav1.ListOptions{
|
||||||
|
FieldSelector: fieldSelector.String(),
|
||||||
|
LabelSelector: labelSelectorString,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []*v1.Pod{}, err
|
return []*v1.Pod{}, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
core "k8s.io/client-go/testing"
|
core "k8s.io/client-go/testing"
|
||||||
@@ -40,6 +41,7 @@ func TestListPodsOnANode(t *testing.T) {
|
|||||||
name string
|
name string
|
||||||
pods map[string][]v1.Pod
|
pods map[string][]v1.Pod
|
||||||
node *v1.Node
|
node *v1.Node
|
||||||
|
labelSelector *metav1.LabelSelector
|
||||||
expectedPodCount int
|
expectedPodCount int
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
@@ -52,6 +54,33 @@ func TestListPodsOnANode(t *testing.T) {
|
|||||||
"n2": {*test.BuildTestPod("pod3", 100, 0, "n2", nil)},
|
"n2": {*test.BuildTestPod("pod3", 100, 0, "n2", nil)},
|
||||||
},
|
},
|
||||||
node: test.BuildTestNode("n1", 2000, 3000, 10, nil),
|
node: test.BuildTestNode("n1", 2000, 3000, 10, nil),
|
||||||
|
labelSelector: nil,
|
||||||
|
expectedPodCount: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "test listing pods with label selector",
|
||||||
|
pods: map[string][]v1.Pod{
|
||||||
|
"n1": {
|
||||||
|
*test.BuildTestPod("pod1", 100, 0, "n1", nil),
|
||||||
|
*test.BuildTestPod("pod2", 100, 0, "n1", func(pod *v1.Pod) {
|
||||||
|
pod.Labels = map[string]string{"foo": "bar"}
|
||||||
|
}),
|
||||||
|
*test.BuildTestPod("pod3", 100, 0, "n1", func(pod *v1.Pod) {
|
||||||
|
pod.Labels = map[string]string{"foo": "bar1"}
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
"n2": {*test.BuildTestPod("pod4", 100, 0, "n2", nil)},
|
||||||
|
},
|
||||||
|
node: test.BuildTestNode("n1", 2000, 3000, 10, nil),
|
||||||
|
labelSelector: &metav1.LabelSelector{
|
||||||
|
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||||
|
{
|
||||||
|
Key: "foo",
|
||||||
|
Operator: metav1.LabelSelectorOpIn,
|
||||||
|
Values: []string{"bar", "bar1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
expectedPodCount: 2,
|
expectedPodCount: 2,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -67,7 +96,7 @@ func TestListPodsOnANode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
return true, nil, fmt.Errorf("Failed to list: %v", list)
|
return true, nil, fmt.Errorf("Failed to list: %v", list)
|
||||||
})
|
})
|
||||||
pods, _ := ListPodsOnANode(context.TODO(), fakeClient, testCase.node)
|
pods, _ := ListPodsOnANode(context.TODO(), fakeClient, testCase.node, WithLabelSelector(testCase.labelSelector))
|
||||||
if len(pods) != testCase.expectedPodCount {
|
if len(pods) != testCase.expectedPodCount {
|
||||||
t.Errorf("expected %v pods on node %v, got %+v", testCase.expectedPodCount, testCase.node.Name, len(pods))
|
t.Errorf("expected %v pods on node %v, got %+v", testCase.expectedPodCount, testCase.node.Name, len(pods))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user