| 
 | 1 | +package resourcelimits  | 
 | 2 | + | 
 | 3 | +import (  | 
 | 4 | +	"fmt"  | 
 | 5 | + | 
 | 6 | +	corev1 "k8s.io/api/core/v1"  | 
 | 7 | +	"k8s.io/autoscaler/cluster-autoscaler/context"  | 
 | 8 | +	"k8s.io/autoscaler/cluster-autoscaler/processors/customresources"  | 
 | 9 | +)  | 
 | 10 | + | 
 | 11 | +// TrackerFactory builds trackers.  | 
 | 12 | +type TrackerFactory struct {  | 
 | 13 | +	crp             customresources.CustomResourcesProcessor  | 
 | 14 | +	limitProviders  []Provider  | 
 | 15 | +	usageCalculator *usageCalculator  | 
 | 16 | +}  | 
 | 17 | + | 
 | 18 | +// NewTrackerFactory creates a new TrackerFactory.  | 
 | 19 | +func NewTrackerFactory(opts TrackerOptions) *TrackerFactory {  | 
 | 20 | +	uc := newUsageCalculator(opts.CRP, opts.NodeFilter)  | 
 | 21 | +	return &TrackerFactory{  | 
 | 22 | +		crp:             opts.CRP,  | 
 | 23 | +		limitProviders:  opts.Providers,  | 
 | 24 | +		usageCalculator: uc,  | 
 | 25 | +	}  | 
 | 26 | +}  | 
 | 27 | + | 
 | 28 | +// NewMaxLimitsTracker builds a new Tracker for max limits.  | 
 | 29 | +func (f *TrackerFactory) NewMaxLimitsTracker(ctx *context.AutoscalingContext, nodes []*corev1.Node) (*Tracker, error) {  | 
 | 30 | +	return f.newLimitsTracker(ctx, nodes, &maxLimitsStrategy{})  | 
 | 31 | +}  | 
 | 32 | + | 
 | 33 | +// NewMinLimitsTracker builds a new Tracker for min limits.  | 
 | 34 | +func (f *TrackerFactory) NewMinLimitsTracker(ctx *context.AutoscalingContext, nodes []*corev1.Node) (*Tracker, error) {  | 
 | 35 | +	return f.newLimitsTracker(ctx, nodes, &minLimitsStrategy{})  | 
 | 36 | +}  | 
 | 37 | + | 
 | 38 | +func (f *TrackerFactory) newLimitsTracker(ctx *context.AutoscalingContext, nodes []*corev1.Node, strategy limitStrategy) (*Tracker, error) {  | 
 | 39 | +	limiters, err := f.limiters()  | 
 | 40 | +	if err != nil {  | 
 | 41 | +		return nil, err  | 
 | 42 | +	}  | 
 | 43 | +	usages, err := f.usageCalculator.calculateUsages(ctx, nodes, limiters)  | 
 | 44 | +	if err != nil {  | 
 | 45 | +		return nil, err  | 
 | 46 | +	}  | 
 | 47 | +	limitsLeft := make(map[string]resourceList)  | 
 | 48 | +	for _, rl := range limiters {  | 
 | 49 | +		limitsLeft[rl.ID()] = make(resourceList)  | 
 | 50 | +		limits := strategy.GetLimits(rl)  | 
 | 51 | +		for resourceType, limit := range limits {  | 
 | 52 | +			usage := usages[rl.ID()][resourceType]  | 
 | 53 | +			limitsLeft[rl.ID()][resourceType] = strategy.CalculateLimitsLeft(limit, usage)  | 
 | 54 | +		}  | 
 | 55 | +	}  | 
 | 56 | +	tracker := newTracker(f.crp, limiters, limitsLeft)  | 
 | 57 | +	return tracker, nil  | 
 | 58 | +}  | 
 | 59 | + | 
 | 60 | +func (f *TrackerFactory) limiters() ([]Limiter, error) {  | 
 | 61 | +	var limiters []Limiter  | 
 | 62 | +	for _, provider := range f.limitProviders {  | 
 | 63 | +		provLimiters, err := provider.AllLimiters()  | 
 | 64 | +		if err != nil {  | 
 | 65 | +			return nil, fmt.Errorf("failed to get limiters from provider: %w", err)  | 
 | 66 | +		}  | 
 | 67 | +		for _, limiter := range provLimiters {  | 
 | 68 | +			limiters = append(limiters, limiter)  | 
 | 69 | +		}  | 
 | 70 | +	}  | 
 | 71 | +	return limiters, nil  | 
 | 72 | +}  | 
 | 73 | + | 
 | 74 | +// limitStrategy is an interface for defining limit calculation strategies.  | 
 | 75 | +type limitStrategy interface {  | 
 | 76 | +	GetLimits(rl Limiter) resourceList  | 
 | 77 | +	CalculateLimitsLeft(limit, usage int64) int64  | 
 | 78 | +}  | 
 | 79 | + | 
 | 80 | +// maxLimitsStrategy is a strategy for max limits.  | 
 | 81 | +type maxLimitsStrategy struct{}  | 
 | 82 | + | 
 | 83 | +// GetLimits returns max limits.  | 
 | 84 | +func (s *maxLimitsStrategy) GetLimits(rl Limiter) resourceList {  | 
 | 85 | +	return rl.MaxLimits()  | 
 | 86 | +}  | 
 | 87 | + | 
 | 88 | +// CalculateLimitsLeft calculates the remaining limits for max limits.  | 
 | 89 | +func (s *maxLimitsStrategy) CalculateLimitsLeft(limit, usage int64) int64 {  | 
 | 90 | +	return max(0, limit-usage)  | 
 | 91 | +}  | 
 | 92 | + | 
 | 93 | +// minLimitsStrategy is a strategy for min limits.  | 
 | 94 | +type minLimitsStrategy struct{}  | 
 | 95 | + | 
 | 96 | +// GetLimits returns min limits.  | 
 | 97 | +func (s *minLimitsStrategy) GetLimits(rl Limiter) resourceList {  | 
 | 98 | +	return rl.MinLimits()  | 
 | 99 | +}  | 
 | 100 | + | 
 | 101 | +// CalculateLimitsLeft calculates the remaining limits for min limits.  | 
 | 102 | +func (s *minLimitsStrategy) CalculateLimitsLeft(limit, usage int64) int64 {  | 
 | 103 | +	return max(0, usage-limit)  | 
 | 104 | +}  | 
0 commit comments