diff --git a/pkg/capacity/resources.go b/pkg/capacity/resources.go index 732e65ab..df613c45 100644 --- a/pkg/capacity/resources.go +++ b/pkg/capacity/resources.go @@ -38,6 +38,7 @@ var SupportedSortAttributes = [...]string{ "mem.util.percentage", "mem.request.percentage", "mem.limit.percentage", + "pod.count", "name", } @@ -275,6 +276,8 @@ func (cm *clusterMetric) getSortedNodeMetrics(sortBy string) []*nodeMetric { return m2.memory.percent(m2.memory.limit) < m1.memory.percent(m1.memory.limit) case "mem.request.percentage": return m2.memory.percent(m2.memory.request) < m1.memory.percent(m1.memory.request) + case "pod.count": + return m2.podCount.current < m1.podCount.current default: return m1.name < m2.name } diff --git a/pkg/capacity/resources_test.go b/pkg/capacity/resources_test.go index 52ad3247..8dea5a11 100644 --- a/pkg/capacity/resources_test.go +++ b/pkg/capacity/resources_test.go @@ -184,6 +184,71 @@ func TestBuildClusterMetricFull(t *testing.T) { ensureEqualResourceMetric(t, pm["default-example-pod"].memory, memoryExpected) } +func TestSortByPodCount(t *testing.T) { + nodeList := &corev1.NodeList{ + Items: []corev1.Node{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "node-1", + }, + Status: corev1.NodeStatus{ + Allocatable: corev1.ResourceList{ + "pods": resource.MustParse("110"), + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "node-2", + }, + Status: corev1.NodeStatus{ + Allocatable: corev1.ResourceList{ + "pods": resource.MustParse("110"), + }, + }, + }, + }, + } + + podList := &corev1.PodList{ + Items: []corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-1", + }, + Spec: corev1.PodSpec{ + NodeName: "node-1", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-2", + }, + Spec: corev1.PodSpec{ + NodeName: "node-1", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-3", + }, + Spec: corev1.PodSpec{ + NodeName: "node-2", + }, + }, + }, + } + + cm := buildClusterMetric(podList, nil, nodeList, nil) + sortedNodes := cm.getSortedNodeMetrics("pod.count") + + // Node 1 should come first as it has 2 pods vs 1 pod on node 2 + assert.Equal(t, "node-1", sortedNodes[0].name) + assert.Equal(t, "node-2", sortedNodes[1].name) + assert.Equal(t, int64(2), sortedNodes[0].podCount.current) + assert.Equal(t, int64(1), sortedNodes[1].podCount.current) +} + func ensureEqualResourceMetric(t *testing.T, actual *resourceMetric, expected *resourceMetric) { assert.Equal(t, actual.allocatable.MilliValue(), expected.allocatable.MilliValue()) assert.Equal(t, actual.utilization.MilliValue(), expected.utilization.MilliValue())