Merge pull request #3593 from chaunceyjiang/top
feat: introducing a karmadactl top command
This commit is contained in:
commit
f243a18296
|
@ -28,6 +28,7 @@ import (
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/register"
|
"github.com/karmada-io/karmada/pkg/karmadactl/register"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/taint"
|
"github.com/karmada-io/karmada/pkg/karmadactl/taint"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/token"
|
"github.com/karmada-io/karmada/pkg/karmadactl/token"
|
||||||
|
"github.com/karmada-io/karmada/pkg/karmadactl/top"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/unjoin"
|
"github.com/karmada-io/karmada/pkg/karmadactl/unjoin"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
"github.com/karmada-io/karmada/pkg/version/sharedcommand"
|
"github.com/karmada-io/karmada/pkg/version/sharedcommand"
|
||||||
|
@ -106,6 +107,7 @@ func NewKarmadaCtlCommand(cmdUse, parentCommand string) *cobra.Command {
|
||||||
Commands: []*cobra.Command{
|
Commands: []*cobra.Command{
|
||||||
apply.NewCmdApply(f, parentCommand, ioStreams),
|
apply.NewCmdApply(f, parentCommand, ioStreams),
|
||||||
promote.NewCmdPromote(f, parentCommand),
|
promote.NewCmdPromote(f, parentCommand),
|
||||||
|
top.NewCmdTop(f, parentCommand, ioStreams),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,207 @@
|
||||||
|
package top
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
|
"k8s.io/cli-runtime/pkg/printers"
|
||||||
|
"k8s.io/kubectl/pkg/metricsutil"
|
||||||
|
metricsapi "k8s.io/metrics/pkg/apis/metrics"
|
||||||
|
|
||||||
|
autoscalingv1alpha1 "github.com/karmada-io/karmada/pkg/apis/autoscaling/v1alpha1"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
MeasuredResources = []corev1.ResourceName{
|
||||||
|
corev1.ResourceCPU,
|
||||||
|
corev1.ResourceMemory,
|
||||||
|
}
|
||||||
|
PodColumns = []string{"NAME", "CLUSTER", "CPU(cores)", "MEMORY(bytes)"}
|
||||||
|
NamespaceColumn = "NAMESPACE"
|
||||||
|
PodColumn = "POD"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ResourceMetricsInfo struct {
|
||||||
|
Cluster string
|
||||||
|
Name string
|
||||||
|
Metrics corev1.ResourceList
|
||||||
|
Available corev1.ResourceList
|
||||||
|
}
|
||||||
|
|
||||||
|
type TopCmdPrinter struct {
|
||||||
|
out io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTopCmdPrinter(out io.Writer) *TopCmdPrinter {
|
||||||
|
return &TopCmdPrinter{out: out}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (printer *TopCmdPrinter) PrintPodMetrics(metrics []metricsapi.PodMetrics, printContainers, withNamespace, noHeaders bool, sortBy string, sum bool) error {
|
||||||
|
if len(metrics) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
w := printers.GetNewTabWriter(printer.out)
|
||||||
|
defer w.Flush()
|
||||||
|
|
||||||
|
columnWidth := len(PodColumns)
|
||||||
|
if !noHeaders {
|
||||||
|
if withNamespace {
|
||||||
|
printValue(w, NamespaceColumn)
|
||||||
|
columnWidth++
|
||||||
|
}
|
||||||
|
if printContainers {
|
||||||
|
printValue(w, PodColumn)
|
||||||
|
columnWidth++
|
||||||
|
}
|
||||||
|
printColumnNames(w, PodColumns)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Sort(NewPodMetricsSorter(metrics, withNamespace, sortBy))
|
||||||
|
|
||||||
|
for i := range metrics {
|
||||||
|
if printContainers {
|
||||||
|
sort.Sort(metricsutil.NewContainerMetricsSorter(metrics[i].Containers, sortBy))
|
||||||
|
printSinglePodContainerMetrics(w, &metrics[i], withNamespace)
|
||||||
|
} else {
|
||||||
|
printSinglePodMetrics(w, &metrics[i], withNamespace)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if sum {
|
||||||
|
adder := NewResourceAdder(MeasuredResources)
|
||||||
|
for i := range metrics {
|
||||||
|
adder.AddPodMetrics(&metrics[i])
|
||||||
|
}
|
||||||
|
printPodResourcesSum(w, adder.total, columnWidth)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func printColumnNames(out io.Writer, names []string) {
|
||||||
|
for _, name := range names {
|
||||||
|
printValue(out, name)
|
||||||
|
}
|
||||||
|
fmt.Fprint(out, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func printSinglePodMetrics(out io.Writer, m *metricsapi.PodMetrics, withNamespace bool) {
|
||||||
|
podMetrics := getPodMetrics(m)
|
||||||
|
if withNamespace {
|
||||||
|
printValue(out, m.Namespace)
|
||||||
|
}
|
||||||
|
printMetricsLine(out, &ResourceMetricsInfo{
|
||||||
|
Name: m.Name,
|
||||||
|
Cluster: m.Annotations[autoscalingv1alpha1.QuerySourceAnnotationKey],
|
||||||
|
Metrics: podMetrics,
|
||||||
|
Available: corev1.ResourceList{},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func printSinglePodContainerMetrics(out io.Writer, m *metricsapi.PodMetrics, withNamespace bool) {
|
||||||
|
for _, c := range m.Containers {
|
||||||
|
if withNamespace {
|
||||||
|
printValue(out, m.Namespace)
|
||||||
|
}
|
||||||
|
printValue(out, m.Name)
|
||||||
|
printMetricsLine(out, &ResourceMetricsInfo{
|
||||||
|
Name: c.Name,
|
||||||
|
Cluster: m.Annotations[autoscalingv1alpha1.QuerySourceAnnotationKey],
|
||||||
|
Metrics: c.Usage,
|
||||||
|
Available: corev1.ResourceList{},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPodMetrics(m *metricsapi.PodMetrics) corev1.ResourceList {
|
||||||
|
podMetrics := make(corev1.ResourceList)
|
||||||
|
for _, res := range MeasuredResources {
|
||||||
|
podMetrics[res], _ = resource.ParseQuantity("0")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range m.Containers {
|
||||||
|
for _, res := range MeasuredResources {
|
||||||
|
quantity := podMetrics[res]
|
||||||
|
quantity.Add(c.Usage[res])
|
||||||
|
podMetrics[res] = quantity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return podMetrics
|
||||||
|
}
|
||||||
|
|
||||||
|
func printMetricsLine(out io.Writer, metrics *ResourceMetricsInfo) {
|
||||||
|
printValue(out, metrics.Name)
|
||||||
|
printValue(out, metrics.Cluster)
|
||||||
|
printAllResourceUsages(out, metrics)
|
||||||
|
fmt.Fprint(out, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func printValue(out io.Writer, value interface{}) {
|
||||||
|
fmt.Fprintf(out, "%v\t", value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printAllResourceUsages(out io.Writer, metrics *ResourceMetricsInfo) {
|
||||||
|
for _, res := range MeasuredResources {
|
||||||
|
quantity := metrics.Metrics[res]
|
||||||
|
printSingleResourceUsage(out, res, quantity)
|
||||||
|
fmt.Fprint(out, "\t")
|
||||||
|
if available, found := metrics.Available[res]; found {
|
||||||
|
fraction := float64(quantity.MilliValue()) / float64(available.MilliValue()) * 100
|
||||||
|
fmt.Fprintf(out, "%d%%\t", int64(fraction))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printSingleResourceUsage(out io.Writer, resourceType corev1.ResourceName, quantity resource.Quantity) {
|
||||||
|
switch resourceType {
|
||||||
|
case corev1.ResourceCPU:
|
||||||
|
fmt.Fprintf(out, "%vm", quantity.MilliValue())
|
||||||
|
case corev1.ResourceMemory:
|
||||||
|
fmt.Fprintf(out, "%vMi", quantity.Value()/(1024*1024))
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(out, "%v", quantity.Value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printPodResourcesSum(out io.Writer, total corev1.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-4; i++ {
|
||||||
|
printValue(out, "")
|
||||||
|
}
|
||||||
|
printMetricsLine(out, &ResourceMetricsInfo{
|
||||||
|
Name: "",
|
||||||
|
Metrics: total,
|
||||||
|
Available: corev1.ResourceList{},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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,73 @@
|
||||||
|
/*
|
||||||
|
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 top
|
||||||
|
|
||||||
|
import (
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metricsapi "k8s.io/metrics/pkg/apis/metrics"
|
||||||
|
|
||||||
|
autoscalingv1alpha1 "github.com/karmada-io/karmada/pkg/apis/autoscaling/v1alpha1"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PodMetricsSorter struct {
|
||||||
|
metrics []metricsapi.PodMetrics
|
||||||
|
sortBy string
|
||||||
|
withNamespace bool
|
||||||
|
podMetrics []corev1.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.metrics[i].Annotations[autoscalingv1alpha1.QuerySourceAnnotationKey] != p.metrics[j].Annotations[autoscalingv1alpha1.QuerySourceAnnotationKey] {
|
||||||
|
return p.metrics[i].Annotations[autoscalingv1alpha1.QuerySourceAnnotationKey] < p.metrics[j].Annotations[autoscalingv1alpha1.QuerySourceAnnotationKey]
|
||||||
|
}
|
||||||
|
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([]corev1.ResourceList, len(metrics))
|
||||||
|
if len(sortBy) > 0 {
|
||||||
|
for i := range metrics {
|
||||||
|
podMetrics[i] = getPodMetrics(&metrics[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &PodMetricsSorter{
|
||||||
|
metrics: metrics,
|
||||||
|
sortBy: sortBy,
|
||||||
|
withNamespace: withNamespace,
|
||||||
|
podMetrics: podMetrics,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
package top
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
|
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||||
|
"k8s.io/kubectl/pkg/util/templates"
|
||||||
|
metricsapi "k8s.io/metrics/pkg/apis/metrics"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
sortByCPU = "cpu"
|
||||||
|
sortByMemory = "memory"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
supportedMetricsAPIVersions = []string{
|
||||||
|
"v1beta1",
|
||||||
|
}
|
||||||
|
topLong = templates.LongDesc(`
|
||||||
|
Display Resource (CPU/Memory) usage of member clusters.
|
||||||
|
|
||||||
|
The top command allows you to see the resource consumption for pods of member clusters.
|
||||||
|
|
||||||
|
This command requires karmada-metrics-adapter to be correctly configured and working on the Karmada control plane and
|
||||||
|
Metrics Server to be correctly configured and working on the member clusters.`)
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewCmdTop(f cmdutil.Factory, parentCommand string, streams genericclioptions.IOStreams) *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "top",
|
||||||
|
Short: "Display resource (CPU/memory) usage of member clusters",
|
||||||
|
Long: topLong,
|
||||||
|
Run: cmdutil.DefaultSubCommandRun(streams.ErrOut),
|
||||||
|
}
|
||||||
|
|
||||||
|
// create subcommands
|
||||||
|
cmd.AddCommand(NewCmdTopPod(f, parentCommand, nil, streams))
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func SupportedMetricsAPIVersionAvailable(discoveredAPIGroups *metav1.APIGroupList) bool {
|
||||||
|
for _, discoveredAPIGroup := range discoveredAPIGroups.Groups {
|
||||||
|
if discoveredAPIGroup.Name != metricsapi.GroupName {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, version := range discoveredAPIGroup.Versions {
|
||||||
|
for _, supportedVersion := range supportedMetricsAPIVersions {
|
||||||
|
if version.Version == supportedVersion {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
|
@ -0,0 +1,274 @@
|
||||||
|
package top
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
|
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||||
|
"k8s.io/kubectl/pkg/util/completion"
|
||||||
|
"k8s.io/kubectl/pkg/util/i18n"
|
||||||
|
"k8s.io/kubectl/pkg/util/templates"
|
||||||
|
metricsapi "k8s.io/metrics/pkg/apis/metrics"
|
||||||
|
metricsv1beta1api "k8s.io/metrics/pkg/apis/metrics/v1beta1"
|
||||||
|
metricsclientset "k8s.io/metrics/pkg/client/clientset/versioned"
|
||||||
|
|
||||||
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TopPodOptions struct {
|
||||||
|
ResourceName string
|
||||||
|
Namespace string
|
||||||
|
LabelSelector string
|
||||||
|
FieldSelector string
|
||||||
|
SortBy string
|
||||||
|
AllNamespaces bool
|
||||||
|
PrintContainers bool
|
||||||
|
NoHeaders bool
|
||||||
|
UseProtocolBuffers bool
|
||||||
|
Sum bool
|
||||||
|
|
||||||
|
PodClient corev1client.PodsGetter
|
||||||
|
Printer *TopCmdPrinter
|
||||||
|
DiscoveryClient discovery.DiscoveryInterface
|
||||||
|
MetricsClient metricsclientset.Interface
|
||||||
|
|
||||||
|
genericclioptions.IOStreams
|
||||||
|
}
|
||||||
|
|
||||||
|
const metricsCreationDelay = 2 * time.Minute
|
||||||
|
|
||||||
|
var (
|
||||||
|
topPodLong = templates.LongDesc(i18n.T(`
|
||||||
|
Display resource (CPU/memory) usage of pods.
|
||||||
|
|
||||||
|
The 'top pod' command allows you to see the resource consumption of pods of member clusters.
|
||||||
|
|
||||||
|
Due to the metrics pipeline delay, they may be unavailable for a few minutes
|
||||||
|
since pod creation.`))
|
||||||
|
|
||||||
|
topPodExample = templates.Examples(i18n.T(`
|
||||||
|
# Show metrics for all pods in the default namespace
|
||||||
|
%[1]s top pod
|
||||||
|
|
||||||
|
# Show metrics for all pods in the given namespace
|
||||||
|
%[1]s top pod --namespace=NAMESPACE
|
||||||
|
|
||||||
|
# Show metrics for a given pod and its containers
|
||||||
|
%[1]s top pod POD_NAME --containers
|
||||||
|
|
||||||
|
# Show metrics for the pods defined by label name=myLabel
|
||||||
|
%[1]s top pod -l name=myLabel`))
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewCmdTopPod(f cmdutil.Factory, parentCommand string, o *TopPodOptions, streams genericclioptions.IOStreams) *cobra.Command {
|
||||||
|
if o == nil {
|
||||||
|
o = &TopPodOptions{
|
||||||
|
IOStreams: streams,
|
||||||
|
UseProtocolBuffers: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "pod [NAME | -l label]",
|
||||||
|
DisableFlagsInUseLine: true,
|
||||||
|
Short: i18n.T("Display resource (CPU/memory) usage of pods of member clusters"),
|
||||||
|
Long: topPodLong,
|
||||||
|
Example: fmt.Sprintf(topPodExample, parentCommand),
|
||||||
|
ValidArgsFunction: completion.ResourceNameCompletionFunc(f, "pod"),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
||||||
|
cmdutil.CheckErr(o.Validate())
|
||||||
|
cmdutil.CheckErr(o.RunTopPod())
|
||||||
|
},
|
||||||
|
Aliases: []string{"pods", "po"},
|
||||||
|
}
|
||||||
|
cmdutil.AddLabelSelectorFlagVar(cmd, &o.LabelSelector)
|
||||||
|
options.AddKubeConfigFlags(cmd.Flags())
|
||||||
|
cmd.Flags().StringVarP(options.DefaultConfigFlags.Namespace, "namespace", "n", *options.DefaultConfigFlags.Namespace, "If present, the namespace scope for this CLI request")
|
||||||
|
cmd.Flags().StringVar(&o.FieldSelector, "field-selector", o.FieldSelector, "Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector key1=value1,key2=value2). The server only supports a limited number of field queries per type.")
|
||||||
|
cmd.Flags().StringVar(&o.SortBy, "sort-by", o.SortBy, "If non-empty, sort pods list using specified field. The field can be either 'cpu' or 'memory'.")
|
||||||
|
cmd.Flags().BoolVar(&o.PrintContainers, "containers", o.PrintContainers, "If present, print usage of containers within a pod.")
|
||||||
|
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.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
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *TopPodOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
|
||||||
|
var err error
|
||||||
|
if len(args) == 1 {
|
||||||
|
o.ResourceName = args[0]
|
||||||
|
} else if len(args) > 1 {
|
||||||
|
return cmdutil.UsageErrorf(cmd, "%s", cmd.Use)
|
||||||
|
}
|
||||||
|
|
||||||
|
o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
clientset, err := f.KubernetesClientSet()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
o.DiscoveryClient = clientset.DiscoveryClient
|
||||||
|
config, err := f.ToRESTConfig()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if o.UseProtocolBuffers {
|
||||||
|
config.ContentType = "application/vnd.kubernetes.protobuf"
|
||||||
|
}
|
||||||
|
o.MetricsClient, err = metricsclientset.NewForConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
o.PodClient = clientset.CoreV1()
|
||||||
|
|
||||||
|
o.Printer = NewTopCmdPrinter(o.Out)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *TopPodOptions) Validate() error {
|
||||||
|
if len(o.SortBy) > 0 {
|
||||||
|
if o.SortBy != sortByCPU && o.SortBy != sortByMemory {
|
||||||
|
return errors.New("--sort-by accepts only cpu or memory")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(o.ResourceName) > 0 && (len(o.LabelSelector) > 0 || len(o.FieldSelector) > 0) {
|
||||||
|
return errors.New("only one of NAME or selector can be provided")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *TopPodOptions) RunTopPod() error {
|
||||||
|
var err error
|
||||||
|
labelSelector := labels.Everything()
|
||||||
|
if len(o.LabelSelector) > 0 {
|
||||||
|
labelSelector, err = labels.Parse(o.LabelSelector)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fieldSelector := fields.Everything()
|
||||||
|
if len(o.FieldSelector) > 0 {
|
||||||
|
fieldSelector, err = fields.ParseSelector(o.FieldSelector)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apiGroups, err := o.DiscoveryClient.ServerGroups()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
metricsAPIAvailable := SupportedMetricsAPIVersionAvailable(apiGroups)
|
||||||
|
|
||||||
|
if !metricsAPIAvailable {
|
||||||
|
return errors.New("Metrics API not available")
|
||||||
|
}
|
||||||
|
metrics, err := getMetricsFromMetricsAPI(o.MetricsClient, o.Namespace, o.ResourceName, o.AllNamespaces, labelSelector, fieldSelector)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// First we check why no metrics have been received.
|
||||||
|
if len(metrics.Items) == 0 {
|
||||||
|
// If the API server query is successful but all the pods are newly created,
|
||||||
|
// the metrics are probably not ready yet, so we return the error here in the first place.
|
||||||
|
err := verifyEmptyMetrics(o, labelSelector, fieldSelector)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we had no errors, be sure we output something.
|
||||||
|
if o.AllNamespaces {
|
||||||
|
fmt.Fprintln(o.ErrOut, "No resources found")
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(o.ErrOut, "No resources found in %s namespace.\n", o.Namespace)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
var err error
|
||||||
|
ns := metav1.NamespaceAll
|
||||||
|
if !allNamespaces {
|
||||||
|
ns = namespace
|
||||||
|
}
|
||||||
|
versionedMetrics := &metricsv1beta1api.PodMetricsList{}
|
||||||
|
if resourceName != "" {
|
||||||
|
m, err := metricsClient.MetricsV1beta1().PodMetricses(ns).Get(context.TODO(), resourceName, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
versionedMetrics.Items = []metricsv1beta1api.PodMetrics{*m}
|
||||||
|
} else {
|
||||||
|
versionedMetrics, err = metricsClient.MetricsV1beta1().PodMetricses(ns).List(context.TODO(), metav1.ListOptions{LabelSelector: labelSelector.String(), FieldSelector: fieldSelector.String()})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
metrics := &metricsapi.PodMetricsList{}
|
||||||
|
err = metricsv1beta1api.Convert_v1beta1_PodMetricsList_To_metrics_PodMetricsList(versionedMetrics, metrics, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return metrics, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func verifyEmptyMetrics(o *TopPodOptions, labelSelector labels.Selector, fieldSelector fields.Selector) error {
|
||||||
|
if len(o.ResourceName) > 0 {
|
||||||
|
pod, err := o.PodClient.Pods(o.Namespace).Get(context.TODO(), o.ResourceName, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := checkPodAge(pod); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pods, err := o.PodClient.Pods(o.Namespace).List(context.TODO(), metav1.ListOptions{
|
||||||
|
LabelSelector: labelSelector.String(),
|
||||||
|
FieldSelector: fieldSelector.String(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(pods.Items) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for i := range pods.Items {
|
||||||
|
if err := checkPodAge(&pods.Items[i]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errors.New("metrics not available yet")
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkPodAge(pod *corev1.Pod) error {
|
||||||
|
age := time.Since(pod.CreationTimestamp.Time)
|
||||||
|
if age > metricsCreationDelay {
|
||||||
|
message := fmt.Sprintf("Metrics not available for pod %s/%s, age: %s", pod.Namespace, pod.Name, age.String())
|
||||||
|
return errors.New(message)
|
||||||
|
} else {
|
||||||
|
klog.V(2).Infof("Metrics not yet available for pod %s/%s, age: %s", pod.Namespace, pod.Name, age.String())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,236 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 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 (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
|
"k8s.io/cli-runtime/pkg/printers"
|
||||||
|
metricsapi "k8s.io/metrics/pkg/apis/metrics"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
MeasuredResources = []v1.ResourceName{
|
||||||
|
v1.ResourceCPU,
|
||||||
|
v1.ResourceMemory,
|
||||||
|
}
|
||||||
|
NodeColumns = []string{"NAME", "CPU(cores)", "CPU%", "MEMORY(bytes)", "MEMORY%"}
|
||||||
|
PodColumns = []string{"NAME", "CPU(cores)", "MEMORY(bytes)"}
|
||||||
|
NamespaceColumn = "NAMESPACE"
|
||||||
|
PodColumn = "POD"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ResourceMetricsInfo struct {
|
||||||
|
Name string
|
||||||
|
Metrics v1.ResourceList
|
||||||
|
Available v1.ResourceList
|
||||||
|
}
|
||||||
|
|
||||||
|
type TopCmdPrinter struct {
|
||||||
|
out io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTopCmdPrinter(out io.Writer) *TopCmdPrinter {
|
||||||
|
return &TopCmdPrinter{out: out}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (printer *TopCmdPrinter) PrintNodeMetrics(metrics []metricsapi.NodeMetrics, availableResources map[string]v1.ResourceList, noHeaders bool, sortBy string) error {
|
||||||
|
if len(metrics) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
w := printers.GetNewTabWriter(printer.out)
|
||||||
|
defer w.Flush()
|
||||||
|
|
||||||
|
sort.Sort(NewNodeMetricsSorter(metrics, sortBy))
|
||||||
|
|
||||||
|
if !noHeaders {
|
||||||
|
printColumnNames(w, NodeColumns)
|
||||||
|
}
|
||||||
|
var usage v1.ResourceList
|
||||||
|
for _, m := range metrics {
|
||||||
|
m.Usage.DeepCopyInto(&usage)
|
||||||
|
printMetricsLine(w, &ResourceMetricsInfo{
|
||||||
|
Name: m.Name,
|
||||||
|
Metrics: usage,
|
||||||
|
Available: availableResources[m.Name],
|
||||||
|
})
|
||||||
|
delete(availableResources, m.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// print lines for nodes of which the metrics is unreachable.
|
||||||
|
for nodeName := range availableResources {
|
||||||
|
printMissingMetricsNodeLine(w, nodeName)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (printer *TopCmdPrinter) PrintPodMetrics(metrics []metricsapi.PodMetrics, printContainers bool, withNamespace bool, noHeaders bool, sortBy string, sum bool) error {
|
||||||
|
if len(metrics) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
w := printers.GetNewTabWriter(printer.out)
|
||||||
|
defer w.Flush()
|
||||||
|
|
||||||
|
columnWidth := len(PodColumns)
|
||||||
|
if !noHeaders {
|
||||||
|
if withNamespace {
|
||||||
|
printValue(w, NamespaceColumn)
|
||||||
|
columnWidth++
|
||||||
|
}
|
||||||
|
if printContainers {
|
||||||
|
printValue(w, PodColumn)
|
||||||
|
columnWidth++
|
||||||
|
}
|
||||||
|
printColumnNames(w, PodColumns)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Sort(NewPodMetricsSorter(metrics, withNamespace, sortBy))
|
||||||
|
|
||||||
|
for _, m := range metrics {
|
||||||
|
if printContainers {
|
||||||
|
sort.Sort(NewContainerMetricsSorter(m.Containers, sortBy))
|
||||||
|
printSinglePodContainerMetrics(w, &m, withNamespace)
|
||||||
|
} else {
|
||||||
|
printSinglePodMetrics(w, &m, withNamespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if sum {
|
||||||
|
adder := NewResourceAdder(MeasuredResources)
|
||||||
|
for _, m := range metrics {
|
||||||
|
adder.AddPodMetrics(&m)
|
||||||
|
}
|
||||||
|
printPodResourcesSum(w, adder.total, columnWidth)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func printColumnNames(out io.Writer, names []string) {
|
||||||
|
for _, name := range names {
|
||||||
|
printValue(out, name)
|
||||||
|
}
|
||||||
|
fmt.Fprint(out, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func printSinglePodMetrics(out io.Writer, m *metricsapi.PodMetrics, withNamespace bool) {
|
||||||
|
podMetrics := getPodMetrics(m)
|
||||||
|
if withNamespace {
|
||||||
|
printValue(out, m.Namespace)
|
||||||
|
}
|
||||||
|
printMetricsLine(out, &ResourceMetricsInfo{
|
||||||
|
Name: m.Name,
|
||||||
|
Metrics: podMetrics,
|
||||||
|
Available: v1.ResourceList{},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func printSinglePodContainerMetrics(out io.Writer, m *metricsapi.PodMetrics, withNamespace bool) {
|
||||||
|
for _, c := range m.Containers {
|
||||||
|
if withNamespace {
|
||||||
|
printValue(out, m.Namespace)
|
||||||
|
}
|
||||||
|
printValue(out, m.Name)
|
||||||
|
printMetricsLine(out, &ResourceMetricsInfo{
|
||||||
|
Name: c.Name,
|
||||||
|
Metrics: c.Usage,
|
||||||
|
Available: v1.ResourceList{},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPodMetrics(m *metricsapi.PodMetrics) v1.ResourceList {
|
||||||
|
podMetrics := make(v1.ResourceList)
|
||||||
|
for _, res := range MeasuredResources {
|
||||||
|
podMetrics[res], _ = resource.ParseQuantity("0")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range m.Containers {
|
||||||
|
for _, res := range MeasuredResources {
|
||||||
|
quantity := podMetrics[res]
|
||||||
|
quantity.Add(c.Usage[res])
|
||||||
|
podMetrics[res] = quantity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return podMetrics
|
||||||
|
}
|
||||||
|
|
||||||
|
func printMetricsLine(out io.Writer, metrics *ResourceMetricsInfo) {
|
||||||
|
printValue(out, metrics.Name)
|
||||||
|
printAllResourceUsages(out, metrics)
|
||||||
|
fmt.Fprint(out, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func printMissingMetricsNodeLine(out io.Writer, nodeName string) {
|
||||||
|
printValue(out, nodeName)
|
||||||
|
unknownMetricsStatus := "<unknown>"
|
||||||
|
for i := 0; i < len(MeasuredResources); i++ {
|
||||||
|
printValue(out, unknownMetricsStatus)
|
||||||
|
printValue(out, unknownMetricsStatus)
|
||||||
|
}
|
||||||
|
fmt.Fprint(out, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func printValue(out io.Writer, value interface{}) {
|
||||||
|
fmt.Fprintf(out, "%v\t", value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printAllResourceUsages(out io.Writer, metrics *ResourceMetricsInfo) {
|
||||||
|
for _, res := range MeasuredResources {
|
||||||
|
quantity := metrics.Metrics[res]
|
||||||
|
printSingleResourceUsage(out, res, quantity)
|
||||||
|
fmt.Fprint(out, "\t")
|
||||||
|
if available, found := metrics.Available[res]; found {
|
||||||
|
fraction := float64(quantity.MilliValue()) / float64(available.MilliValue()) * 100
|
||||||
|
fmt.Fprintf(out, "%d%%\t", int64(fraction))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printSingleResourceUsage(out io.Writer, resourceType v1.ResourceName, quantity resource.Quantity) {
|
||||||
|
switch resourceType {
|
||||||
|
case v1.ResourceCPU:
|
||||||
|
fmt.Fprintf(out, "%vm", quantity.MilliValue())
|
||||||
|
case v1.ResourceMemory:
|
||||||
|
fmt.Fprintf(out, "%vMi", quantity.Value()/(1024*1024))
|
||||||
|
default:
|
||||||
|
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,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,
|
||||||
|
}
|
||||||
|
}
|
133
vendor/k8s.io/metrics/pkg/client/clientset/versioned/clientset.go
generated
vendored
Normal file
133
vendor/k8s.io/metrics/pkg/client/clientset/versioned/clientset.go
generated
vendored
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
Copyright 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package versioned
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
discovery "k8s.io/client-go/discovery"
|
||||||
|
rest "k8s.io/client-go/rest"
|
||||||
|
flowcontrol "k8s.io/client-go/util/flowcontrol"
|
||||||
|
metricsv1alpha1 "k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1alpha1"
|
||||||
|
metricsv1beta1 "k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Interface interface {
|
||||||
|
Discovery() discovery.DiscoveryInterface
|
||||||
|
MetricsV1alpha1() metricsv1alpha1.MetricsV1alpha1Interface
|
||||||
|
MetricsV1beta1() metricsv1beta1.MetricsV1beta1Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clientset contains the clients for groups.
|
||||||
|
type Clientset struct {
|
||||||
|
*discovery.DiscoveryClient
|
||||||
|
metricsV1alpha1 *metricsv1alpha1.MetricsV1alpha1Client
|
||||||
|
metricsV1beta1 *metricsv1beta1.MetricsV1beta1Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// MetricsV1alpha1 retrieves the MetricsV1alpha1Client
|
||||||
|
func (c *Clientset) MetricsV1alpha1() metricsv1alpha1.MetricsV1alpha1Interface {
|
||||||
|
return c.metricsV1alpha1
|
||||||
|
}
|
||||||
|
|
||||||
|
// MetricsV1beta1 retrieves the MetricsV1beta1Client
|
||||||
|
func (c *Clientset) MetricsV1beta1() metricsv1beta1.MetricsV1beta1Interface {
|
||||||
|
return c.metricsV1beta1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discovery retrieves the DiscoveryClient
|
||||||
|
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return c.DiscoveryClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForConfig creates a new Clientset for the given config.
|
||||||
|
// If config's RateLimiter is not set and QPS and Burst are acceptable,
|
||||||
|
// NewForConfig will generate a rate-limiter in configShallowCopy.
|
||||||
|
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
|
||||||
|
// where httpClient was generated with rest.HTTPClientFor(c).
|
||||||
|
func NewForConfig(c *rest.Config) (*Clientset, error) {
|
||||||
|
configShallowCopy := *c
|
||||||
|
|
||||||
|
if configShallowCopy.UserAgent == "" {
|
||||||
|
configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||||
|
}
|
||||||
|
|
||||||
|
// share the transport between all clients
|
||||||
|
httpClient, err := rest.HTTPClientFor(&configShallowCopy)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewForConfigAndClient(&configShallowCopy, httpClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForConfigAndClient creates a new Clientset for the given config and http client.
|
||||||
|
// Note the http client provided takes precedence over the configured transport values.
|
||||||
|
// If config's RateLimiter is not set and QPS and Burst are acceptable,
|
||||||
|
// NewForConfigAndClient will generate a rate-limiter in configShallowCopy.
|
||||||
|
func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error) {
|
||||||
|
configShallowCopy := *c
|
||||||
|
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
|
||||||
|
if configShallowCopy.Burst <= 0 {
|
||||||
|
return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0")
|
||||||
|
}
|
||||||
|
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
|
||||||
|
}
|
||||||
|
|
||||||
|
var cs Clientset
|
||||||
|
var err error
|
||||||
|
cs.metricsV1alpha1, err = metricsv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cs.metricsV1beta1, err = metricsv1beta1.NewForConfigAndClient(&configShallowCopy, httpClient)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &cs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForConfigOrDie creates a new Clientset for the given config and
|
||||||
|
// panics if there is an error in the config.
|
||||||
|
func NewForConfigOrDie(c *rest.Config) *Clientset {
|
||||||
|
cs, err := NewForConfig(c)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return cs
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new Clientset for the given RESTClient.
|
||||||
|
func New(c rest.Interface) *Clientset {
|
||||||
|
var cs Clientset
|
||||||
|
cs.metricsV1alpha1 = metricsv1alpha1.New(c)
|
||||||
|
cs.metricsV1beta1 = metricsv1beta1.New(c)
|
||||||
|
|
||||||
|
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
|
||||||
|
return &cs
|
||||||
|
}
|
20
vendor/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1alpha1/doc.go
generated
vendored
Normal file
20
vendor/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1alpha1/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
Copyright 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
// This package has the automatically generated typed clients.
|
||||||
|
package v1alpha1
|
23
vendor/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1alpha1/generated_expansion.go
generated
vendored
Normal file
23
vendor/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1alpha1/generated_expansion.go
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
Copyright 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
type NodeMetricsExpansion interface{}
|
||||||
|
|
||||||
|
type PodMetricsExpansion interface{}
|
112
vendor/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1alpha1/metrics_client.go
generated
vendored
Normal file
112
vendor/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1alpha1/metrics_client.go
generated
vendored
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
Copyright 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
rest "k8s.io/client-go/rest"
|
||||||
|
v1alpha1 "k8s.io/metrics/pkg/apis/metrics/v1alpha1"
|
||||||
|
"k8s.io/metrics/pkg/client/clientset/versioned/scheme"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MetricsV1alpha1Interface interface {
|
||||||
|
RESTClient() rest.Interface
|
||||||
|
NodeMetricsesGetter
|
||||||
|
PodMetricsesGetter
|
||||||
|
}
|
||||||
|
|
||||||
|
// MetricsV1alpha1Client is used to interact with features provided by the metrics.k8s.io group.
|
||||||
|
type MetricsV1alpha1Client struct {
|
||||||
|
restClient rest.Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MetricsV1alpha1Client) NodeMetricses() NodeMetricsInterface {
|
||||||
|
return newNodeMetricses(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MetricsV1alpha1Client) PodMetricses(namespace string) PodMetricsInterface {
|
||||||
|
return newPodMetricses(c, namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForConfig creates a new MetricsV1alpha1Client for the given config.
|
||||||
|
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
|
||||||
|
// where httpClient was generated with rest.HTTPClientFor(c).
|
||||||
|
func NewForConfig(c *rest.Config) (*MetricsV1alpha1Client, error) {
|
||||||
|
config := *c
|
||||||
|
if err := setConfigDefaults(&config); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
httpClient, err := rest.HTTPClientFor(&config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return NewForConfigAndClient(&config, httpClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForConfigAndClient creates a new MetricsV1alpha1Client for the given config and http client.
|
||||||
|
// Note the http client provided takes precedence over the configured transport values.
|
||||||
|
func NewForConfigAndClient(c *rest.Config, h *http.Client) (*MetricsV1alpha1Client, error) {
|
||||||
|
config := *c
|
||||||
|
if err := setConfigDefaults(&config); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
client, err := rest.RESTClientForConfigAndClient(&config, h)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &MetricsV1alpha1Client{client}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForConfigOrDie creates a new MetricsV1alpha1Client for the given config and
|
||||||
|
// panics if there is an error in the config.
|
||||||
|
func NewForConfigOrDie(c *rest.Config) *MetricsV1alpha1Client {
|
||||||
|
client, err := NewForConfig(c)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new MetricsV1alpha1Client for the given RESTClient.
|
||||||
|
func New(c rest.Interface) *MetricsV1alpha1Client {
|
||||||
|
return &MetricsV1alpha1Client{c}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setConfigDefaults(config *rest.Config) error {
|
||||||
|
gv := v1alpha1.SchemeGroupVersion
|
||||||
|
config.GroupVersion = &gv
|
||||||
|
config.APIPath = "/apis"
|
||||||
|
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
|
||||||
|
|
||||||
|
if config.UserAgent == "" {
|
||||||
|
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RESTClient returns a RESTClient that is used to communicate
|
||||||
|
// with API server by this client implementation.
|
||||||
|
func (c *MetricsV1alpha1Client) RESTClient() rest.Interface {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return c.restClient
|
||||||
|
}
|
98
vendor/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1alpha1/nodemetrics.go
generated
vendored
Normal file
98
vendor/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1alpha1/nodemetrics.go
generated
vendored
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
Copyright 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
watch "k8s.io/apimachinery/pkg/watch"
|
||||||
|
rest "k8s.io/client-go/rest"
|
||||||
|
v1alpha1 "k8s.io/metrics/pkg/apis/metrics/v1alpha1"
|
||||||
|
scheme "k8s.io/metrics/pkg/client/clientset/versioned/scheme"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NodeMetricsesGetter has a method to return a NodeMetricsInterface.
|
||||||
|
// A group's client should implement this interface.
|
||||||
|
type NodeMetricsesGetter interface {
|
||||||
|
NodeMetricses() NodeMetricsInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
// NodeMetricsInterface has methods to work with NodeMetrics resources.
|
||||||
|
type NodeMetricsInterface interface {
|
||||||
|
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.NodeMetrics, error)
|
||||||
|
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.NodeMetricsList, error)
|
||||||
|
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
|
||||||
|
NodeMetricsExpansion
|
||||||
|
}
|
||||||
|
|
||||||
|
// nodeMetricses implements NodeMetricsInterface
|
||||||
|
type nodeMetricses struct {
|
||||||
|
client rest.Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
// newNodeMetricses returns a NodeMetricses
|
||||||
|
func newNodeMetricses(c *MetricsV1alpha1Client) *nodeMetricses {
|
||||||
|
return &nodeMetricses{
|
||||||
|
client: c.RESTClient(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get takes name of the nodeMetrics, and returns the corresponding nodeMetrics object, and an error if there is any.
|
||||||
|
func (c *nodeMetricses) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.NodeMetrics, err error) {
|
||||||
|
result = &v1alpha1.NodeMetrics{}
|
||||||
|
err = c.client.Get().
|
||||||
|
Resource("nodes").
|
||||||
|
Name(name).
|
||||||
|
VersionedParams(&options, scheme.ParameterCodec).
|
||||||
|
Do(ctx).
|
||||||
|
Into(result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// List takes label and field selectors, and returns the list of NodeMetricses that match those selectors.
|
||||||
|
func (c *nodeMetricses) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.NodeMetricsList, err error) {
|
||||||
|
var timeout time.Duration
|
||||||
|
if opts.TimeoutSeconds != nil {
|
||||||
|
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||||
|
}
|
||||||
|
result = &v1alpha1.NodeMetricsList{}
|
||||||
|
err = c.client.Get().
|
||||||
|
Resource("nodes").
|
||||||
|
VersionedParams(&opts, scheme.ParameterCodec).
|
||||||
|
Timeout(timeout).
|
||||||
|
Do(ctx).
|
||||||
|
Into(result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Watch returns a watch.Interface that watches the requested nodeMetricses.
|
||||||
|
func (c *nodeMetricses) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||||
|
var timeout time.Duration
|
||||||
|
if opts.TimeoutSeconds != nil {
|
||||||
|
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||||
|
}
|
||||||
|
opts.Watch = true
|
||||||
|
return c.client.Get().
|
||||||
|
Resource("nodes").
|
||||||
|
VersionedParams(&opts, scheme.ParameterCodec).
|
||||||
|
Timeout(timeout).
|
||||||
|
Watch(ctx)
|
||||||
|
}
|
103
vendor/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1alpha1/podmetrics.go
generated
vendored
Normal file
103
vendor/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1alpha1/podmetrics.go
generated
vendored
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
Copyright 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
watch "k8s.io/apimachinery/pkg/watch"
|
||||||
|
rest "k8s.io/client-go/rest"
|
||||||
|
v1alpha1 "k8s.io/metrics/pkg/apis/metrics/v1alpha1"
|
||||||
|
scheme "k8s.io/metrics/pkg/client/clientset/versioned/scheme"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PodMetricsesGetter has a method to return a PodMetricsInterface.
|
||||||
|
// A group's client should implement this interface.
|
||||||
|
type PodMetricsesGetter interface {
|
||||||
|
PodMetricses(namespace string) PodMetricsInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodMetricsInterface has methods to work with PodMetrics resources.
|
||||||
|
type PodMetricsInterface interface {
|
||||||
|
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.PodMetrics, error)
|
||||||
|
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.PodMetricsList, error)
|
||||||
|
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
|
||||||
|
PodMetricsExpansion
|
||||||
|
}
|
||||||
|
|
||||||
|
// podMetricses implements PodMetricsInterface
|
||||||
|
type podMetricses struct {
|
||||||
|
client rest.Interface
|
||||||
|
ns string
|
||||||
|
}
|
||||||
|
|
||||||
|
// newPodMetricses returns a PodMetricses
|
||||||
|
func newPodMetricses(c *MetricsV1alpha1Client, namespace string) *podMetricses {
|
||||||
|
return &podMetricses{
|
||||||
|
client: c.RESTClient(),
|
||||||
|
ns: namespace,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get takes name of the podMetrics, and returns the corresponding podMetrics object, and an error if there is any.
|
||||||
|
func (c *podMetricses) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.PodMetrics, err error) {
|
||||||
|
result = &v1alpha1.PodMetrics{}
|
||||||
|
err = c.client.Get().
|
||||||
|
Namespace(c.ns).
|
||||||
|
Resource("pods").
|
||||||
|
Name(name).
|
||||||
|
VersionedParams(&options, scheme.ParameterCodec).
|
||||||
|
Do(ctx).
|
||||||
|
Into(result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// List takes label and field selectors, and returns the list of PodMetricses that match those selectors.
|
||||||
|
func (c *podMetricses) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.PodMetricsList, err error) {
|
||||||
|
var timeout time.Duration
|
||||||
|
if opts.TimeoutSeconds != nil {
|
||||||
|
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||||
|
}
|
||||||
|
result = &v1alpha1.PodMetricsList{}
|
||||||
|
err = c.client.Get().
|
||||||
|
Namespace(c.ns).
|
||||||
|
Resource("pods").
|
||||||
|
VersionedParams(&opts, scheme.ParameterCodec).
|
||||||
|
Timeout(timeout).
|
||||||
|
Do(ctx).
|
||||||
|
Into(result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Watch returns a watch.Interface that watches the requested podMetricses.
|
||||||
|
func (c *podMetricses) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||||
|
var timeout time.Duration
|
||||||
|
if opts.TimeoutSeconds != nil {
|
||||||
|
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||||
|
}
|
||||||
|
opts.Watch = true
|
||||||
|
return c.client.Get().
|
||||||
|
Namespace(c.ns).
|
||||||
|
Resource("pods").
|
||||||
|
VersionedParams(&opts, scheme.ParameterCodec).
|
||||||
|
Timeout(timeout).
|
||||||
|
Watch(ctx)
|
||||||
|
}
|
|
@ -1608,6 +1608,7 @@ k8s.io/kubectl/pkg/cmd/util/editor/crlf
|
||||||
k8s.io/kubectl/pkg/cmd/util/podcmd
|
k8s.io/kubectl/pkg/cmd/util/podcmd
|
||||||
k8s.io/kubectl/pkg/cmd/wait
|
k8s.io/kubectl/pkg/cmd/wait
|
||||||
k8s.io/kubectl/pkg/describe
|
k8s.io/kubectl/pkg/describe
|
||||||
|
k8s.io/kubectl/pkg/metricsutil
|
||||||
k8s.io/kubectl/pkg/polymorphichelpers
|
k8s.io/kubectl/pkg/polymorphichelpers
|
||||||
k8s.io/kubectl/pkg/rawhttp
|
k8s.io/kubectl/pkg/rawhttp
|
||||||
k8s.io/kubectl/pkg/scheme
|
k8s.io/kubectl/pkg/scheme
|
||||||
|
@ -1644,7 +1645,9 @@ k8s.io/metrics/pkg/apis/metrics
|
||||||
k8s.io/metrics/pkg/apis/metrics/install
|
k8s.io/metrics/pkg/apis/metrics/install
|
||||||
k8s.io/metrics/pkg/apis/metrics/v1alpha1
|
k8s.io/metrics/pkg/apis/metrics/v1alpha1
|
||||||
k8s.io/metrics/pkg/apis/metrics/v1beta1
|
k8s.io/metrics/pkg/apis/metrics/v1beta1
|
||||||
|
k8s.io/metrics/pkg/client/clientset/versioned
|
||||||
k8s.io/metrics/pkg/client/clientset/versioned/scheme
|
k8s.io/metrics/pkg/client/clientset/versioned/scheme
|
||||||
|
k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1alpha1
|
||||||
k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1
|
k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1
|
||||||
k8s.io/metrics/pkg/client/custom_metrics
|
k8s.io/metrics/pkg/client/custom_metrics
|
||||||
k8s.io/metrics/pkg/client/custom_metrics/scheme
|
k8s.io/metrics/pkg/client/custom_metrics/scheme
|
||||||
|
|
Loading…
Reference in New Issue