Skip to content

fix: Refuse a claim that requests one type twice - #983

Merged
vvoytovych merged 1 commit into
mainfrom
fix/claim-requests-one-per-type
Nov 3, 2026
Merged

vvoytovych merged 1 commit into
mainfrom
fix/claim-requests-one-per-type

Conversation

@vvoytovych

Copy link
Copy Markdown
Contributor

Related to #978.

A claim holds one allocation per resource type, but its schema let it request one type twice; only the doc comment said once. The requests are now a map list keyed by resourceType, as the claim's allocations already are, so the API server refuses the second request. A claim stored before keeps working, because the API server ratchets a list-map rule that the stored object already broke.

Corner cases

case what happens proof
A new claim requests one type twice Refused as invalid TestResourceClaimRefusesTwoRequestsOfOneType
A claim stored before, with one type twice Its spec, status and finalizer updates and its deletion are accepted TestResourceClaimStoredWithTwoRequestsOfOneTypeStaysUpdatable, and apiextensions-apiserver's ratcheting
A ClaimCreationPolicy whose templates request one type twice Its claims are refused, so the resource it claims for is refused None does: the 28 policies across the services' repositories request one type each
A server-side apply of a claim's requests Merges by resourceType instead of replacing the list Milo writes a claim's spec only by create (the admission plugin); its status and owner references by apply

Test plan

  • Both tests fail on main (the claim is stored; the upgraded schema never refuses) and pass here, 3 runs of 3, with envtest 1.37.0.
  • task generate changes only the claim CRD's two list lines. go test ./pkg/apis/quota/... ./internal/quota/... passes.
  • Production holds no claim that requests one type twice: 0 of 6,166 claims in the 151 projects that hold claims, read 2026-11-03 16:47–16:50Z; the count finds a planted one. A code search of datum-cloud and milo-os (102 files, all 47 YAML ones read) finds 28 ClaimCreationPolicies, in datum-cloud/datum, datum-cloud/network-services-operator and this repository, and each requests one type. A policy applied by hand in production cannot be listed with a staff login.

A claim holds one allocation per resource type, so its requests are now a map list keyed by resourceType and the API
server refuses a second request of one type. A claim stored before keeps working: the API server ratchets a list-map
rule that the stored object already broke, so its updates, status, finalizers and deletion are accepted.
@vvoytovych vvoytovych self-assigned this Nov 3, 2026
@vvoytovych
vvoytovych marked this pull request as ready for review November 3, 2026 20:13
@vvoytovych
vvoytovych requested a review from ecv November 3, 2026 20:13

@ecv ecv left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve.

The +listType=map on spec.requests keyed by resourceType is the rule asked for on milo#978, and the upgrade path is tested: CI is green at 6995ac7 including ci / Build and test.

  • Pre-existing duplicates are covered: TestResourceClaimStoredWithTwoRequestsOfOneTypeStaysUpdatable stores a duplicate under the old schema, swaps in the new CRD, then requires a finalizer update, a status update, finalizer removal and delete to all succeed. That matches CRD validation ratcheting for list-map uniqueness, so no stored claim gets stuck.
  • resourceType is required on ResourceRequest, so the map key is valid and the CRD installs; the envtest installs the generated CRD, which proves it.
  • The test fails hard when KUBEBUILDER_ASSETS is unset in CI, so it cannot skip silently.

Follow-ups:

  • Ratcheting only covers unchanged duplicates. A controller or client that rewrites spec.requests on a legacy claim while keeping the duplicate is fine, but any edit that changes the duplicate entries will be refused; worth a note in the release text.
  • Count legacy duplicates in production before the tag (a one-off list across projects), so any caller still producing them shows up as a failed create rather than a surprise.

@vvoytovych

Copy link
Copy Markdown
Contributor Author

Both follow-ups go with the release that carries this:

  • Its release notes will say that a claim stored with one type twice stays updatable only while its duplicate entries stay unchanged.
  • I counted on 2026-11-03, 16:47–16:50 UTC: 0 of 6,166 claims request one type twice (the third box above). I will run the same count again before the tag.

@vvoytovych
vvoytovych merged commit d7e729c into main Nov 3, 2026
9 checks passed
@vvoytovych
vvoytovych deleted the fix/claim-requests-one-per-type branch November 3, 2026 20:33
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.

2 participants