Repository navigation
Conversation
delete() nested propagationPolicy and gracePeriodSeconds inside the preconditions map, where the Kubernetes API ignores them. Worse, the refresh() call that followed replaced the resource attributes entirely, so the DeleteOptions body sent to the API was just the refreshed resource relabelled as kind DeleteOptions with no propagationPolicy anywhere. Job deletes therefore fell back to the API default (Orphan), leaving completed pods with no ownerRef and no TTL, which pins PVCs via pvc-protection and permanently wedges dedicated database resizes (DAT-1869). Build the DeleteOptions payload explicitly instead of mutating the resource: propagationPolicy and gracePeriodSeconds at the top level, and preconditions carrying only the resource uid. The resourceVersion precondition is dropped deliberately: it never took effect before, and enforcing it now would introduce conflict failures into every consumer's delete path whenever a controller bumps the resource between refresh and delete. The uid precondition still guards against deleting a recreated resource of the same name. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The propagation policy was an unchecked string, so a typo reached the API and came back as a server-side rejection. It is now a PropagationPolicy enum, accepted either as the case or as its string value, and validated before the request with the valid values in the message. Four tests asserted an immediate 404 after delete(), which stopped being true once the policy defaulted to Foreground: the resource stays readable until its dependents are gone. They now wait for it to disappear through a bounded helper that fails with the kind and name rather than hanging. DeleteOptionsTest no longer round-trips the payload through json_encode to assert its shape; deleteOptions() already returns a plain array. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The suite only called deleteOptions() and asserted the array it returns, so it could have passed while delete() sent something else entirely - which is the failure this fixes. A RecordingCluster now answers from canned responses and keeps the requests, and the new test drives delete() and reads propagationPolicy, gracePeriodSeconds and preconditions out of the DELETE body. Confirmed against the original bug: nesting the fields back under preconditions fails the new test. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
getClient() is called once per request, so building a MockHandler from the full response list each time replayed the first response to every call: delete()'s DELETE was answered with the refresh GET's body and the queued Status response was never reached. The client and its handler are now built once, and the test asserts both requests in order. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.
Problem
RunsClusterOperations::delete()claims to supportpropagationPolicy, but it never reaches the Kubernetes API. Two stacked bugs:propagationPolicyandgracePeriodSecondswere nested inside thepreconditionsmap, where the API ignores them (preconditions only acceptsuidandresourceVersion).$this->refresh()call that followedsetAttribute('preconditions', ...)replaces the resource attributes entirely (syncWith()assigns$this->attributes), so even the misplaced fields were wiped before serialization. The actual body sent was the refreshed resource relabelled askind: DeleteOptions:{ "apiVersion": "batch/v1", "kind": "DeleteOptions", "metadata": { "name": "reap", "uid": "...", "resourceVersion": "12345", "namespace": "default" } }No
propagationPolicyanywhere, so Job deletes fall back to the API default for batch/v1 (Orphan). This is the root cause of the DAT-1869 reopen: edge's resize reap calls$job->delete(propagationPolicy: 'Foreground'), the delete orphans the Completed pods (no ownerRef, no TTL),pvc-protectionnever releases the claim, and the resize wedges permanently.Fix
Build the DeleteOptions payload explicitly instead of mutating the resource. New body:
{ "apiVersion": "v1", "kind": "DeleteOptions", "propagationPolicy": "Foreground", "preconditions": { "uid": "..." } }propagationPolicyandgracePeriodSeconds(when set) are top-level DeleteOptions fields.preconditionscarries only the resourceuid, guarding against deleting a recreated resource of the same name.resourceVersionprecondition is dropped deliberately: it never took effect before (see bug 2), and enforcing it now would introduce conflict failures into every consumer's delete path whenever a controller bumps the resource betweenrefresh()and the DELETE call.deleteOptions()so the shape is unit-testable without a cluster.Tests
tests/DeleteOptionsTest.phpasserts the payload shape:propagationPolicyat the top level (and not inpreconditions),gracePeriodSecondsat the top level when set,preconditionslimited touidand omitted when the uid is unknown, and no resource attributes leaking into the body.Consumers
Edge's dedicated-database resize reap depends on this fix; the edge-side bump should happen after this merges and a release is tagged.
🤖 Generated with Claude Code