in pkg/frontend/adminactions/clusterresourceusage.go [60:168]
func (k *kubeActions) TopPods(ctx context.Context, restConfig *restclient.Config, allNamespaces bool) ([]PodMetrics, error) {
var ns string
if allNamespaces {
ns = "" // Empty string fetches pods from all namespaces
} else {
return nil, fmt.Errorf("explicit namespace must be provided when allNamespaces is false")
}
// Create metrics client
client, err := metricsv1beta1.NewForConfig(restConfig)
if err != nil {
return nil, err
}
// Get metrics for all pods
podMetricsList, err := client.MetricsV1beta1().PodMetricses(ns).List(ctx, metav1.ListOptions{})
if err != nil {
return nil, err
}
// Map pods to their assigned nodes
podsList, err := k.kubecli.CoreV1().Pods(ns).List(ctx, metav1.ListOptions{})
if err != nil {
return nil, err
}
podToNode := make(map[string]string)
for _, pod := range podsList.Items {
podToNode[pod.Name] = pod.Spec.NodeName
}
// Fetch node capacities
nodeList, err := k.kubecli.CoreV1().Nodes().List(ctx, metav1.ListOptions{})
if err != nil {
return nil, err
}
nodeCPUMap := make(map[string]int64)
nodeMemMap := make(map[string]int64)
for _, node := range nodeList.Items {
if cpuQty, ok := node.Status.Capacity["cpu"]; ok {
if cpuVal, ok := cpuQty.AsInt64(); ok {
nodeCPUMap[node.Name] = cpuVal
}
}
if memQty, ok := node.Status.Capacity["memory"]; ok {
if memVal, ok := memQty.AsInt64(); ok {
nodeMemMap[node.Name] = memVal
}
}
}
var result []PodMetrics
// Aggregate metrics per pod
for _, item := range podMetricsList.Items {
var totalCPUMilli int64
var totalMemBytes int64
for _, c := range item.Containers {
if c.Usage.Cpu() != nil {
totalCPUMilli += c.Usage.Cpu().MilliValue() // CPU in millicores
}
if c.Usage.Memory() != nil {
totalMemBytes += c.Usage.Memory().Value() // Memory in bytes
}
}
// Skip pods with no usage
if totalCPUMilli == 0 && totalMemBytes == 0 {
continue
}
// 🔐 Filter to only include "openshift-" namespaces
if !strings.HasPrefix(item.Namespace, "openshift-") {
continue
}
nodeName := podToNode[item.Name]
nodeCPU := nodeCPUMap[nodeName]
nodeMem := nodeMemMap[nodeName]
// Compute CPU and memory usage percent relative to node capacity
cpuPct := 0.0
memPct := 0.0
if nodeCPU > 0 {
cpuPct = (float64(totalCPUMilli) / float64(nodeCPU*1000)) * 100
}
if nodeMem > 0 {
memPct = (float64(totalMemBytes) / float64(nodeMem)) * 100
}
// Append formatted pod metrics
result = append(result, PodMetrics{
Namespace: item.Namespace,
PodName: item.Name,
NodeName: nodeName,
CPUUsage: fmt.Sprintf("%dm", totalCPUMilli),
MemoryUsage: fmt.Sprintf("%dKi", totalMemBytes/1024),
CPUPercentage: roundPercentage(cpuPct),
MemoryPercentage: roundPercentage(memPct),
})
}
// Sort pods by memory percentage (highest first)
sort.Slice(result, func(i, j int) bool {
return result[i].MemoryPercentage > result[j].MemoryPercentage
})
return result, nil
}