From 5e51a850eac96c4267338512485ba452b5966a19 Mon Sep 17 00:00:00 2001 From: amirschw <24677563+amirschw@users.noreply.github.com> Date: Sat, 20 Nov 2021 14:21:24 +0200 Subject: [PATCH] Add an optional metric type field to the scale trigger spec Signed-off-by: amirschw <24677563+amirschw@users.noreply.github.com> --- CHANGELOG.md | 1 + apis/keda/v1alpha1/scaledobject_types.go | 2 + config/crd/bases/keda.sh_scaledjobs.yaml | 5 ++ config/crd/bases/keda.sh_scaledobjects.yaml | 5 ++ pkg/scalers/artemis_scaler.go | 6 +- pkg/scalers/aws_cloudwatch_scaler.go | 6 +- pkg/scalers/aws_kinesis_stream_scaler.go | 6 +- pkg/scalers/aws_sqs_queue_scaler.go | 6 +- pkg/scalers/azure_blob_scaler.go | 6 +- pkg/scalers/azure_eventhub_scaler.go | 6 +- pkg/scalers/azure_log_analytics_scaler.go | 5 +- pkg/scalers/azure_monitor_scaler.go | 6 +- pkg/scalers/azure_pipelines_scaler.go | 6 +- pkg/scalers/azure_queue_scaler.go | 6 +- pkg/scalers/azure_servicebus_scaler.go | 7 +- pkg/scalers/cassandra_scaler.go | 6 +- pkg/scalers/cpu_memory_scaler.go | 18 +++-- pkg/scalers/cpu_memory_scaler_test.go | 36 ++++++--- pkg/scalers/cron_scaler.go | 6 +- pkg/scalers/external_scaler.go | 25 +++--- pkg/scalers/gcp_pub_sub_scaler.go | 8 +- pkg/scalers/graphite_scaler.go | 6 +- pkg/scalers/huawei_cloudeye_scaler.go | 6 +- pkg/scalers/ibmmq_scaler.go | 6 +- pkg/scalers/influxdb_scaler.go | 6 +- pkg/scalers/kafka_scaler.go | 6 +- pkg/scalers/kubernetes_workload_scaler.go | 6 +- pkg/scalers/liiklus_scaler.go | 6 +- pkg/scalers/metrics_api_scaler.go | 6 +- pkg/scalers/mongo_scaler.go | 7 +- pkg/scalers/mssql_scaler.go | 6 +- pkg/scalers/mysql_scaler.go | 7 +- pkg/scalers/openstack_metrics_scaler.go | 6 +- pkg/scalers/openstack_swift_scaler.go | 7 +- pkg/scalers/postgresql_scaler.go | 7 +- pkg/scalers/prometheus_scaler.go | 6 +- pkg/scalers/rabbitmq_scaler.go | 6 +- pkg/scalers/redis_scaler.go | 6 +- pkg/scalers/redis_streams_scaler.go | 6 +- pkg/scalers/scaler.go | 34 ++++++++ pkg/scalers/scaler_test.go | 87 +++++++++++++++++++++ pkg/scalers/selenium_grid_scaler.go | 6 +- pkg/scalers/solace_scaler.go | 12 +-- pkg/scalers/stan_scaler.go | 6 +- pkg/scaling/scale_handler.go | 1 + 45 files changed, 226 insertions(+), 210 deletions(-) create mode 100644 pkg/scalers/scaler_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 050667a147a..f7285e5154c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ - Improve Redis Scaler, upgrade library, add username and Sentinel support ([#2181](https://github.com/kedacore/keda/pull/2181)) - Add GCP identity authentication when using Pubsub Scaler ([#2225](https://github.com/kedacore/keda/pull/2225)) - Add ScalersCache to reuse scalers unless they need changing ([#2187](https://github.com/kedacore/keda/pull/2187)) +- Add support for `ValueMetricType` in all scalers except cpu/memory ([#2309](https://github.com/kedacore/keda/pull/2309)) ### Improvements diff --git a/apis/keda/v1alpha1/scaledobject_types.go b/apis/keda/v1alpha1/scaledobject_types.go index 52fa85d39e7..6107eadcab9 100644 --- a/apis/keda/v1alpha1/scaledobject_types.go +++ b/apis/keda/v1alpha1/scaledobject_types.go @@ -127,6 +127,8 @@ type ScaleTriggers struct { AuthenticationRef *ScaledObjectAuthRef `json:"authenticationRef,omitempty"` // +optional FallbackReplicas *int32 `json:"fallback,omitempty"` + // +optional + MetricType autoscalingv2beta2.MetricTargetType `json:"metricType,omitempty"` } // +k8s:openapi-gen=true diff --git a/config/crd/bases/keda.sh_scaledjobs.yaml b/config/crd/bases/keda.sh_scaledjobs.yaml index 19edd6ca0d6..fe4c928b3d9 100644 --- a/config/crd/bases/keda.sh_scaledjobs.yaml +++ b/config/crd/bases/keda.sh_scaledjobs.yaml @@ -7401,6 +7401,11 @@ spec: additionalProperties: type: string type: object + metricType: + description: MetricTargetType specifies the type of metric being + targeted, and should be either "Value", "AverageValue", or + "Utilization" + type: string name: type: string type: diff --git a/config/crd/bases/keda.sh_scaledobjects.yaml b/config/crd/bases/keda.sh_scaledobjects.yaml index 1ff6f64fd0c..fb153c87507 100644 --- a/config/crd/bases/keda.sh_scaledobjects.yaml +++ b/config/crd/bases/keda.sh_scaledobjects.yaml @@ -268,6 +268,11 @@ spec: additionalProperties: type: string type: object + metricType: + description: MetricTargetType specifies the type of metric being + targeted, and should be either "Value", "AverageValue", or + "Utilization" + type: string name: type: string type: diff --git a/pkg/scalers/artemis_scaler.go b/pkg/scalers/artemis_scaler.go index c1190f2911d..86d8b15fb58 100644 --- a/pkg/scalers/artemis_scaler.go +++ b/pkg/scalers/artemis_scaler.go @@ -251,15 +251,11 @@ func (s *artemisScaler) getQueueMessageCount(ctx context.Context) (int, error) { } func (s *artemisScaler) GetMetricSpecForScaling(ctx context.Context) []v2beta2.MetricSpec { - targetMetricValue := resource.NewQuantity(int64(s.metadata.queueLength), resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("artemis-%s", s.metadata.queueName))), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetMetricValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.queueLength)), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: artemisMetricType} return []v2beta2.MetricSpec{metricSpec} diff --git a/pkg/scalers/aws_cloudwatch_scaler.go b/pkg/scalers/aws_cloudwatch_scaler.go index 14be0d6bfd6..04c49409a78 100644 --- a/pkg/scalers/aws_cloudwatch_scaler.go +++ b/pkg/scalers/aws_cloudwatch_scaler.go @@ -289,15 +289,11 @@ func (c *awsCloudwatchScaler) GetMetrics(ctx context.Context, metricName string, } func (c *awsCloudwatchScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetMetricValue := resource.NewQuantity(int64(c.metadata.targetMetricValue), resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(c.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("aws-cloudwatch-%s", c.metadata.dimensionName[0]))), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetMetricValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(c.metadata.targetMetricValue)), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: externalMetricType} return []v2beta2.MetricSpec{metricSpec} diff --git a/pkg/scalers/aws_kinesis_stream_scaler.go b/pkg/scalers/aws_kinesis_stream_scaler.go index 4a4c6db059c..9b9d23c18ae 100644 --- a/pkg/scalers/aws_kinesis_stream_scaler.go +++ b/pkg/scalers/aws_kinesis_stream_scaler.go @@ -133,15 +133,11 @@ func (s *awsKinesisStreamScaler) Close(context.Context) error { } func (s *awsKinesisStreamScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetShardCountQty := resource.NewQuantity(int64(s.metadata.targetShardCount), resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("aws-kinesis-%s", s.metadata.streamName))), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetShardCountQty, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.targetShardCount)), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: externalMetricType} return []v2beta2.MetricSpec{metricSpec} diff --git a/pkg/scalers/aws_sqs_queue_scaler.go b/pkg/scalers/aws_sqs_queue_scaler.go index 7a0c7517a6a..f3b47b08ed3 100644 --- a/pkg/scalers/aws_sqs_queue_scaler.go +++ b/pkg/scalers/aws_sqs_queue_scaler.go @@ -155,15 +155,11 @@ func (s *awsSqsQueueScaler) Close(context.Context) error { } func (s *awsSqsQueueScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetQueueLengthQty := resource.NewQuantity(int64(s.metadata.targetQueueLength), resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("aws-sqs-%s", s.metadata.queueName))), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetQueueLengthQty, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.targetQueueLength)), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: externalMetricType} return []v2beta2.MetricSpec{metricSpec} diff --git a/pkg/scalers/azure_blob_scaler.go b/pkg/scalers/azure_blob_scaler.go index 129a1f233e9..838bc40f3eb 100644 --- a/pkg/scalers/azure_blob_scaler.go +++ b/pkg/scalers/azure_blob_scaler.go @@ -181,15 +181,11 @@ func (s *azureBlobScaler) Close(context.Context) error { } func (s *azureBlobScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetBlobCount := resource.NewQuantity(int64(s.metadata.targetBlobCount), resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, s.metadata.metricName), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetBlobCount, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.targetBlobCount)), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: externalMetricType} return []v2beta2.MetricSpec{metricSpec} diff --git a/pkg/scalers/azure_eventhub_scaler.go b/pkg/scalers/azure_eventhub_scaler.go index 9db01737565..745e2edc23a 100644 --- a/pkg/scalers/azure_eventhub_scaler.go +++ b/pkg/scalers/azure_eventhub_scaler.go @@ -252,15 +252,11 @@ func (scaler *azureEventHubScaler) IsActive(ctx context.Context) (bool, error) { // GetMetricSpecForScaling returns metric spec func (scaler *azureEventHubScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetMetricVal := resource.NewQuantity(scaler.metadata.threshold, resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(scaler.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("azure-eventhub-%s", scaler.metadata.eventHubInfo.EventHubConnection))), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetMetricVal, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, scaler.metadata.threshold), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: eventHubMetricType} return []v2beta2.MetricSpec{metricSpec} diff --git a/pkg/scalers/azure_log_analytics_scaler.go b/pkg/scalers/azure_log_analytics_scaler.go index df06c899794..4a26802cdef 100644 --- a/pkg/scalers/azure_log_analytics_scaler.go +++ b/pkg/scalers/azure_log_analytics_scaler.go @@ -227,10 +227,7 @@ func (s *azureLogAnalyticsScaler) GetMetricSpecForScaling(ctx context.Context) [ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, s.metadata.metricName), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: resource.NewQuantity(s.cache.metricThreshold, resource.DecimalSI), - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, s.cache.metricThreshold), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: externalMetricType} return []v2beta2.MetricSpec{metricSpec} diff --git a/pkg/scalers/azure_monitor_scaler.go b/pkg/scalers/azure_monitor_scaler.go index 2032f2f5917..96a9ad5c723 100644 --- a/pkg/scalers/azure_monitor_scaler.go +++ b/pkg/scalers/azure_monitor_scaler.go @@ -191,15 +191,11 @@ func (s *azureMonitorScaler) Close(context.Context) error { } func (s *azureMonitorScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetMetricVal := resource.NewQuantity(int64(s.metadata.targetValue), resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("azure-monitor-%s", s.metadata.azureMonitorInfo.Name))), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetMetricVal, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.targetValue)), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: externalMetricType} return []v2beta2.MetricSpec{metricSpec} diff --git a/pkg/scalers/azure_pipelines_scaler.go b/pkg/scalers/azure_pipelines_scaler.go index c088ab9059e..562f238f3da 100644 --- a/pkg/scalers/azure_pipelines_scaler.go +++ b/pkg/scalers/azure_pipelines_scaler.go @@ -166,15 +166,11 @@ func (s *azurePipelinesScaler) GetAzurePipelinesQueueLength(ctx context.Context) } func (s *azurePipelinesScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetPipelinesQueueLengthQty := resource.NewQuantity(int64(s.metadata.targetPipelinesQueueLength), resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("azure-pipelines-%s", s.metadata.poolID))), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetPipelinesQueueLengthQty, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.targetPipelinesQueueLength)), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: externalMetricType} return []v2beta2.MetricSpec{metricSpec} diff --git a/pkg/scalers/azure_queue_scaler.go b/pkg/scalers/azure_queue_scaler.go index 4b39986d633..9282e40d113 100644 --- a/pkg/scalers/azure_queue_scaler.go +++ b/pkg/scalers/azure_queue_scaler.go @@ -163,15 +163,11 @@ func (s *azureQueueScaler) Close(context.Context) error { } func (s *azureQueueScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetQueueLengthQty := resource.NewQuantity(int64(s.metadata.targetQueueLength), resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("azure-queue-%s", s.metadata.queueName))), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetQueueLengthQty, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.targetQueueLength)), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: externalMetricType} return []v2beta2.MetricSpec{metricSpec} diff --git a/pkg/scalers/azure_servicebus_scaler.go b/pkg/scalers/azure_servicebus_scaler.go index 6dfeb65068d..d7269932962 100755 --- a/pkg/scalers/azure_servicebus_scaler.go +++ b/pkg/scalers/azure_servicebus_scaler.go @@ -181,8 +181,6 @@ func (s *azureServiceBusScaler) Close(context.Context) error { // Returns the metric spec to be used by the HPA func (s *azureServiceBusScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetLengthQty := resource.NewQuantity(int64(s.metadata.targetLength), resource.DecimalSI) - metricName := "" if s.metadata.entityType == queue { metricName = s.metadata.queueName @@ -194,10 +192,7 @@ func (s *azureServiceBusScaler) GetMetricSpecForScaling(context.Context) []v2bet Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("azure-servicebus-%s", metricName))), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetLengthQty, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.targetLength)), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: externalMetricType} return []v2beta2.MetricSpec{metricSpec} diff --git a/pkg/scalers/cassandra_scaler.go b/pkg/scalers/cassandra_scaler.go index ed54b69e2ae..4665df300a8 100644 --- a/pkg/scalers/cassandra_scaler.go +++ b/pkg/scalers/cassandra_scaler.go @@ -175,15 +175,11 @@ func (s *cassandraScaler) IsActive(ctx context.Context) (bool, error) { // GetMetricSpecForScaling returns the MetricSpec for the Horizontal Pod Autoscaler. func (s *cassandraScaler) GetMetricSpecForScaling(ctx context.Context) []v2beta2.MetricSpec { - targetQueryValue := resource.NewQuantity(int64(s.metadata.targetQueryValue), resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, s.metadata.metricName), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetQueryValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.targetQueryValue)), } metricSpec := v2beta2.MetricSpec{ External: externalMetric, Type: externalMetricType, diff --git a/pkg/scalers/cpu_memory_scaler.go b/pkg/scalers/cpu_memory_scaler.go index 4e6283779bb..023c9caf644 100644 --- a/pkg/scalers/cpu_memory_scaler.go +++ b/pkg/scalers/cpu_memory_scaler.go @@ -38,14 +38,20 @@ func NewCPUMemoryScaler(resourceName v1.ResourceName, config *ScalerConfig) (Sca func parseResourceMetadata(config *ScalerConfig) (*cpuMemoryMetadata, error) { meta := &cpuMemoryMetadata{} - if val, ok := config.TriggerMetadata["type"]; ok && val != "" { - meta.Type = v2beta2.MetricTargetType(val) - } else { - return nil, fmt.Errorf("no type given") - } - var value string var ok bool + value, ok = config.TriggerMetadata["type"] + switch { + case ok && value != "" && config.MetricType != "": + return nil, fmt.Errorf("only one of trigger.metadata.type or trigger.metricType should be defined") + case ok && value != "": + meta.Type = v2beta2.MetricTargetType(value) + case config.MetricType != "": + meta.Type = config.MetricType + default: + return nil, fmt.Errorf("no type given in neither trigger.metadata.type or trigger.metricType") + } + if value, ok = config.TriggerMetadata["value"]; !ok || value == "" { return nil, fmt.Errorf("no value given") } diff --git a/pkg/scalers/cpu_memory_scaler_test.go b/pkg/scalers/cpu_memory_scaler_test.go index 18a6a491449..212c5350744 100644 --- a/pkg/scalers/cpu_memory_scaler_test.go +++ b/pkg/scalers/cpu_memory_scaler_test.go @@ -10,8 +10,9 @@ import ( ) type parseCPUMemoryMetadataTestData struct { - metadata map[string]string - isError bool + metricType v2beta2.MetricTargetType + metadata map[string]string + isError bool } // A complete valid metadata example for reference @@ -21,19 +22,23 @@ var validCPUMemoryMetadata = map[string]string{ } var testCPUMemoryMetadata = []parseCPUMemoryMetadataTestData{ - {map[string]string{}, true}, - {validCPUMemoryMetadata, false}, - {map[string]string{"type": "Utilization", "value": "50"}, false}, - {map[string]string{"type": "AverageValue", "value": "50"}, false}, - {map[string]string{"type": "Value", "value": "50"}, true}, - {map[string]string{"type": "AverageValue"}, true}, - {map[string]string{"type": "xxx", "value": "50"}, true}, + {"", map[string]string{}, true}, + {"", validCPUMemoryMetadata, false}, + {"", map[string]string{"type": "Utilization", "value": "50"}, false}, + {v2beta2.UtilizationMetricType, map[string]string{"value": "50"}, false}, + {"", map[string]string{"type": "AverageValue", "value": "50"}, false}, + {v2beta2.AverageValueMetricType, map[string]string{"value": "50"}, false}, + {"", map[string]string{"type": "Value", "value": "50"}, true}, + {v2beta2.ValueMetricType, map[string]string{"value": "50"}, true}, + {"", map[string]string{"type": "AverageValue"}, true}, + {"", map[string]string{"type": "xxx", "value": "50"}, true}, } func TestCPUMemoryParseMetadata(t *testing.T) { for _, testData := range testCPUMemoryMetadata { config := &ScalerConfig{ TriggerMetadata: testData.metadata, + MetricType: testData.metricType, } _, err := parseResourceMetadata(config) if err != nil && !testData.isError { @@ -46,6 +51,7 @@ func TestCPUMemoryParseMetadata(t *testing.T) { } func TestGetMetricSpecForScaling(t *testing.T) { + // Using trigger.metadata.type field for type config := &ScalerConfig{ TriggerMetadata: validCPUMemoryMetadata, } @@ -55,4 +61,16 @@ func TestGetMetricSpecForScaling(t *testing.T) { assert.Equal(t, metricSpec[0].Type, v2beta2.ResourceMetricSourceType) assert.Equal(t, metricSpec[0].Resource.Name, v1.ResourceCPU) assert.Equal(t, metricSpec[0].Resource.Target.Type, v2beta2.UtilizationMetricType) + + // Using trigger.metricType field for type + config = &ScalerConfig{ + TriggerMetadata: map[string]string{"value": "50"}, + MetricType: v2beta2.UtilizationMetricType, + } + scaler, _ = NewCPUMemoryScaler(v1.ResourceCPU, config) + metricSpec = scaler.GetMetricSpecForScaling(context.Background()) + + assert.Equal(t, metricSpec[0].Type, v2beta2.ResourceMetricSourceType) + assert.Equal(t, metricSpec[0].Resource.Name, v1.ResourceCPU) + assert.Equal(t, metricSpec[0].Resource.Target.Type, v2beta2.UtilizationMetricType) } diff --git a/pkg/scalers/cron_scaler.go b/pkg/scalers/cron_scaler.go index bb838878111..ac7d4c7f4e7 100644 --- a/pkg/scalers/cron_scaler.go +++ b/pkg/scalers/cron_scaler.go @@ -154,15 +154,11 @@ func parseCronTimeFormat(s string) string { // GetMetricSpecForScaling returns the metric spec for the HPA func (s *cronScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { specReplicas := 1 - targetMetricValue := resource.NewQuantity(int64(specReplicas), resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("cron-%s-%s-%s", s.metadata.timezone, parseCronTimeFormat(s.metadata.start), parseCronTimeFormat(s.metadata.end)))), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetMetricValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(specReplicas)), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: cronMetricType} return []v2beta2.MetricSpec{metricSpec} diff --git a/pkg/scalers/external_scaler.go b/pkg/scalers/external_scaler.go index 6a7f8693b41..ef3f03f4073 100644 --- a/pkg/scalers/external_scaler.go +++ b/pkg/scalers/external_scaler.go @@ -21,6 +21,7 @@ import ( ) type externalScaler struct { + metricType v2beta2.MetricTargetType metadata externalScalerMetadata scaledObjectRef pb.ScaledObjectRef } @@ -49,13 +50,19 @@ var externalLog = logf.Log.WithName("external_scaler") // NewExternalScaler creates a new external scaler - calls the GRPC interface // to create a new scaler func NewExternalScaler(config *ScalerConfig) (Scaler, error) { + metricType, err := GetExternalMetricTargetType(config.MetricType) + if err != nil { + return nil, fmt.Errorf("error getting external scaler metric type: %s", err) + } + meta, err := parseExternalScalerMetadata(config) if err != nil { return nil, fmt.Errorf("error parsing external scaler metadata: %s", err) } return &externalScaler{ - metadata: meta, + metricType: metricType, + metadata: meta, scaledObjectRef: pb.ScaledObjectRef{ Name: config.Name, Namespace: config.Namespace, @@ -66,6 +73,11 @@ func NewExternalScaler(config *ScalerConfig) (Scaler, error) { // NewExternalPushScaler creates a new externalPushScaler push scaler func NewExternalPushScaler(config *ScalerConfig) (PushScaler, error) { + metricType, err := GetExternalMetricTargetType(config.MetricType) + if err != nil { + return nil, fmt.Errorf("error getting external scaler metric type: %s", err) + } + meta, err := parseExternalScalerMetadata(config) if err != nil { return nil, fmt.Errorf("error parsing external scaler metadata: %s", err) @@ -73,7 +85,8 @@ func NewExternalPushScaler(config *ScalerConfig) (PushScaler, error) { return &externalPushScaler{ externalScaler{ - metadata: meta, + metricType: metricType, + metadata: meta, scaledObjectRef: pb.ScaledObjectRef{ Name: config.Name, Namespace: config.Namespace, @@ -155,17 +168,11 @@ func (s *externalScaler) GetMetricSpecForScaling(ctx context.Context) []v2beta2. } for _, spec := range response.MetricSpecs { - // Construct the target subscription size as a quantity - qty := resource.NewQuantity(spec.TargetSize, resource.DecimalSI) - externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, spec.MetricName), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: qty, - }, + Target: GetExternalMetricTarget(s.metricType, spec.TargetSize), } // Create the metric spec for the HPA diff --git a/pkg/scalers/gcp_pub_sub_scaler.go b/pkg/scalers/gcp_pub_sub_scaler.go index b084a3a0d94..63d41cd8a23 100644 --- a/pkg/scalers/gcp_pub_sub_scaler.go +++ b/pkg/scalers/gcp_pub_sub_scaler.go @@ -111,17 +111,11 @@ func (s *pubsubScaler) Close(context.Context) error { // GetMetricSpecForScaling returns the metric spec for the HPA func (s *pubsubScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - // Construct the target subscription size as a quantity - targetSubscriptionSizeQty := resource.NewQuantity(int64(s.metadata.targetSubscriptionSize), resource.DecimalSI) - externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("gcp-ps-%s", s.metadata.subscriptionName))), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetSubscriptionSizeQty, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.targetSubscriptionSize)), } // Create the metric spec for the HPA diff --git a/pkg/scalers/graphite_scaler.go b/pkg/scalers/graphite_scaler.go index 854fa4b9483..80c26bbb74c 100644 --- a/pkg/scalers/graphite_scaler.go +++ b/pkg/scalers/graphite_scaler.go @@ -144,15 +144,11 @@ func (s *graphiteScaler) Close(context.Context) error { } func (s *graphiteScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetMetricValue := resource.NewQuantity(int64(s.metadata.threshold), resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("graphite-%s", s.metadata.metricName))), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetMetricValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.threshold)), } metricSpec := v2beta2.MetricSpec{ External: externalMetric, Type: externalMetricType, diff --git a/pkg/scalers/huawei_cloudeye_scaler.go b/pkg/scalers/huawei_cloudeye_scaler.go index 2f090a0993f..c8b26470331 100644 --- a/pkg/scalers/huawei_cloudeye_scaler.go +++ b/pkg/scalers/huawei_cloudeye_scaler.go @@ -242,15 +242,11 @@ func (h *huaweiCloudeyeScaler) GetMetrics(ctx context.Context, metricName string } func (h *huaweiCloudeyeScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetMetricValue := resource.NewQuantity(int64(h.metadata.targetMetricValue), resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(h.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("huawei-cloudeye-%s", h.metadata.metricsName))), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetMetricValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(h.metadata.targetMetricValue)), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: externalMetricType} return []v2beta2.MetricSpec{metricSpec} diff --git a/pkg/scalers/ibmmq_scaler.go b/pkg/scalers/ibmmq_scaler.go index c1f28ff623c..c1a3a72f81f 100644 --- a/pkg/scalers/ibmmq_scaler.go +++ b/pkg/scalers/ibmmq_scaler.go @@ -202,15 +202,11 @@ func (s *IBMMQScaler) getQueueDepthViaHTTP(ctx context.Context) (int, error) { // GetMetricSpecForScaling returns the MetricSpec for the Horizontal Pod Autoscaler func (s *IBMMQScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetQueueLengthQty := resource.NewQuantity(int64(s.metadata.targetQueueDepth), resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("ibmmq-%s", s.metadata.queueName))), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetQueueLengthQty, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.targetQueueDepth)), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: externalMetricType} return []v2beta2.MetricSpec{metricSpec} diff --git a/pkg/scalers/influxdb_scaler.go b/pkg/scalers/influxdb_scaler.go index 7da547fa3ba..f17b0e732fd 100644 --- a/pkg/scalers/influxdb_scaler.go +++ b/pkg/scalers/influxdb_scaler.go @@ -211,15 +211,11 @@ func (s *influxDBScaler) GetMetrics(ctx context.Context, metricName string, metr // GetMetricSpecForScaling returns the metric spec for the Horizontal Pod Autoscaler func (s *influxDBScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetMetricValue := resource.NewQuantity(int64(s.metadata.thresholdValue), resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, s.metadata.metricName), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetMetricValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.thresholdValue)), } metricSpec := v2beta2.MetricSpec{ External: externalMetric, Type: externalMetricType, diff --git a/pkg/scalers/kafka_scaler.go b/pkg/scalers/kafka_scaler.go index 0007da4fc9d..1ad9c9ada23 100644 --- a/pkg/scalers/kafka_scaler.go +++ b/pkg/scalers/kafka_scaler.go @@ -350,15 +350,11 @@ func (s *kafkaScaler) Close(context.Context) error { } func (s *kafkaScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetMetricValue := resource.NewQuantity(s.metadata.lagThreshold, resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("kafka-%s", s.metadata.topic))), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetMetricValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, s.metadata.lagThreshold), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: kafkaMetricType} return []v2beta2.MetricSpec{metricSpec} diff --git a/pkg/scalers/kubernetes_workload_scaler.go b/pkg/scalers/kubernetes_workload_scaler.go index 153683ee32e..54b18e0037a 100644 --- a/pkg/scalers/kubernetes_workload_scaler.go +++ b/pkg/scalers/kubernetes_workload_scaler.go @@ -81,15 +81,11 @@ func (s *kubernetesWorkloadScaler) Close(context.Context) error { // GetMetricSpecForScaling returns the metric spec for the HPA func (s *kubernetesWorkloadScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetMetricValue := resource.NewQuantity(s.metadata.value, resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("workload-%s", s.metadata.namespace))), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetMetricValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, s.metadata.value), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: kubernetesWorkloadMetricType} return []v2beta2.MetricSpec{metricSpec} diff --git a/pkg/scalers/liiklus_scaler.go b/pkg/scalers/liiklus_scaler.go index 3e7c069c73a..3f46f2c85de 100644 --- a/pkg/scalers/liiklus_scaler.go +++ b/pkg/scalers/liiklus_scaler.go @@ -83,15 +83,11 @@ func (s *liiklusScaler) GetMetrics(ctx context.Context, metricName string, metri } func (s *liiklusScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetMetricValue := resource.NewQuantity(s.metadata.lagThreshold, resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("liiklus-%s", s.metadata.topic))), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetMetricValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, s.metadata.lagThreshold), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: liiklusMetricType} return []v2beta2.MetricSpec{metricSpec} diff --git a/pkg/scalers/metrics_api_scaler.go b/pkg/scalers/metrics_api_scaler.go index 901b234435b..5624e2135b3 100644 --- a/pkg/scalers/metrics_api_scaler.go +++ b/pkg/scalers/metrics_api_scaler.go @@ -246,15 +246,11 @@ func (s *metricsAPIScaler) IsActive(ctx context.Context) (bool, error) { // GetMetricSpecForScaling returns the MetricSpec for the Horizontal Pod Autoscaler func (s *metricsAPIScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetValue := resource.NewQuantity(int64(s.metadata.targetValue), resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("metric-api-%s", s.metadata.valueLocation))), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.targetValue)), } metricSpec := v2beta2.MetricSpec{ External: externalMetric, Type: externalMetricType, diff --git a/pkg/scalers/mongo_scaler.go b/pkg/scalers/mongo_scaler.go index 788c31c2d2a..caafe475d4e 100644 --- a/pkg/scalers/mongo_scaler.go +++ b/pkg/scalers/mongo_scaler.go @@ -245,16 +245,11 @@ func (s *mongoDBScaler) GetMetrics(ctx context.Context, metricName string, metri // GetMetricSpecForScaling get the query value for scaling func (s *mongoDBScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetQueryValue := resource.NewQuantity(int64(s.metadata.queryValue), resource.DecimalSI) - externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, s.metadata.metricName), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetQueryValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.queryValue)), } metricSpec := v2beta2.MetricSpec{ External: externalMetric, Type: externalMetricType, diff --git a/pkg/scalers/mssql_scaler.go b/pkg/scalers/mssql_scaler.go index 764131667c8..ee80c33130e 100644 --- a/pkg/scalers/mssql_scaler.go +++ b/pkg/scalers/mssql_scaler.go @@ -210,15 +210,11 @@ func getMSSQLConnectionString(meta *mssqlMetadata) string { // GetMetricSpecForScaling returns the MetricSpec for the Horizontal Pod Autoscaler func (s *mssqlScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetQueryValue := resource.NewQuantity(int64(s.metadata.targetValue), resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, s.metadata.metricName), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetQueryValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.targetValue)), } metricSpec := v2beta2.MetricSpec{ diff --git a/pkg/scalers/mysql_scaler.go b/pkg/scalers/mysql_scaler.go index 0bd04435b8f..49dc858c28c 100644 --- a/pkg/scalers/mysql_scaler.go +++ b/pkg/scalers/mysql_scaler.go @@ -199,16 +199,11 @@ func (s *mySQLScaler) getQueryResult(ctx context.Context) (int, error) { // GetMetricSpecForScaling returns the MetricSpec for the Horizontal Pod Autoscaler func (s *mySQLScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetQueryValue := resource.NewQuantity(int64(s.metadata.queryValue), resource.DecimalSI) - externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: s.metadata.metricName, }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetQueryValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.queryValue)), } metricSpec := v2beta2.MetricSpec{ External: externalMetric, Type: externalMetricType, diff --git a/pkg/scalers/openstack_metrics_scaler.go b/pkg/scalers/openstack_metrics_scaler.go index acbf1aca551..f80e276b4ea 100644 --- a/pkg/scalers/openstack_metrics_scaler.go +++ b/pkg/scalers/openstack_metrics_scaler.go @@ -196,17 +196,13 @@ func parseOpenstackMetricAuthenticationMetadata(config *ScalerConfig) (openstack } func (a *openstackMetricScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetMetricVal := resource.NewQuantity(int64(a.metadata.threshold), resource.DecimalSI) metricName := kedautil.NormalizeString(fmt.Sprintf("openstack-metric-%s", a.metadata.metricID)) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(a.metadata.scalerIndex, metricName), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetMetricVal, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(a.metadata.threshold)), } metricSpec := v2beta2.MetricSpec{ diff --git a/pkg/scalers/openstack_swift_scaler.go b/pkg/scalers/openstack_swift_scaler.go index 58adf178a47..c26db6c8b62 100644 --- a/pkg/scalers/openstack_swift_scaler.go +++ b/pkg/scalers/openstack_swift_scaler.go @@ -382,8 +382,6 @@ func (s *openstackSwiftScaler) GetMetrics(ctx context.Context, metricName string } func (s *openstackSwiftScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetObjectCount := resource.NewQuantity(int64(s.metadata.objectCount), resource.DecimalSI) - var metricName string if s.metadata.objectPrefix != "" { @@ -398,10 +396,7 @@ func (s *openstackSwiftScaler) GetMetricSpecForScaling(context.Context) []v2beta Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, metricName), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetObjectCount, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.objectCount)), } metricSpec := v2beta2.MetricSpec{ diff --git a/pkg/scalers/postgresql_scaler.go b/pkg/scalers/postgresql_scaler.go index 7e8323ee098..ce4616deb95 100644 --- a/pkg/scalers/postgresql_scaler.go +++ b/pkg/scalers/postgresql_scaler.go @@ -184,16 +184,11 @@ func (s *postgreSQLScaler) getActiveNumber(ctx context.Context) (int, error) { // GetMetricSpecForScaling returns the MetricSpec for the Horizontal Pod Autoscaler func (s *postgreSQLScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetQueryValue := resource.NewQuantity(int64(s.metadata.targetQueryValue), resource.DecimalSI) - externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, s.metadata.metricName), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetQueryValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.targetQueryValue)), } metricSpec := v2beta2.MetricSpec{ External: externalMetric, Type: externalMetricType, diff --git a/pkg/scalers/prometheus_scaler.go b/pkg/scalers/prometheus_scaler.go index fadad7baa8a..327bfe51ee3 100644 --- a/pkg/scalers/prometheus_scaler.go +++ b/pkg/scalers/prometheus_scaler.go @@ -201,16 +201,12 @@ func (s *prometheusScaler) Close(context.Context) error { } func (s *prometheusScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetMetricValue := resource.NewQuantity(int64(s.metadata.threshold), resource.DecimalSI) metricName := kedautil.NormalizeString(fmt.Sprintf("prometheus-%s", s.metadata.metricName)) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, metricName), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetMetricValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.threshold)), } metricSpec := v2beta2.MetricSpec{ External: externalMetric, Type: externalMetricType, diff --git a/pkg/scalers/rabbitmq_scaler.go b/pkg/scalers/rabbitmq_scaler.go index 1448d75d39c..6cdcdee513f 100644 --- a/pkg/scalers/rabbitmq_scaler.go +++ b/pkg/scalers/rabbitmq_scaler.go @@ -443,15 +443,11 @@ func (s *rabbitMQScaler) getQueueInfoViaHTTP() (*queueInfo, error) { // GetMetricSpecForScaling returns the MetricSpec for the Horizontal Pod Autoscaler func (s *rabbitMQScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - metricValue := resource.NewQuantity(int64(s.metadata.value), resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, s.metadata.metricName), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: metricValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.value)), } metricSpec := v2beta2.MetricSpec{ External: externalMetric, Type: rabbitMetricType, diff --git a/pkg/scalers/redis_scaler.go b/pkg/scalers/redis_scaler.go index 0fa76c2eeb3..9e372445336 100644 --- a/pkg/scalers/redis_scaler.go +++ b/pkg/scalers/redis_scaler.go @@ -234,16 +234,12 @@ func (s *redisScaler) Close(context.Context) error { // GetMetricSpecForScaling returns the metric spec for the HPA func (s *redisScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetListLengthQty := resource.NewQuantity(int64(s.metadata.targetListLength), resource.DecimalSI) metricName := kedautil.NormalizeString(fmt.Sprintf("redis-%s", s.metadata.listName)) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, metricName), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetListLengthQty, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.targetListLength)), } metricSpec := v2beta2.MetricSpec{ External: externalMetric, Type: externalMetricType, diff --git a/pkg/scalers/redis_streams_scaler.go b/pkg/scalers/redis_streams_scaler.go index 1857837ac36..7479e209e09 100644 --- a/pkg/scalers/redis_streams_scaler.go +++ b/pkg/scalers/redis_streams_scaler.go @@ -218,15 +218,11 @@ func (s *redisStreamsScaler) Close(context.Context) error { // GetMetricSpecForScaling returns the metric spec for the HPA func (s *redisStreamsScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetPendingEntriesCount := resource.NewQuantity(int64(s.metadata.targetPendingEntriesCount), resource.DecimalSI) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("redis-streams-%s", s.metadata.streamName))), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetPendingEntriesCount, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.targetPendingEntriesCount)), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: externalMetricType} return []v2beta2.MetricSpec{metricSpec} diff --git a/pkg/scalers/scaler.go b/pkg/scalers/scaler.go index 32583336ede..f27e26965a5 100644 --- a/pkg/scalers/scaler.go +++ b/pkg/scalers/scaler.go @@ -22,6 +22,7 @@ import ( "time" "k8s.io/api/autoscaling/v2beta2" + "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/labels" "k8s.io/metrics/pkg/apis/external_metrics" @@ -84,6 +85,9 @@ type ScalerConfig struct { // ScalerIndex ScalerIndex int + + // MetricType + MetricType v2beta2.MetricTargetType } // GetFromAuthOrMeta helps getting a field from Auth or Meta sections @@ -105,3 +109,33 @@ func GetFromAuthOrMeta(config *ScalerConfig, field string) (string, error) { func GenerateMetricNameWithIndex(scalerIndex int, metricName string) string { return fmt.Sprintf("s%d-%s", scalerIndex, metricName) } + +// GetExternalMetricTargetType helps getting the metric target type of the scaler +func GetExternalMetricTargetType(metricType v2beta2.MetricTargetType) (v2beta2.MetricTargetType, error) { + switch metricType { + case v2beta2.UtilizationMetricType: + return "", fmt.Errorf("'Utilization' metric type is unsupported for external metrics, allowed values are 'Value' or 'AverageValue'") + case "": + // Use AverageValue if no metric type was provided + return v2beta2.AverageValueMetricType, nil + default: + return metricType, nil + } +} + +// GetExternalMetricTarget returns a metric target for a valid given metric target type (Value or AverageValue) and value +func GetExternalMetricTarget(metricType v2beta2.MetricTargetType, metricValue int64) v2beta2.MetricTarget { + target := v2beta2.MetricTarget{ + Type: metricType, + } + + // Construct the target size as a quantity + targetQty := resource.NewQuantity(metricValue, resource.DecimalSI) + if metricType == v2beta2.AverageValueMetricType { + target.AverageValue = targetQty + } else { + target.Value = targetQty + } + + return target +} diff --git a/pkg/scalers/scaler_test.go b/pkg/scalers/scaler_test.go new file mode 100644 index 00000000000..04b845e3431 --- /dev/null +++ b/pkg/scalers/scaler_test.go @@ -0,0 +1,87 @@ +package scalers + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + v2beta2 "k8s.io/api/autoscaling/v2beta2" + "k8s.io/apimachinery/pkg/api/resource" +) + +func TestGetExternalMetricTargetType(t *testing.T) { + cases := []struct { + name string + metricType v2beta2.MetricTargetType + wantmetricType v2beta2.MetricTargetType + wantErr error + }{ + { + name: "utilization metric type", + metricType: v2beta2.UtilizationMetricType, + wantmetricType: "", + wantErr: fmt.Errorf("'Utilization' metric type is unsupported for external metrics, allowed values are 'Value' or 'AverageValue'"), + }, + { + name: "average value metric type", + metricType: v2beta2.AverageValueMetricType, + wantmetricType: v2beta2.AverageValueMetricType, + wantErr: nil, + }, + { + name: "value metric type", + metricType: v2beta2.ValueMetricType, + wantmetricType: v2beta2.ValueMetricType, + wantErr: nil, + }, + { + name: "no metric type", + metricType: "", + wantmetricType: v2beta2.AverageValueMetricType, + wantErr: nil, + }, + } + + for _, testCase := range cases { + c := testCase + t.Run(c.name, func(t *testing.T) { + metricType, err := GetExternalMetricTargetType(c.metricType) + if c.wantErr != nil { + assert.Contains(t, err.Error(), c.wantErr.Error()) + } else { + assert.NoError(t, err) + } + assert.Equal(t, c.wantmetricType, metricType) + }) + } +} + +func TestGetExternalMetricTarget(t *testing.T) { + cases := []struct { + name string + metricType v2beta2.MetricTargetType + metricValue int64 + wantmetricTarget v2beta2.MetricTarget + }{ + { + name: "average value metric type", + metricType: v2beta2.AverageValueMetricType, + metricValue: 10, + wantmetricTarget: v2beta2.MetricTarget{Type: v2beta2.AverageValueMetricType, AverageValue: resource.NewQuantity(10, resource.DecimalSI)}, + }, + { + name: "value metric type", + metricType: v2beta2.ValueMetricType, + metricValue: 20, + wantmetricTarget: v2beta2.MetricTarget{Type: v2beta2.ValueMetricType, Value: resource.NewQuantity(20, resource.DecimalSI)}, + }, + } + + for _, testCase := range cases { + c := testCase + t.Run(c.name, func(t *testing.T) { + metricTarget := GetExternalMetricTarget(c.metricType, c.metricValue) + assert.Equal(t, c.wantmetricTarget, metricTarget) + }) + } +} diff --git a/pkg/scalers/selenium_grid_scaler.go b/pkg/scalers/selenium_grid_scaler.go index be3d0d58b55..c2444b6ec38 100644 --- a/pkg/scalers/selenium_grid_scaler.go +++ b/pkg/scalers/selenium_grid_scaler.go @@ -136,16 +136,12 @@ func (s *seleniumGridScaler) GetMetrics(ctx context.Context, metricName string, } func (s *seleniumGridScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetValue := resource.NewQuantity(s.metadata.targetValue, resource.DecimalSI) metricName := kedautil.NormalizeString(fmt.Sprintf("seleniumgrid-%s", s.metadata.browserName)) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, metricName), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, s.metadata.targetValue), } metricSpec := v2beta2.MetricSpec{ External: externalMetric, Type: externalMetricType, diff --git a/pkg/scalers/solace_scaler.go b/pkg/scalers/solace_scaler.go index de471b50143..e13d68dc731 100644 --- a/pkg/scalers/solace_scaler.go +++ b/pkg/scalers/solace_scaler.go @@ -243,32 +243,24 @@ func (s *SolaceScaler) GetMetricSpecForScaling(context.Context) []v2beta2.Metric var metricSpecList []v2beta2.MetricSpec // Message Count Target Spec if s.metadata.msgCountTarget > 0 { - targetMetricValue := resource.NewQuantity(int64(s.metadata.msgCountTarget), resource.DecimalSI) metricName := kedautil.NormalizeString(fmt.Sprintf("solace-%s-%s", s.metadata.queueName, solaceTriggermsgcount)) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, metricName), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetMetricValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.msgCountTarget)), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: solaceExtMetricType} metricSpecList = append(metricSpecList, metricSpec) } // Message Spool Usage Target Spec if s.metadata.msgSpoolUsageTarget > 0 { - targetMetricValue := resource.NewQuantity(int64(s.metadata.msgSpoolUsageTarget), resource.DecimalSI) metricName := kedautil.NormalizeString(fmt.Sprintf("solace-%s-%s", s.metadata.queueName, solaceTriggermsgspoolusage)) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, metricName), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetMetricValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, int64(s.metadata.msgSpoolUsageTarget)), } metricSpec := v2beta2.MetricSpec{External: externalMetric, Type: solaceExtMetricType} metricSpecList = append(metricSpecList, metricSpec) diff --git a/pkg/scalers/stan_scaler.go b/pkg/scalers/stan_scaler.go index 22119010e74..f8d8d64d65f 100644 --- a/pkg/scalers/stan_scaler.go +++ b/pkg/scalers/stan_scaler.go @@ -197,16 +197,12 @@ func (s *stanScaler) hasPendingMessage() bool { } func (s *stanScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - targetMetricValue := resource.NewQuantity(s.metadata.lagThreshold, resource.DecimalSI) metricName := kedautil.NormalizeString(fmt.Sprintf("stan-%s", s.metadata.subject)) externalMetric := &v2beta2.ExternalMetricSource{ Metric: v2beta2.MetricIdentifier{ Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, metricName), }, - Target: v2beta2.MetricTarget{ - Type: v2beta2.AverageValueMetricType, - AverageValue: targetMetricValue, - }, + Target: GetExternalMetricTarget(v2beta2.AverageValueMetricType, s.metadata.lagThreshold), } metricSpec := v2beta2.MetricSpec{ External: externalMetric, Type: stanMetricType, diff --git a/pkg/scaling/scale_handler.go b/pkg/scaling/scale_handler.go index 68be3bcadb9..fc4edb1a67b 100644 --- a/pkg/scaling/scale_handler.go +++ b/pkg/scaling/scale_handler.go @@ -295,6 +295,7 @@ func (h *scaleHandler) buildScalers(ctx context.Context, withTriggers *kedav1alp AuthParams: make(map[string]string), GlobalHTTPTimeout: h.globalHTTPTimeout, ScalerIndex: scalerIndex, + MetricType: trigger.MetricType, } config.AuthParams, config.PodIdentity, err = resolver.ResolveAuthRefAndPodIdentity(ctx, h.client, logger, trigger.AuthenticationRef, podTemplateSpec, withTriggers.Namespace)