func()

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
}