fix(resources-management): parse fractional CPU and memory quantities - #217
Merged
Merged
Conversation
`helm_lib_resources_management_cpu_units_to_millicores` and `helm_lib_resources_management_memory_units_to_bytes` converted a quantity with `atoi`, which parses integers only and returns 0 on failure. Every fractional quantity therefore became 0, silently and without an error. Kubernetes accepts a decimal mantissa, so `0.5` and `500m` denote the same amount of CPU, and `0.5Gi` is a valid amount of memory. The schemas of the modules that consume these helpers accept such values as well: the memory pattern permits a decimal part outright, and a CPU value passes as a plain YAML number. The damage is worst in `helm_lib_resources_management_original_pod_resources`, which copies requests from the raw value while computing limits through the conversion. With `vpa.cpu.min: 0.5` and a `limitRatio` it produced `requests.cpu: 0.5` against `limits.cpu: 0m`, and the API server rejects such a pod. Both helpers now keep exact integer arithmetic for an integer mantissa and switch to float arithmetic only for a fractional one, so no existing value changes its result. A fractional result is rounded up, so a limit is never smaller than the value asked for. The CPU helper also gained the validation the memory helper already had: an unparsable value now fails the rendering instead of silently yielding 0. A value that reaches this branch already produced a limit of `0m`, so nothing that worked before stops working. Signed-off-by: suselz <suselz@mail.ru>
Suselz
added a commit
to deckhouse/deckhouse
that referenced
this pull request
Sep 18, 2026
The previous commit carried a local copy of the CPU and memory conversion, because the helm_lib helpers cannot parse a fractional quantity. That defect belongs to the library and is fixed there in deckhouse/lib-helm#217, so the module calls the helpers again and this pull request keeps only what is specific to it. What remains is the lower bound. The limits of the `self-signed-generator` init container are the sum of the main container limits, and the requests of that container are hardcoded as 10m and 10Mi. A DexAuthenticator whose limits sum to less than that produced a Deployment with a limit below its own request, which the API server rejects. The sum is now never lower than the requests. Staying under the sum is safe: a ResourceQuota counts a pod as max(init, sum(app)), so the accounting is still driven by the main containers. Fixing a fractional quantity such as `cpu: "0.5"` needs the library release and a bump of LIB_HELM_VERSION, and is not part of this pull request. Signed-off-by: suselz <suselz@mail.ru>
4 tasks
Signed-off-by: suselz <suselz@mail.ru>
yalosev
approved these changes
Sep 18, 2026
Suselz
marked this pull request as ready for review
September 18, 2026 21:27
Suselz
added a commit
to deckhouse/deckhouse
that referenced
this pull request
Sep 18, 2026
deckhouse/lib-helm#217 taught `helm_lib_resources_management_cpu_units_to_millicores` and `helm_lib_resources_management_memory_units_to_bytes` to parse a fractional quantity, which they previously converted to 0 through `atoi`. The module calls those helpers when it sums the main container limits into the limits of the `self-signed-generator` init container, so a DexAuthenticator with `cpu: "0.5"` rendered `limits.cpu: 0m` against `requests.cpu: 10m` and the API server rejected the Deployment. The bump also carries deckhouse/lib-helm#216, which renders an extra ClusterRoleBinding from `helm_lib_module_controller_rbac`. No module in this repository uses that helper, so nothing here changes because of it. The test for a fractional quantity is restored now that the conversion works. Signed-off-by: suselz <suselz@mail.ru>
This was referenced Sep 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is broken
helm_lib_resources_management_cpu_units_to_millicoresandhelm_lib_resources_management_memory_units_to_bytesconvert a quantity withatoi, which isstrconv.Atoiwith the error discarded. It parses integers only, so every fractional quantitybecomes
0— silently, without an error:Kubernetes accepts a decimal mantissa, so
0.5and500mdenote the same amount of CPU, and0.5Giis a valid amount of memory.Why it reaches users
helm_lib_resources_management_original_pod_resourcescopiesrequestsfrom the raw value whilecomputing
limitsthrough the conversion, so the two disagree. Withvpa.cpu.minset to afractional value and a
limitRatio:The API server rejects such a pod:
requestsmust not exceedlimits.The schemas of the consuming modules let these values through. In
istioandcni-ciliumthememory pattern is
^[0-9]+(\.[0-9]+)?(E|P|T|G|M|k|Ei|Pi|Ti|Gi|Mi|Ki)?$, which permits a decimalpart outright. The CPU pattern
^[0-9]+m?$rejects the quoted form"0.5", but the schema alsoallows
type: number, so an unquoted0.5passes validation and then breaks.The reason this has gone unnoticed is that the affected branch is opt-in: no
limitsare computedunless
limitRatiois set, and it has no default. Every documented example usesmandMinotation.
What this pull request changes
Both helpers now resolve the mantissa and the multiplier first, then convert:
result, including the large binary suffixes where float arithmetic would lose precision;
smaller than the value asked for.
The CPU helper also gained the validation that the memory helper already had. An unparsable value
now fails the rendering instead of silently yielding
0.Please weigh that last point: it is a behaviour change. A value that reaches this branch already
produced
limits.cpu: 0m, which the API server rejects, so it cannot be a working configurationtoday. Failing loudly seemed better than keeping a silent zero, but say so if you would rather keep
the helpers permissive and fix only the parsing.
Verification
helm unittest ./tests— 411 tests pass, including the existing snapshot. The two helper suitesgained cases for fractional values, a leading-dot value, an unquoted YAML number, and rounding up
of a fractional millicore.
Rendering
helm_lib_resources_management_original_pod_resourceswith the same input as above nowgives a valid object, and the whole-unit case is byte-for-byte unchanged:
Release
The chart version is bumped to
1.72.23. The platform picks the fix up throughmake update-lib-helm version=1.72.23, which also movesLIB_HELM_VERSIONin its Makefile,currently pinned at
1.72.21.Context
Found while fixing the same defect in the
user-authnmodule of the platform, where aDexAuthenticator with
cpu: "0.5"rendered an init container withlimits.cpu: 0magainstrequests.cpu: 10mand stopped themainqueue:deckhouse/deckhouse#23170.
charts/helm_lib/README.mdis regenerated bygo run tools/build-doc.go.