k9s/internal/dao/scalable.go

87 lines
2.1 KiB
Go

// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of K9s
package dao
import (
"context"
"log/slog"
"github.com/derailed/k9s/internal/client"
"github.com/derailed/k9s/internal/slogs"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/restmapper"
"k8s.io/client-go/scale"
)
var (
_ Scalable = (*Scaler)(nil)
_ ReplicasGetter = (*Scaler)(nil)
)
// Scaler represents a generic resource with scaling.
type Scaler struct {
Generic
}
// Replicas returns the number of replicas for the resource located at the given path.
func (s *Scaler) Replicas(ctx context.Context, path string) (int32, error) {
scaleClient, err := s.scaleClient()
if err != nil {
return 0, err
}
ns, name := client.Namespaced(path)
currScale, err := scaleClient.Scales(ns).Get(ctx, *s.gvr.GR(), name, metav1.GetOptions{})
if err != nil {
return 0, err
}
return currScale.Spec.Replicas, nil
}
// Scale modifies the number of replicas for a given resource specified by the path.
func (s *Scaler) Scale(ctx context.Context, path string, replicas int32) error {
ns, name := client.Namespaced(path)
scaleClient, err := s.scaleClient()
if err != nil {
return err
}
currentScale, err := scaleClient.Scales(ns).Get(ctx, *s.gvr.GR(), name, metav1.GetOptions{})
if err != nil {
return err
}
currentScale.Spec.Replicas = replicas
updatedScale, err := scaleClient.Scales(ns).Update(ctx, *s.gvr.GR(), currentScale, metav1.UpdateOptions{})
if err != nil {
return err
}
slog.Debug("Scaled resource",
slogs.FQN, path,
slogs.Replicas, updatedScale.Spec.Replicas,
)
return nil
}
func (s *Scaler) scaleClient() (scale.ScalesGetter, error) {
cfg, err := s.Client().RestConfig()
if err != nil {
return nil, err
}
discoveryClient, err := s.Client().CachedDiscovery()
if err != nil {
return nil, err
}
mapper := restmapper.NewDeferredDiscoveryRESTMapper(discoveryClient)
scaleKindResolver := scale.NewDiscoveryScaleKindResolver(discoveryClient)
return scale.NewForConfig(cfg, mapper, dynamic.LegacyAPIPathResolverFunc, scaleKindResolver)
}