Description
resources.requests and resources.limits both point at the same resourcesLimits definition in the schema, so they share one memory pattern and one cpu pattern. That's fine for most values, but it falls apart on zero.
Today requests.cpu: "0" validates, while requests.memory: "0" gets rejected by the memory regex (^(0\.\d+|[1-9]\d*(\.\d+)?)…, which needs at least one non-zero digit or a 0.x decimal). So the exact same "reserve nothing" intent passes for CPU and fails for memory, which doesn't look deliberate.
In Kubernetes requests.memory: "0" is valid and just means "no reservation". After #199 the memory pattern was aligned with the k8s resource.Quantity grammar, where 0 is a legal quantity, but plain 0 still doesn't pass here.
This is the follow-up we agreed to split out of #195. The plan there was to keep 0 rejected for limits (a zero limit isn't meaningful) and handle it separately for requests.
One smaller thing that falls out of the shared definition: its descriptions all say "limit" ("The compute and memory resource limits", "The memory limit in bytes", "The CPU limit…"). When the same block is reused under requests, those descriptions are just wrong.
Expected behavior
requests.memory: "0" should validate, matching how requests.cpu: "0" already behaves and how Kubernetes treats it.
Concretely, requests needs its own handling instead of reusing the limits block, either a dedicated definition or a requests-specific memory pattern that also accepts 0. Keeping 0 rejected under limits is fine and was the agreed behavior. While splitting it out, the reused descriptions shouldn't say "limit" when they apply to requests.
Steps to reproduce
-
Save this as score-requests-zero.yaml:
apiVersion: score.dev/v1b1
metadata:
name: requests-zero
containers:
main:
image: my-app
resources:
requests:
memory: "0"
-
Validate it: jv --assert-format --assert-content ./score-v1b1.json score-requests-zero.yaml
-
It fails with: '0' does not match '^(0\.\d+|[1-9]\d*(\.\d+)?)(K|M|G|T|P|E|Ki|Mi|Gi|Ti|Pi|Ei)?$'
-
Now change memory: "0" to cpu: "0" and validate again. It passes. kubectl accepts both.
Screenshots
N/A
Context
This came straight out of #195. When we aligned the memory pattern with the Kubernetes Quantity grammar, @chris-stephenson and I agreed the requests: 0 case was separate from the decimal and suffix fixes and should be its own issue, since 0 only makes sense for requests, not limits, and the two currently share a schema. This is that issue.
I first ran into the underlying problem porting an existing Kubernetes deployment to a score.yaml. It sets requests.memory: "0" on a sidecar (no reservation, let it burst), it's run fine that way for a long time, and schema validation rejected it while kubectl was perfectly happy with the same value.
Additional information
Description
resources.requestsandresources.limitsboth point at the sameresourcesLimitsdefinition in the schema, so they share one memory pattern and one cpu pattern. That's fine for most values, but it falls apart on zero.Today
requests.cpu: "0"validates, whilerequests.memory: "0"gets rejected by the memory regex (^(0\.\d+|[1-9]\d*(\.\d+)?)…, which needs at least one non-zero digit or a0.xdecimal). So the exact same "reserve nothing" intent passes for CPU and fails for memory, which doesn't look deliberate.In Kubernetes
requests.memory: "0"is valid and just means "no reservation". After #199 the memory pattern was aligned with the k8sresource.Quantitygrammar, where0is a legal quantity, but plain0still doesn't pass here.This is the follow-up we agreed to split out of #195. The plan there was to keep
0rejected forlimits(a zero limit isn't meaningful) and handle it separately forrequests.One smaller thing that falls out of the shared definition: its descriptions all say "limit" ("The compute and memory resource limits", "The memory limit in bytes", "The CPU limit…"). When the same block is reused under
requests, those descriptions are just wrong.Expected behavior
requests.memory: "0"should validate, matching howrequests.cpu: "0"already behaves and how Kubernetes treats it.Concretely,
requestsneeds its own handling instead of reusing thelimitsblock, either a dedicated definition or a requests-specific memory pattern that also accepts0. Keeping0rejected underlimitsis fine and was the agreed behavior. While splitting it out, the reused descriptions shouldn't say "limit" when they apply torequests.Steps to reproduce
Save this as
score-requests-zero.yaml:Validate it:
jv --assert-format --assert-content ./score-v1b1.json score-requests-zero.yamlIt fails with:
'0' does not match '^(0\.\d+|[1-9]\d*(\.\d+)?)(K|M|G|T|P|E|Ki|Mi|Gi|Ti|Pi|Ei)?$'Now change
memory: "0"tocpu: "0"and validate again. It passes.kubectlaccepts both.Screenshots
N/A
Context
This came straight out of #195. When we aligned the memory pattern with the Kubernetes Quantity grammar, @chris-stephenson and I agreed the
requests: 0case was separate from the decimal and suffix fixes and should be its own issue, since0only makes sense forrequests, notlimits, and the two currently share a schema. This is that issue.I first ran into the underlying problem porting an existing Kubernetes deployment to a score.yaml. It sets
requests.memory: "0"on a sidecar (no reservation, let it burst), it's run fine that way for a long time, and schema validation rejected it whilekubectlwas perfectly happy with the same value.Additional information
limitsandrequestsreference#/$defs/resourcesLimits(score-v1b1.jsonL401-404 and L405-408,$refon L403 and L407), so they can't diverge today.^\d+(?:m|\.\d+)?$already accepts0; the memory one doesn't. That's the inconsistency.resourcesLimitsdescriptions (L180, L185, L190) all say "limit", which is inaccurate once the block is reused underrequests.