Skip to content

Commit 720ae0e

Browse files
authored
Add time.Duration in TypedConfig (#6650)
* Add time Duration at TypedConfig Signed-off-by: Rick Brouwer <[email protected]> * Add time duration prometheus scaler Signed-off-by: Rick Brouwer <[email protected]> * Correct changelog Signed-off-by: Rick Brouwer <[email protected]> * Update after feedback Signed-off-by: Rick Brouwer <[email protected]> --------- Signed-off-by: Rick Brouwer <[email protected]> Signed-off-by: rickbrouwer <[email protected]>
1 parent dafd9a8 commit 720ae0e

File tree

5 files changed

+45
-34
lines changed

5 files changed

+45
-34
lines changed

Diff for: CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ New deprecation(s):
156156
### Other
157157

158158
- **General**: Add debug logs tracking validation of ScaledObjects on webhook ([#6498](https://github.com/kedacore/keda/pull/6498))
159+
- **General**: Add time.Duration in TypedConfig ([#6650](https://github.com/kedacore/keda/pull/6650))
159160
- **General**: New eventreason KEDAScalersInfo to display important information ([#6328](https://github.com/kedacore/keda/issues/6328))
160161
- **Apache Kafka Scaler**: Remove unused awsEndpoint in Apache Kafka scaler ([#6627](https://github.com/kedacore/keda/pull/6627))
161162
- **External Scalers**: Allow `float64` values in externalmetrics' `MetricValue` & `TargetSize`. The old fields are still there because of backward compatibility. ([#5159](https://github.com/kedacore/keda/issues/5159))

Diff for: pkg/scalers/beanstalkd_scaler.go

+7-9
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ type BeanstalkdScaler struct {
3434
}
3535

3636
type BeanstalkdMetadata struct {
37-
Server string `keda:"name=server, order=triggerMetadata"`
38-
Tube string `keda:"name=tube, order=triggerMetadata"`
39-
Value float64 `keda:"name=value, order=triggerMetadata"`
40-
ActivationValue float64 `keda:"name=activationValue, order=triggerMetadata, optional"`
41-
IncludeDelayed bool `keda:"name=includeDelayed, order=triggerMetadata, optional"`
42-
Timeout uint `keda:"name=timeout, order=triggerMetadata, default=30"`
37+
Server string `keda:"name=server, order=triggerMetadata"`
38+
Tube string `keda:"name=tube, order=triggerMetadata"`
39+
Value float64 `keda:"name=value, order=triggerMetadata"`
40+
ActivationValue float64 `keda:"name=activationValue, order=triggerMetadata, optional"`
41+
IncludeDelayed bool `keda:"name=includeDelayed, order=triggerMetadata, optional"`
42+
Timeout time.Duration `keda:"name=timeout, order=triggerMetadata, default=30"`
4343
TriggerIndex int
4444
}
4545

@@ -70,9 +70,7 @@ func NewBeanstalkdScaler(config *scalersconfig.ScalerConfig) (Scaler, error) {
7070
}
7171
s.metadata = meta
7272

73-
timeout := time.Duration(s.metadata.Timeout) * time.Second
74-
75-
conn, err := beanstalk.DialTimeout(beanstalkdNetworkProtocol, s.metadata.Server, timeout)
73+
conn, err := beanstalk.DialTimeout(beanstalkdNetworkProtocol, s.metadata.Server, s.metadata.Timeout)
7674
if err != nil {
7775
return nil, fmt.Errorf("error connecting to beanstalkd: %w", err)
7876
}

Diff for: pkg/scalers/prometheus_scaler.go

+9-14
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,15 @@ type prometheusMetadata struct {
4242
PrometheusAuth *authentication.Config `keda:"optional"`
4343
ServerAddress string `keda:"name=serverAddress, order=triggerMetadata"`
4444
Query string `keda:"name=query, order=triggerMetadata"`
45-
QueryParameters map[string]string `keda:"name=queryParameters, order=triggerMetadata, optional"`
45+
QueryParameters map[string]string `keda:"name=queryParameters, order=triggerMetadata, optional"`
4646
Threshold float64 `keda:"name=threshold, order=triggerMetadata"`
47-
ActivationThreshold float64 `keda:"name=activationThreshold, order=triggerMetadata, optional"`
48-
Namespace string `keda:"name=namespace, order=triggerMetadata, optional"`
49-
CustomHeaders map[string]string `keda:"name=customHeaders, order=triggerMetadata, optional"`
50-
IgnoreNullValues bool `keda:"name=ignoreNullValues, order=triggerMetadata, default=true"`
51-
UnsafeSSL bool `keda:"name=unsafeSsl, order=triggerMetadata, optional"`
52-
AwsRegion string `keda:"name=awsRegion, order=triggerMetadata;authParams, optional"`
53-
Timeout int `keda:"name=timeout, order=triggerMetadata, optional"` // custom HTTP client timeout
47+
ActivationThreshold float64 `keda:"name=activationThreshold, order=triggerMetadata, optional"`
48+
Namespace string `keda:"name=namespace, order=triggerMetadata, optional"`
49+
CustomHeaders map[string]string `keda:"name=customHeaders, order=triggerMetadata, optional"`
50+
IgnoreNullValues bool `keda:"name=ignoreNullValues, order=triggerMetadata, default=true"`
51+
UnsafeSSL bool `keda:"name=unsafeSsl, order=triggerMetadata, optional"`
52+
AwsRegion string `keda:"name=awsRegion, order=triggerMetadata;authParams, optional"`
53+
Timeout time.Duration `keda:"name=timeout, order=triggerMetadata, optional"` // custom HTTP client timeout
5454
}
5555

5656
type promQueryResult struct {
@@ -82,7 +82,7 @@ func NewPrometheusScaler(config *scalersconfig.ScalerConfig) (Scaler, error) {
8282
// handle HTTP client timeout
8383
httpClientTimeout := config.GlobalHTTPTimeout
8484
if meta.Timeout > 0 {
85-
httpClientTimeout = time.Duration(meta.Timeout) * time.Millisecond
85+
httpClientTimeout = meta.Timeout * time.Millisecond
8686
}
8787

8888
httpClient := kedautil.CreateHTTPClient(httpClientTimeout, meta.UnsafeSSL)
@@ -155,11 +155,6 @@ func parsePrometheusMetadata(config *scalersconfig.ScalerConfig) (meta *promethe
155155
return nil, err
156156
}
157157

158-
// validate the timeout
159-
if meta.Timeout < 0 {
160-
return nil, fmt.Errorf("timeout must be greater than 0: %d", meta.Timeout)
161-
}
162-
163158
return meta, nil
164159
}
165160

Diff for: pkg/scalers/rabbitmq_scaler.go

+6-11
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ type rabbitMQMetadata struct {
9696
// specify the operation to apply in case of multiples queues
9797
Operation string `keda:"name=operation, order=triggerMetadata, default=sum"`
9898
// custom http timeout for a specific trigger
99-
TimeoutMs int `keda:"name=timeout, order=triggerMetadata, optional"`
99+
Timeout time.Duration `keda:"name=timeout, order=triggerMetadata, optional"`
100100

101101
Username string `keda:"name=username, order=authParams;resolvedEnv, optional"`
102102
Password string `keda:"name=password, order=authParams;resolvedEnv, optional"`
@@ -210,13 +210,10 @@ func (r *rabbitMQMetadata) validateTrigger() error {
210210
return fmt.Errorf("protocol %s not supported; must be http to use mode %s", r.Protocol, rabbitModeMessageRate)
211211
}
212212

213-
if r.Protocol == amqpProtocol && r.TimeoutMs != 0 {
214-
return fmt.Errorf("amqp protocol doesn't support custom timeouts: %d", r.TimeoutMs)
213+
if r.Protocol == amqpProtocol && r.Timeout != 0 {
214+
return fmt.Errorf("amqp protocol doesn't support custom timeouts: %d", r.Timeout)
215215
}
216216

217-
if r.TimeoutMs < 0 {
218-
return fmt.Errorf("timeout must be greater than 0: %d", r.TimeoutMs)
219-
}
220217
return nil
221218
}
222219

@@ -260,11 +257,9 @@ func NewRabbitMQScaler(config *scalersconfig.ScalerConfig) (Scaler, error) {
260257

261258
s.metadata = meta
262259

263-
var timeout time.Duration
264-
if s.metadata.TimeoutMs != 0 {
265-
timeout = time.Duration(s.metadata.TimeoutMs) * time.Millisecond
266-
} else {
267-
timeout = config.GlobalHTTPTimeout
260+
timeout := config.GlobalHTTPTimeout
261+
if s.metadata.Timeout != 0 {
262+
timeout = s.metadata.Timeout * time.Millisecond
268263
}
269264

270265
s.httpClient = kedautil.CreateHTTPClient(timeout, meta.UnsafeSsl)

Diff for: pkg/scalers/scalersconfig/typed_config.go

+22
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"slices"
2828
"strconv"
2929
"strings"
30+
"time"
3031

3132
corev1 "k8s.io/api/core/v1"
3233

@@ -401,6 +402,27 @@ func setConfigValueHelper(params Params, valFromConfig string, field reflect.Val
401402
field.Set(paramValue.Convert(field.Type()))
402403
return nil
403404
}
405+
if field.Type() == reflect.TypeOf(time.Duration(0)) {
406+
// Try to parse as duration string first
407+
duration, err := time.ParseDuration(valFromConfig)
408+
if err == nil {
409+
if duration < 0 {
410+
return fmt.Errorf("duration cannot be negative: %q", valFromConfig)
411+
}
412+
field.Set(reflect.ValueOf(duration))
413+
return nil
414+
}
415+
// If that fails, interpret as number of seconds
416+
seconds, err := strconv.ParseInt(valFromConfig, 10, 64)
417+
if err != nil {
418+
return fmt.Errorf("unable to parse duration value %q: must be either a duration string (e.g. '30s', '5m') or a number of seconds", valFromConfig)
419+
}
420+
if seconds < 0 {
421+
return fmt.Errorf("duration cannot be negative: %d seconds", seconds)
422+
}
423+
field.Set(reflect.ValueOf(time.Duration(seconds) * time.Second))
424+
return nil
425+
}
404426
if field.Type() == reflect.TypeOf(url.Values{}) {
405427
return setConfigValueURLParams(params, valFromConfig, field)
406428
}

0 commit comments

Comments
 (0)