Skip to content

chore: harden container labeling and e2e tests - #918

Merged
mckornfield merged 1 commit into
mainfrom
harden-labeling-test-fixes/mck
Jul 28, 2026
Merged

chore: harden container labeling and e2e tests#918
mckornfield merged 1 commit into
mainfrom
harden-labeling-test-fixes/mck

Conversation

@mckornfield

@mckornfield mckornfield commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Added configurable “resource scope” to Docker executor deployments, volumes, and identity labels to isolate discovery and cleanup across platform instances.
    • E2E config rendering now stamps the appropriate scope for Docker executors during materialization.
  • Bug Fixes

    • Improved deployment DELETE behavior with bounded retries on concurrent updates and graceful handling when entities disappear mid-delete.
    • Docker backend now enforces resource-scoped container matching across readiness checks, sidecars, listing, logging, and deletion.
    • Enhanced E2E anonymizer job timeouts with clearer diagnostics.

@mckornfield
mckornfield requested review from a team as code owners July 27, 2026 18:39
@github-actions github-actions Bot added the chore label Jul 27, 2026
Comment thread plugins/nemo-agents/src/nemo_agents_plugin/api/v2/deployments.py Fixed
Comment thread plugins/nemo-agents/src/nemo_agents_plugin/api/v2/deployments.py Fixed
Comment thread plugins/nemo-agents/src/nemo_agents_plugin/api/v2/deployments.py Fixed
Comment thread plugins/nemo-agents/src/nemo_agents_plugin/api/v2/deployments.py Dismissed
Comment thread plugins/nemo-agents/src/nemo_agents_plugin/api/v2/deployments.py Dismissed
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

The PR adds resource-scope isolation for E2E Docker deployments, improves anonymizer E2E diagnostics and typing, and makes deployment deletion retry through concurrent updates and transient disappearance.

Changes

Docker resource scoping

