Skip to content

Commit 0d6f578

Browse files
fix(api,ui): Fix autoscaling target parsing (caraml-dev#380)
* Allow setting of autoscaling targets on the ui without constraints on number of decimal places * Add parsing of autoscaling targets to int for cpu and rps * Update min and step size for autoscaling target field * Update unit tests and error messages
1 parent c96619d commit 0d6f578

File tree

5 files changed

+50
-17
lines changed

5 files changed

+50
-17
lines changed

api/turing/cluster/knative_service.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,16 @@ func (cfg *KnativeService) buildSvcSpec(
196196
}
197197

198198
func (cfg *KnativeService) getAutoscalingTarget() (string, error) {
199-
if cfg.AutoscalingMetric == "memory" {
199+
switch cfg.AutoscalingMetric {
200+
case "cpu", "rps":
201+
// Parse the autoscaling target to an integer
202+
rawTarget, err := strconv.ParseFloat(cfg.AutoscalingTarget, 64)
203+
if err != nil {
204+
return "", err
205+
}
206+
targetValue := fmt.Sprintf("%.0f", rawTarget)
207+
return targetValue, nil
208+
case "memory":
200209
// The value is supplied as a % of requested memory but the Knative API expects the value in Mi.
201210
targetPercent, err := strconv.ParseFloat(cfg.AutoscalingTarget, 64)
202211
if err != nil {
@@ -205,15 +214,16 @@ func (cfg *KnativeService) getAutoscalingTarget() (string, error) {
205214
targetResource := ComputeResource(cfg.BaseService.MemoryRequests, targetPercent/100)
206215
// Divide value by (1024^2) to convert to Mi
207216
return fmt.Sprintf("%.0f", float64(targetResource.Value())/math.Pow(1024, 2)), nil
208-
209-
} else if cfg.AutoscalingMetric == "concurrency" {
217+
case "concurrency":
218+
// Parse the autoscaling target to a value up to 2 decimal places because Knative allows it
210219
rawTarget, err := strconv.ParseFloat(cfg.AutoscalingTarget, 64)
211220
if err != nil {
212221
return "", err
213222
}
214223
targetValue := fmt.Sprintf("%.2f", rawTarget)
215224
if targetValue == "0.00" {
216-
return "", fmt.Errorf("concurrency target %v should be at least 0.01", cfg.AutoscalingTarget)
225+
return "", fmt.Errorf("concurrency target %v should be at least 0.01 after rounding to 2 decimal places",
226+
cfg.AutoscalingTarget)
217227
}
218228
return targetValue, nil
219229
}

api/turing/cluster/knative_service_test.go

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -512,24 +512,45 @@ func TestGetAutoscalingTarget(t *testing.T) {
512512
expectedTarget string
513513
expectedErr string
514514
}{
515+
"concurrency | target is not a number": {
516+
cfg: &KnativeService{
517+
AutoscalingMetric: "concurrency",
518+
AutoscalingTarget: "10.1.1",
519+
},
520+
expectedErr: "strconv.ParseFloat: parsing \"10.1.1\": invalid syntax",
521+
},
522+
"concurrency | target when rounded to 2 decimal places is equals to 0.00": {
523+
cfg: &KnativeService{
524+
AutoscalingMetric: "concurrency",
525+
AutoscalingTarget: "0.004",
526+
},
527+
expectedErr: "concurrency target 0.004 should be at least 0.01 after rounding to 2 decimal places",
528+
},
515529
"concurrency": {
516530
cfg: &KnativeService{
517531
AutoscalingMetric: "concurrency",
518532
AutoscalingTarget: "10",
519533
},
520534
expectedTarget: "10.00",
521535
},
536+
"rps | target is not a number": {
537+
cfg: &KnativeService{
538+
AutoscalingMetric: "rps",
539+
AutoscalingTarget: "100.1.1",
540+
},
541+
expectedErr: "strconv.ParseFloat: parsing \"100.1.1\": invalid syntax",
542+
},
522543
"rps": {
523544
cfg: &KnativeService{
524545
AutoscalingMetric: "rps",
525-
AutoscalingTarget: "100",
546+
AutoscalingTarget: "100.1",
526547
},
527548
expectedTarget: "100",
528549
},
529550
"cpu": {
530551
cfg: &KnativeService{
531552
AutoscalingMetric: "cpu",
532-
AutoscalingTarget: "80",
553+
AutoscalingTarget: "80.2",
533554
},
534555
expectedTarget: "80",
535556
},
@@ -563,7 +584,7 @@ func TestGetAutoscalingTarget(t *testing.T) {
563584
},
564585
expectedTarget: "1335", // (70/100) * ((2G * 10^9) bytes / 1024^2)Mi
565586
},
566-
"memory | failure": {
587+
"memory | target is not a number": {
567588
cfg: &KnativeService{
568589
BaseService: &BaseService{
569590
MemoryRequests: resource.MustParse("1Gi"),

ui/src/router/components/form/components/autoscaling_policy/AutoscalingPolicyPanel.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ export const AutoscalingPolicyPanel = ({
2424
errors = {},
2525
}) => {
2626
const { onChange } = useOnChangeHandler(onChangeHandler);
27-
// Parse the integer portion of the value
27+
// Parse the float portion of the value
2828
const onChangeTarget = (value) => {
29-
const parsedInt = parseInt(value);
30-
onChange("target")(isNaN(parsedInt) ? "" : parsedInt.toString());
29+
const parsedFloat = parseFloat(value);
30+
onChange("target")(isNaN(value) ? "" : parsedFloat.toString());
3131
};
3232
// Update default target if the metric is changing
3333
const onChangeMetric = (value) => {
@@ -93,8 +93,10 @@ export const AutoscalingPolicyPanel = ({
9393
onChange={(e) => onChangeTarget(e.target.value)}
9494
isInvalid={!!errors.target}
9595
name="memory"
96-
min={1}
97-
step={1}
96+
// The min value is set as 0.005 because it's the smallest value, when rounded to 2 decimal places, gives
97+
// 0.01, the smallest value accepted as an autoscaling target (concurrency).
98+
min={0.005}
99+
step={"any"}
98100
append={selectedMetric.unit}
99101
/>
100102
</EuiFormRow>

ui/src/router/components/form/validation/schema.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ const autoscalingPolicySchema = yup.object().shape({
233233
target: yup
234234
.string()
235235
.required("Valid target should be specified")
236-
.matches(/^[0-9]+$/, "Must be a number"),
236+
.matches(/(\d+(?:\.\d+)?)/, "Must be a number"),
237237
});
238238

239239
const enricherSchema = yup.object().shape({

ui/src/services/version/RouterVersion.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export class RouterVersion {
9595
resource_request: this.resource_request,
9696
autoscaling_policy: {
9797
...this.autoscaling_policy,
98-
target: parseInt(this.autoscaling_policy.target),
98+
target: parseFloat(this.autoscaling_policy.target),
9999
},
100100
protocol: this.protocol,
101101
},
@@ -112,7 +112,7 @@ export class RouterVersion {
112112
resource_request: this.enricher.resource_request,
113113
autoscaling_policy: {
114114
...this.enricher.autoscaling_policy,
115-
target: parseInt(this.enricher.autoscaling_policy.target),
115+
target: parseFloat(this.enricher.autoscaling_policy.target),
116116
},
117117
}
118118
: {
@@ -136,7 +136,7 @@ export class RouterVersion {
136136
...this.ensembler.docker_config,
137137
autoscaling_policy: {
138138
...this.ensembler.docker_config.autoscaling_policy,
139-
target: parseInt(
139+
target: parseFloat(
140140
this.ensembler.docker_config.autoscaling_policy.target
141141
),
142142
},
@@ -148,7 +148,7 @@ export class RouterVersion {
148148
...this.ensembler.pyfunc_config,
149149
autoscaling_policy: {
150150
...this.ensembler.pyfunc_config.autoscaling_policy,
151-
target: parseInt(
151+
target: parseFloat(
152152
this.ensembler.pyfunc_config.autoscaling_policy.target
153153
),
154154
},

0 commit comments

Comments
 (0)