karmada/pkg/karmadactl/top/top.go

118 lines
3.2 KiB
Go

package top
import (
"context"
"fmt"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/kubernetes"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/templates"
metricsapi "k8s.io/metrics/pkg/apis/metrics"
metricsclientset "k8s.io/metrics/pkg/client/clientset/versioned"
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
"github.com/karmada-io/karmada/pkg/karmadactl/util"
)
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 util.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
}
func GenClusterList(clientSet karmadaclientset.Interface, clusters []string) ([]string, error) {
if len(clusters) != 0 {
return clusters, nil
}
clusterList, err := clientSet.ClusterV1alpha1().Clusters().List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("failed to list all member clusters in control plane, err: %w", err)
}
for i := range clusterList.Items {
clusters = append(clusters, clusterList.Items[i].Name)
}
return clusters, nil
}
func GetMemberAndMetricsClientSet(f util.Factory,
cluster string, useProtocolBuffers bool) (*kubernetes.Clientset, *metricsclientset.Clientset, error) {
memberFactory, err := f.FactoryForMemberCluster(cluster)
if err != nil {
return nil, nil, err
}
clientset, err := memberFactory.KubernetesClientSet()
if err != nil {
return nil, nil, err
}
discoveryClient := clientset.DiscoveryClient
apiGroups, err := discoveryClient.ServerGroups()
if err != nil {
return nil, nil, err
}
metricsAPIAvailable := SupportedMetricsAPIVersionAvailable(apiGroups)
if !metricsAPIAvailable {
return nil, nil, fmt.Errorf("Metrics API not available")
}
config, err := memberFactory.ToRESTConfig()
if err != nil {
return nil, nil, err
}
if useProtocolBuffers {
config.ContentType = "application/vnd.kubernetes.protobuf"
}
metricsClient, err := metricsclientset.NewForConfig(config)
if err != nil {
return nil, nil, err
}
return clientset, metricsClient, nil
}