Skip to content

feat: publish checkpoint source facts - #63

Closed
leeZardNav wants to merge 7 commits into
lirane/restore-compatibility-checksfrom
lirane/RUN-42232-declared-volumes-source-status
Closed

feat: publish checkpoint source facts#63
leeZardNav wants to merge 7 commits into
lirane/restore-compatibility-checksfrom
lirane/RUN-42232-declared-volumes-source-status

Conversation

@leeZardNav

@leeZardNav leeZardNav commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • PodSnapshotContent gains an optional status.source publishing what a checkpoint was captured on: the node, the container, and the devices.
  • The block is projected from the artifact's manifest.yaml and written in the same status patch that marks the capture Ready, so a content that is Ready already carries its facts.
  • Device facts are grouped under one property per vendor, so each payload stays typed and validated and a second vendor can join without a discriminator or a CEL rule.
  • Nothing reads the block back. The restore compatibility gates compare the manifest, so this cannot become a second source of truth.

Design: #99, section 7.1. Stacked on #140, which records the facts this publishes.

What it looks like

status:
  conditions:
    - type: Ready
      status: "True"
      reason: Captured
  source:
    devices:
      nvidia:
        driverVersion: 580.82.07
        instances:
          - productName: NVIDIA A100-SXM4-80GB
          - productName: NVIDIA A100-SXM4-80GB
    node:
      name: gpu-node-3
      architecture: amd64
      kernelVersion: 5.15.0-1071-aws
    pod:
      image: nvcr.io/nvidia/ai-dynamo/vllm-runtime:0.6.1
      imageDigest: sha256:9f2c...
      memory: 64Gi

instances[].productName and driverVersion are the names the NVIDIA DRA driver publishes on a ResourceSlice, so the same GPU reads the same way in both places. The GPU count is the length of the instance list rather than a field of its own, so the two cannot disagree.

How to read this

The 7 commits form a ladder; each introduces one idea with its own tests.

Commits What it does
1-3 The published shape, one block per commit: node, then pod, then vendor-keyed devices. Each regenerates both CRD copies and the deepcopy
4 The projection from manifest to status as a pure function, reusing compat.ImageDigest. Nothing calls it yet
5 Wires it into the Ready write, at all three call sites
6 A test per Ready path — fresh dump, artifact recovery, and a work order reconciled after the source pod is gone — plus the conflict retry and the do-not-erase guard
7 E2E assertion against the node object and nvidia-smi rather than against the manifest

Decisions worth a look

Absent, not empty. A fact the agent could not read is left out, and a block with nothing in it is omitted entirely. An artifact captured before a fact was ever recorded still publishes; a reader can tell unknown from a value that happens to be blank.

The published digest is the compared digest. compat.ImageDigest is exported rather than reimplemented, so the reduction that decides whether two images are the same content is the one this publishes. Runtimes wrap a digest differently and the artifact keeps whichever form it was handed, so a second implementation could show a value the gate never compares.

One read, not one per retry. The Ready write retries on optimistic-lock conflict, so the manifest is read once before the loop.

Losing the facts never costs the capture. By the time this runs the artifact is committed, so an unreadable manifest logs and Ready is written anyway.

No node.agentVersion yet. The design lists it, but #140 dropped agent-version recording along with the major/minor comparison, so the field would only ever be empty. It arrives with the deferred agent-version compatibility mapping, which is also what will give it a meaning.

No new RBAC. The agent already holds podsnapshotcontents/status update and patch. PodSnapshot keeps mirroring only Ready and Failed.

Single container. Capture is still one container per content (PodReference.Containers is MinItems=1/MaxItems=1), so one source block per content is correct. Multi-container restore does not change that; if multi-container capture arrives, this block is where it grows a key.

Verification

  • Every one of the 7 commits builds, vets and tests on its own (go vet ./... and go test ./... for the agent under Linux, go test ./... for the api module, at each rung).
  • Full suites green for api, agent and operator; make verify-crds clean, so the chart CRD copy matches the generated one; license headers, fmt, tidy and helm lint clean; govulncheck clean.
  • Manual cluster validation pending.

