Skip to content

Commit

Permalink
Add an optional metric type field to the scale trigger spec
Browse files Browse the repository at this point in the history
Signed-off-by: amirschw <24677563+amirschw@users.noreply.github.com>
  • Loading branch information
amirschw committed Nov 21, 2021
1 parent cf1b365 commit 5e51a85
Show file tree
Hide file tree
Showing 45 changed files with 226 additions and 210 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions apis/keda/v1alpha1/scaledobject_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions config/crd/bases/keda.sh_scaledjobs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
5 changes: 5 additions & 0 deletions config/crd/bases/keda.sh_scaledobjects.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
6 changes: 1 addition & 5 deletions pkg/scalers/artemis_scaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
6 changes: 1 addition & 5 deletions pkg/scalers/aws_cloudwatch_scaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
6 changes: 1 addition & 5 deletions pkg/scalers/aws_kinesis_stream_scaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
6 changes: 1 addition & 5 deletions pkg/scalers/aws_sqs_queue_scaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
6 changes: 1 addition & 5 deletions pkg/scalers/azure_blob_scaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
6 changes: 1 addition & 5 deletions pkg/scalers/azure_eventhub_scaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
5 changes: 1 addition & 4 deletions pkg/scalers/azure_log_analytics_scaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
6 changes: 1 addition & 5 deletions pkg/scalers/azure_monitor_scaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
6 changes: 1 addition & 5 deletions pkg/scalers/azure_pipelines_scaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
6 changes: 1 addition & 5 deletions pkg/scalers/azure_queue_scaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
7 changes: 1 addition & 6 deletions pkg/scalers/azure_servicebus_scaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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}
Expand Down
6 changes: 1 addition & 5 deletions pkg/scalers/cassandra_scaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
18 changes: 12 additions & 6 deletions pkg/scalers/cpu_memory_scaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand Down
36 changes: 27 additions & 9 deletions pkg/scalers/cpu_memory_scaler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand All @@ -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,
}
Expand All @@ -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)
}
6 changes: 1 addition & 5 deletions pkg/scalers/cron_scaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
Loading

0 comments on commit 5e51a85

Please sign in to comment.