Skip to content

fix: preserve fractional scale target minimum - #4067

Open
Elvand-Lie wants to merge 1 commit into
knative:mainfrom
Elvand-Lie:fix/schema-fractional-numeric-constraints
Open

Elvand-Lie wants to merge 1 commit into
knative:mainfrom
Elvand-Lie:fix/schema-fractional-numeric-constraints

Conversation

@Elvand-Lie

@Elvand-Lie Elvand-Lie commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Changes

  • 🐛 Preserve the 0.01 minimum for scale.kpa.target in the generated func.yaml schema instead of emitting 0.
  • 🔥 Remove the exclusiveMinimum=true workaround that Add top-level scale field to func.yaml #4063 added to that same field while the fractional minimum was still being truncated.

/kind bug

Fixes #4066

Problem

KPAScaleOptions.Target declares:

Target *float64 `yaml:"target,omitempty" jsonschema_extras:"minimum=0.01"`

but the pinned github.com/alecthomas/jsonschema implementation represents minimum as an int and parses its tag value with strconv.Atoi, discarding the error:

type Type struct {
	Minimum int `json:"minimum,omitempty"`
}

"0.01" fails to parse, silently degrades to zero, and the generated schema publishes "minimum": 0 where runtime validation requires target >= 0.01. A func.yaml with scale.kpa.target: 0.001 therefore validated against the published schema and was rejected at deploy time. The schema was looser than the validation it documents.

Fix

After the normal reflection pass, restore the fractional minimum on the already-reflected KPAScaleOptions.target property before the schema is marshalled. The value is read back from the same jsonschema_extras tag rather than duplicated in the generator, so the constraint stays declared once and cannot drift from the runtime check it documents.

Removing the exclusiveMinimum=true workaround

#4063 declared exclusiveMinimum=true on this field as a stopgap for exactly this truncation, so the schema at least excluded the concrete invalid value 0. That stopgap must not survive this fix.

This document declares draft-04, where a boolean exclusiveMinimum makes minimum exclusive. The two changes together would have produced:

"target": { "exclusiveMinimum": true, "minimum": 0.01 }

which means target > 0.01, while validateKPAScale rejects only values < 0.01:

if kpa.Target != nil && *kpa.Target < 0.01 {

so it accepts exactly 0.01. Keeping both would have inverted the original bug: the schema would have become stricter than the runtime check, rejecting a valid target: 0.01 that deploys fine. Removing the workaround now that the real minimum is preserved correctly gets both to target >= 0.01.

Tests

TestTargetMinimumIsPreserved verifies the whole neighbourhood, not just the corrected value:

  • KPAScaleOptions.target.minimum is emitted as exactly 0.01
  • KPAScaleOptions.target.exclusiveMinimum is absent, so the bound stays inclusive
  • the neighbouring utilization.minimum / utilization.maximum are still 1 and 100

Test_ValidateScale covers the runtime boundary on both sides of the same value:

target ValidateScale
0.01 valid
math.Nextafter(0.01, 0) (largest float64 below 0.01) invalid
0.02 valid

together pinning the contract at target >= 0.01 on both the schema and the validation side.

You can also confirm the diff by inspection — regenerating changes exactly one line of schema/func_yaml-schema.json:

 			"target": {
-				"exclusiveMinimum": true,
 				"type": "number",
-				"minimum": 0
+				"minimum": 0.01
 			},

Validated locally with:

go run schema/generator/main.go                 # produces no further diff
go test -count=1 -v ./schema/generator/... -run TestTargetMinimumIsPreserved
go test -race -count=1 ./schema/... ./pkg/functions/...
go vet ./schema/generator/...
gofmt -l .
git diff --check

Release Note

The generated func.yaml schema now preserves the 0.01 minimum for scale.kpa.target, and no longer declares the exclusiveMinimum workaround that made the bound exclusive.

@knative-prow knative-prow Bot added the kind/bug Bugs label Sep 26, 2026
@knative-prow

knative-prow Bot commented Sep 26, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Elvand-Lie
Once this PR has been reviewed and has the lgtm label, please assign matejvasek for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@knative-prow

knative-prow Bot commented Sep 26, 2026

Copy link
Copy Markdown

Hi @Elvand-Lie. Thanks for your PR.

I'm waiting for a knative member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Tip

We noticed you've done this a few times! Consider joining the org to skip this step and gain /lgtm and other bot rights. We recommend asking approvers on your previous PRs to sponsor you.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@knative-prow knative-prow Bot added needs-ok-to-test 🤖 Needs an org member to approve testing size/L 🤖 PR changes 100-499 lines, ignoring generated files. labels Sep 26, 2026
@lkingland

Copy link
Copy Markdown
Member

Thanks for the contribution. I think this will need a rebase as the scale option has a PR coming in now which moves it up to top-level.

@knative-prow-robot knative-prow-robot added the needs-rebase Cannot be merged due to conflicts with HEAD. label Sep 28, 2026
@Elvand-Lie
Elvand-Lie force-pushed the fix/schema-fractional-numeric-constraints branch from b965ed0 to 71bbb54 Compare September 28, 2026 18:26
@knative-prow-robot knative-prow-robot removed the needs-rebase Cannot be merged due to conflicts with HEAD. label Sep 28, 2026
The func.yaml schema generator published a lower bound that was looser
than the validation actually enforced. Reflection truncates the
fractional minimum declared on KPAScaleOptions.Target, so the schema said

	"target": { "minimum": 0 }

where ValidateScale requires target >= 0.01. A func.yaml with a scale
target of 0.001 therefore validated against the schema and was rejected
at deploy time.

The reflector (github.com/alecthomas/jsonschema) represents the
`minimum` keyword as an int and parses the tag value with strconv.Atoi,
discarding the error:

	type Type struct {
		Minimum int `json:"minimum,omitempty"`
	}

KPAScaleOptions.Target declares jsonschema_extras:"minimum=0.01", so
"0.01" fails to parse and silently degrades to zero.

Re-apply that one keyword on the already-reflected KPAScaleOptions.target
property, reading the value back from the same struct tag so the
constraint stays declared once and cannot drift from the runtime check
it documents. Nothing else about the generated schema changes.

knative#4063 declared exclusiveMinimum=true on this field as a workaround for
exactly this truncation, so that the schema at least rejected the
concrete invalid value 0. Now that the fractional minimum survives, that
workaround is removed: under the draft-04 this document declares, a
boolean exclusiveMinimum would require target > 0.01 and so contradict
ValidateScale, which accepts exactly 0.01.
@Elvand-Lie
Elvand-Lie force-pushed the fix/schema-fractional-numeric-constraints branch from 71bbb54 to e0a4557 Compare September 29, 2026 14:04
@Elvand-Lie

Copy link
Copy Markdown
Contributor Author

@lkingland Rebased and revised for the top-level scale changes. Re-verified against the latest main and ready for another look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/bug Bugs needs-ok-to-test 🤖 Needs an org member to approve testing size/L 🤖 PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

func.yaml schema generator truncates fractional minimum values (e.g. 0.01 -> 0)

3 participants