Added --sum flag to kubectl top pod
Kubernetes-commit: 71acf56766c966653c3d1fe0ef6f3f036277d546
This commit is contained in:
parent
472713ca0c
commit
7254bd442d
|
@ -22,7 +22,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/fields"
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
|
@ -52,6 +52,7 @@ type TopPodOptions struct {
|
||||||
PrintContainers bool
|
PrintContainers bool
|
||||||
NoHeaders bool
|
NoHeaders bool
|
||||||
UseProtocolBuffers bool
|
UseProtocolBuffers bool
|
||||||
|
Sum bool
|
||||||
|
|
||||||
PodClient corev1client.PodsGetter
|
PodClient corev1client.PodsGetter
|
||||||
Printer *metricsutil.TopCmdPrinter
|
Printer *metricsutil.TopCmdPrinter
|
||||||
|
@ -115,6 +116,7 @@ func NewCmdTopPod(f cmdutil.Factory, o *TopPodOptions, streams genericclioptions
|
||||||
cmd.Flags().BoolVarP(&o.AllNamespaces, "all-namespaces", "A", o.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.")
|
cmd.Flags().BoolVarP(&o.AllNamespaces, "all-namespaces", "A", o.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.")
|
||||||
cmd.Flags().BoolVar(&o.NoHeaders, "no-headers", o.NoHeaders, "If present, print output without headers.")
|
cmd.Flags().BoolVar(&o.NoHeaders, "no-headers", o.NoHeaders, "If present, print output without headers.")
|
||||||
cmd.Flags().BoolVar(&o.UseProtocolBuffers, "use-protocol-buffers", o.UseProtocolBuffers, "Enables using protocol-buffers to access Metrics API.")
|
cmd.Flags().BoolVar(&o.UseProtocolBuffers, "use-protocol-buffers", o.UseProtocolBuffers, "Enables using protocol-buffers to access Metrics API.")
|
||||||
|
cmd.Flags().BoolVar(&o.Sum, "sum", o.Sum, "Print the sum of the resource usage")
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +217,7 @@ func (o TopPodOptions) RunTopPod() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return o.Printer.PrintPodMetrics(metrics.Items, o.PrintContainers, o.AllNamespaces, o.NoHeaders, o.SortBy)
|
return o.Printer.PrintPodMetrics(metrics.Items, o.PrintContainers, o.AllNamespaces, o.NoHeaders, o.SortBy, o.Sum)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMetricsFromMetricsAPI(metricsClient metricsclientset.Interface, namespace, resourceName string, allNamespaces bool, labelSelector labels.Selector, fieldSelector fields.Selector) (*metricsapi.PodMetricsList, error) {
|
func getMetricsFromMetricsAPI(metricsClient metricsclientset.Interface, namespace, resourceName string, allNamespaces bool, labelSelector labels.Selector, fieldSelector fields.Selector) (*metricsapi.PodMetricsList, error) {
|
||||||
|
@ -274,7 +276,7 @@ func verifyEmptyMetrics(o TopPodOptions, labelSelector labels.Selector, fieldSel
|
||||||
return errors.New("metrics not available yet")
|
return errors.New("metrics not available yet")
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkPodAge(pod *v1.Pod) error {
|
func checkPodAge(pod *corev1.Pod) error {
|
||||||
age := time.Since(pod.CreationTimestamp.Time)
|
age := time.Since(pod.CreationTimestamp.Time)
|
||||||
if age > metricsCreationDelay {
|
if age > metricsCreationDelay {
|
||||||
message := fmt.Sprintf("Metrics not available for pod %s/%s, age: %s", pod.Namespace, pod.Name, age.String())
|
message := fmt.Sprintf("Metrics not available for pod %s/%s, age: %s", pod.Namespace, pod.Name, age.String())
|
||||||
|
|
|
@ -52,114 +52,6 @@ func NewTopCmdPrinter(out io.Writer) *TopCmdPrinter {
|
||||||
return &TopCmdPrinter{out: out}
|
return &TopCmdPrinter{out: out}
|
||||||
}
|
}
|
||||||
|
|
||||||
type NodeMetricsSorter struct {
|
|
||||||
metrics []metricsapi.NodeMetrics
|
|
||||||
sortBy string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NodeMetricsSorter) Len() int {
|
|
||||||
return len(n.metrics)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NodeMetricsSorter) Swap(i, j int) {
|
|
||||||
n.metrics[i], n.metrics[j] = n.metrics[j], n.metrics[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NodeMetricsSorter) Less(i, j int) bool {
|
|
||||||
switch n.sortBy {
|
|
||||||
case "cpu":
|
|
||||||
return n.metrics[i].Usage.Cpu().MilliValue() > n.metrics[j].Usage.Cpu().MilliValue()
|
|
||||||
case "memory":
|
|
||||||
return n.metrics[i].Usage.Memory().Value() > n.metrics[j].Usage.Memory().Value()
|
|
||||||
default:
|
|
||||||
return n.metrics[i].Name < n.metrics[j].Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewNodeMetricsSorter(metrics []metricsapi.NodeMetrics, sortBy string) *NodeMetricsSorter {
|
|
||||||
return &NodeMetricsSorter{
|
|
||||||
metrics: metrics,
|
|
||||||
sortBy: sortBy,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type PodMetricsSorter struct {
|
|
||||||
metrics []metricsapi.PodMetrics
|
|
||||||
sortBy string
|
|
||||||
withNamespace bool
|
|
||||||
podMetrics []v1.ResourceList
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PodMetricsSorter) Len() int {
|
|
||||||
return len(p.metrics)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PodMetricsSorter) Swap(i, j int) {
|
|
||||||
p.metrics[i], p.metrics[j] = p.metrics[j], p.metrics[i]
|
|
||||||
p.podMetrics[i], p.podMetrics[j] = p.podMetrics[j], p.podMetrics[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PodMetricsSorter) Less(i, j int) bool {
|
|
||||||
switch p.sortBy {
|
|
||||||
case "cpu":
|
|
||||||
return p.podMetrics[i].Cpu().MilliValue() > p.podMetrics[j].Cpu().MilliValue()
|
|
||||||
case "memory":
|
|
||||||
return p.podMetrics[i].Memory().Value() > p.podMetrics[j].Memory().Value()
|
|
||||||
default:
|
|
||||||
if p.withNamespace && p.metrics[i].Namespace != p.metrics[j].Namespace {
|
|
||||||
return p.metrics[i].Namespace < p.metrics[j].Namespace
|
|
||||||
}
|
|
||||||
return p.metrics[i].Name < p.metrics[j].Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewPodMetricsSorter(metrics []metricsapi.PodMetrics, withNamespace bool, sortBy string) *PodMetricsSorter {
|
|
||||||
var podMetrics = make([]v1.ResourceList, len(metrics))
|
|
||||||
if len(sortBy) > 0 {
|
|
||||||
for i, v := range metrics {
|
|
||||||
podMetrics[i] = getPodMetrics(&v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &PodMetricsSorter{
|
|
||||||
metrics: metrics,
|
|
||||||
sortBy: sortBy,
|
|
||||||
withNamespace: withNamespace,
|
|
||||||
podMetrics: podMetrics,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type ContainerMetricsSorter struct {
|
|
||||||
metrics []metricsapi.ContainerMetrics
|
|
||||||
sortBy string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ContainerMetricsSorter) Len() int {
|
|
||||||
return len(s.metrics)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ContainerMetricsSorter) Swap(i, j int) {
|
|
||||||
s.metrics[i], s.metrics[j] = s.metrics[j], s.metrics[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ContainerMetricsSorter) Less(i, j int) bool {
|
|
||||||
switch s.sortBy {
|
|
||||||
case "cpu":
|
|
||||||
return s.metrics[i].Usage.Cpu().MilliValue() > s.metrics[j].Usage.Cpu().MilliValue()
|
|
||||||
case "memory":
|
|
||||||
return s.metrics[i].Usage.Memory().Value() > s.metrics[j].Usage.Memory().Value()
|
|
||||||
default:
|
|
||||||
return s.metrics[i].Name < s.metrics[j].Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewContainerMetricsSorter(metrics []metricsapi.ContainerMetrics, sortBy string) *ContainerMetricsSorter {
|
|
||||||
return &ContainerMetricsSorter{
|
|
||||||
metrics: metrics,
|
|
||||||
sortBy: sortBy,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (printer *TopCmdPrinter) PrintNodeMetrics(metrics []metricsapi.NodeMetrics, availableResources map[string]v1.ResourceList, noHeaders bool, sortBy string) error {
|
func (printer *TopCmdPrinter) PrintNodeMetrics(metrics []metricsapi.NodeMetrics, availableResources map[string]v1.ResourceList, noHeaders bool, sortBy string) error {
|
||||||
if len(metrics) == 0 {
|
if len(metrics) == 0 {
|
||||||
return nil
|
return nil
|
||||||
|
@ -190,18 +82,22 @@ func (printer *TopCmdPrinter) PrintNodeMetrics(metrics []metricsapi.NodeMetrics,
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (printer *TopCmdPrinter) PrintPodMetrics(metrics []metricsapi.PodMetrics, printContainers bool, withNamespace bool, noHeaders bool, sortBy string) error {
|
func (printer *TopCmdPrinter) PrintPodMetrics(metrics []metricsapi.PodMetrics, printContainers bool, withNamespace bool, noHeaders bool, sortBy string, sum bool) error {
|
||||||
if len(metrics) == 0 {
|
if len(metrics) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
w := printers.GetNewTabWriter(printer.out)
|
w := printers.GetNewTabWriter(printer.out)
|
||||||
defer w.Flush()
|
defer w.Flush()
|
||||||
|
|
||||||
|
columnWidth := len(PodColumns)
|
||||||
if !noHeaders {
|
if !noHeaders {
|
||||||
if withNamespace {
|
if withNamespace {
|
||||||
printValue(w, NamespaceColumn)
|
printValue(w, NamespaceColumn)
|
||||||
|
columnWidth++
|
||||||
}
|
}
|
||||||
if printContainers {
|
if printContainers {
|
||||||
printValue(w, PodColumn)
|
printValue(w, PodColumn)
|
||||||
|
columnWidth++
|
||||||
}
|
}
|
||||||
printColumnNames(w, PodColumns)
|
printColumnNames(w, PodColumns)
|
||||||
}
|
}
|
||||||
|
@ -215,7 +111,17 @@ func (printer *TopCmdPrinter) PrintPodMetrics(metrics []metricsapi.PodMetrics, p
|
||||||
} else {
|
} else {
|
||||||
printSinglePodMetrics(w, &m, withNamespace)
|
printSinglePodMetrics(w, &m, withNamespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sum {
|
||||||
|
adder := NewResourceAdder(MeasuredResources)
|
||||||
|
for _, m := range metrics {
|
||||||
|
adder.AddPodMetrics(&m)
|
||||||
|
}
|
||||||
|
printPodResourcesSum(w, adder.total, columnWidth)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,3 +216,21 @@ func printSingleResourceUsage(out io.Writer, resourceType v1.ResourceName, quant
|
||||||
fmt.Fprintf(out, "%v", quantity.Value())
|
fmt.Fprintf(out, "%v", quantity.Value())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printPodResourcesSum(out io.Writer, total v1.ResourceList, columnWidth int) {
|
||||||
|
for i := 0; i < columnWidth-2; i++ {
|
||||||
|
printValue(out, "")
|
||||||
|
}
|
||||||
|
printValue(out, "________")
|
||||||
|
printValue(out, "________")
|
||||||
|
fmt.Fprintf(out, "\n")
|
||||||
|
for i := 0; i < columnWidth-3; i++ {
|
||||||
|
printValue(out, "")
|
||||||
|
}
|
||||||
|
printMetricsLine(out, &ResourceMetricsInfo{
|
||||||
|
Name: "",
|
||||||
|
Metrics: total,
|
||||||
|
Available: v1.ResourceList{},
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package metricsutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metricsapi "k8s.io/metrics/pkg/apis/metrics"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ResourceAdder struct {
|
||||||
|
resources []corev1.ResourceName
|
||||||
|
total corev1.ResourceList
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewResourceAdder(resources []corev1.ResourceName) *ResourceAdder {
|
||||||
|
return &ResourceAdder{
|
||||||
|
resources: resources,
|
||||||
|
total: make(corev1.ResourceList),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddPodMetrics adds each pod metric to the total
|
||||||
|
func (adder *ResourceAdder) AddPodMetrics(m *metricsapi.PodMetrics) {
|
||||||
|
for _, c := range m.Containers {
|
||||||
|
for _, res := range adder.resources {
|
||||||
|
total := adder.total[res]
|
||||||
|
total.Add(c.Usage[res])
|
||||||
|
adder.total[res] = total
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package metricsutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
|
"k8s.io/metrics/pkg/apis/metrics"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getResourceQuantity(t *testing.T, quantityStr string) resource.Quantity {
|
||||||
|
t.Helper()
|
||||||
|
var err error
|
||||||
|
quantity, err := resource.ParseQuantity("0")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed when parsing 0 into resource.Quantity")
|
||||||
|
}
|
||||||
|
if quantityStr != "" {
|
||||||
|
quantity, err = resource.ParseQuantity(quantityStr)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%s is not a valid resource value", quantityStr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return quantity
|
||||||
|
}
|
||||||
|
|
||||||
|
func addContainerMetricsToPodMetrics(t *testing.T, podMetrics *metrics.PodMetrics, cpuUsage, memUsage string) {
|
||||||
|
t.Helper()
|
||||||
|
containerMetrics := metrics.ContainerMetrics{
|
||||||
|
Usage: corev1.ResourceList{},
|
||||||
|
}
|
||||||
|
|
||||||
|
containerMetrics.Usage["cpu"] = getResourceQuantity(t, cpuUsage)
|
||||||
|
containerMetrics.Usage["memory"] = getResourceQuantity(t, memUsage)
|
||||||
|
|
||||||
|
podMetrics.Containers = append(podMetrics.Containers, containerMetrics)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initResourceAdder() *ResourceAdder {
|
||||||
|
resources := []corev1.ResourceName{
|
||||||
|
corev1.ResourceCPU,
|
||||||
|
corev1.ResourceMemory,
|
||||||
|
}
|
||||||
|
return NewResourceAdder(resources)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddPodMetrics(t *testing.T) {
|
||||||
|
resourceAdder := initResourceAdder()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
cpuUsage string
|
||||||
|
memUsage string
|
||||||
|
expectedCpuUsage resource.Quantity
|
||||||
|
expectedMemUsage resource.Quantity
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "initial value",
|
||||||
|
cpuUsage: "0",
|
||||||
|
memUsage: "0",
|
||||||
|
expectedCpuUsage: getResourceQuantity(t, "0"),
|
||||||
|
expectedMemUsage: getResourceQuantity(t, "0"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "add first container metric",
|
||||||
|
cpuUsage: "1m",
|
||||||
|
memUsage: "10Mi",
|
||||||
|
expectedCpuUsage: getResourceQuantity(t, "1m"),
|
||||||
|
expectedMemUsage: getResourceQuantity(t, "10Mi"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "add second container metric",
|
||||||
|
cpuUsage: "5m",
|
||||||
|
memUsage: "25Mi",
|
||||||
|
expectedCpuUsage: getResourceQuantity(t, "6m"),
|
||||||
|
expectedMemUsage: getResourceQuantity(t, "35Mi"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "add third container zero metric",
|
||||||
|
cpuUsage: "0m",
|
||||||
|
memUsage: "0Mi",
|
||||||
|
expectedCpuUsage: getResourceQuantity(t, "6m"),
|
||||||
|
expectedMemUsage: getResourceQuantity(t, "35Mi"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
podMetrics := metrics.PodMetrics{}
|
||||||
|
addContainerMetricsToPodMetrics(t, &podMetrics, test.cpuUsage, test.memUsage)
|
||||||
|
|
||||||
|
resourceAdder.AddPodMetrics(&podMetrics)
|
||||||
|
cpuUsage := resourceAdder.total["cpu"]
|
||||||
|
memUsage := resourceAdder.total["memory"]
|
||||||
|
|
||||||
|
if !test.expectedCpuUsage.Equal(cpuUsage) {
|
||||||
|
t.Errorf("expecting cpu usage %s but getting %s", test.expectedCpuUsage.String(), cpuUsage.String())
|
||||||
|
}
|
||||||
|
if !test.expectedMemUsage.Equal(memUsage) {
|
||||||
|
t.Errorf("expecting memeory usage %s but getting %s", test.expectedMemUsage.String(), memUsage.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package metricsutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
metricsapi "k8s.io/metrics/pkg/apis/metrics"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NodeMetricsSorter struct {
|
||||||
|
metrics []metricsapi.NodeMetrics
|
||||||
|
sortBy string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NodeMetricsSorter) Len() int {
|
||||||
|
return len(n.metrics)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NodeMetricsSorter) Swap(i, j int) {
|
||||||
|
n.metrics[i], n.metrics[j] = n.metrics[j], n.metrics[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NodeMetricsSorter) Less(i, j int) bool {
|
||||||
|
switch n.sortBy {
|
||||||
|
case "cpu":
|
||||||
|
return n.metrics[i].Usage.Cpu().MilliValue() > n.metrics[j].Usage.Cpu().MilliValue()
|
||||||
|
case "memory":
|
||||||
|
return n.metrics[i].Usage.Memory().Value() > n.metrics[j].Usage.Memory().Value()
|
||||||
|
default:
|
||||||
|
return n.metrics[i].Name < n.metrics[j].Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNodeMetricsSorter(metrics []metricsapi.NodeMetrics, sortBy string) *NodeMetricsSorter {
|
||||||
|
return &NodeMetricsSorter{
|
||||||
|
metrics: metrics,
|
||||||
|
sortBy: sortBy,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type PodMetricsSorter struct {
|
||||||
|
metrics []metricsapi.PodMetrics
|
||||||
|
sortBy string
|
||||||
|
withNamespace bool
|
||||||
|
podMetrics []v1.ResourceList
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PodMetricsSorter) Len() int {
|
||||||
|
return len(p.metrics)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PodMetricsSorter) Swap(i, j int) {
|
||||||
|
p.metrics[i], p.metrics[j] = p.metrics[j], p.metrics[i]
|
||||||
|
p.podMetrics[i], p.podMetrics[j] = p.podMetrics[j], p.podMetrics[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PodMetricsSorter) Less(i, j int) bool {
|
||||||
|
switch p.sortBy {
|
||||||
|
case "cpu":
|
||||||
|
return p.podMetrics[i].Cpu().MilliValue() > p.podMetrics[j].Cpu().MilliValue()
|
||||||
|
case "memory":
|
||||||
|
return p.podMetrics[i].Memory().Value() > p.podMetrics[j].Memory().Value()
|
||||||
|
default:
|
||||||
|
if p.withNamespace && p.metrics[i].Namespace != p.metrics[j].Namespace {
|
||||||
|
return p.metrics[i].Namespace < p.metrics[j].Namespace
|
||||||
|
}
|
||||||
|
return p.metrics[i].Name < p.metrics[j].Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPodMetricsSorter(metrics []metricsapi.PodMetrics, withNamespace bool, sortBy string) *PodMetricsSorter {
|
||||||
|
var podMetrics = make([]v1.ResourceList, len(metrics))
|
||||||
|
if len(sortBy) > 0 {
|
||||||
|
for i, v := range metrics {
|
||||||
|
podMetrics[i] = getPodMetrics(&v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &PodMetricsSorter{
|
||||||
|
metrics: metrics,
|
||||||
|
sortBy: sortBy,
|
||||||
|
withNamespace: withNamespace,
|
||||||
|
podMetrics: podMetrics,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContainerMetricsSorter struct {
|
||||||
|
metrics []metricsapi.ContainerMetrics
|
||||||
|
sortBy string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ContainerMetricsSorter) Len() int {
|
||||||
|
return len(s.metrics)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ContainerMetricsSorter) Swap(i, j int) {
|
||||||
|
s.metrics[i], s.metrics[j] = s.metrics[j], s.metrics[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ContainerMetricsSorter) Less(i, j int) bool {
|
||||||
|
switch s.sortBy {
|
||||||
|
case "cpu":
|
||||||
|
return s.metrics[i].Usage.Cpu().MilliValue() > s.metrics[j].Usage.Cpu().MilliValue()
|
||||||
|
case "memory":
|
||||||
|
return s.metrics[i].Usage.Memory().Value() > s.metrics[j].Usage.Memory().Value()
|
||||||
|
default:
|
||||||
|
return s.metrics[i].Name < s.metrics[j].Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewContainerMetricsSorter(metrics []metricsapi.ContainerMetrics, sortBy string) *ContainerMetricsSorter {
|
||||||
|
return &ContainerMetricsSorter{
|
||||||
|
metrics: metrics,
|
||||||
|
sortBy: sortBy,
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue