Skip to content

Commit

Permalink
refactoring table printer, container output working
Browse files Browse the repository at this point in the history
  • Loading branch information
robscott committed Apr 1, 2019
1 parent 476062a commit 6e9106a
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 166 deletions.
11 changes: 6 additions & 5 deletions pkg/capacity/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ type podMetric struct {
namespace string
cpu *resourceMetric
memory *resourceMetric
containers []containerMetric
containers []*containerMetric
}

type containerMetric struct {
Expand Down Expand Up @@ -82,11 +82,11 @@ func (cm *clusterMetric) addPodMetric(pod *corev1.Pod, podMetrics v1beta1.PodMet
request: req["memory"],
limit: limit["memory"],
},
containers: []containerMetric{},
containers: []*containerMetric{},
}

for _, container := range pod.Spec.Containers {
pm.containers = append(pm.containers, containerMetric{
pm.containers = append(pm.containers, &containerMetric{
name: container.Name,
cpu: &resourceMetric{
resourceType: "cpu",
Expand Down Expand Up @@ -159,9 +159,10 @@ func resourceString(actual, allocatable resource.Quantity, resourceType string)
}

if resourceType == "cpu" {
return fmt.Sprintf("%dm (%d%%)", actual.MilliValue(), int64(utilPercent))
return fmt.Sprintf("%dm (%d", actual.MilliValue(), int64(utilPercent)) + "%%)"
}
return fmt.Sprintf("%dMi (%d%%)", actual.Value()/1048576, int64(utilPercent))

return fmt.Sprintf("%dMi (%d", actual.Value()/1048576, int64(utilPercent)) + "%%)"
}

// NOTE: This might not be a great place for closures due to the cyclical nature of how resourceType works. Perhaps better implemented another way.
Expand Down
302 changes: 141 additions & 161 deletions pkg/capacity/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"fmt"
"os"
"sort"
"strings"
"text/tabwriter"
)

Expand All @@ -29,198 +30,177 @@ type tablePrinter struct {
w *tabwriter.Writer
}

type tableLine struct {
node string
namespace string
pod string
container string
cpuRequests string
cpuLimits string
cpuUtil string
memoryRequests string
memoryLimits string
memoryUtil string
}

var headerStrings = tableLine{
node: "NODE",
namespace: "NAMESPACE",
pod: "POD",
container: "CONTAINER",
cpuRequests: "CPU REQUESTS",
cpuLimits: "CPU LIMITS",
cpuUtil: "CPU UTIL",
memoryRequests: "MEMORY REQUESTS",
memoryLimits: "MEMORY LIMITS",
memoryUtil: "MEMORY UTIL",
}

func (tp *tablePrinter) Print() {
tp.w.Init(os.Stdout, 0, 8, 2, ' ', 0)
names := make([]string, len(tp.cm.nodeMetrics))
nodeNames := getSortedNodeNames(tp.cm.nodeMetrics)

i := 0
for name := range tp.cm.nodeMetrics {
names[i] = name
i++
}
sort.Strings(names)
tp.printLine(&headerStrings)

tp.printHeaders()
if len(nodeNames) > 1 {
tp.printClusterLine()
tp.printLine(&tableLine{})
}

for _, name := range names {
tp.printNode(name, tp.cm.nodeMetrics[name])
for _, nodeName := range nodeNames {
nm := tp.cm.nodeMetrics[nodeName]
tp.printNodeLine(nodeName, nm)
tp.printLine(&tableLine{})

podNames := getSortedPodNames(nm.podMetrics)
if tp.showPods || tp.showContainers {
for _, podName := range podNames {
pm := nm.podMetrics[podName]
tp.printPodLine(nodeName, pm)
if tp.showContainers {
for _, containerMetric := range pm.containers {
tp.printContainerLine(nodeName, pm, containerMetric)
}
}
}
}
}

tp.w.Flush()
}

func (tp *tablePrinter) printHeaders() {
if tp.showContainers && tp.showUtil {
fmt.Fprintln(tp.w, "NODE\t NAMESPACE\t POD\t CONTAINER \t CPU REQUESTS \t CPU LIMITS \t CPU UTIL \t MEMORY REQUESTS \t MEMORY LIMITS \t MEMORY UTIL")
func (tp *tablePrinter) printLine(tl *tableLine) {
lineItems := []string{tl.node, tl.namespace}

if len(tp.cm.nodeMetrics) > 1 {
fmt.Fprintf(tp.w, "* \t *\t *\t *\t %s \t %s \t %s \t %s \t %s \t %s \n",
tp.cm.cpu.requestString(),
tp.cm.cpu.limitString(),
tp.cm.cpu.utilString(),
tp.cm.memory.requestString(),
tp.cm.memory.limitString(),
tp.cm.memory.utilString())
if tp.showContainers || tp.showPods {
lineItems = append(lineItems, tl.pod)
}

fmt.Fprintln(tp.w, "\t\t\t\t\t\t\t\t\t")
}
if tp.showContainers {
lineItems = append(lineItems, tl.container)
}

} else if tp.showContainers && tp.showUtil {
fmt.Fprintln(tp.w, "NODE\t NAMESPACE\t POD\t CONTAINER\t CPU REQUESTS \t CPU LIMITS \t MEMORY REQUESTS \t MEMORY LIMITS")
lineItems = append(lineItems, tl.cpuRequests)
lineItems = append(lineItems, tl.cpuLimits)

fmt.Fprintf(tp.w, "* \t *\t *\t *\t %s \t %s \t %s \t %s \n",
tp.cm.cpu.requestString(),
tp.cm.cpu.limitString(),
tp.cm.memory.requestString(),
tp.cm.memory.limitString())
if tp.showUtil {
lineItems = append(lineItems, tl.cpuUtil)
}

fmt.Fprintln(tp.w, "\t\t\t\t\t\t\t")
lineItems = append(lineItems, tl.memoryRequests)
lineItems = append(lineItems, tl.memoryLimits)

} else if tp.showPods && tp.showUtil {
fmt.Fprintln(tp.w, "NODE\t NAMESPACE\t POD\t CPU REQUESTS \t CPU LIMITS \t CPU UTIL \t MEMORY REQUESTS \t MEMORY LIMITS \t MEMORY UTIL")
if tp.showUtil {
lineItems = append(lineItems, tl.memoryUtil)
}

if len(tp.cm.nodeMetrics) > 1 {
fmt.Fprintf(tp.w, "* \t *\t *\t %s \t %s \t %s \t %s \t %s \t %s \n",
tp.cm.cpu.requestString(),
tp.cm.cpu.limitString(),
tp.cm.cpu.utilString(),
tp.cm.memory.requestString(),
tp.cm.memory.limitString(),
tp.cm.memory.utilString())
fmt.Fprintf(tp.w, strings.Join(lineItems[:], "\t ")+"\n")
}

fmt.Fprintln(tp.w, "\t\t\t\t\t\t\t\t")
}
func (tp *tablePrinter) printClusterLine() {
tp.printLine(&tableLine{
node: "*",
namespace: "*",
pod: "*",
container: "*",
cpuRequests: tp.cm.cpu.requestString(),
cpuLimits: tp.cm.cpu.limitString(),
cpuUtil: tp.cm.cpu.utilString(),
memoryRequests: tp.cm.memory.requestString(),
memoryLimits: tp.cm.memory.limitString(),
memoryUtil: tp.cm.memory.utilString(),
})
}

} else if tp.showPods {
fmt.Fprintln(tp.w, "NODE\t NAMESPACE\t POD\t CPU REQUESTS \t CPU LIMITS \t MEMORY REQUESTS \t MEMORY LIMITS")
func (tp *tablePrinter) printNodeLine(nodeName string, nm *nodeMetric) {
tp.printLine(&tableLine{
node: nodeName,
namespace: "*",
pod: "*",
container: "*",
cpuRequests: nm.cpu.requestString(),
cpuLimits: nm.cpu.limitString(),
cpuUtil: nm.cpu.utilString(),
memoryRequests: nm.memory.requestString(),
memoryLimits: nm.memory.limitString(),
memoryUtil: nm.memory.utilString(),
})
}

fmt.Fprintf(tp.w, "* \t *\t *\t %s \t %s \t %s \t %s \n",
tp.cm.cpu.requestString(),
tp.cm.cpu.limitString(),
tp.cm.memory.requestString(),
tp.cm.memory.limitString())
func (tp *tablePrinter) printPodLine(nodeName string, pm *podMetric) {
tp.printLine(&tableLine{
node: nodeName,
namespace: pm.namespace,
pod: pm.name,
container: "*",
cpuRequests: pm.cpu.requestString(),
cpuLimits: pm.cpu.limitString(),
cpuUtil: pm.cpu.utilString(),
memoryRequests: pm.memory.requestString(),
memoryLimits: pm.memory.limitString(),
memoryUtil: pm.memory.utilString(),
})
}

fmt.Fprintln(tp.w, "\t\t\t\t\t\t")
func (tp *tablePrinter) printContainerLine(nodeName string, pm *podMetric, cm *containerMetric) {
tp.printLine(&tableLine{
node: nodeName,
namespace: pm.namespace,
pod: pm.name,
container: cm.name,
cpuRequests: cm.cpu.requestString(),
cpuLimits: cm.cpu.limitString(),
cpuUtil: "",
memoryRequests: cm.memory.requestString(),
memoryLimits: cm.memory.limitString(),
memoryUtil: "",
})
}

} else if tp.showUtil {
fmt.Fprintln(tp.w, "NODE\t CPU REQUESTS \t CPU LIMITS \t CPU UTIL \t MEMORY REQUESTS \t MEMORY LIMITS \t MEMORY UTIL")
func getSortedNodeNames(nodeMetrics map[string]*nodeMetric) []string {
sortedNames := make([]string, len(nodeMetrics))

fmt.Fprintf(tp.w, "* \t %s \t %s \t %s \t %s \t %s \t %s \n",
tp.cm.cpu.requestString(),
tp.cm.cpu.limitString(),
tp.cm.cpu.utilString(),
tp.cm.memory.requestString(),
tp.cm.memory.limitString(),
tp.cm.memory.utilString())
i := 0
for name := range nodeMetrics {
sortedNames[i] = name
i++
}

} else {
fmt.Fprintln(tp.w, "NODE\t CPU REQUESTS \t CPU LIMITS \t MEMORY REQUESTS \t MEMORY LIMITS")
sort.Strings(sortedNames)

if len(tp.cm.nodeMetrics) > 1 {
fmt.Fprintf(tp.w, "* \t %s \t %s \t %s \t %s \n",
tp.cm.cpu.requestString(), tp.cm.cpu.limitString(),
tp.cm.memory.requestString(), tp.cm.memory.limitString())
}
}
return sortedNames
}

func (tp *tablePrinter) printNode(name string, nm *nodeMetric) {
podNames := make([]string, len(nm.podMetrics))
func getSortedPodNames(podMetrics map[string]*podMetric) []string {
sortedNames := make([]string, len(podMetrics))

i := 0
for name := range nm.podMetrics {
podNames[i] = name
for name := range podMetrics {
sortedNames[i] = name
i++
}
sort.Strings(podNames)

if tp.showContainers && tp.showUtil {
fmt.Fprintf(tp.w, "%s \t *\t *\t *\t %s \t %s \t %s \t %s \t %s \t %s \n",
name,
nm.cpu.requestString(),
nm.cpu.limitString(),
nm.cpu.utilString(),
nm.memory.requestString(),
nm.memory.limitString(),
nm.memory.utilString())

for _, podName := range podNames {
pm := nm.podMetrics[podName]
fmt.Fprintf(tp.w, "%s \t %s \t %s \t %s \t %s \t %s \t %s \t %s \t %s \n",
name,
pm.namespace,
pm.name,
pm.cpu.requestString(),
pm.cpu.limitString(),
pm.cpu.utilString(),
pm.memory.requestString(),
pm.memory.limitString(),
pm.memory.utilString())
}

fmt.Fprintln(tp.w, "\t\t\t\t\t\t\t\t")

} else if tp.showPods && tp.showUtil {
fmt.Fprintf(tp.w, "%s \t *\t *\t %s \t %s \t %s \t %s \t %s \t %s \n",
name,
nm.cpu.requestString(),
nm.cpu.limitString(),
nm.cpu.utilString(),
nm.memory.requestString(),
nm.memory.limitString(),
nm.memory.utilString())

for _, podName := range podNames {
pm := nm.podMetrics[podName]
fmt.Fprintf(tp.w, "%s \t %s \t %s \t %s \t %s \t %s \t %s \t %s \t %s \n",
name,
pm.namespace,
pm.name,
pm.cpu.requestString(),
pm.cpu.limitString(),
pm.cpu.utilString(),
pm.memory.requestString(),
pm.memory.limitString(),
pm.memory.utilString())
}
sort.Strings(sortedNames)

fmt.Fprintln(tp.w, "\t\t\t\t\t\t\t\t")

} else if tp.showPods {
fmt.Fprintf(tp.w, "%s \t *\t *\t %s \t %s \t %s \t %s \n",
name,
nm.cpu.requestString(),
nm.cpu.limitString(),
nm.memory.requestString(),
nm.memory.limitString())

for _, podName := range podNames {
pm := nm.podMetrics[podName]
fmt.Fprintf(tp.w, "%s \t %s \t %s \t %s \t %s \t %s \t %s \n",
name,
pm.namespace,
pm.name,
pm.cpu.requestString(),
pm.cpu.limitString(),
pm.memory.requestString(),
pm.memory.limitString())
}

fmt.Fprintln(tp.w, "\t\t\t\t\t\t")

} else if tp.showUtil {
fmt.Fprintf(tp.w, "%s \t %s \t %s \t %s \t %s \t %s \t %s \n",
name,
nm.cpu.requestString(),
nm.cpu.limitString(),
nm.cpu.utilString(),
nm.memory.requestString(),
nm.memory.limitString(),
nm.memory.utilString())

} else {
fmt.Fprintf(tp.w, "%s \t %s \t %s \t %s \t %s \n", name,
nm.cpu.requestString(), nm.cpu.limitString(),
nm.memory.requestString(), nm.memory.limitString())
}
return sortedNames
}

0 comments on commit 6e9106a

Please sign in to comment.