reworked cpu/mem limits
parent
995158d446
commit
f9e32003b9
|
|
@ -32,7 +32,7 @@ func TestTableReconcile(t *testing.T) {
|
|||
err := ta.reconcile(ctx)
|
||||
assert.Nil(t, err)
|
||||
data := ta.Peek()
|
||||
assert.Equal(t, 13, len(data.Header))
|
||||
assert.Equal(t, 15, len(data.Header))
|
||||
assert.Equal(t, 1, len(data.RowEvents))
|
||||
assert.Equal(t, client.NamespaceAll, data.Namespace)
|
||||
}
|
||||
|
|
@ -110,7 +110,7 @@ func TestTableHydrate(t *testing.T) {
|
|||
|
||||
assert.Nil(t, hydrate("blee", oo, rr, render.Pod{}))
|
||||
assert.Equal(t, 1, len(rr))
|
||||
assert.Equal(t, 12, len(rr[0].Fields))
|
||||
assert.Equal(t, 14, len(rr[0].Fields))
|
||||
}
|
||||
|
||||
func TestTableGenericHydrate(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ func TestTableRefresh(t *testing.T) {
|
|||
ctx = context.WithValue(ctx, internal.KeyFields, "")
|
||||
ta.Refresh(ctx)
|
||||
data := ta.Peek()
|
||||
assert.Equal(t, 13, len(data.Header))
|
||||
assert.Equal(t, 15, len(data.Header))
|
||||
assert.Equal(t, 1, len(data.RowEvents))
|
||||
assert.Equal(t, client.NamespaceAll, data.Namespace)
|
||||
assert.Equal(t, 1, l.count)
|
||||
|
|
|
|||
|
|
@ -77,6 +77,8 @@ func (Container) Header(ns string) HeaderRow {
|
|||
Header{Name: "MEM", Align: tview.AlignRight},
|
||||
Header{Name: "%CPU", Align: tview.AlignRight},
|
||||
Header{Name: "%MEM", Align: tview.AlignRight},
|
||||
Header{Name: "%MAX-CPU", Align: tview.AlignRight},
|
||||
Header{Name: "%MAX-MEM", Align: tview.AlignRight},
|
||||
Header{Name: "PORTS"},
|
||||
Header{Name: "AGE", Decorator: AgeDecorator},
|
||||
}
|
||||
|
|
@ -89,7 +91,7 @@ func (c Container) Render(o interface{}, name string, r *Row) error {
|
|||
return fmt.Errorf("Expected ContainerRes, but got %T", o)
|
||||
}
|
||||
|
||||
cur, perc := gatherMetrics(co.Container, co.MX)
|
||||
cur, perc, limit := gatherMetrics(co.Container, co.MX)
|
||||
ready, state, restarts := "false", MissingValue, "0"
|
||||
if co.Status != nil {
|
||||
ready, state, restarts = boolToStr(co.Status.Ready), toState(co.Status.State), strconv.Itoa(int(co.Status.RestartCount))
|
||||
|
|
@ -109,6 +111,8 @@ func (c Container) Render(o interface{}, name string, r *Row) error {
|
|||
cur.mem,
|
||||
perc.cpu,
|
||||
perc.mem,
|
||||
limit.cpu,
|
||||
limit.mem,
|
||||
toStrPorts(co.Container.Ports),
|
||||
toAge(co.Age),
|
||||
)
|
||||
|
|
@ -119,8 +123,8 @@ func (c Container) Render(o interface{}, name string, r *Row) error {
|
|||
// ----------------------------------------------------------------------------
|
||||
// Helpers...
|
||||
|
||||
func gatherMetrics(co *v1.Container, mx *mv1beta1.ContainerMetrics) (c, p metric) {
|
||||
c, p = noMetric(), noMetric()
|
||||
func gatherMetrics(co *v1.Container, mx *mv1beta1.ContainerMetrics) (c, p, l metric) {
|
||||
c, p, l = noMetric(), noMetric(), noMetric()
|
||||
if mx == nil {
|
||||
return
|
||||
}
|
||||
|
|
@ -140,6 +144,14 @@ func gatherMetrics(co *v1.Container, mx *mv1beta1.ContainerMetrics) (c, p metric
|
|||
p.mem = AsPerc(toPerc(mem, ToMB(rmem.Value())))
|
||||
}
|
||||
|
||||
lcpu, lmem := containerLimits(*co)
|
||||
if lcpu != nil {
|
||||
l.cpu = AsPerc(toPerc(float64(cpu), float64(lcpu.MilliValue())))
|
||||
}
|
||||
if lmem != nil {
|
||||
l.mem = AsPerc(toPerc(mem, ToMB(lmem.Value())))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ func TestContainer(t *testing.T) {
|
|||
"20",
|
||||
"50",
|
||||
"20",
|
||||
"50",
|
||||
"20",
|
||||
"",
|
||||
},
|
||||
r.Fields[:len(r.Fields)-1],
|
||||
|
|
|
|||
|
|
@ -75,11 +75,13 @@ func (Pod) Header(ns string) HeaderRow {
|
|||
Header{Name: "NAME"},
|
||||
Header{Name: "READY"},
|
||||
Header{Name: "STATUS"},
|
||||
Header{Name: "RESTART", Align: tview.AlignRight},
|
||||
Header{Name: "RS", Align: tview.AlignRight},
|
||||
Header{Name: "CPU", Align: tview.AlignRight},
|
||||
Header{Name: "MEM", Align: tview.AlignRight},
|
||||
Header{Name: "%CPU (LIM)", Align: tview.AlignRight},
|
||||
Header{Name: "%MEM (LIM)", Align: tview.AlignRight},
|
||||
Header{Name: "%CPU", Align: tview.AlignRight},
|
||||
Header{Name: "%MEM", Align: tview.AlignRight},
|
||||
Header{Name: "%MAX_CPU", Align: tview.AlignRight},
|
||||
Header{Name: "%MAX_MEM", Align: tview.AlignRight},
|
||||
Header{Name: "IP"},
|
||||
Header{Name: "NODE"},
|
||||
Header{Name: "QOS"},
|
||||
|
|
@ -116,8 +118,10 @@ func (p Pod) Render(o interface{}, ns string, r *Row) error {
|
|||
strconv.Itoa(rc),
|
||||
c.cpu,
|
||||
c.mem,
|
||||
perc.cpu+" ("+fmt.Sprintf("%3v",perc.cpuLim)+")",
|
||||
perc.mem+" ("+fmt.Sprintf("%3v",perc.memLim)+")",
|
||||
perc.cpu,
|
||||
perc.mem,
|
||||
perc.cpuLim,
|
||||
perc.memLim,
|
||||
na(po.Status.PodIP),
|
||||
na(po.Spec.NodeName),
|
||||
p.mapQOS(po.Status.QOSClass),
|
||||
|
|
@ -158,11 +162,11 @@ func (*Pod) gatherPodMX(pod *v1.Pod, mx *mv1beta1.PodMetrics) (c, p metric) {
|
|||
mem: ToMi(ToMB(mem.Value())),
|
||||
}
|
||||
|
||||
rc, rm := requestedRes(pod)
|
||||
lc, lm := resourceLimits(pod)
|
||||
rc, rm := requestedRes(pod.Spec.Containers)
|
||||
lc, lm := resourceLimits(pod.Spec.Containers)
|
||||
p = metric{
|
||||
cpu: AsPerc(toPerc(float64(cpu.MilliValue()), float64(rc.MilliValue()))),
|
||||
mem: AsPerc(toPerc(ToMB(mem.Value()), ToMB(rm.Value()))),
|
||||
cpu: AsPerc(toPerc(float64(cpu.MilliValue()), float64(rc.MilliValue()))),
|
||||
mem: AsPerc(toPerc(ToMB(mem.Value()), ToMB(rm.Value()))),
|
||||
cpuLim: AsPerc(toPerc(float64(cpu.MilliValue()), float64(lc.MilliValue()))),
|
||||
memLim: AsPerc(toPerc(ToMB(mem.Value()), ToMB(lm.Value()))),
|
||||
}
|
||||
|
|
@ -172,7 +176,6 @@ func (*Pod) gatherPodMX(pod *v1.Pod, mx *mv1beta1.PodMetrics) (c, p metric) {
|
|||
|
||||
func containerResources(co v1.Container) (cpu, mem *resource.Quantity) {
|
||||
req, limit := co.Resources.Requests, co.Resources.Limits
|
||||
|
||||
switch {
|
||||
case len(req) != 0:
|
||||
cpu, mem = req.Cpu(), req.Memory()
|
||||
|
|
@ -183,23 +186,32 @@ func containerResources(co v1.Container) (cpu, mem *resource.Quantity) {
|
|||
return
|
||||
}
|
||||
|
||||
func resourceLimits(po *v1.Pod) (cpu, mem resource.Quantity) {
|
||||
for _, co := range po.Spec.Containers {
|
||||
func containerLimits(co v1.Container) (cpu, mem *resource.Quantity) {
|
||||
limit := co.Resources.Limits
|
||||
if len(limit) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return limit.Cpu(), limit.Memory()
|
||||
}
|
||||
|
||||
func resourceLimits(cc []v1.Container) (cpu, mem resource.Quantity) {
|
||||
for _, co := range cc {
|
||||
limit := co.Resources.Limits
|
||||
if len(limit) != 0 {
|
||||
if limit.Cpu() != nil {
|
||||
cpu.Add(*limit.Cpu())
|
||||
}
|
||||
if limit.Memory() != nil {
|
||||
mem.Add(*limit.Memory())
|
||||
}
|
||||
if len(limit) == 0 {
|
||||
continue
|
||||
}
|
||||
if limit.Cpu() != nil {
|
||||
cpu.Add(*limit.Cpu())
|
||||
}
|
||||
if limit.Memory() != nil {
|
||||
mem.Add(*limit.Memory())
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func requestedRes(po *v1.Pod) (cpu, mem resource.Quantity) {
|
||||
for _, co := range po.Spec.Containers {
|
||||
func requestedRes(cc []v1.Container) (cpu, mem resource.Quantity) {
|
||||
for _, co := range cc {
|
||||
c, m := containerResources(co)
|
||||
if c != nil {
|
||||
cpu.Add(*c)
|
||||
|
|
@ -212,6 +224,9 @@ func requestedRes(po *v1.Pod) (cpu, mem resource.Quantity) {
|
|||
}
|
||||
|
||||
func currentRes(mx *mv1beta1.PodMetrics) (cpu, mem resource.Quantity) {
|
||||
if mx == nil {
|
||||
return
|
||||
}
|
||||
for _, co := range mx.Containers {
|
||||
c, m := co.Usage.Cpu(), co.Usage.Memory()
|
||||
cpu.Add(*c)
|
||||
|
|
|
|||
|
|
@ -65,13 +65,13 @@ func TestPodRender(t *testing.T) {
|
|||
}
|
||||
|
||||
var po render.Pod
|
||||
r := render.NewRow(12)
|
||||
r := render.NewRow(14)
|
||||
err := po.Render(&pom, "", &r)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, "default/nginx", r.ID)
|
||||
e := render.Fields{"default", "nginx", "1/1", "Running", "0", "10", "10", "10 ( 0)", "14 ( 5)", "172.17.0.6", "minikube", "BE"}
|
||||
assert.Equal(t, e, r.Fields[:12])
|
||||
e := render.Fields{"default", "nginx", "1/1", "Running", "0", "10", "10", "10", "14", "0", "5", "172.17.0.6", "minikube", "BE"}
|
||||
assert.Equal(t, e, r.Fields[:14])
|
||||
}
|
||||
|
||||
func BenchmarkPodRender(b *testing.B) {
|
||||
|
|
@ -96,13 +96,13 @@ func TestPodInitRender(t *testing.T) {
|
|||
}
|
||||
|
||||
var po render.Pod
|
||||
r := render.NewRow(12)
|
||||
r := render.NewRow(14)
|
||||
err := po.Render(&pom, "", &r)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, "default/nginx", r.ID)
|
||||
e := render.Fields{"default", "nginx", "1/1", "Init:0/1", "0", "10", "10", "10 ( 0)", "14 ( 5)", "172.17.0.6", "minikube", "BE"}
|
||||
assert.Equal(t, e, r.Fields[:12])
|
||||
e := render.Fields{"default", "nginx", "1/1", "Init:0/1", "0", "10", "10", "10", "14", "0", "5", "172.17.0.6", "minikube", "BE"}
|
||||
assert.Equal(t, e, r.Fields[:14])
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ func TestHelp(t *testing.T) {
|
|||
v := view.NewHelp()
|
||||
|
||||
assert.Nil(t, v.Init(ctx))
|
||||
assert.Equal(t, 17, v.GetRowCount())
|
||||
assert.Equal(t, 19, v.GetRowCount())
|
||||
assert.Equal(t, 8, v.GetColumnCount())
|
||||
assert.Equal(t, "<ctrl-k>", strings.TrimSpace(v.GetCell(1, 0).Text))
|
||||
assert.Equal(t, "Kill", strings.TrimSpace(v.GetCell(1, 1).Text))
|
||||
|
|
|
|||
|
|
@ -48,8 +48,10 @@ func (p *Pod) bindKeys(aa ui.KeyActions) {
|
|||
ui.KeyShiftM: ui.NewKeyAction("Sort MEM", p.GetTable().SortColCmd(5, false), false),
|
||||
ui.KeyShiftX: ui.NewKeyAction("Sort CPU%", p.GetTable().SortColCmd(6, false), false),
|
||||
ui.KeyShiftZ: ui.NewKeyAction("Sort MEM%", p.GetTable().SortColCmd(7, false), false),
|
||||
ui.KeyShiftI: ui.NewKeyAction("Sort IP", p.GetTable().SortColCmd(8, true), false),
|
||||
ui.KeyShiftO: ui.NewKeyAction("Sort Node", p.GetTable().SortColCmd(9, true), false),
|
||||
tcell.KeyCtrlX: ui.NewKeyAction("Sort CPU% LIMITS", p.GetTable().SortColCmd(8, false), false),
|
||||
tcell.KeyCtrlZ: ui.NewKeyAction("Sort MEM% LIMITS", p.GetTable().SortColCmd(9, false), false),
|
||||
ui.KeyShiftI: ui.NewKeyAction("Sort IP", p.GetTable().SortColCmd(10, true), false),
|
||||
ui.KeyShiftO: ui.NewKeyAction("Sort Node", p.GetTable().SortColCmd(11, true), false),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ func TestPodNew(t *testing.T) {
|
|||
|
||||
assert.Nil(t, po.Init(makeCtx()))
|
||||
assert.Equal(t, "Pods", po.Name())
|
||||
assert.Equal(t, 16, len(po.Hints()))
|
||||
assert.Equal(t, 18, len(po.Hints()))
|
||||
}
|
||||
|
||||
// Helpers...
|
||||
|
|
|
|||
Loading…
Reference in New Issue