Skip to content

nodetask: read RestartPod podUID from spec, drop status snapshot#388

Merged
bdchatham merged 1 commit into
mainfrom
refactor/restartpod-read-spec-uid
Jun 7, 2026
Merged

nodetask: read RestartPod podUID from spec, drop status snapshot#388
bdchatham merged 1 commit into
mainfrom
refactor/restartpod-read-spec-uid

Conversation

@bdchatham

Copy link
Copy Markdown
Collaborator

What

Removes the RestartPod-specific branch from the SeiNodeTask synthesis path. Reconcile now seeds status.task identically for every kind.

Why

RestartPod's pod UID was snapshotted from spec.restartPod.podUIDstatus.task.restartedPodUID at synthesis, then read back by restartPodParams to build the task. That loop is a vestige of the original fetch-at-synthesis design (a live-fetched UID had to be persisted to survive reconciles). Now that the UID is a caller-supplied spec field, the value is already stable on the object — restartPodParams was already reading spec.restartPod.podUID two lines up for its non-empty guard, then turning around to read the redundant copy off status.

Change

  • restartPodParams reads spec.restartPod.podUID directly into the task params; the status.task read and the nil-status early-validation dance are gone.
  • spec.restartPod.podUID is now immutable (CEL transition rule, mirroring the existing spec.kind immutability) — preserves the frozen-at-synthesis guarantee the snapshot provided.
  • status.task.restartedPodUID is removed — fully determined by the immutable spec field (implicit over explicit).
  • The synthesis SeiNodeTaskExecution literal is now kind-agnostic ({ID, Status, ExecutionStartedAt}); Reconcile no longer branches on spec.kind.

Net: −code, and the only kind-specific concern leaves the generic reconcile surface.

Upgrade safety

Apply the CRD and controller together. Forward-safe:

  • The removed status.task.restartedPodUID is pruned by the structural schema and is read by nothing post-refactor.
  • In-flight RestartPod tasks rebuild params from spec every reconcile (driveTasktaskParamsForKind), and the task ID is keyed on cr.UID/kind/index (not the removed field) — so content-addressed completion is unaffected and identity is stable across the controller swap.

Test

  • restartPodParams yields RestartedPodUID == spec.restartPod.podUID on both the status.task == nil (early-validation) and populated paths.
  • envtest: podUID immutability (create → patch podUID → rejected); existing required/union/kind-immutability cases stay green.
  • RestartPod end-to-end (HappyPath / NeverReady / TimesOut) green; restart-pod behavior tests unchanged.
  • make manifests generate, make test, make test-integration, golangci-lint --new-from-rev=origin/main → 0.

🤖 Generated with Claude Code

The synthesis path special-cased RestartPod to copy spec.restartPod.podUID into
status.task.restartedPodUID, which restartPodParams then read back to build the
task. That snapshot loop was a vestige of the original fetch-at-synthesis design
(the live-fetched UID had to be persisted). With the UID now a caller-supplied
spec field, the value is already stable on the object — restartPodParams already
reads spec.restartPod.podUID for its non-empty guard.

- restartPodParams reads spec.restartPod.podUID directly into the task params;
  the status read and the nil-status early-validation dance are gone.
- spec.restartPod.podUID is now immutable (CEL transition rule, mirroring the
  existing spec.kind immutability) — preserves the frozen-at-synthesis guarantee
  the snapshot gave.
- status.task.restartedPodUID is removed — it was fully determined by the
  immutable spec field.
- The synthesis SeiNodeTaskExecution literal is now kind-agnostic; Reconcile no
  longer branches on spec.kind.

Forward-safe across upgrade: the removed status field is pruned by the
structural schema and is read by nothing post-refactor; in-flight RestartPod
tasks rebuild params from spec every reconcile, so content-addressed completion
is unaffected. Apply the CRD and controller together.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@cursor

cursor Bot commented Jun 7, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes SeiNodeTask CRD schema and RestartPod reconcile params; in-flight tasks rely on spec each reconcile, so CRD and controller should roll out together.

Overview
RestartPod no longer copies spec.restartPod.podUID into status.task.restartedPodUID at synthesis. The nodetask reconciler seeds status.task the same way for every kind (ID, Status, ExecutionStartedAt only), and restartPodParams always sets RestartedPodUID from spec.restartPod.podUID, including before status.task exists.

To keep the restart target fixed after create, admission adds a CEL immutability rule on spec.restartPod.podUID (mirroring spec.kind). The restartedPodUID status field is removed from the Go API and regenerated CRD/manifest YAML.

Tests and envtest cover spec-sourced params (with and without status.task) and rejection when podUID is patched after creation.

Reviewed by Cursor Bugbot for commit b5d7d74. Bugbot is set up for automated code reviews on this repo. Configure here.

@bdchatham bdchatham merged commit 719c4d5 into main Jun 7, 2026
5 checks passed
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