diff --git a/internal/k8s/metrics.go b/internal/k8s/metrics.go index 5c1bc60a..11516dfe 100644 --- a/internal/k8s/metrics.go +++ b/internal/k8s/metrics.go @@ -13,20 +13,21 @@ type ( Connection } - // NodeMetrics describes raw node metrics. - NodeMetrics struct { + currentMetrics struct { CurrentCPU int64 CurrentMEM float64 - AvailCPU int64 - AvailMEM float64 - TotalCPU int64 - TotalMEM float64 } // PodMetrics represent an aggregation of all pod containers metrics. - PodMetrics struct { - CurrentCPU int64 - CurrentMEM float64 + PodMetrics currentMetrics + + // NodeMetrics describes raw node metrics. + NodeMetrics struct { + currentMetrics + AvailCPU int64 + AvailMEM float64 + TotalCPU int64 + TotalMEM float64 } // ClusterMetrics summarizes total node metrics as percentages. diff --git a/internal/resource/hpa_v2beta1.go b/internal/resource/hpa_v2beta1.go index ec81625e..b4de4b68 100644 --- a/internal/resource/hpa_v2beta1.go +++ b/internal/resource/hpa_v2beta1.go @@ -170,11 +170,8 @@ func (*HorizontalPodAutoscalerV2Beta1) externalMetrics(i int, spec autoscalingv2 func (*HorizontalPodAutoscalerV2Beta1) resourceMetrics(i int, spec autoscalingv2beta1.MetricSpec, statuses []autoscalingv2beta1.MetricStatus) string { current := "" - if spec.Resource.TargetAverageValue != nil { - if len(statuses) > i && statuses[i].Resource != nil { - current = statuses[i].Resource.CurrentAverageValue.String() - } - return current + "/" + spec.Resource.TargetAverageValue.String() + if status := checkTargetMetrics(i, spec, statuses); status != "" { + return status } if len(statuses) > i && statuses[i].Resource != nil && statuses[i].Resource.CurrentAverageUtilization != nil { @@ -188,3 +185,15 @@ func (*HorizontalPodAutoscalerV2Beta1) resourceMetrics(i int, spec autoscalingv2 return current + "/" + target } + +func checkTargetMetrics(i int, spec autoscalingv2beta1.MetricSpec, statuses []autoscalingv2beta1.MetricStatus) string { + if spec.Resource.TargetAverageValue == nil { + return "" + } + + var current string + if len(statuses) > i && statuses[i].Resource != nil { + current = statuses[i].Resource.CurrentAverageValue.String() + } + return current + "/" + spec.Resource.TargetAverageValue.String() +} diff --git a/internal/views/details.go b/internal/views/details.go index c2c53f9a..8c9d602e 100644 --- a/internal/views/details.go +++ b/internal/views/details.go @@ -14,48 +14,62 @@ import ( const detailsTitleFmt = "[fg:bg:b] %s([hilite:bg:b]%s[fg:bg:-])[fg:bg:-] " -// detailsView displays text output. -type detailsView struct { - *tview.TextView +type ( + textView struct { + *tview.TextView - app *appView - actions keyActions - title string - category string - cmdBuff *cmdBuff - backFn actionHandler - numSelections int + app *appView + actions keyActions + cmdBuff *cmdBuff + title string + } + + detailsView struct { + *textView + + category string + backFn actionHandler + numSelections int + } +) + +func newTextView(app *appView) *textView { + return &textView{ + TextView: tview.NewTextView(), + app: app, + actions: make(keyActions), + } } func newDetailsView(app *appView, backFn actionHandler) *detailsView { - v := detailsView{TextView: tview.NewTextView(), app: app, actions: make(keyActions)} - { - v.backFn = backFn - v.SetScrollable(true) - v.SetWrap(true) - v.SetDynamicColors(true) - v.SetRegions(true) - v.SetBorder(true) - v.SetBorderFocusColor(config.AsColor(v.app.styles.Frame().Border.FocusColor)) - v.SetHighlightColor(tcell.ColorOrange) - v.SetTitleColor(tcell.ColorAqua) - v.SetInputCapture(v.keyboard) - v.cmdBuff = newCmdBuff('/') - { - v.cmdBuff.addListener(app.cmd()) - v.cmdBuff.reset() - } - v.SetChangedFunc(func() { - app.Draw() - }) - } + v := detailsView{textView: newTextView(app)} + v.backFn = backFn + v.SetScrollable(true) + v.SetWrap(true) + v.SetDynamicColors(true) + v.SetRegions(true) + v.SetBorder(true) + v.SetBorderFocusColor(config.AsColor(v.app.styles.Frame().Border.FocusColor)) + v.SetHighlightColor(tcell.ColorOrange) + v.SetTitleColor(tcell.ColorAqua) + v.SetInputCapture(v.keyboard) - v.actions[tcell.KeyBackspace2] = newKeyAction("Erase", v.eraseCmd, false) - v.actions[tcell.KeyBackspace] = newKeyAction("Erase", v.eraseCmd, false) - v.actions[tcell.KeyDelete] = newKeyAction("Erase", v.eraseCmd, false) - v.actions[tcell.KeyEscape] = newKeyAction("Back", v.backCmd, true) - v.actions[tcell.KeyTab] = newKeyAction("Next Match", v.nextCmd, false) - v.actions[tcell.KeyBacktab] = newKeyAction("Previous Match", v.prevCmd, false) + v.cmdBuff = newCmdBuff('/') + v.cmdBuff.addListener(app.cmd()) + v.cmdBuff.reset() + + v.SetChangedFunc(func() { + app.Draw() + }) + + v.actions = keyActions{ + tcell.KeyBackspace2: newKeyAction("Erase", v.eraseCmd, false), + tcell.KeyBackspace: newKeyAction("Erase", v.eraseCmd, false), + tcell.KeyDelete: newKeyAction("Erase", v.eraseCmd, false), + tcell.KeyEscape: newKeyAction("Back", v.backCmd, true), + tcell.KeyTab: newKeyAction("Next Match", v.nextCmd, false), + tcell.KeyBacktab: newKeyAction("Previous Match", v.prevCmd, false), + } return &v } @@ -129,7 +143,6 @@ func (v *detailsView) searchCmd(evt *tcell.EventKey) *tcell.EventKey { func (v *detailsView) search(evt *tcell.EventKey) { v.numSelections = 0 - v.Highlight() log.Debug().Msgf("Searching... %s - %d", v.cmdBuff, v.numSelections) v.Highlight("") v.SetText(v.decorateLines(v.GetText(false), v.cmdBuff.String())) diff --git a/internal/views/menu.go b/internal/views/menu.go index 78e64000..e09bedd9 100644 --- a/internal/views/menu.go +++ b/internal/views/menu.go @@ -167,7 +167,10 @@ func (v *menuView) buildMenuTable(hh hints) [][]string { return strTable } -func (*menuView) toMnemonic(s string) string { +// ---------------------------------------------------------------------------- +// Helpers... + +func toMnemonic(s string) string { if len(s) == 0 { return s } @@ -178,17 +181,25 @@ func (*menuView) toMnemonic(s string) string { func (v *menuView) formatMenu(h hint, size int) string { i, err := strconv.Atoi(h.mnemonic) if err == nil { - fmat := strings.Replace(menuIndexFmt, "[key", "["+v.styles.Frame().Menu.NumKeyColor, 1) - fmat = strings.Replace(fmat, ":bg:", ":"+v.styles.Frame().Title.BgColor+":", -1) - fmat = strings.Replace(fmat, "[fg", "["+v.styles.Frame().Menu.FgColor, 1) - return fmt.Sprintf(fmat, i, resource.Truncate(h.description, 14)) + return formatNSMenu(i, h.description, v.styles.Frame()) } + return formatPlainMenu(h, size, v.styles.Frame()) +} + +func formatNSMenu(i int, name string, styles config.Frame) string { + fmat := strings.Replace(menuIndexFmt, "[key", "["+styles.Menu.NumKeyColor, 1) + fmat = strings.Replace(fmat, ":bg:", ":"+styles.Title.BgColor+":", -1) + fmat = strings.Replace(fmat, "[fg", "["+styles.Menu.FgColor, 1) + return fmt.Sprintf(fmat, i, resource.Truncate(name, 14)) +} + +func formatPlainMenu(h hint, size int, styles config.Frame) string { menuFmt := " [key:bg:b]%-" + strconv.Itoa(size+2) + "s [fg:bg:d]%s " - fmat := strings.Replace(menuFmt, "[key", "["+v.styles.Frame().Menu.KeyColor, 1) - fmat = strings.Replace(fmat, "[fg", "["+v.styles.Frame().Menu.FgColor, 1) - fmat = strings.Replace(fmat, ":bg:", ":"+v.styles.Frame().Title.BgColor+":", -1) - return fmt.Sprintf(fmat, v.toMnemonic(h.mnemonic), h.description) + fmat := strings.Replace(menuFmt, "[key", "["+styles.Menu.KeyColor, 1) + fmat = strings.Replace(fmat, "[fg", "["+styles.Menu.FgColor, 1) + fmat = strings.Replace(fmat, ":bg:", ":"+styles.Title.BgColor+":", -1) + return fmt.Sprintf(fmat, toMnemonic(h.mnemonic), h.description) } // ----------------------------------------------------------------------------- diff --git a/internal/views/pod.go b/internal/views/pod.go index e0a7df98..f66fca47 100644 --- a/internal/views/pod.go +++ b/internal/views/pod.go @@ -52,20 +52,23 @@ func newPodView(t string, app *appView, list resource.List) resourceViewer { } func (v *podView) extraActions(aa keyActions) { - // aa[KeyAltS] = newKeyAction("Sniff", v.sniffCmd, true) - - aa[KeyL] = newKeyAction("Logs", v.logsCmd, true) - aa[KeyShiftL] = newKeyAction("Logs Previous", v.prevLogsCmd, true) - aa[KeyS] = newKeyAction("Shell", v.shellCmd, true) - aa[KeyShiftR] = newKeyAction("Sort Ready", v.sortColCmd(1, false), true) - aa[KeyShiftS] = newKeyAction("Sort Status", v.sortColCmd(2, true), true) - aa[KeyShiftT] = newKeyAction("Sort Restart", v.sortColCmd(3, false), true) - aa[KeyShiftC] = newKeyAction("Sort CPU", v.sortColCmd(4, false), true) - aa[KeyShiftM] = newKeyAction("Sort MEM", v.sortColCmd(5, false), true) - aa[KeyAltC] = newKeyAction("Sort CPU%", v.sortColCmd(6, false), true) - aa[KeyAltM] = newKeyAction("Sort MEM%", v.sortColCmd(7, false), true) - aa[KeyShiftD] = newKeyAction("Sort IP", v.sortColCmd(8, true), true) - aa[KeyShiftO] = newKeyAction("Sort Node", v.sortColCmd(9, true), true) + actions := keyActions{ + KeyL: newKeyAction("Logs", v.logsCmd, true), + KeyShiftL: newKeyAction("Logs Previous", v.prevLogsCmd, true), + KeyS: newKeyAction("Shell", v.shellCmd, true), + KeyShiftR: newKeyAction("Sort Ready", v.sortColCmd(1, false), true), + KeyShiftS: newKeyAction("Sort Status", v.sortColCmd(2, true), true), + KeyShiftT: newKeyAction("Sort Restart", v.sortColCmd(3, false), true), + KeyShiftC: newKeyAction("Sort CPU", v.sortColCmd(4, false), true), + KeyShiftM: newKeyAction("Sort MEM", v.sortColCmd(5, false), true), + KeyAltC: newKeyAction("Sort CPU%", v.sortColCmd(6, false), true), + KeyAltM: newKeyAction("Sort MEM%", v.sortColCmd(7, false), true), + KeyShiftD: newKeyAction("Sort IP", v.sortColCmd(8, true), true), + KeyShiftO: newKeyAction("Sort Node", v.sortColCmd(9, true), true), + } + for k, v := range actions { + aa[k] = v + } } func (v *podView) listContainers(app *appView, _, res, sel string) {