mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Merge pull request #112554 from kushagra98/variable-name-change
variable name change for better understanding
This commit is contained in:
		@@ -373,7 +373,7 @@ func (a *HorizontalController) reconcileKey(ctx context.Context, key string) (de
 | 
			
		||||
// computeStatusForObjectMetric computes the desired number of replicas for the specified metric of type ObjectMetricSourceType.
 | 
			
		||||
func (a *HorizontalController) computeStatusForObjectMetric(specReplicas, statusReplicas int32, metricSpec autoscalingv2.MetricSpec, hpa *autoscalingv2.HorizontalPodAutoscaler, selector labels.Selector, status *autoscalingv2.MetricStatus, metricSelector labels.Selector) (replicas int32, timestamp time.Time, metricName string, condition autoscalingv2.HorizontalPodAutoscalerCondition, err error) {
 | 
			
		||||
	if metricSpec.Object.Target.Type == autoscalingv2.ValueMetricType {
 | 
			
		||||
		replicaCountProposal, utilizationProposal, timestampProposal, err := a.replicaCalc.GetObjectMetricReplicas(specReplicas, metricSpec.Object.Target.Value.MilliValue(), metricSpec.Object.Metric.Name, hpa.Namespace, &metricSpec.Object.DescribedObject, selector, metricSelector)
 | 
			
		||||
		replicaCountProposal, usageProposal, timestampProposal, err := a.replicaCalc.GetObjectMetricReplicas(specReplicas, metricSpec.Object.Target.Value.MilliValue(), metricSpec.Object.Metric.Name, hpa.Namespace, &metricSpec.Object.DescribedObject, selector, metricSelector)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			condition := a.getUnableComputeReplicaCountCondition(hpa, "FailedGetObjectMetric", err)
 | 
			
		||||
			return 0, timestampProposal, "", condition, err
 | 
			
		||||
@@ -387,13 +387,13 @@ func (a *HorizontalController) computeStatusForObjectMetric(specReplicas, status
 | 
			
		||||
					Selector: metricSpec.Object.Metric.Selector,
 | 
			
		||||
				},
 | 
			
		||||
				Current: autoscalingv2.MetricValueStatus{
 | 
			
		||||
					Value: resource.NewMilliQuantity(utilizationProposal, resource.DecimalSI),
 | 
			
		||||
					Value: resource.NewMilliQuantity(usageProposal, resource.DecimalSI),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
		return replicaCountProposal, timestampProposal, fmt.Sprintf("%s metric %s", metricSpec.Object.DescribedObject.Kind, metricSpec.Object.Metric.Name), autoscalingv2.HorizontalPodAutoscalerCondition{}, nil
 | 
			
		||||
	} else if metricSpec.Object.Target.Type == autoscalingv2.AverageValueMetricType {
 | 
			
		||||
		replicaCountProposal, utilizationProposal, timestampProposal, err := a.replicaCalc.GetObjectPerPodMetricReplicas(statusReplicas, metricSpec.Object.Target.AverageValue.MilliValue(), metricSpec.Object.Metric.Name, hpa.Namespace, &metricSpec.Object.DescribedObject, metricSelector)
 | 
			
		||||
		replicaCountProposal, usageProposal, timestampProposal, err := a.replicaCalc.GetObjectPerPodMetricReplicas(statusReplicas, metricSpec.Object.Target.AverageValue.MilliValue(), metricSpec.Object.Metric.Name, hpa.Namespace, &metricSpec.Object.DescribedObject, metricSelector)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			condition := a.getUnableComputeReplicaCountCondition(hpa, "FailedGetObjectMetric", err)
 | 
			
		||||
			return 0, time.Time{}, "", condition, fmt.Errorf("failed to get %s object metric: %v", metricSpec.Object.Metric.Name, err)
 | 
			
		||||
@@ -406,7 +406,7 @@ func (a *HorizontalController) computeStatusForObjectMetric(specReplicas, status
 | 
			
		||||
					Selector: metricSpec.Object.Metric.Selector,
 | 
			
		||||
				},
 | 
			
		||||
				Current: autoscalingv2.MetricValueStatus{
 | 
			
		||||
					AverageValue: resource.NewMilliQuantity(utilizationProposal, resource.DecimalSI),
 | 
			
		||||
					AverageValue: resource.NewMilliQuantity(usageProposal, resource.DecimalSI),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
@@ -420,7 +420,7 @@ func (a *HorizontalController) computeStatusForObjectMetric(specReplicas, status
 | 
			
		||||
 | 
			
		||||
// computeStatusForPodsMetric computes the desired number of replicas for the specified metric of type PodsMetricSourceType.
 | 
			
		||||
func (a *HorizontalController) computeStatusForPodsMetric(currentReplicas int32, metricSpec autoscalingv2.MetricSpec, hpa *autoscalingv2.HorizontalPodAutoscaler, selector labels.Selector, status *autoscalingv2.MetricStatus, metricSelector labels.Selector) (replicaCountProposal int32, timestampProposal time.Time, metricNameProposal string, condition autoscalingv2.HorizontalPodAutoscalerCondition, err error) {
 | 
			
		||||
	replicaCountProposal, utilizationProposal, timestampProposal, err := a.replicaCalc.GetMetricReplicas(currentReplicas, metricSpec.Pods.Target.AverageValue.MilliValue(), metricSpec.Pods.Metric.Name, hpa.Namespace, selector, metricSelector)
 | 
			
		||||
	replicaCountProposal, usageProposal, timestampProposal, err := a.replicaCalc.GetMetricReplicas(currentReplicas, metricSpec.Pods.Target.AverageValue.MilliValue(), metricSpec.Pods.Metric.Name, hpa.Namespace, selector, metricSelector)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		condition = a.getUnableComputeReplicaCountCondition(hpa, "FailedGetPodsMetric", err)
 | 
			
		||||
		return 0, timestampProposal, "", condition, err
 | 
			
		||||
@@ -433,7 +433,7 @@ func (a *HorizontalController) computeStatusForPodsMetric(currentReplicas int32,
 | 
			
		||||
				Selector: metricSpec.Pods.Metric.Selector,
 | 
			
		||||
			},
 | 
			
		||||
			Current: autoscalingv2.MetricValueStatus{
 | 
			
		||||
				AverageValue: resource.NewMilliQuantity(utilizationProposal, resource.DecimalSI),
 | 
			
		||||
				AverageValue: resource.NewMilliQuantity(usageProposal, resource.DecimalSI),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
@@ -449,7 +449,7 @@ func (a *HorizontalController) computeStatusForResourceMetricGeneric(ctx context
 | 
			
		||||
		var rawProposal int64
 | 
			
		||||
		replicaCountProposal, rawProposal, timestampProposal, err := a.replicaCalc.GetRawResourceReplicas(ctx, currentReplicas, target.AverageValue.MilliValue(), resourceName, namespace, selector, container)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return 0, nil, time.Time{}, "", condition, fmt.Errorf("failed to get %s utilization: %v", resourceName, err)
 | 
			
		||||
			return 0, nil, time.Time{}, "", condition, fmt.Errorf("failed to get %s usage: %v", resourceName, err)
 | 
			
		||||
		}
 | 
			
		||||
		metricNameProposal = fmt.Sprintf("%s resource", resourceName.String())
 | 
			
		||||
		status := autoscalingv2.MetricValueStatus{
 | 
			
		||||
@@ -459,7 +459,7 @@ func (a *HorizontalController) computeStatusForResourceMetricGeneric(ctx context
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if target.AverageUtilization == nil {
 | 
			
		||||
		errMsg := "invalid resource metric source: neither an average utilization target nor an average value target was set"
 | 
			
		||||
		errMsg := "invalid resource metric source: neither an average utilization target nor an average value (usage) target was set"
 | 
			
		||||
		return 0, nil, time.Time{}, "", condition, fmt.Errorf(errMsg)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -519,7 +519,7 @@ func (a *HorizontalController) computeStatusForContainerResourceMetric(ctx conte
 | 
			
		||||
// computeStatusForExternalMetric computes the desired number of replicas for the specified metric of type ExternalMetricSourceType.
 | 
			
		||||
func (a *HorizontalController) computeStatusForExternalMetric(specReplicas, statusReplicas int32, metricSpec autoscalingv2.MetricSpec, hpa *autoscalingv2.HorizontalPodAutoscaler, selector labels.Selector, status *autoscalingv2.MetricStatus) (replicaCountProposal int32, timestampProposal time.Time, metricNameProposal string, condition autoscalingv2.HorizontalPodAutoscalerCondition, err error) {
 | 
			
		||||
	if metricSpec.External.Target.AverageValue != nil {
 | 
			
		||||
		replicaCountProposal, utilizationProposal, timestampProposal, err := a.replicaCalc.GetExternalPerPodMetricReplicas(statusReplicas, metricSpec.External.Target.AverageValue.MilliValue(), metricSpec.External.Metric.Name, hpa.Namespace, metricSpec.External.Metric.Selector)
 | 
			
		||||
		replicaCountProposal, usageProposal, timestampProposal, err := a.replicaCalc.GetExternalPerPodMetricReplicas(statusReplicas, metricSpec.External.Target.AverageValue.MilliValue(), metricSpec.External.Metric.Name, hpa.Namespace, metricSpec.External.Metric.Selector)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			condition = a.getUnableComputeReplicaCountCondition(hpa, "FailedGetExternalMetric", err)
 | 
			
		||||
			return 0, time.Time{}, "", condition, fmt.Errorf("failed to get %s external metric: %v", metricSpec.External.Metric.Name, err)
 | 
			
		||||
@@ -532,14 +532,14 @@ func (a *HorizontalController) computeStatusForExternalMetric(specReplicas, stat
 | 
			
		||||
					Selector: metricSpec.External.Metric.Selector,
 | 
			
		||||
				},
 | 
			
		||||
				Current: autoscalingv2.MetricValueStatus{
 | 
			
		||||
					AverageValue: resource.NewMilliQuantity(utilizationProposal, resource.DecimalSI),
 | 
			
		||||
					AverageValue: resource.NewMilliQuantity(usageProposal, resource.DecimalSI),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
		return replicaCountProposal, timestampProposal, fmt.Sprintf("external metric %s(%+v)", metricSpec.External.Metric.Name, metricSpec.External.Metric.Selector), autoscalingv2.HorizontalPodAutoscalerCondition{}, nil
 | 
			
		||||
	}
 | 
			
		||||
	if metricSpec.External.Target.Value != nil {
 | 
			
		||||
		replicaCountProposal, utilizationProposal, timestampProposal, err := a.replicaCalc.GetExternalMetricReplicas(specReplicas, metricSpec.External.Target.Value.MilliValue(), metricSpec.External.Metric.Name, hpa.Namespace, metricSpec.External.Metric.Selector, selector)
 | 
			
		||||
		replicaCountProposal, usageProposal, timestampProposal, err := a.replicaCalc.GetExternalMetricReplicas(specReplicas, metricSpec.External.Target.Value.MilliValue(), metricSpec.External.Metric.Name, hpa.Namespace, metricSpec.External.Metric.Selector, selector)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			condition = a.getUnableComputeReplicaCountCondition(hpa, "FailedGetExternalMetric", err)
 | 
			
		||||
			return 0, time.Time{}, "", condition, fmt.Errorf("failed to get external metric %s: %v", metricSpec.External.Metric.Name, err)
 | 
			
		||||
@@ -552,7 +552,7 @@ func (a *HorizontalController) computeStatusForExternalMetric(specReplicas, stat
 | 
			
		||||
					Selector: metricSpec.External.Metric.Selector,
 | 
			
		||||
				},
 | 
			
		||||
				Current: autoscalingv2.MetricValueStatus{
 | 
			
		||||
					Value: resource.NewMilliQuantity(utilizationProposal, resource.DecimalSI),
 | 
			
		||||
					Value: resource.NewMilliQuantity(usageProposal, resource.DecimalSI),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -51,16 +51,16 @@ func GetResourceUtilizationRatio(metrics PodMetricsInfo, requests map[string]int
 | 
			
		||||
	return float64(currentUtilization) / float64(targetUtilization), currentUtilization, metricsTotal / int64(numEntries), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetMetricUtilizationRatio takes in a set of metrics and a target utilization value,
 | 
			
		||||
// and calculates the ratio of desired to actual utilization
 | 
			
		||||
// (returning that and the actual utilization)
 | 
			
		||||
func GetMetricUtilizationRatio(metrics PodMetricsInfo, targetUtilization int64) (utilizationRatio float64, currentUtilization int64) {
 | 
			
		||||
// GetMetricUsageRatio takes in a set of metrics and a target usage value,
 | 
			
		||||
// and calculates the ratio of desired to actual usage
 | 
			
		||||
// (returning that and the actual usage)
 | 
			
		||||
func GetMetricUsageRatio(metrics PodMetricsInfo, targetUsage int64) (usageRatio float64, currentUsage int64) {
 | 
			
		||||
	metricsTotal := int64(0)
 | 
			
		||||
	for _, metric := range metrics {
 | 
			
		||||
		metricsTotal += metric.Value
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	currentUtilization = metricsTotal / int64(len(metrics))
 | 
			
		||||
	currentUsage = metricsTotal / int64(len(metrics))
 | 
			
		||||
 | 
			
		||||
	return float64(currentUtilization) / float64(targetUtilization), currentUtilization
 | 
			
		||||
	return float64(currentUsage) / float64(targetUsage), currentUsage
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -49,19 +49,19 @@ func (tc *resourceUtilizationRatioTestCase) runTest(t *testing.T) {
 | 
			
		||||
	assert.Equal(t, tc.expectedRawAverageValue, actualRawAverageValue, "the raw average value should be as expected")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type metricUtilizationRatioTestCase struct {
 | 
			
		||||
	metrics           PodMetricsInfo
 | 
			
		||||
	targetUtilization int64
 | 
			
		||||
type metricUsageRatioTestCase struct {
 | 
			
		||||
	metrics     PodMetricsInfo
 | 
			
		||||
	targetUsage int64
 | 
			
		||||
 | 
			
		||||
	expectedUtilizationRatio   float64
 | 
			
		||||
	expectedCurrentUtilization int64
 | 
			
		||||
	expectedUsageRatio   float64
 | 
			
		||||
	expectedCurrentUsage int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (tc *metricUtilizationRatioTestCase) runTest(t *testing.T) {
 | 
			
		||||
	actualUtilizationRatio, actualCurrentUtilization := GetMetricUtilizationRatio(tc.metrics, tc.targetUtilization)
 | 
			
		||||
func (tc *metricUsageRatioTestCase) runTest(t *testing.T) {
 | 
			
		||||
	actualUsageRatio, actualCurrentUsage := GetMetricUsageRatio(tc.metrics, tc.targetUsage)
 | 
			
		||||
 | 
			
		||||
	assert.Equal(t, tc.expectedUtilizationRatio, actualUtilizationRatio, "the utilization ratios should be as expected")
 | 
			
		||||
	assert.Equal(t, tc.expectedCurrentUtilization, actualCurrentUtilization, "the current utilization should be as expected")
 | 
			
		||||
	assert.Equal(t, tc.expectedUsageRatio, actualUsageRatio, "the usage ratios should be as expected")
 | 
			
		||||
	assert.Equal(t, tc.expectedCurrentUsage, actualCurrentUsage, "the current usage should be as expected")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGetResourceUtilizationRatioBaseCase(t *testing.T) {
 | 
			
		||||
@@ -135,14 +135,14 @@ func TestGetResourceUtilizationRatioNoRequests(t *testing.T) {
 | 
			
		||||
	tc.runTest(t)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGetMetricUtilizationRatioBaseCase(t *testing.T) {
 | 
			
		||||
	tc := metricUtilizationRatioTestCase{
 | 
			
		||||
func TestGetMetricUsageRatioBaseCase(t *testing.T) {
 | 
			
		||||
	tc := metricUsageRatioTestCase{
 | 
			
		||||
		metrics: PodMetricsInfo{
 | 
			
		||||
			"test-pod-0": {Value: 5000}, "test-pod-1": {Value: 10000},
 | 
			
		||||
		},
 | 
			
		||||
		targetUtilization:          10000,
 | 
			
		||||
		expectedUtilizationRatio:   .75,
 | 
			
		||||
		expectedCurrentUtilization: 7500,
 | 
			
		||||
		targetUsage:          10000,
 | 
			
		||||
		expectedUsageRatio:   .75,
 | 
			
		||||
		expectedCurrentUsage: 7500,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tc.runTest(t)
 | 
			
		||||
 
 | 
			
		||||
@@ -149,33 +149,33 @@ func (c *ReplicaCalculator) GetResourceReplicas(ctx context.Context, currentRepl
 | 
			
		||||
	return newReplicas, utilization, rawUtilization, timestamp, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetRawResourceReplicas calculates the desired replica count based on a target resource utilization (as a raw milli-value)
 | 
			
		||||
// GetRawResourceReplicas calculates the desired replica count based on a target resource usage (as a raw milli-value)
 | 
			
		||||
// for pods matching the given selector in the given namespace, and the current replica count
 | 
			
		||||
func (c *ReplicaCalculator) GetRawResourceReplicas(ctx context.Context, currentReplicas int32, targetUtilization int64, resource v1.ResourceName, namespace string, selector labels.Selector, container string) (replicaCount int32, utilization int64, timestamp time.Time, err error) {
 | 
			
		||||
func (c *ReplicaCalculator) GetRawResourceReplicas(ctx context.Context, currentReplicas int32, targetUsage int64, resource v1.ResourceName, namespace string, selector labels.Selector, container string) (replicaCount int32, usage int64, timestamp time.Time, err error) {
 | 
			
		||||
	metrics, timestamp, err := c.metricsClient.GetResourceMetric(ctx, resource, namespace, selector, container)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0, time.Time{}, fmt.Errorf("unable to get metrics for resource %s: %v", resource, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	replicaCount, utilization, err = c.calcPlainMetricReplicas(metrics, currentReplicas, targetUtilization, namespace, selector, resource)
 | 
			
		||||
	return replicaCount, utilization, timestamp, err
 | 
			
		||||
	replicaCount, usage, err = c.calcPlainMetricReplicas(metrics, currentReplicas, targetUsage, namespace, selector, resource)
 | 
			
		||||
	return replicaCount, usage, timestamp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetMetricReplicas calculates the desired replica count based on a target metric utilization
 | 
			
		||||
// GetMetricReplicas calculates the desired replica count based on a target metric usage
 | 
			
		||||
// (as a milli-value) for pods matching the given selector in the given namespace, and the
 | 
			
		||||
// current replica count
 | 
			
		||||
func (c *ReplicaCalculator) GetMetricReplicas(currentReplicas int32, targetUtilization int64, metricName string, namespace string, selector labels.Selector, metricSelector labels.Selector) (replicaCount int32, utilization int64, timestamp time.Time, err error) {
 | 
			
		||||
func (c *ReplicaCalculator) GetMetricReplicas(currentReplicas int32, targetUsage int64, metricName string, namespace string, selector labels.Selector, metricSelector labels.Selector) (replicaCount int32, usage int64, timestamp time.Time, err error) {
 | 
			
		||||
	metrics, timestamp, err := c.metricsClient.GetRawMetric(metricName, namespace, selector, metricSelector)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0, time.Time{}, fmt.Errorf("unable to get metric %s: %v", metricName, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	replicaCount, utilization, err = c.calcPlainMetricReplicas(metrics, currentReplicas, targetUtilization, namespace, selector, v1.ResourceName(""))
 | 
			
		||||
	return replicaCount, utilization, timestamp, err
 | 
			
		||||
	replicaCount, usage, err = c.calcPlainMetricReplicas(metrics, currentReplicas, targetUsage, namespace, selector, v1.ResourceName(""))
 | 
			
		||||
	return replicaCount, usage, timestamp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// calcPlainMetricReplicas calculates the desired replicas for plain (i.e. non-utilization percentage) metrics.
 | 
			
		||||
func (c *ReplicaCalculator) calcPlainMetricReplicas(metrics metricsclient.PodMetricsInfo, currentReplicas int32, targetUtilization int64, namespace string, selector labels.Selector, resource v1.ResourceName) (replicaCount int32, utilization int64, err error) {
 | 
			
		||||
func (c *ReplicaCalculator) calcPlainMetricReplicas(metrics metricsclient.PodMetricsInfo, currentReplicas int32, targetUsage int64, namespace string, selector labels.Selector, resource v1.ResourceName) (replicaCount int32, usage int64, err error) {
 | 
			
		||||
 | 
			
		||||
	podList, err := c.podLister.Pods(namespace).List(selector)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -194,25 +194,25 @@ func (c *ReplicaCalculator) calcPlainMetricReplicas(metrics metricsclient.PodMet
 | 
			
		||||
		return 0, 0, fmt.Errorf("did not receive metrics for any ready pods")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	usageRatio, utilization := metricsclient.GetMetricUtilizationRatio(metrics, targetUtilization)
 | 
			
		||||
	usageRatio, usage := metricsclient.GetMetricUsageRatio(metrics, targetUsage)
 | 
			
		||||
 | 
			
		||||
	scaleUpWithUnready := len(unreadyPods) > 0 && usageRatio > 1.0
 | 
			
		||||
 | 
			
		||||
	if !scaleUpWithUnready && len(missingPods) == 0 {
 | 
			
		||||
		if math.Abs(1.0-usageRatio) <= c.tolerance {
 | 
			
		||||
			// return the current replicas if the change would be too small
 | 
			
		||||
			return currentReplicas, utilization, nil
 | 
			
		||||
			return currentReplicas, usage, nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// if we don't have any unready or missing pods, we can calculate the new replica count now
 | 
			
		||||
		return int32(math.Ceil(usageRatio * float64(readyPodCount))), utilization, nil
 | 
			
		||||
		return int32(math.Ceil(usageRatio * float64(readyPodCount))), usage, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(missingPods) > 0 {
 | 
			
		||||
		if usageRatio < 1.0 {
 | 
			
		||||
			// on a scale-down, treat missing pods as using exactly the target amount
 | 
			
		||||
			for podName := range missingPods {
 | 
			
		||||
				metrics[podName] = metricsclient.PodMetric{Value: targetUtilization}
 | 
			
		||||
				metrics[podName] = metricsclient.PodMetric{Value: targetUsage}
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			// on a scale-up, treat missing pods as using 0% of the resource request
 | 
			
		||||
@@ -229,37 +229,37 @@ func (c *ReplicaCalculator) calcPlainMetricReplicas(metrics metricsclient.PodMet
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// re-run the utilization calculation with our new numbers
 | 
			
		||||
	newUsageRatio, _ := metricsclient.GetMetricUtilizationRatio(metrics, targetUtilization)
 | 
			
		||||
	// re-run the usage calculation with our new numbers
 | 
			
		||||
	newUsageRatio, _ := metricsclient.GetMetricUsageRatio(metrics, targetUsage)
 | 
			
		||||
 | 
			
		||||
	if math.Abs(1.0-newUsageRatio) <= c.tolerance || (usageRatio < 1.0 && newUsageRatio > 1.0) || (usageRatio > 1.0 && newUsageRatio < 1.0) {
 | 
			
		||||
		// return the current replicas if the change would be too small,
 | 
			
		||||
		// or if the new usage ratio would cause a change in scale direction
 | 
			
		||||
		return currentReplicas, utilization, nil
 | 
			
		||||
		return currentReplicas, usage, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	newReplicas := int32(math.Ceil(newUsageRatio * float64(len(metrics))))
 | 
			
		||||
	if (newUsageRatio < 1.0 && newReplicas > currentReplicas) || (newUsageRatio > 1.0 && newReplicas < currentReplicas) {
 | 
			
		||||
		// return the current replicas if the change of metrics length would cause a change in scale direction
 | 
			
		||||
		return currentReplicas, utilization, nil
 | 
			
		||||
		return currentReplicas, usage, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// return the result, where the number of replicas considered is
 | 
			
		||||
	// however many replicas factored into our calculation
 | 
			
		||||
	return newReplicas, utilization, nil
 | 
			
		||||
	return newReplicas, usage, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetObjectMetricReplicas calculates the desired replica count based on a target metric utilization (as a milli-value)
 | 
			
		||||
// GetObjectMetricReplicas calculates the desired replica count based on a target metric usage (as a milli-value)
 | 
			
		||||
// for the given object in the given namespace, and the current replica count.
 | 
			
		||||
func (c *ReplicaCalculator) GetObjectMetricReplicas(currentReplicas int32, targetUtilization int64, metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference, selector labels.Selector, metricSelector labels.Selector) (replicaCount int32, utilization int64, timestamp time.Time, err error) {
 | 
			
		||||
	utilization, _, err = c.metricsClient.GetObjectMetric(metricName, namespace, objectRef, metricSelector)
 | 
			
		||||
func (c *ReplicaCalculator) GetObjectMetricReplicas(currentReplicas int32, targetUsage int64, metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference, selector labels.Selector, metricSelector labels.Selector) (replicaCount int32, usage int64, timestamp time.Time, err error) {
 | 
			
		||||
	usage, _, err = c.metricsClient.GetObjectMetric(metricName, namespace, objectRef, metricSelector)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0, time.Time{}, fmt.Errorf("unable to get metric %s: %v on %s %s/%s", metricName, objectRef.Kind, namespace, objectRef.Name, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	usageRatio := float64(utilization) / float64(targetUtilization)
 | 
			
		||||
	usageRatio := float64(usage) / float64(targetUsage)
 | 
			
		||||
	replicaCount, timestamp, err = c.getUsageRatioReplicaCount(currentReplicas, usageRatio, namespace, selector)
 | 
			
		||||
	return replicaCount, utilization, timestamp, err
 | 
			
		||||
	return replicaCount, usage, timestamp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getUsageRatioReplicaCount calculates the desired replica count based on usageRatio and ready pods count.
 | 
			
		||||
@@ -284,22 +284,22 @@ func (c *ReplicaCalculator) getUsageRatioReplicaCount(currentReplicas int32, usa
 | 
			
		||||
	return replicaCount, timestamp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetObjectPerPodMetricReplicas calculates the desired replica count based on a target metric utilization (as a milli-value)
 | 
			
		||||
// GetObjectPerPodMetricReplicas calculates the desired replica count based on a target metric usage (as a milli-value)
 | 
			
		||||
// for the given object in the given namespace, and the current replica count.
 | 
			
		||||
func (c *ReplicaCalculator) GetObjectPerPodMetricReplicas(statusReplicas int32, targetAverageUtilization int64, metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference, metricSelector labels.Selector) (replicaCount int32, utilization int64, timestamp time.Time, err error) {
 | 
			
		||||
	utilization, timestamp, err = c.metricsClient.GetObjectMetric(metricName, namespace, objectRef, metricSelector)
 | 
			
		||||
func (c *ReplicaCalculator) GetObjectPerPodMetricReplicas(statusReplicas int32, targetAverageUsage int64, metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference, metricSelector labels.Selector) (replicaCount int32, usage int64, timestamp time.Time, err error) {
 | 
			
		||||
	usage, timestamp, err = c.metricsClient.GetObjectMetric(metricName, namespace, objectRef, metricSelector)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0, time.Time{}, fmt.Errorf("unable to get metric %s: %v on %s %s/%s", metricName, objectRef.Kind, namespace, objectRef.Name, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	replicaCount = statusReplicas
 | 
			
		||||
	usageRatio := float64(utilization) / (float64(targetAverageUtilization) * float64(replicaCount))
 | 
			
		||||
	usageRatio := float64(usage) / (float64(targetAverageUsage) * float64(replicaCount))
 | 
			
		||||
	if math.Abs(1.0-usageRatio) > c.tolerance {
 | 
			
		||||
		// update number of replicas if change is large enough
 | 
			
		||||
		replicaCount = int32(math.Ceil(float64(utilization) / float64(targetAverageUtilization)))
 | 
			
		||||
		replicaCount = int32(math.Ceil(float64(usage) / float64(targetAverageUsage)))
 | 
			
		||||
	}
 | 
			
		||||
	utilization = int64(math.Ceil(float64(utilization) / float64(statusReplicas)))
 | 
			
		||||
	return replicaCount, utilization, timestamp, nil
 | 
			
		||||
	usage = int64(math.Ceil(float64(usage) / float64(statusReplicas)))
 | 
			
		||||
	return replicaCount, usage, timestamp, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// @TODO(mattjmcnaughton) Many different functions in this module use variations
 | 
			
		||||
@@ -329,7 +329,7 @@ func (c *ReplicaCalculator) getReadyPodsCount(namespace string, selector labels.
 | 
			
		||||
// GetExternalMetricReplicas calculates the desired replica count based on a
 | 
			
		||||
// target metric value (as a milli-value) for the external metric in the given
 | 
			
		||||
// namespace, and the current replica count.
 | 
			
		||||
func (c *ReplicaCalculator) GetExternalMetricReplicas(currentReplicas int32, targetUtilization int64, metricName, namespace string, metricSelector *metav1.LabelSelector, podSelector labels.Selector) (replicaCount int32, utilization int64, timestamp time.Time, err error) {
 | 
			
		||||
func (c *ReplicaCalculator) GetExternalMetricReplicas(currentReplicas int32, targetUsage int64, metricName, namespace string, metricSelector *metav1.LabelSelector, podSelector labels.Selector) (replicaCount int32, usage int64, timestamp time.Time, err error) {
 | 
			
		||||
	metricLabelSelector, err := metav1.LabelSelectorAsSelector(metricSelector)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0, time.Time{}, err
 | 
			
		||||
@@ -338,20 +338,20 @@ func (c *ReplicaCalculator) GetExternalMetricReplicas(currentReplicas int32, tar
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0, time.Time{}, fmt.Errorf("unable to get external metric %s/%s/%+v: %s", namespace, metricName, metricSelector, err)
 | 
			
		||||
	}
 | 
			
		||||
	utilization = 0
 | 
			
		||||
	usage = 0
 | 
			
		||||
	for _, val := range metrics {
 | 
			
		||||
		utilization = utilization + val
 | 
			
		||||
		usage = usage + val
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	usageRatio := float64(utilization) / float64(targetUtilization)
 | 
			
		||||
	usageRatio := float64(usage) / float64(targetUsage)
 | 
			
		||||
	replicaCount, timestamp, err = c.getUsageRatioReplicaCount(currentReplicas, usageRatio, namespace, podSelector)
 | 
			
		||||
	return replicaCount, utilization, timestamp, err
 | 
			
		||||
	return replicaCount, usage, timestamp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetExternalPerPodMetricReplicas calculates the desired replica count based on a
 | 
			
		||||
// target metric value per pod (as a milli-value) for the external metric in the
 | 
			
		||||
// given namespace, and the current replica count.
 | 
			
		||||
func (c *ReplicaCalculator) GetExternalPerPodMetricReplicas(statusReplicas int32, targetUtilizationPerPod int64, metricName, namespace string, metricSelector *metav1.LabelSelector) (replicaCount int32, utilization int64, timestamp time.Time, err error) {
 | 
			
		||||
func (c *ReplicaCalculator) GetExternalPerPodMetricReplicas(statusReplicas int32, targetUsagePerPod int64, metricName, namespace string, metricSelector *metav1.LabelSelector) (replicaCount int32, usage int64, timestamp time.Time, err error) {
 | 
			
		||||
	metricLabelSelector, err := metav1.LabelSelectorAsSelector(metricSelector)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0, time.Time{}, err
 | 
			
		||||
@@ -360,19 +360,19 @@ func (c *ReplicaCalculator) GetExternalPerPodMetricReplicas(statusReplicas int32
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0, time.Time{}, fmt.Errorf("unable to get external metric %s/%s/%+v: %s", namespace, metricName, metricSelector, err)
 | 
			
		||||
	}
 | 
			
		||||
	utilization = 0
 | 
			
		||||
	usage = 0
 | 
			
		||||
	for _, val := range metrics {
 | 
			
		||||
		utilization = utilization + val
 | 
			
		||||
		usage = usage + val
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	replicaCount = statusReplicas
 | 
			
		||||
	usageRatio := float64(utilization) / (float64(targetUtilizationPerPod) * float64(replicaCount))
 | 
			
		||||
	usageRatio := float64(usage) / (float64(targetUsagePerPod) * float64(replicaCount))
 | 
			
		||||
	if math.Abs(1.0-usageRatio) > c.tolerance {
 | 
			
		||||
		// update number of replicas if the change is large enough
 | 
			
		||||
		replicaCount = int32(math.Ceil(float64(utilization) / float64(targetUtilizationPerPod)))
 | 
			
		||||
		replicaCount = int32(math.Ceil(float64(usage) / float64(targetUsagePerPod)))
 | 
			
		||||
	}
 | 
			
		||||
	utilization = int64(math.Ceil(float64(utilization) / float64(statusReplicas)))
 | 
			
		||||
	return replicaCount, utilization, timestamp, nil
 | 
			
		||||
	usage = int64(math.Ceil(float64(usage) / float64(statusReplicas)))
 | 
			
		||||
	return replicaCount, usage, timestamp, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func groupPods(pods []*v1.Pod, metrics metricsclient.PodMetricsInfo, resource v1.ResourceName, cpuInitializationPeriod, delayOfInitialReadinessStatus time.Duration) (readyPodCount int, unreadyPods, missingPods, ignoredPods sets.String) {
 | 
			
		||||
 
 | 
			
		||||
@@ -78,9 +78,9 @@ type metricInfo struct {
 | 
			
		||||
	selector     *metav1.LabelSelector
 | 
			
		||||
	metricType   metricType
 | 
			
		||||
 | 
			
		||||
	targetUtilization       int64
 | 
			
		||||
	perPodTargetUtilization int64
 | 
			
		||||
	expectedUtilization     int64
 | 
			
		||||
	targetUsage       int64
 | 
			
		||||
	perPodTargetUsage int64
 | 
			
		||||
	expectedUsage     int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type replicaCalcTestCase struct {
 | 
			
		||||
@@ -376,38 +376,38 @@ func (tc *replicaCalcTestCase) runTest(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var outReplicas int32
 | 
			
		||||
	var outUtilization int64
 | 
			
		||||
	var outUsage int64
 | 
			
		||||
	var outTimestamp time.Time
 | 
			
		||||
	switch tc.metric.metricType {
 | 
			
		||||
	case objectMetric:
 | 
			
		||||
		if tc.metric.singleObject == nil {
 | 
			
		||||
			t.Fatal("Metric specified as objectMetric but metric.singleObject is nil.")
 | 
			
		||||
		}
 | 
			
		||||
		outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetObjectMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, tc.metric.singleObject, selector, nil)
 | 
			
		||||
		outReplicas, outUsage, outTimestamp, err = replicaCalc.GetObjectMetricReplicas(tc.currentReplicas, tc.metric.targetUsage, tc.metric.name, testNamespace, tc.metric.singleObject, selector, nil)
 | 
			
		||||
	case objectPerPodMetric:
 | 
			
		||||
		if tc.metric.singleObject == nil {
 | 
			
		||||
			t.Fatal("Metric specified as objectMetric but metric.singleObject is nil.")
 | 
			
		||||
		}
 | 
			
		||||
		outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetObjectPerPodMetricReplicas(tc.currentReplicas, tc.metric.perPodTargetUtilization, tc.metric.name, testNamespace, tc.metric.singleObject, nil)
 | 
			
		||||
		outReplicas, outUsage, outTimestamp, err = replicaCalc.GetObjectPerPodMetricReplicas(tc.currentReplicas, tc.metric.perPodTargetUsage, tc.metric.name, testNamespace, tc.metric.singleObject, nil)
 | 
			
		||||
	case externalMetric:
 | 
			
		||||
		if tc.metric.selector == nil {
 | 
			
		||||
			t.Fatal("Metric specified as externalMetric but metric.selector is nil.")
 | 
			
		||||
		}
 | 
			
		||||
		if tc.metric.targetUtilization <= 0 {
 | 
			
		||||
			t.Fatalf("Metric specified as externalMetric but metric.targetUtilization is %d which is <=0.", tc.metric.targetUtilization)
 | 
			
		||||
		if tc.metric.targetUsage <= 0 {
 | 
			
		||||
			t.Fatalf("Metric specified as externalMetric but metric.targetUsage is %d which is <=0.", tc.metric.targetUsage)
 | 
			
		||||
		}
 | 
			
		||||
		outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetExternalMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, tc.metric.selector, selector)
 | 
			
		||||
		outReplicas, outUsage, outTimestamp, err = replicaCalc.GetExternalMetricReplicas(tc.currentReplicas, tc.metric.targetUsage, tc.metric.name, testNamespace, tc.metric.selector, selector)
 | 
			
		||||
	case externalPerPodMetric:
 | 
			
		||||
		if tc.metric.selector == nil {
 | 
			
		||||
			t.Fatal("Metric specified as externalPerPodMetric but metric.selector is nil.")
 | 
			
		||||
		}
 | 
			
		||||
		if tc.metric.perPodTargetUtilization <= 0 {
 | 
			
		||||
			t.Fatalf("Metric specified as externalPerPodMetric but metric.perPodTargetUtilization is %d which is <=0.", tc.metric.perPodTargetUtilization)
 | 
			
		||||
		if tc.metric.perPodTargetUsage <= 0 {
 | 
			
		||||
			t.Fatalf("Metric specified as externalPerPodMetric but metric.perPodTargetUsage is %d which is <=0.", tc.metric.perPodTargetUsage)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetExternalPerPodMetricReplicas(tc.currentReplicas, tc.metric.perPodTargetUtilization, tc.metric.name, testNamespace, tc.metric.selector)
 | 
			
		||||
		outReplicas, outUsage, outTimestamp, err = replicaCalc.GetExternalPerPodMetricReplicas(tc.currentReplicas, tc.metric.perPodTargetUsage, tc.metric.name, testNamespace, tc.metric.selector)
 | 
			
		||||
	case podMetric:
 | 
			
		||||
		outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, selector, nil)
 | 
			
		||||
		outReplicas, outUsage, outTimestamp, err = replicaCalc.GetMetricReplicas(tc.currentReplicas, tc.metric.targetUsage, tc.metric.name, testNamespace, selector, nil)
 | 
			
		||||
	default:
 | 
			
		||||
		t.Fatalf("Unknown metric type: %d", tc.metric.metricType)
 | 
			
		||||
	}
 | 
			
		||||
@@ -419,7 +419,7 @@ func (tc *replicaCalcTestCase) runTest(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
	require.NoError(t, err, "there should not have been an error calculating the replica count")
 | 
			
		||||
	assert.Equal(t, tc.expectedReplicas, outReplicas, "replicas should be as expected")
 | 
			
		||||
	assert.Equal(t, tc.metric.expectedUtilization, outUtilization, "utilization should be as expected")
 | 
			
		||||
	assert.Equal(t, tc.metric.expectedUsage, outUsage, "usage should be as expected")
 | 
			
		||||
	assert.True(t, tc.timestamp.Equal(outTimestamp), "timestamp should be as expected")
 | 
			
		||||
}
 | 
			
		||||
func makePodMetricLevels(containerMetric ...int64) [][]int64 {
 | 
			
		||||
@@ -674,11 +674,11 @@ func TestReplicaCalcScaleUpCM(t *testing.T) {
 | 
			
		||||
		currentReplicas:  3,
 | 
			
		||||
		expectedReplicas: 4,
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			name:                "qps",
 | 
			
		||||
			levels:              []int64{20000, 10000, 30000},
 | 
			
		||||
			targetUtilization:   15000,
 | 
			
		||||
			expectedUtilization: 20000,
 | 
			
		||||
			metricType:          podMetric,
 | 
			
		||||
			name:          "qps",
 | 
			
		||||
			levels:        []int64{20000, 10000, 30000},
 | 
			
		||||
			targetUsage:   15000,
 | 
			
		||||
			expectedUsage: 20000,
 | 
			
		||||
			metricType:    podMetric,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	tc.runTest(t)
 | 
			
		||||
@@ -691,11 +691,11 @@ func TestReplicaCalcScaleUpCMUnreadyHotCpuNoLessScale(t *testing.T) {
 | 
			
		||||
		podReadiness:     []v1.ConditionStatus{v1.ConditionTrue, v1.ConditionTrue, v1.ConditionFalse},
 | 
			
		||||
		podStartTime:     []metav1.Time{coolCPUCreationTime(), coolCPUCreationTime(), hotCPUCreationTime()},
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			name:                "qps",
 | 
			
		||||
			levels:              []int64{50000, 10000, 30000},
 | 
			
		||||
			targetUtilization:   15000,
 | 
			
		||||
			expectedUtilization: 30000,
 | 
			
		||||
			metricType:          podMetric,
 | 
			
		||||
			name:          "qps",
 | 
			
		||||
			levels:        []int64{50000, 10000, 30000},
 | 
			
		||||
			targetUsage:   15000,
 | 
			
		||||
			expectedUsage: 30000,
 | 
			
		||||
			metricType:    podMetric,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	tc.runTest(t)
 | 
			
		||||
@@ -708,11 +708,11 @@ func TestReplicaCalcScaleUpCMUnreadyHotCpuScaleWouldScaleDown(t *testing.T) {
 | 
			
		||||
		podReadiness:     []v1.ConditionStatus{v1.ConditionFalse, v1.ConditionTrue, v1.ConditionFalse},
 | 
			
		||||
		podStartTime:     []metav1.Time{hotCPUCreationTime(), coolCPUCreationTime(), hotCPUCreationTime()},
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			name:                "qps",
 | 
			
		||||
			levels:              []int64{50000, 15000, 30000},
 | 
			
		||||
			targetUtilization:   15000,
 | 
			
		||||
			expectedUtilization: 31666,
 | 
			
		||||
			metricType:          podMetric,
 | 
			
		||||
			name:          "qps",
 | 
			
		||||
			levels:        []int64{50000, 15000, 30000},
 | 
			
		||||
			targetUsage:   15000,
 | 
			
		||||
			expectedUsage: 31666,
 | 
			
		||||
			metricType:    podMetric,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	tc.runTest(t)
 | 
			
		||||
@@ -723,10 +723,10 @@ func TestReplicaCalcScaleUpCMObject(t *testing.T) {
 | 
			
		||||
		currentReplicas:  3,
 | 
			
		||||
		expectedReplicas: 4,
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			name:                "qps",
 | 
			
		||||
			levels:              []int64{20000},
 | 
			
		||||
			targetUtilization:   15000,
 | 
			
		||||
			expectedUtilization: 20000,
 | 
			
		||||
			name:          "qps",
 | 
			
		||||
			levels:        []int64{20000},
 | 
			
		||||
			targetUsage:   15000,
 | 
			
		||||
			expectedUsage: 20000,
 | 
			
		||||
			singleObject: &autoscalingv2.CrossVersionObjectReference{
 | 
			
		||||
				Kind:       "Deployment",
 | 
			
		||||
				APIVersion: "apps/v1",
 | 
			
		||||
@@ -742,11 +742,11 @@ func TestReplicaCalcScaleUpCMPerPodObject(t *testing.T) {
 | 
			
		||||
		currentReplicas:  3,
 | 
			
		||||
		expectedReplicas: 4,
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			metricType:              objectPerPodMetric,
 | 
			
		||||
			name:                    "qps",
 | 
			
		||||
			levels:                  []int64{20000},
 | 
			
		||||
			perPodTargetUtilization: 5000,
 | 
			
		||||
			expectedUtilization:     6667,
 | 
			
		||||
			metricType:        objectPerPodMetric,
 | 
			
		||||
			name:              "qps",
 | 
			
		||||
			levels:            []int64{20000},
 | 
			
		||||
			perPodTargetUsage: 5000,
 | 
			
		||||
			expectedUsage:     6667,
 | 
			
		||||
			singleObject: &autoscalingv2.CrossVersionObjectReference{
 | 
			
		||||
				Kind:       "Deployment",
 | 
			
		||||
				APIVersion: "apps/v1",
 | 
			
		||||
@@ -763,10 +763,10 @@ func TestReplicaCalcScaleUpCMObjectIgnoresUnreadyPods(t *testing.T) {
 | 
			
		||||
		expectedReplicas: 5, // If we did not ignore unready pods, we'd expect 15 replicas.
 | 
			
		||||
		podReadiness:     []v1.ConditionStatus{v1.ConditionFalse, v1.ConditionTrue, v1.ConditionFalse},
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			name:                "qps",
 | 
			
		||||
			levels:              []int64{50000},
 | 
			
		||||
			targetUtilization:   10000,
 | 
			
		||||
			expectedUtilization: 50000,
 | 
			
		||||
			name:          "qps",
 | 
			
		||||
			levels:        []int64{50000},
 | 
			
		||||
			targetUsage:   10000,
 | 
			
		||||
			expectedUsage: 50000,
 | 
			
		||||
			singleObject: &autoscalingv2.CrossVersionObjectReference{
 | 
			
		||||
				Kind:       "Deployment",
 | 
			
		||||
				APIVersion: "apps/v1",
 | 
			
		||||
@@ -782,12 +782,12 @@ func TestReplicaCalcScaleUpCMExternal(t *testing.T) {
 | 
			
		||||
		currentReplicas:  1,
 | 
			
		||||
		expectedReplicas: 2,
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			name:                "qps",
 | 
			
		||||
			levels:              []int64{8600},
 | 
			
		||||
			targetUtilization:   4400,
 | 
			
		||||
			expectedUtilization: 8600,
 | 
			
		||||
			selector:            &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
 | 
			
		||||
			metricType:          podMetric,
 | 
			
		||||
			name:          "qps",
 | 
			
		||||
			levels:        []int64{8600},
 | 
			
		||||
			targetUsage:   4400,
 | 
			
		||||
			expectedUsage: 8600,
 | 
			
		||||
			selector:      &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
 | 
			
		||||
			metricType:    podMetric,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	tc.runTest(t)
 | 
			
		||||
@@ -799,12 +799,12 @@ func TestReplicaCalcScaleUpCMExternalIgnoresUnreadyPods(t *testing.T) {
 | 
			
		||||
		expectedReplicas: 2, // Would expect 6 if we didn't ignore unready pods
 | 
			
		||||
		podReadiness:     []v1.ConditionStatus{v1.ConditionFalse, v1.ConditionTrue, v1.ConditionFalse},
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			name:                "qps",
 | 
			
		||||
			levels:              []int64{8600},
 | 
			
		||||
			targetUtilization:   4400,
 | 
			
		||||
			expectedUtilization: 8600,
 | 
			
		||||
			selector:            &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
 | 
			
		||||
			metricType:          externalMetric,
 | 
			
		||||
			name:          "qps",
 | 
			
		||||
			levels:        []int64{8600},
 | 
			
		||||
			targetUsage:   4400,
 | 
			
		||||
			expectedUsage: 8600,
 | 
			
		||||
			selector:      &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
 | 
			
		||||
			metricType:    externalMetric,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	tc.runTest(t)
 | 
			
		||||
@@ -815,11 +815,11 @@ func TestReplicaCalcScaleUpCMExternalNoLabels(t *testing.T) {
 | 
			
		||||
		currentReplicas:  1,
 | 
			
		||||
		expectedReplicas: 2,
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			name:                "qps",
 | 
			
		||||
			levels:              []int64{8600},
 | 
			
		||||
			targetUtilization:   4400,
 | 
			
		||||
			expectedUtilization: 8600,
 | 
			
		||||
			metricType:          podMetric,
 | 
			
		||||
			name:          "qps",
 | 
			
		||||
			levels:        []int64{8600},
 | 
			
		||||
			targetUsage:   4400,
 | 
			
		||||
			expectedUsage: 8600,
 | 
			
		||||
			metricType:    podMetric,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	tc.runTest(t)
 | 
			
		||||
@@ -830,12 +830,12 @@ func TestReplicaCalcScaleUpPerPodCMExternal(t *testing.T) {
 | 
			
		||||
		currentReplicas:  3,
 | 
			
		||||
		expectedReplicas: 4,
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			name:                    "qps",
 | 
			
		||||
			levels:                  []int64{8600},
 | 
			
		||||
			perPodTargetUtilization: 2150,
 | 
			
		||||
			expectedUtilization:     2867,
 | 
			
		||||
			selector:                &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
 | 
			
		||||
			metricType:              externalPerPodMetric,
 | 
			
		||||
			name:              "qps",
 | 
			
		||||
			levels:            []int64{8600},
 | 
			
		||||
			perPodTargetUsage: 2150,
 | 
			
		||||
			expectedUsage:     2867,
 | 
			
		||||
			selector:          &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
 | 
			
		||||
			metricType:        externalPerPodMetric,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	tc.runTest(t)
 | 
			
		||||
@@ -881,11 +881,11 @@ func TestReplicaCalcScaleDownCM(t *testing.T) {
 | 
			
		||||
		currentReplicas:  5,
 | 
			
		||||
		expectedReplicas: 3,
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			name:                "qps",
 | 
			
		||||
			levels:              []int64{12000, 12000, 12000, 12000, 12000},
 | 
			
		||||
			targetUtilization:   20000,
 | 
			
		||||
			expectedUtilization: 12000,
 | 
			
		||||
			metricType:          podMetric,
 | 
			
		||||
			name:          "qps",
 | 
			
		||||
			levels:        []int64{12000, 12000, 12000, 12000, 12000},
 | 
			
		||||
			targetUsage:   20000,
 | 
			
		||||
			expectedUsage: 12000,
 | 
			
		||||
			metricType:    podMetric,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	tc.runTest(t)
 | 
			
		||||
@@ -896,10 +896,10 @@ func TestReplicaCalcScaleDownPerPodCMObject(t *testing.T) {
 | 
			
		||||
		currentReplicas:  5,
 | 
			
		||||
		expectedReplicas: 3,
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			name:                    "qps",
 | 
			
		||||
			levels:                  []int64{6000},
 | 
			
		||||
			perPodTargetUtilization: 2000,
 | 
			
		||||
			expectedUtilization:     1200,
 | 
			
		||||
			name:              "qps",
 | 
			
		||||
			levels:            []int64{6000},
 | 
			
		||||
			perPodTargetUsage: 2000,
 | 
			
		||||
			expectedUsage:     1200,
 | 
			
		||||
			singleObject: &autoscalingv2.CrossVersionObjectReference{
 | 
			
		||||
				Kind:       "Deployment",
 | 
			
		||||
				APIVersion: "apps/v1",
 | 
			
		||||
@@ -916,10 +916,10 @@ func TestReplicaCalcScaleDownCMObject(t *testing.T) {
 | 
			
		||||
		currentReplicas:  5,
 | 
			
		||||
		expectedReplicas: 3,
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			name:                "qps",
 | 
			
		||||
			levels:              []int64{12000},
 | 
			
		||||
			targetUtilization:   20000,
 | 
			
		||||
			expectedUtilization: 12000,
 | 
			
		||||
			name:          "qps",
 | 
			
		||||
			levels:        []int64{12000},
 | 
			
		||||
			targetUsage:   20000,
 | 
			
		||||
			expectedUsage: 12000,
 | 
			
		||||
			singleObject: &autoscalingv2.CrossVersionObjectReference{
 | 
			
		||||
				Kind:       "Deployment",
 | 
			
		||||
				APIVersion: "apps/v1",
 | 
			
		||||
@@ -935,12 +935,12 @@ func TestReplicaCalcScaleDownCMExternal(t *testing.T) {
 | 
			
		||||
		currentReplicas:  5,
 | 
			
		||||
		expectedReplicas: 3,
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			name:                "qps",
 | 
			
		||||
			levels:              []int64{8600},
 | 
			
		||||
			targetUtilization:   14334,
 | 
			
		||||
			expectedUtilization: 8600,
 | 
			
		||||
			selector:            &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
 | 
			
		||||
			metricType:          externalMetric,
 | 
			
		||||
			name:          "qps",
 | 
			
		||||
			levels:        []int64{8600},
 | 
			
		||||
			targetUsage:   14334,
 | 
			
		||||
			expectedUsage: 8600,
 | 
			
		||||
			selector:      &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
 | 
			
		||||
			metricType:    externalMetric,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	tc.runTest(t)
 | 
			
		||||
@@ -951,12 +951,12 @@ func TestReplicaCalcScaleDownPerPodCMExternal(t *testing.T) {
 | 
			
		||||
		currentReplicas:  5,
 | 
			
		||||
		expectedReplicas: 3,
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			name:                    "qps",
 | 
			
		||||
			levels:                  []int64{8600},
 | 
			
		||||
			perPodTargetUtilization: 2867,
 | 
			
		||||
			expectedUtilization:     1720,
 | 
			
		||||
			selector:                &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
 | 
			
		||||
			metricType:              externalPerPodMetric,
 | 
			
		||||
			name:              "qps",
 | 
			
		||||
			levels:            []int64{8600},
 | 
			
		||||
			perPodTargetUsage: 2867,
 | 
			
		||||
			expectedUsage:     1720,
 | 
			
		||||
			selector:          &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
 | 
			
		||||
			metricType:        externalPerPodMetric,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	tc.runTest(t)
 | 
			
		||||
@@ -1178,11 +1178,11 @@ func TestReplicaCalcToleranceCM(t *testing.T) {
 | 
			
		||||
		currentReplicas:  3,
 | 
			
		||||
		expectedReplicas: 3,
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			name:                "qps",
 | 
			
		||||
			levels:              []int64{20000, 21000, 21000},
 | 
			
		||||
			targetUtilization:   20000,
 | 
			
		||||
			expectedUtilization: 20666,
 | 
			
		||||
			metricType:          podMetric,
 | 
			
		||||
			name:          "qps",
 | 
			
		||||
			levels:        []int64{20000, 21000, 21000},
 | 
			
		||||
			targetUsage:   20000,
 | 
			
		||||
			expectedUsage: 20666,
 | 
			
		||||
			metricType:    podMetric,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	tc.runTest(t)
 | 
			
		||||
@@ -1193,10 +1193,10 @@ func TestReplicaCalcToleranceCMObject(t *testing.T) {
 | 
			
		||||
		currentReplicas:  3,
 | 
			
		||||
		expectedReplicas: 3,
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			name:                "qps",
 | 
			
		||||
			levels:              []int64{20666},
 | 
			
		||||
			targetUtilization:   20000,
 | 
			
		||||
			expectedUtilization: 20666,
 | 
			
		||||
			name:          "qps",
 | 
			
		||||
			levels:        []int64{20666},
 | 
			
		||||
			targetUsage:   20000,
 | 
			
		||||
			expectedUsage: 20666,
 | 
			
		||||
			singleObject: &autoscalingv2.CrossVersionObjectReference{
 | 
			
		||||
				Kind:       "Deployment",
 | 
			
		||||
				APIVersion: "apps/v1",
 | 
			
		||||
@@ -1212,11 +1212,11 @@ func TestReplicaCalcTolerancePerPodCMObject(t *testing.T) {
 | 
			
		||||
		currentReplicas:  4,
 | 
			
		||||
		expectedReplicas: 4,
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			metricType:              objectPerPodMetric,
 | 
			
		||||
			name:                    "qps",
 | 
			
		||||
			levels:                  []int64{20166},
 | 
			
		||||
			perPodTargetUtilization: 5000,
 | 
			
		||||
			expectedUtilization:     5042,
 | 
			
		||||
			metricType:        objectPerPodMetric,
 | 
			
		||||
			name:              "qps",
 | 
			
		||||
			levels:            []int64{20166},
 | 
			
		||||
			perPodTargetUsage: 5000,
 | 
			
		||||
			expectedUsage:     5042,
 | 
			
		||||
			singleObject: &autoscalingv2.CrossVersionObjectReference{
 | 
			
		||||
				Kind:       "Deployment",
 | 
			
		||||
				APIVersion: "apps/v1",
 | 
			
		||||
@@ -1232,12 +1232,12 @@ func TestReplicaCalcToleranceCMExternal(t *testing.T) {
 | 
			
		||||
		currentReplicas:  3,
 | 
			
		||||
		expectedReplicas: 3,
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			name:                "qps",
 | 
			
		||||
			levels:              []int64{8600},
 | 
			
		||||
			targetUtilization:   8888,
 | 
			
		||||
			expectedUtilization: 8600,
 | 
			
		||||
			selector:            &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
 | 
			
		||||
			metricType:          externalMetric,
 | 
			
		||||
			name:          "qps",
 | 
			
		||||
			levels:        []int64{8600},
 | 
			
		||||
			targetUsage:   8888,
 | 
			
		||||
			expectedUsage: 8600,
 | 
			
		||||
			selector:      &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
 | 
			
		||||
			metricType:    externalMetric,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	tc.runTest(t)
 | 
			
		||||
@@ -1248,12 +1248,12 @@ func TestReplicaCalcTolerancePerPodCMExternal(t *testing.T) {
 | 
			
		||||
		currentReplicas:  3,
 | 
			
		||||
		expectedReplicas: 3,
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			name:                    "qps",
 | 
			
		||||
			levels:                  []int64{8600},
 | 
			
		||||
			perPodTargetUtilization: 2900,
 | 
			
		||||
			expectedUtilization:     2867,
 | 
			
		||||
			selector:                &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
 | 
			
		||||
			metricType:              externalPerPodMetric,
 | 
			
		||||
			name:              "qps",
 | 
			
		||||
			levels:            []int64{8600},
 | 
			
		||||
			perPodTargetUsage: 2900,
 | 
			
		||||
			expectedUsage:     2867,
 | 
			
		||||
			selector:          &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
 | 
			
		||||
			metricType:        externalPerPodMetric,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	tc.runTest(t)
 | 
			
		||||
@@ -1506,11 +1506,11 @@ func TestReplicaCalcDuringRollingUpdateWithMaxSurgeCM(t *testing.T) {
 | 
			
		||||
		expectedReplicas: 2,
 | 
			
		||||
		podPhase:         []v1.PodPhase{v1.PodRunning, v1.PodRunning, v1.PodRunning},
 | 
			
		||||
		metric: &metricInfo{
 | 
			
		||||
			name:                "qps",
 | 
			
		||||
			levels:              []int64{10000, 10000},
 | 
			
		||||
			targetUtilization:   17000,
 | 
			
		||||
			expectedUtilization: 10000,
 | 
			
		||||
			metricType:          podMetric,
 | 
			
		||||
			name:          "qps",
 | 
			
		||||
			levels:        []int64{10000, 10000},
 | 
			
		||||
			targetUsage:   17000,
 | 
			
		||||
			expectedUsage: 10000,
 | 
			
		||||
			metricType:    podMetric,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	tc.runTest(t)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user