Skip to content

Instantly share code, notes, and snippets.

@circa10a
Last active December 29, 2019 01:55
Show Gist options
  • Save circa10a/10ffb65104cec36fd31ac7d63d69063d to your computer and use it in GitHub Desktop.
Save circa10a/10ffb65104cec36fd31ac7d63d69063d to your computer and use it in GitHub Desktop.
render terminal ui of cluster usage metrics
package main
import (
"flag"
"fmt"
"log"
"os"
"path/filepath"
"strconv"
ui "github.com/gizak/termui/v3"
"github.com/gizak/termui/v3/widgets"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
metrics "k8s.io/metrics/pkg/client/clientset/versioned"
)
func main() {
var kubeconfig *string
if home := homeDir(); home != "" {
kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
} else {
kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
}
flag.Parse()
if err := ui.Init(); err != nil {
log.Fatalf("failed to initialize termui: %v", err)
}
defer ui.Close()
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
if err != nil {
panic(err)
}
coreClient, err := kubernetes.NewForConfig(config)
mc, err := metrics.NewForConfig(config)
if err != nil {
panic(err)
}
nodeMetrics, err := mc.MetricsV1beta1().NodeMetricses().List(metav1.ListOptions{})
if err != nil {
fmt.Println("Error:", err)
return
}
for _, nodeMetric := range nodeMetrics.Items {
nodeData, _ := coreClient.CoreV1().Nodes().Get(nodeMetric.Name, metav1.GetOptions{})
pods, _ := coreClient.CoreV1().Pods("").List(metav1.ListOptions{
FieldSelector: fmt.Sprintf("spec.nodeName=%v", nodeMetric.Name),
})
cpuTotal := nodeData.Status.Allocatable.Cpu().MilliValue()
cpuUsed := nodeMetric.Usage.Cpu().MilliValue()
cpu := float64(cpuUsed) / float64(cpuTotal)
memTotal, _ := nodeData.Status.Allocatable.Memory().AsInt64()
memUsed, _ := nodeMetric.Usage.Memory().AsInt64()
mem := float64(memUsed) / float64(memTotal)
table := widgets.NewTable()
table.Rows = [][]string{
[]string{"Nodes", "CPU", "Memory", "Pods"},
[]string{nodeMetric.Name, fmt.Sprintf("%f%%", cpu*100), fmt.Sprintf("%f%%", mem*100), strconv.Itoa(len(pods.Items))},
}
table.TextStyle = ui.NewStyle(ui.ColorWhite)
table.RowSeparator = true
table.SetRect(0, 0, 60, 10)
p := widgets.NewParagraph()
p.Text = "Cluster Resource Utilization"
p.SetRect(0, 13, 60, 10)
p.Border = true
ui.Render(table, p, createCPUGraph("CPU", cpu), createMemGraph("Mem", mem))
uiEvents := ui.PollEvents()
for {
e := <-uiEvents
switch e.ID {
case "q", "<C-c>":
return
}
}
//storage, _ := nodeMetric.Usage.StorageEphemeral().AsInt64()
}
}
func createCPUGraph(name string, val float64) *widgets.Gauge {
w := widgets.NewGauge()
w.Title = name
w.SetRect(0, 13, 30, 18)
w.Percent = int(val * 100)
w.BarColor = ui.ColorGreen
w.BorderStyle.Fg = ui.ColorWhite
w.TitleStyle.Fg = ui.ColorCyan
return w
}
func createMemGraph(name string, val float64) *widgets.Gauge {
w := widgets.NewGauge()
w.Title = name
w.SetRect(60, 13, 30, 18)
w.Percent = int(val * 100)
w.BarColor = ui.ColorGreen
w.BorderStyle.Fg = ui.ColorWhite
w.TitleStyle.Fg = ui.ColorCyan
return w
}
func homeDir() string {
if h := os.Getenv("HOME"); h != "" {
return h
}
return os.Getenv("USERPROFILE") // windows
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment