Skip to content

Accept fractional component limits on the ordering and limit-change paths - #94

Open
thomasbergernz wants to merge 1 commit into
waldur:developfrom
thomasbergernz:feature/accept-fractional-component-limits
Open

thomasbergernz wants to merge 1 commit into
waldur:developfrom
thomasbergernz:feature/accept-fractional-component-limits

Conversation

@thomasbergernz

Copy link
Copy Markdown

Problem

Every component limit field is DictField(child=IntegerField()), so a fractional limit can only ever reach a resource through the provider set_limits action, whose serializer uses a plain JSONField. Ordering one, changing one from the UI, renewing with one, or reallocating one all return "A valid integer is required".

That matters for storage components measured in TiB, where a sub-TiB allocation is legitimate: a free-tier quota of 0.1 TiB has no integer representation. Today it can be provisioned by an operator but never requested by a customer — and the asymmetry is also why the two billing bugs in this area went unnoticed for so long, since set_limits was the only door a fraction could come through.

Change

LimitValueField widens the six limit fields:

serializer field
BaseOrderSerializer limits
ResourceRenewSerializer limits
RenewalEstimateRequestSerializer limits
ResourceUpdateLimitsSerializer limits
ResourceReallocateTargetSerializer allocated_limits
ResourceReallocateLimitsSerializer limits

It keeps the stored shape: whole numbers come back as int, so a limit of 5 still serialises as 5 rather than 5.0 and existing payloads are byte-identical.

FloatField rather than DecimalField is deliberate — Order.limits and Resource.limits are JSONFields written with the stdlib encoder, and a Decimal raises at save time. The billing path coerces to Decimal at the point of arithmetic instead, which is what 595327d does.

QuotasUpdateSerializer.quotas is left alone; quotas are counts, not measures. Read-only report serializers are untouched.

Verified

Against DRF: 0.1 and "0.1" become 0.1 (float); 2 and 2.0 become 2 (int); "abc" is rejected; min_value=0 still rejects -0.5.

Built on 8.1.2 and run in a test deployment: an order carrying storage_project: 0.1 reaches done and the resource stores {"cpu": 2000, "storage_project": 0.1, "storage_scratch": 2} — types int, float, int.

Related

Licensing: I agree to license this contribution under the MIT license.

…aths

Every limit field is DictField(child=IntegerField()), so a fractional limit can
only ever reach a resource through the provider set_limits action, whose
serializer uses a plain JSONField. Ordering one, changing one from the UI,
renewing with one or reallocating one all return "A valid integer is required".

That matters for storage components measured in TiB, where a sub-TiB allocation
is legitimate — a free-tier quota of 0.1 TiB cannot be expressed as an integer,
so it can be provisioned by an operator but never requested by a customer.

LimitValueField widens the six limit fields while keeping the stored shape:
whole numbers come back as int, so a limit of 5 still serialises as 5 rather
than 5.0 and existing payloads are byte-identical. It is a FloatField rather
than DecimalField deliberately — Order.limits and Resource.limits are
JSONFields written with the stdlib encoder, and a Decimal raises at save time.

QuotasUpdateSerializer.quotas is left alone; quotas are counts, not measures.

The client half is waldur/waldur-homeport#105
— without it the forms still parse every limit input with parseInt, so the
widened API is unreachable from the UI.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant