Skip to content

test(e2e): add nemo-deployments plugin e2e tests for docker and k8s backends#766

Open
benmccown wants to merge 2 commits into
mainfrom
deployments-plugin-e2e
Open

test(e2e): add nemo-deployments plugin e2e tests for docker and k8s backends#766
benmccown wants to merge 2 commits into
mainfrom
deployments-plugin-e2e

Conversation

@benmccown

@benmccown benmccown commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

What

Adds e2e coverage for the nemo-deployments plugin's own public API (DeploymentConfig / Deployment / Volume CRUD) end to end through the reconcile controller, on both the Docker and Kubernetes executor backends. Mirrors the existing nemo-agents deployment e2e structure (test_nemo_agents_docker.py / test_nemo_agents_k8s.py + shared helpers).

Files

  • e2e/deployments_helpers.py — backend-agnostic scenario cores driven via sdk._client against /apis/deployments/v2/...:
    • service (restart_policy=Always nginx) → READY with a routable endpoint
    • job (restart_policy=Never alpine) → SUCCEEDED, exit 0
    • volume round-trip: provision → mount into a job → write sentinel → read back
  • e2e/test_nemo_deployments_docker.py — subprocess harness + docker executor (subprocess_only); skips cleanly without a reachable Docker daemon.
  • e2e/test_nemo_deployments_k8s.py — external kind cluster + k8s executor (container_only); wider timeouts for pod scheduling / PVC binding.
  • e2e/configs/local-docker-deployments.yaml — subprocess platform wired with a docker deployments executor (pull_images enabled, tightened reconcile loop).

Notes

  • Workload image refs default to docker.io/library/alpine|nginx and are env-overridable (NMP_E2E_DEPLOYMENTS_ALPINE_IMAGE / _NGINX_IMAGE), matching the POSTGRES_IMAGE / BUSYBOX_IMAGE knobs the kind e2e install already exposes. Pulling public docker.io/library/* at cluster runtime is the same pattern the kind CPU e2e job already relies on for postgres/busybox/cloud-provider-kind (no pull-through cache is configured today).
  • The k8s tests run under the existing kind-cpu-e2e job (whole e2e/ dir), gated by container_only. Docker tests are subprocess_only.
  • Opened as draft to see how the tests fare in CI.

Local: ruff check, ruff format --check, and ty check all pass; full e2e/ collects.

Summary by CodeRabbit

  • New Features

    • Expanded end-to-end coverage for the deployments plugin on both local Docker and Kubernetes.
    • Added lifecycle validation for long-running services, one-shot jobs, and a Docker volume round-trip (provision, mount, write, and read back).
  • Tests

    • Introduced Docker- and Kubernetes-specific E2E scenarios with clear readiness/success assertions.
    • Added environment-aware skipping and best-effort cleanup to keep repeated runs stable.
    • Centralized shared test logic for resource creation, status polling, and teardown handling.

…ackends

Exercise the nemo-deployments plugin's own public API
(DeploymentConfig / Deployment / Volume CRUD) end to end through the
reconcile controller on both the Docker and Kubernetes executor
backends, mirroring the existing nemo-agents deployment e2e structure.

- deployments_helpers.py: backend-agnostic scenario cores driven via
  sdk._client against /apis/deployments/v2/... (service->READY,
  job->SUCCEEDED, and a volume provision+mount+read-back round-trip).
  Workload image refs default to docker.io/library/alpine|nginx and are
  env-overridable, matching the POSTGRES_IMAGE/BUSYBOX_IMAGE knobs the
  kind e2e install already exposes.
- test_nemo_deployments_docker.py: subprocess harness + docker executor
  (subprocess_only), skips cleanly without a reachable Docker daemon.
- test_nemo_deployments_k8s.py: external kind cluster + k8s executor
  (container_only), wider timeouts for pod scheduling / PVC binding.
- configs/local-docker-deployments.yaml: subprocess platform wired with a
  docker deployments executor (pull_images enabled, tightened reconcile
  loop).

Signed-off-by: Ben McCown <bmccown@nvidia.com>
@github-actions github-actions Bot added the test conventional-commit type label Jul 17, 2026
@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 25534/32751 78.0% 62.6%
Integration Tests 14732/31400 46.9% 19.2%

@benmccown
benmccown marked this pull request as ready for review July 17, 2026 18:12
@benmccown
benmccown requested review from a team as code owners July 17, 2026 18:12
@benmccown benmccown self-assigned this Jul 17, 2026
@benmccown
benmccown requested a review from tylersbray July 17, 2026 18:12
…mer)

Manual testing in a kind cluster surfaced a hard deadlock in the k8s
volume round-trip: DeploymentReconciler gates a deployment's create on
every mounted Volume already being BOUND (volume_mounts_ready), but
kind's default local-path StorageClass binds WaitForFirstConsumer, so
the PVC only binds once a consumer pod is scheduled — which never happens
while the deployment is gated. The Kind CPU e2e job uses this same
storage class, so the test would have hung until timeout in CI.

This mirrors a known limitation the k8s reconcile integration test
already documents and sidesteps (tests/integration/test_reconcile_k8s.py).

- Remove the volume scenario from test_nemo_deployments_k8s.py (keeps
  service->READY and job->SUCCEEDED, both verified passing against a
  kind Helm platform).
- Keep the volume round-trip in the docker module, where volumes bind
  eagerly (verified passing); tighten its volume-status wait to require
  BOUND rather than tolerating PENDING.
- Document the storage-binding portability constraint in both the k8s
  module and the run_volume_deployment_round_trip helper.

Signed-off-by: Ben McCown <bmccown@nvidia.com>
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d6da559b-3faf-4eba-aa95-cf6966282f0f

📥 Commits

Reviewing files that changed from the base of the PR and between a3ef017 and 6869a80.

📒 Files selected for processing (2)
  • e2e/deployments_helpers.py
  • e2e/test_nemo_deployments_k8s.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • e2e/deployments_helpers.py

📝 Walkthrough

Walkthrough

Added shared REST and lifecycle helpers for the deployments plugin, a local Docker E2E configuration, and Docker/Kubernetes tests covering services, jobs, and volume round trips.

Changes

Deployments E2E coverage

Layer / File(s) Summary
Deployment API primitives
e2e/deployments_helpers.py
Adds REST wrappers, resource listing, unique naming, and idempotent deletion for deployment configs, volumes, and deployments.
Lifecycle convergence and round trips
e2e/deployments_helpers.py
Adds status and deletion polling plus reusable service, job, and volume workflows with cleanup.
Backend test harnesses
e2e/configs/local-docker-deployments.yaml, e2e/test_nemo_deployments_docker.py, e2e/test_nemo_deployments_k8s.py
Configures local Docker execution and wires Docker availability, subprocess, and Kubernetes test settings.
Backend lifecycle scenarios
e2e/test_nemo_deployments_docker.py, e2e/test_nemo_deployments_k8s.py
Adds service readiness, successful job, and volume read/write E2E tests for Docker and Kubernetes.

Sequence Diagram(s)

sequenceDiagram
  participant E2ETest
  participant NeMoDeploymentsAPI
  participant ReconcileController
  participant Backend
  E2ETest->>NeMoDeploymentsAPI: Create deployment resources
  NeMoDeploymentsAPI->>ReconcileController: Reconcile resources
  ReconcileController->>Backend: Provision workload or volume
  E2ETest->>NeMoDeploymentsAPI: Poll status and validate result
  E2ETest->>NeMoDeploymentsAPI: Delete resources
Loading

Suggested reviewers: tylersbray, mckornfield

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: new nemo-deployments E2E tests for Docker and Kubernetes backends.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch deployments-plugin-e2e

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

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@e2e/deployments_helpers.py`:
- Around line 444-485: Move the create_volume, wait_for_volume_status, and
create_deployment_config calls into the existing try block so every resource
creation and polling operation is protected by teardown. Keep the existing
cleanup logic and deployment configuration unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 2f6944f3-bb15-4656-ae97-c6ee01f1e9b5

📥 Commits

Reviewing files that changed from the base of the PR and between 44cee38 and a3ef017.

📒 Files selected for processing (4)
  • e2e/configs/local-docker-deployments.yaml
  • e2e/deployments_helpers.py
  • e2e/test_nemo_deployments_docker.py
  • e2e/test_nemo_deployments_k8s.py

Comment on lines +444 to +485
create_volume(
sdk,
workspace=workspace,
name=volume_name,
size="1Gi",
access_modes=["ReadWriteOnce"],
backend_config=volume_backend_config,
)

# A freshly-created volume must at least leave the initial state; lazy-binding
# k8s storage classes keep it PENDING until first mount, so accept either.
wait_for_volume_status(
sdk,
workspace=workspace,
name=volume_name,
target_statuses=("BOUND", "PENDING"),
timeout_seconds=120,
)

create_deployment_config(
sdk,
workspace=workspace,
name=config_name,
restart_policy="Never",
volume_mounts=[{"name": volume_name, "mountPath": mount_path}],
containers=[
{
"name": "main",
"image": ALPINE_IMAGE,
"command": ["sh", "-c"],
"args": [
# Write a sentinel to the mounted volume then read it back and
# assert its content, exiting non-zero (=> FAILED) on mismatch.
f"set -e; echo {sentinel} > {sentinel_file}; grep -q {sentinel} {sentinel_file}; "
f"echo mount-verified",
],
"volumeMounts": [{"name": volume_name, "mountPath": mount_path}],
}
],
)

try:

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.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Include all resource creation within the teardown-protected block.

Volume polling or config creation can fail before entering try, bypassing cleanup and leaking resources. Move Lines 444-483 inside the existing try.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/deployments_helpers.py` around lines 444 - 485, Move the create_volume,
wait_for_volume_status, and create_deployment_config calls into the existing try
block so every resource creation and polling operation is protected by teardown.
Keep the existing cleanup logic and deployment configuration unchanged.

@tylersbray tylersbray 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.

Approving modulo knocking out code rabbit comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test conventional-commit type

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants