From aca1830ca5abf37568090c3da429568b70f51147 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Thu, 14 Nov 2024 12:57:45 +0100 Subject: [PATCH] Printing the node capacity and allocated resources Signed-off-by: cmoulliard --- pkg/cmd/get/clusters.go | 100 +++++++++++++++++++++++++++++++++------- 1 file changed, 84 insertions(+), 16 deletions(-) diff --git a/pkg/cmd/get/clusters.go b/pkg/cmd/get/clusters.go index f2fa0948..b5ebddd3 100644 --- a/pkg/cmd/get/clusters.go +++ b/pkg/cmd/get/clusters.go @@ -8,9 +8,12 @@ import ( "github.com/cnoe-io/idpbuilder/pkg/util" "github.com/spf13/cobra" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" "k8s.io/client-go/tools/clientcmd/api" "os" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/kind/pkg/cluster" + "strings" ) var ClustersCmd = &cobra.Command{ @@ -69,7 +72,7 @@ func list(cmd *cobra.Command, args []string) error { logger.Error(err, "failed to load the kube config.") } - // Search about the idp cluster within the kubeconfig file + // Search about the idp cluster within the kubeconfig file and show information cluster, found := findClusterByName(config, "kind-"+cluster) if !found { fmt.Printf("Cluster %q not found\n", cluster) @@ -77,27 +80,92 @@ func list(cmd *cobra.Command, args []string) error { fmt.Printf("URL of the kube API server: %s\n", cluster.Server) fmt.Printf("TLS Verify: %t\n", cluster.InsecureSkipTLSVerify) } + fmt.Println("----------------------------------------") + } + + // Let's check what the current node reports + var nodeList corev1.NodeList + err = cli.List(context.TODO(), &nodeList) + if err != nil { + logger.Error(err, "failed to list nodes for the current kube cluster.") + } + + for _, node := range nodeList.Items { + nodeName := node.Name + fmt.Printf("Node: %s\n", nodeName) + + for _, addr := range node.Status.Addresses { + switch addr.Type { + case corev1.NodeInternalIP: + fmt.Printf("Internal IP: %s\n", addr.Address) + case corev1.NodeExternalIP: + fmt.Printf("External IP: %s\n", addr.Address) + } + } + + // Show node capacity + fmt.Printf("Capacity of the node: \n") + printFormattedResourceList(node.Status.Capacity) - var nodeList corev1.NodeList - err = cli.List(context.TODO(), &nodeList) + // Show node allocated resources + err = printAllocatedResources(context.Background(), cli, node.Name) if err != nil { - logger.Error(err, "failed to list nodes for cluster: %s", cluster) + logger.Error(err, "Failed to get the node's allocated resources.") } + fmt.Println("--------------------") + } + + return nil +} + +func printFormattedResourceList(resources corev1.ResourceList) { + // Define the fixed width for the resource name column (adjust as needed) + nameWidth := 20 - for _, node := range nodeList.Items { - nodeName := node.Name - fmt.Printf(" Node: %s\n", nodeName) - - for _, addr := range node.Status.Addresses { - switch addr.Type { - case corev1.NodeInternalIP: - fmt.Printf(" Internal IP: %s\n", addr.Address) - case corev1.NodeExternalIP: - fmt.Printf(" External IP: %s\n", addr.Address) - } + for name, quantity := range resources { + if strings.HasPrefix(string(name), "hugepages-") { + continue + } + + if name == corev1.ResourceMemory { + // Convert memory from bytes to gigabytes (GB) + memoryInBytes := quantity.Value() // .Value() gives the value in bytes + memoryInGB := float64(memoryInBytes) / (1024 * 1024 * 1024) // Convert to GB + fmt.Printf(" %-*s %.2f GB\n", nameWidth, name, memoryInGB) + } else { + // Format each line with the fixed name width and quantity + fmt.Printf(" %-*s %s\n", nameWidth, name, quantity.String()) + } + } +} + +func printAllocatedResources(ctx context.Context, k8sClient client.Client, nodeName string) error { + // List all pods on the specified node + var podList corev1.PodList + if err := k8sClient.List(ctx, &podList, client.MatchingFields{"spec.nodeName": nodeName}); err != nil { + return fmt.Errorf("failed to list pods on node %s: %w", nodeName, err) + } + + // Initialize counters for CPU and memory requests + totalCPU := resource.NewQuantity(0, resource.DecimalSI) + totalMemory := resource.NewQuantity(0, resource.BinarySI) + + // Sum up CPU and memory requests from each container in each pod + for _, pod := range podList.Items { + for _, container := range pod.Spec.Containers { + if reqCPU, found := container.Resources.Requests[corev1.ResourceCPU]; found { + totalCPU.Add(reqCPU) + } + if reqMemory, found := container.Resources.Requests[corev1.ResourceMemory]; found { + totalMemory.Add(reqMemory) } - fmt.Println("----------") } } + + // Display the total allocated resources + fmt.Printf("Allocated resources on node:\n") + fmt.Printf(" CPU Requests: %s\n", totalCPU.String()) + fmt.Printf(" Memory Requests: %s\n", totalMemory.String()) + return nil }