Summary by CodeRabbit

  • New Features

    • Pod snapshot content now reports checkpoint provenance, including source node, pod, container image, and captured device details.
    • NVIDIA GPU information includes driver version, product names, and device counts.
    • Vendor-specific device fields are preserved for broader hardware compatibility.
    • Source information is recorded across fresh captures and artifact recovery workflows.
  • Bug Fixes

    • Snapshot readiness now completes even when provenance data cannot be read, while retaining previously available metadata.
    • Image digest handling is consistently normalized for compatibility checks.

Superseded by #141 after removing the internal task reference from the head branch.

@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: a014c968-7567-41c3-b728-6006893a179b

📥 Commits

Reviewing files that changed from the base of the PR and between 50f501c and 007f46d.

⛔ Files ignored due to path filters (2)
  • api/v1alpha1/zz_generated.deepcopy.go is excluded by !**/zz_generated*.go
  • charts/snapshot/crds/nvidia.com_podsnapshotcontents.yaml is excluded by !charts/snapshot/crds/**
📒 Files selected for processing (11)
  • agent/internal/controller/checkpointsource.go
  • agent/internal/controller/checkpointsource_test.go
  • agent/internal/controller/podsnapshotcontent.go
  • agent/internal/controller/podsnapshotcontent_coverage_test.go
  • api/compat/checks.go
  • api/v1alpha1/checkpoint_source_types.go
  • api/v1alpha1/crds/embed_test.go
  • api/v1alpha1/crds/nvidia.com_podsnapshotcontents.yaml
  • api/v1alpha1/podsnapshot_types_test.go
  • api/v1alpha1/podsnapshotcontent_types.go
  • e2e/tests/test_snapshot_lifecycle.py

Included review availability: Your plan provides up to 12 included reviews per hour; 10 remain after this review.


Walkthrough

The change adds checkpoint provenance types and CRD fields. The controller reads manifests beside artifacts, projects captured node, pod, and NVIDIA facts, and publishes them when PodSnapshotContent reaches Ready. Tests cover capture, recovery, conflicts, deep copies, schema preservation, and lifecycle validation.

Changes

Checkpoint source publication

Layer / File(s) Summary
Checkpoint source API contract
api/v1alpha1/checkpoint_source_types.go, api/v1alpha1/podsnapshotcontent_types.go, api/v1alpha1/crds/*, api/compat/checks.go, api/v1alpha1/podsnapshot_types_test.go
Adds checkpoint source types for node, pod, and NVIDIA device facts. Adds status.source to the CRD and preserves unknown device fields. Exports ImageDigest and validates deep-copy behavior.
Manifest projection and Ready publication
agent/internal/controller/checkpointsource.go, agent/internal/controller/podsnapshotcontent.go, agent/internal/controller/checkpointsource_test.go, agent/internal/controller/podsnapshotcontent_coverage_test.go
Reads manifests beside artifacts and projects available compatibility facts. Capture and recovery paths pass artifact paths to Ready finalization. Manifest errors are logged while Ready status is still written. Tests cover retries, missing manifests, and source preservation.
Lifecycle and schema validation
e2e/tests/test_snapshot_lifecycle.py, api/v1alpha1/crds/embed_test.go
Validates published node, pod, image, resource, driver, and GPU facts against capture-time data. Verifies preservation of unknown device vendor fields.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Merge Risk: ⚪ Minimal · up to 007f4

This change publishes checkpoint source facts alongside Ready status without introducing an actionable merge-blocking risk; it is merge-ready after normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant Capture
  participant Controller
  participant Manifest
  participant PodSnapshotContent
  Capture->>Controller: artifact path
  Controller->>Manifest: read checkpoint manifest
  Manifest-->>Controller: compatibility facts
  Controller->>PodSnapshotContent: publish Ready status and source facts
Loading
🚥 Pre-merge checks | ✅ 6 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 46.88% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 32 functions across 10 files. (1 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (6 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Breaking Api Changes ✅ Passed No breaking API change matches the check. The only existing Kubernetes API struct changed is PodSnapshotContentStatus, which adds Source *CheckpointSource with json:"source,omitempty" and `// +o…
Rbac Least Privilege ✅ Passed No RBAC least-privilege violation was introduced. The complete PR diff from merge-base c1206a4 to HEAD changes no kubebuilder RBAC marker or Helm Role/ClusterRole grant. All current markers and Helm R…
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title uses the required feat: Conventional Commit prefix, is 37 characters long, and clearly describes publishing checkpoint source facts.
Full details: Docstring Coverage

Explanation

Docstring coverage is 46.88% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 32 functions across 10 files. (1 skipped: 1 unsupported.)

Full details: Breaking Api Changes

Explanation

No breaking API change matches the check. The only existing Kubernetes API struct changed is PodSnapshotContentStatus, which adds Source *CheckpointSource with json:"source,omitempty" and // +optional. All fields in the new checkpoint-source types also have // +optional and omitempty tags. The diff does not remove, rename, retag, or change the Go type of an existing exported field. PodSnapshotSpec and PodSnapshotContentSpec immutability markers are unchanged. ImageDigest is a function rename, not an exported field change.

Full details: Rbac Least Privilege

Explanation

No RBAC least-privilege violation was introduced. The complete PR diff from merge-base c1206a4 to HEAD changes no kubebuilder RBAC marker or Helm Role/ClusterRole grant. All current markers and Helm RBAC rules use explicit verbs and resources; an exact wildcard search found no * in either field. The changed Helm role test only asserts an existing pods/status patch rule.

  • Fix all pre-merge checks with AI

Comment @coderabbitai help to get the list of available commands.

@leeZardNav
leeZardNav force-pushed the lirane/RUN-42232-declared-volumes-source-status branch 4 times, most recently from 9f55d79 to 820a149 Compare August 18, 2026 12:03
@leeZardNav leeZardNav changed the title ✨ RUN-42232: expose declared checkpoint volumes ✨ RUN-42232: publish checkpoint source facts as an extensible vendor variant Aug 18, 2026
@leeZardNav leeZardNav changed the title ✨ RUN-42232: publish checkpoint source facts as an extensible vendor variant ✨ RUN-42232: expose checkpoint source compatibility facts Aug 23, 2026
@leeZardNav
leeZardNav changed the base branch from main to lirane/RUN-42197-restore-compatibility-checker August 23, 2026 17:04
@leeZardNav
leeZardNav force-pushed the lirane/RUN-42197-restore-compatibility-checker branch 15 times, most recently from c7399cb to c6fbe01 Compare August 30, 2026 08:17
@leeZardNav
leeZardNav changed the base branch from lirane/RUN-42197-restore-compatibility-checker to lirane/RUN-42197-restore-compatibility-checker-v2 August 30, 2026 09:34
@leeZardNav
leeZardNav force-pushed the lirane/RUN-42232-declared-volumes-source-status branch from c6f8a42 to 77b1951 Compare August 30, 2026 09:35
@leeZardNav leeZardNav changed the title ✨ RUN-42232: expose checkpoint source compatibility facts ✨ RUN-42232: publish what a checkpoint was captured on Aug 30, 2026
@leeZardNav
leeZardNav force-pushed the lirane/RUN-42232-declared-volumes-source-status branch from 77b1951 to e773be3 Compare August 30, 2026 11:25
@leeZardNav
leeZardNav force-pushed the lirane/RUN-42197-restore-compatibility-checker-v2 branch from 235bbd8 to 50f501c Compare August 30, 2026 11:35
@leeZardNav
leeZardNav force-pushed the lirane/RUN-42232-declared-volumes-source-status branch from e773be3 to 007f46d Compare August 30, 2026 11:46
@leeZardNav
leeZardNav marked this pull request as ready for review August 30, 2026 12:03
@leeZardNav

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 30, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@leeZardNav
leeZardNav force-pushed the lirane/RUN-42197-restore-compatibility-checker-v2 branch from 1a25a63 to 995d159 Compare August 31, 2026 05:01
Everything that decides whether a checkpoint can be restored is read at
capture time and lands in the artifact's manifest, where nobody preparing
a restore target can see it. PodSnapshotContent gains an optional
status.source so those facts are visible on the object the user already
has, starting with the machine the capture ran on.

The block is projected from the manifest and never read back: the restore
compatibility gates compare the manifest, so this cannot become a second
source of truth. Nothing is required, so an artifact captured before a
fact was recorded still publishes.

Signed-off-by: liran elisha <lirane@nvidia.com>
A restore has to offer the container the same image and at least the
resources it had, so the source status now names them: the image, the
digest that pins which build of it ran, and the memory and CPU limits.

The digest is published beside the reference rather than folded into it,
because a tag is mutable and the two answer different questions.

Signed-off-by: liran elisha <lirane@nvidia.com>
The GPU model, the driver version and how many GPUs the capture could see
are what a restore has to match on the device side, so they join the
source status.

Vendors are plain properties rather than a discriminated union: each
payload stays typed, validated by the API server and visible through
kubectl explain, and several vendors can be present without a selector or
a CEL rule tying them together. An unknown vendor is preserved rather
than pruned, so a newer agent's facts survive an older installed CRD.

The GPU count is the length of the instance list rather than a field of
its own, so the two cannot disagree. UUIDs are left out: they name a
physical card instead of describing what a target has to offer.

Signed-off-by: liran elisha <lirane@nvidia.com>
…tured from

The facts are already written beside every artifact; publishing them is a
matter of naming them the way the API does. The projection reads the same
CompatFacts view the restore gates compare, so what a user sees cannot
drift from what a restore is actually checked against.

The digest is the one fact that cannot be copied straight across: runtimes
wrap it differently and the artifact keeps whichever form it was handed. So
compat.ImageDigest is exported and reused rather than reimplemented, and the
reduction a user reads is the one the gate compares.

A block with nothing recorded in it is left out rather than published
blank, and a manifest with nothing to say at all projects to nothing, so
an absent fact reads as unknown instead of as a value that happens to be
empty. Nothing calls this yet.

Signed-off-by: liran elisha <lirane@nvidia.com>
The facts ride along on the write that already announces the capture, so
a content that is Ready carries what it was captured on in the same
observation. Nothing polls, and no second write can be seen half-applied.

The manifest is read once before the conflict-retry loop rather than per
attempt, and a manifest that cannot be read costs the facts and not the
capture: the artifact is already committed, so Ready is written either
way and the failure is logged.

Signed-off-by: liran elisha <lirane@nvidia.com>
A capture reaches Ready three ways: the dump finishing, an artifact
recovered after the agent died mid-write, and a work order reconciled
again once the killed source pod is gone. The facts come off the artifact
rather than out of memory, so all three publish them, and a test per path
is what keeps that true as the paths change.

Two more sit beside them, for the paths that decide whether the facts
survive rather than which write publishes them: a Ready write that only lands
after a conflict still carries them, and a read that came back empty does not
erase what an earlier write already published.

Signed-off-by: liran elisha <lirane@nvidia.com>
The point of publishing is that nobody has to exec into an agent pod to
see what a snapshot came from, so the assertion goes against the object a
user would actually read.

It compares the published block to the node and to nvidia-smi rather than
to the manifest, so a projection that renamed a field or dropped one is
caught instead of agreeing with itself. The pod block is compared whole,
because the CPU limit this workload never set has to stay absent there
too.

Signed-off-by: liran elisha <lirane@nvidia.com>
@leeZardNav
leeZardNav force-pushed the lirane/RUN-42232-declared-volumes-source-status branch from 007f46d to a230fe1 Compare August 31, 2026 05:21
@leeZardNav leeZardNav changed the title ✨ RUN-42232: publish what a checkpoint was captured on feat: publish checkpoint source facts Aug 31, 2026
@leeZardNav leeZardNav closed this Aug 31, 2026
@leeZardNav
leeZardNav deleted the lirane/RUN-42232-declared-volumes-source-status branch August 31, 2026 12:55
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