package dev.dinauer.monitoring; import java.util.*; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import io.fabric8.kubernetes.api.model.Node; import io.fabric8.kubernetes.api.model.Pod; import dev.dinauer.utils.ProcessRunner; import dev.dinauer.monitoring.nodes.MonitoredNode; import dev.dinauer.monitoring.nodes.NodeMetrics; import dev.dinauer.monitoring.nodes.client.NodeDiskMetrics; import dev.dinauer.monitoring.nodes.client.NodeDiskService; import dev.dinauer.service.PodService; import dev.dinauer.utils.ClientProvider; @ApplicationScoped public class TopNodesService { @Inject ClientProvider clientProvider; @Inject ProcessRunner processRunner; @Inject PodService podService; @Inject NodeDiskService nodeDiskService; public List findAll() { List result = new ArrayList<>(); List stats = runTopNodesCommand(); Map podsOnNodes = countPods(); Map nodeDiskMetrics = nodeDiskService.getDiskMetrics(); for (String nodeName : stats) { String[] parts = nodeName.split("\\s+"); if (parts.length == 5) { String name = parts[0]; Node node = clientProvider.getClient().nodes().withName(name).get(); Integer absoluteCpu = extractInteger(parts[1]); Integer relativeCpu = extractInteger(parts[2]); Integer absoluteMemory = extractMemory(parts[3]); Integer relativeMemory = extractInteger(parts[4]); Integer totalCpu = Integer.parseInt(node.getStatus().getAllocatable().get("cpu").getAmount()) * 1000; Integer totalMemory = extractMemory(node.getStatus().getAllocatable().get("memory").getAmount()); Integer totalPods = podsOnNodes.get(node.getMetadata().getName()); NodeDiskMetrics diskMetrics = nodeDiskMetrics.get(node.getMetadata().getName()); if (diskMetrics != null) { NodeMetrics metrics = new NodeMetrics(absoluteCpu, relativeCpu, totalCpu, absoluteMemory, relativeMemory, totalMemory, totalPods, diskMetrics.relativeDiskUsage(), diskMetrics.totalDiskSpace()); result.add(new MonitoredNode(node, metrics)); } else { NodeMetrics metrics = new NodeMetrics(absoluteCpu, relativeCpu, totalCpu, absoluteMemory, relativeMemory, totalMemory, totalPods, null, null); result.add(new MonitoredNode(node, metrics)); } } } return result; } private Map countPods() { List pods = podService.findAll(); Map result = new HashMap<>(); for (Pod pod : pods) { String nodeName = pod.getSpec().getNodeName(); result.put(nodeName, Optional.ofNullable(result.get(nodeName)).orElse(0) + 1); } return result; } private List runTopNodesCommand() { return processRunner.runToLines("kubectl top nodes --no-headers"); } private Integer extractInteger(String input) { return Integer.valueOf(input.replace("m", "").replace("%", "")); } private Integer extractMemory(String input) { if (input.contains("Ki")) { return Integer.parseInt(input.replace("Ki", "")); } if (input.contains("Mi")) { return Integer.parseInt(input.replace("Mi", "")) * 1024; } if (input.contains("Gi")) { return Integer.parseInt(input.replace("Gi", "")) * 1024 * 1024; } return Integer.parseInt(input); } }