Layer / File(s) Summary
Scope contract and E2E materialization
plugins/nemo-deployments/.../docker/config.py, plugins/nemo-deployments/.../backends/labels.py, plugins/nemo-deployments/.../docker/volumes.py, plugins/nemo-deployments/.../k8s/jobs.py, e2e/services_pool.py
Resource-scope configuration, labels, filters, volume identity, Kubernetes labels, and E2E Docker executor stamping are updated.
Scoped Docker lifecycle operations
plugins/nemo-deployments/.../docker/backend.py
Container creation, readiness, sidecar handling, deletion, matching, listing, logs, and volume creation apply resource-scope matching.
Resource-scope behavior validation
packages/nmp_testing/tests/unit/test_e2e_harness.py, plugins/nemo-deployments/tests/unit/backends/docker/*
Tests cover scope defaults, label filters, E2E stamping, scoped lifecycle behavior, and cross-scope isolation.

Anonymizer E2E diagnostics

Layer / File(s) Summary
Workspace-safe helpers and polling diagnostics
e2e/test_anonymizer_plugin.py
Workspace-dependent references enforce workspace presence, polling records errors and log tails, and response assertions use explicit type checks.

Deployment deletion retries

Layer / File(s) Summary
Bounded deployment deletion flow
plugins/nemo-agents/src/nemo_agents_plugin/api/v2/deployments.py, e2e/test_nemo_agents.py
Deletion retries marking operations up to three attempts and handles already-deleted resources after conflict or server errors.
Deletion retry tests
plugins/nemo-agents/tests/unit/test_deployments_api.py
Tests cover marking deployments deleting, conflict retries, disappearance during retry, and exhausted conflicts.

Sequence Diagram(s)

sequenceDiagram
  participant E2EConfig
  participant DockerBackend
  participant DockerDaemon
  E2EConfig->>DockerBackend: provide resource_scope
  DockerBackend->>DockerDaemon: create labeled resources
  DockerBackend->>DockerDaemon: query matching scope
  DockerDaemon-->>DockerBackend: return scoped resources
Loading
sequenceDiagram
  participant Client
  participant DeleteAPI
  participant EntityClient
  Client->>DeleteAPI: delete deployment
  DeleteAPI->>EntityClient: fetch and mark deleting
  EntityClient-->>DeleteAPI: success, conflict, or not found
  DeleteAPI->>EntityClient: retry on conflict
Loading

Possibly related PRs

Suggested reviewers: crookedstorm, svvarom, tylersbray, benmccown

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.18% 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 matches the main changes: resource-scope container labeling hardening and e2e test updates.
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 harden-labeling-test-fixes/mck

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: 2

🧹 Nitpick comments (2)
plugins/nemo-agents/tests/unit/test_deployments_api.py (1)

123-168: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing test for exhausted-retry → 409 path.

Tests cover success, single-retry, and disappear-during-retry, but not the case where update raises NemoEntityConflictError on all _DELETE_MARK_ATTEMPTS attempts (deployments.py lines 236-240), which should return 409. That's the most novel logic added in this cohort and currently has no coverage.

✅ Suggested additional test
def test_delete_returns_409_when_conflicts_exhausted(self) -> None:
    mock_entity_client = AsyncMock()
    mock_entity_client.get = AsyncMock(
        side_effect=[_make_deployment(status="pending") for _ in range(3)]
    )
    mock_entity_client.update = AsyncMock(side_effect=NemoEntityConflictError("conflict"))
    client = _test_client(mock_entity_client)

    resp = client.delete("/apis/agents/v2/workspaces/default/deployments/fabric-dep")

    assert resp.status_code == 409
    assert mock_entity_client.update.await_count == 3
🤖 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 `@plugins/nemo-agents/tests/unit/test_deployments_api.py` around lines 123 -
168, Add a test to TestDeleteDeployment covering NemoEntityConflictError on
every _DELETE_MARK_ATTEMPTS attempt. Configure get and update mocks for all
retries, call the deployment delete endpoint, and assert it returns 409 with
update awaited once per attempt.
e2e/test_nemo_agents.py (1)

133-145: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Consider handling 409 like 500 here.

The delete endpoint now returns 409 once concurrency-conflict retries are exhausted (see deployments.py _DELETE_MARK_ATTEMPTS logic). Since delete_deployment's docstring indicates a controller reconciles/updates the entity concurrently, a 409 here is plausible, not just theoretical — but this helper only tolerates 404/500, so a 409 will fail the test even if the deployment is genuinely gone or about to be reconciled away.

♻️ Proposed fix
     except httpx.HTTPStatusError as exc:
         if exc.response.status_code == 404:
             return
-        if exc.response.status_code == 500:
+        if exc.response.status_code in (500, 409):
             try:
                 sdk.agents.deployments.get(name, workspace=workspace)
             except httpx.HTTPStatusError as get_exc:
                 if get_exc.response.status_code == 404:
                     return
         raise
🤖 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/test_nemo_agents.py` around lines 133 - 145, Update
_delete_deployment_if_exists to handle HTTP 409 the same way as HTTP 500: after
either status, call sdk.agents.deployments.get and return when that verification
responds with 404; otherwise preserve the existing exception propagation
behavior.
🤖 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/test_anonymizer_plugin.py`:
- Around line 301-306: Update the timeout handling around job.get_logs() so
log-retrieval failures cannot replace the intended TimeoutError. Catch failures
from get_logs, fall back to an empty or unavailable log tail, and still raise
TimeoutError with the job status and last_poll_error diagnostics preserved.

In
`@plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/backend.py`:
- Around line 698-711: Apply _container_matches_deployment_group to every
direct-name containers.get result, including the force-removal path for
same-name init containers, read_status, and get_logs. Treat any container
failing the workspace, deployment name, managed-by, or resource-scope checks as
absent, preserving the existing behavior for genuinely matching containers and
preventing foreign containers from being inspected or removed.

---

Nitpick comments:
In `@e2e/test_nemo_agents.py`:
- Around line 133-145: Update _delete_deployment_if_exists to handle HTTP 409
the same way as HTTP 500: after either status, call sdk.agents.deployments.get
and return when that verification responds with 404; otherwise preserve the
existing exception propagation behavior.

In `@plugins/nemo-agents/tests/unit/test_deployments_api.py`:
- Around line 123-168: Add a test to TestDeleteDeployment covering
NemoEntityConflictError on every _DELETE_MARK_ATTEMPTS attempt. Configure get
and update mocks for all retries, call the deployment delete endpoint, and
assert it returns 409 with update awaited once per attempt.
🪄 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: 902de918-0c73-45b2-b7eb-590bbbc29cc0

📥 Commits

Reviewing files that changed from the base of the PR and between 579de6b and 56d4fe7.

📒 Files selected for processing (11)
  • e2e/services_pool.py
  • e2e/test_anonymizer_plugin.py
  • e2e/test_nemo_agents.py
  • packages/nmp_testing/tests/unit/test_e2e_harness.py
  • plugins/nemo-agents/src/nemo_agents_plugin/api/v2/deployments.py
  • plugins/nemo-agents/tests/unit/test_deployments_api.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/backend.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/config.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/labels.py
  • plugins/nemo-deployments/tests/unit/backends/docker/test_backend_mocked.py
  • plugins/nemo-deployments/tests/unit/backends/docker/test_labels.py

Comment thread e2e/test_anonymizer_plugin.py Outdated
Comment thread plugins/nemo-deployments/src/nemo_deployments_plugin/backends/labels.py Outdated
Comment thread plugins/nemo-agents/src/nemo_agents_plugin/api/v2/deployments.py
@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 27236/34958 77.9% 62.2%
Integration Tests 15998/33670 47.5% 19.9%

Signed-off-by: Matt Kornfield <mkornfield@nvidia.com>
@mckornfield
mckornfield force-pushed the harden-labeling-test-fixes/mck branch from 56d4fe7 to b3b63e7 Compare July 27, 2026 19:06
Comment thread plugins/nemo-agents/src/nemo_agents_plugin/api/v2/deployments.py Dismissed

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/volumes.py (1)

30-42: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Prevent cross-scope volume reuse.

docker_volume_name(workspace, name) omits resource_scope, and an existing volume is accepted without checking its labels. Two scopes with the same workspace/name will share data. Namespace volume names by scope or reject volumes whose scope label differs; apply the same scope rule to read/delete operations.

🤖 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
`@plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/volumes.py`
around lines 30 - 42, The volume lifecycle around _create must prevent
cross-scope reuse: incorporate resource_scope into docker_volume_name or
validate the existing volume’s scope label against resource_scope before
returning it. Apply the same scoped naming or label-validation rule consistently
to the corresponding read and delete operations.
🤖 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.

Outside diff comments:
In
`@plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/volumes.py`:
- Around line 30-42: The volume lifecycle around _create must prevent
cross-scope reuse: incorporate resource_scope into docker_volume_name or
validate the existing volume’s scope label against resource_scope before
returning it. Apply the same scoped naming or label-validation rule consistently
to the corresponding read and delete operations.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 1f5dcd12-2ffe-4982-9f66-452870f28718

📥 Commits

Reviewing files that changed from the base of the PR and between 56d4fe7 and b3b63e7.

📒 Files selected for processing (15)
  • e2e/services_pool.py
  • e2e/test_anonymizer_plugin.py
  • e2e/test_nemo_agents.py
  • packages/nmp_testing/tests/unit/test_e2e_harness.py
  • plugins/nemo-agents/src/nemo_agents_plugin/api/v2/deployments.py
  • plugins/nemo-agents/tests/unit/test_deployments_api.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/backend.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/config.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/volumes.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/k8s/jobs.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/labels.py
  • plugins/nemo-deployments/tests/unit/backends/docker/test_backend_mocked.py
  • plugins/nemo-deployments/tests/unit/backends/docker/test_executor_config.py
  • plugins/nemo-deployments/tests/unit/backends/docker/test_idempotency.py
  • plugins/nemo-deployments/tests/unit/backends/docker/test_labels.py
🚧 Files skipped from review as they are similar to previous changes (6)
  • e2e/test_nemo_agents.py
  • plugins/nemo-deployments/tests/unit/backends/docker/test_labels.py
  • plugins/nemo-agents/tests/unit/test_deployments_api.py
  • plugins/nemo-agents/src/nemo_agents_plugin/api/v2/deployments.py
  • e2e/test_anonymizer_plugin.py
  • e2e/services_pool.py

@mckornfield
mckornfield requested a review from ironcommit July 27, 2026 23:52
@svvarom
svvarom self-requested a review July 27, 2026 23:53
@mckornfield
mckornfield enabled auto-merge July 28, 2026 22:03
@mckornfield
mckornfield added this pull request to the merge queue Jul 28, 2026
Merged via the queue into main with commit 05cd69f Jul 28, 2026
208 of 210 checks passed
@mckornfield
mckornfield deleted the harden-labeling-test-fixes/mck branch July 28, 2026 22:49
ngoncharenko pushed a commit that referenced this pull request Jul 29, 2026
Signed-off-by: Matt Kornfield <mkornfield@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants