Skip to content

Commit

Permalink
work in progress on container output support
Browse files Browse the repository at this point in the history
  • Loading branch information
robscott committed Apr 1, 2019
1 parent 6e4f348 commit 476062a
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 39 deletions.
4 changes: 2 additions & 2 deletions pkg/capacity/capacity.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
)

// FetchAndPrint gathers cluster resource data and outputs it
func FetchAndPrint(showPods, showUtil bool, podLabels, nodeLabels, namespaceLabels, kubeContext string, output string) {
func FetchAndPrint(showContainers, showPods, showUtil bool, podLabels, nodeLabels, namespaceLabels, kubeContext string, output string) {
clientset, err := kube.NewClientSet(kubeContext)
if err != nil {
fmt.Printf("Error connecting to Kubernetes: %v\n", err)
Expand All @@ -48,7 +48,7 @@ func FetchAndPrint(showPods, showUtil bool, podLabels, nodeLabels, namespaceLabe
}

cm := buildClusterMetric(podList, pmList, nodeList)
printList(&cm, showPods, showUtil, output)
printList(&cm, showContainers, showPods, showUtil, output)
}

func getPodsAndNodes(clientset kubernetes.Interface, podLabels, nodeLabels, namespaceLabels string) (*corev1.PodList, *corev1.NodeList) {
Expand Down
55 changes: 37 additions & 18 deletions pkg/capacity/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,17 @@ type listNodeMetric struct {
}

type listPod struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
CPU *listResourceOutput `json:"cpu"`
Memory *listResourceOutput `json:"memory"`
Name string `json:"name"`
Namespace string `json:"namespace"`
CPU *listResourceOutput `json:"cpu"`
Memory *listResourceOutput `json:"memory"`
Containers []listContainer `json:"containers"`
}

type listContainer struct {
Name string `json:"name"`
CPU *listResourceOutput `json:"cpu"`
Memory *listResourceOutput `json:"memory"`
}

type listResourceOutput struct {
Expand All @@ -53,9 +60,10 @@ type listClusterMetrics struct {
}

type listPrinter struct {
cm *clusterMetric
showPods bool
showUtil bool
cm *clusterMetric
showPods bool
showContainers bool
showUtil bool
}

func (lp listPrinter) Print(outputType string) {
Expand Down Expand Up @@ -89,19 +97,30 @@ func (lp *listPrinter) buildListClusterMetrics() listClusterMetrics {
response.ClusterTotals.CPU = lp.buildListResourceOutput(lp.cm.cpu)
response.ClusterTotals.Memory = lp.buildListResourceOutput(lp.cm.memory)

for key, val := range lp.cm.nodeMetrics {
for key, nodeMetric := range lp.cm.nodeMetrics {
var node listNodeMetric
node.Name = key
node.CPU = lp.buildListResourceOutput(val.cpu)
node.Memory = lp.buildListResourceOutput(val.memory)
if lp.showPods {
for _, val := range val.podMetrics {
var newNode listPod
newNode.Name = val.name
newNode.Namespace = val.namespace
newNode.CPU = lp.buildListResourceOutput(val.cpu)
newNode.Memory = lp.buildListResourceOutput(val.memory)
node.Pods = append(node.Pods, &newNode)
node.CPU = lp.buildListResourceOutput(nodeMetric.cpu)
node.Memory = lp.buildListResourceOutput(nodeMetric.memory)

if lp.showPods || lp.showContainers {
for _, podMetric := range nodeMetric.podMetrics {
var pod listPod
pod.Name = podMetric.name
pod.Namespace = podMetric.namespace
pod.CPU = lp.buildListResourceOutput(podMetric.cpu)
pod.Memory = lp.buildListResourceOutput(podMetric.memory)

if lp.showContainers {
for _, containerMetric := range podMetric.containers {
pod.Containers = append(pod.Containers, listContainer{
Name: containerMetric.name,
Memory: lp.buildListResourceOutput(containerMetric.memory),
CPU: lp.buildListResourceOutput(containerMetric.cpu),
})
}
}
node.Pods = append(node.Pods, &pod)
}
}
response.Nodes = append(response.Nodes, &node)
Expand Down
18 changes: 10 additions & 8 deletions pkg/capacity/printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,22 @@ func SupportedOutputs() []string {
}
}

func printList(cm *clusterMetric, showPods bool, showUtil bool, output string) {
func printList(cm *clusterMetric, showContainers bool, showPods bool, showUtil bool, output string) {
if output == JSONOutput || output == YAMLOutput {
lp := &listPrinter{
cm: cm,
showPods: showPods,
showUtil: showUtil,
cm: cm,
showPods: showPods,
showUtil: showUtil,
showContainers: showContainers,
}
lp.Print(output)
} else if output == TableOutput {
tp := &tablePrinter{
cm: cm,
showPods: showPods,
showUtil: showUtil,
w: new(tabwriter.Writer),
cm: cm,
showPods: showPods,
showUtil: showUtil,
showContainers: showContainers,
w: new(tabwriter.Writer),
}
tp.Print()
} else {
Expand Down
33 changes: 29 additions & 4 deletions pkg/capacity/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,17 @@ type nodeMetric struct {
}

type podMetric struct {
name string
namespace string
cpu *resourceMetric
memory *resourceMetric
name string
namespace string
cpu *resourceMetric
memory *resourceMetric
containers []containerMetric
}

type containerMetric struct {
name string
cpu *resourceMetric
memory *resourceMetric
}

func (rm *resourceMetric) addMetric(m *resourceMetric) {
Expand All @@ -75,7 +82,25 @@ func (cm *clusterMetric) addPodMetric(pod *corev1.Pod, podMetrics v1beta1.PodMet
request: req["memory"],
limit: limit["memory"],
},
containers: []containerMetric{},
}

for _, container := range pod.Spec.Containers {
pm.containers = append(pm.containers, containerMetric{
name: container.Name,
cpu: &resourceMetric{
resourceType: "cpu",
request: container.Resources.Requests["cpu"],
limit: container.Resources.Limits["cpu"],
},
memory: &resourceMetric{
resourceType: "memory",
request: container.Resources.Requests["memory"],
limit: container.Resources.Limits["memory"],
},
})
}

cm.podMetrics[key] = pm

nm := cm.nodeMetrics[pod.Spec.NodeName]
Expand Down
66 changes: 60 additions & 6 deletions pkg/capacity/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ import (
)

type tablePrinter struct {
cm *clusterMetric
showPods bool
showUtil bool
w *tabwriter.Writer
cm *clusterMetric
showPods bool
showUtil bool
showContainers bool
w *tabwriter.Writer
}

func (tp *tablePrinter) Print() {
Expand All @@ -49,7 +50,33 @@ func (tp *tablePrinter) Print() {
}

func (tp *tablePrinter) printHeaders() {
if tp.showPods && tp.showUtil {
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")

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())

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

} 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")

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())

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

} 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 len(tp.cm.nodeMetrics) > 1 {
Expand All @@ -63,6 +90,7 @@ func (tp *tablePrinter) printHeaders() {

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

} 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")

Expand Down Expand Up @@ -106,7 +134,33 @@ func (tp *tablePrinter) printNode(name string, nm *nodeMetric) {
}
sort.Strings(podNames)

if tp.showPods && tp.showUtil {
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(),
Expand Down
4 changes: 3 additions & 1 deletion pkg/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/spf13/cobra"
)

var showContainers bool
var showPods bool
var showUtil bool
var podLabels string
Expand All @@ -44,11 +45,12 @@ var rootCmd = &cobra.Command{
os.Exit(1)
}

capacity.FetchAndPrint(showPods, showUtil, podLabels, nodeLabels, namespaceLabels, kubeContext, outputFormat)
capacity.FetchAndPrint(showContainers, showPods, showUtil, podLabels, nodeLabels, namespaceLabels, kubeContext, outputFormat)
},
}

func init() {
rootCmd.PersistentFlags().BoolVarP(&showContainers, "containers", "c", false, "includes containers in output")
rootCmd.PersistentFlags().BoolVarP(&showPods, "pods", "p", false, "includes pods in output")
rootCmd.PersistentFlags().BoolVarP(&showUtil, "util", "u", false, "includes resource utilization in output")
rootCmd.PersistentFlags().StringVarP(&podLabels, "pod-labels", "l", "", "labels to filter pods with")
Expand Down

0 comments on commit 476062a

Please sign in to comment.