Skip to content

feat(api): Added support for automatic prefix selection by VPC ID#3456

Draft
bcavnvidia wants to merge 1 commit into
NVIDIA:mainfrom
bcavnvidia:auto-prefix-selection
Draft

feat(api): Added support for automatic prefix selection by VPC ID#3456
bcavnvidia wants to merge 1 commit into
NVIDIA:mainfrom
bcavnvidia:auto-prefix-selection

Conversation

@bcavnvidia

Copy link
Copy Markdown
Contributor

This PR adds support for callers to auto-select VPC prefixes per interface by specifying only a VPC ID, which gets resolved to a VPC prefix with capacity. Some effort is made to avoid sparse allocation, but we're favoring simplicity and deadlock+serialization avoidance over strong avoidance of sparse-allocation for the moment. Not too hard to change later.

  • Adds typed VPC selection with IPv4-only, IPv6-only, and dual-stack modes, plus family-keyed resolved-prefix status in crates/rpc/proto/forge.proto.
  • Preserves caller intent while retaining legacy-readable prefix resolution for rolling compatibility.
  • Implements deterministic static first-fit allocation, canonical lock ordering, savepoint-based retries, and correct exhaustion/contention classification.
  • Supports all family modes internally through prefix, segment, and address persistence. Inbound IPv6 automatic modes remain temporarily gated at the RPC boundary.
  • Makes repeated VPC-selection updates idempotent and reuses resources when transitioning from an explicit prefix to its owning VPC.
  • Applies tenant ownership checks to explicit and automatic selections and updates cleanup, status, CLI output, documentation, and lifecycle tests.

Related issues

#3110

Type of Change

  • Add - New feature or capability
  • Change - Changes in existing functionality
  • Fix - Bug fixes
  • Remove - Removed features or deprecated functionality
  • Internal - Internal changes (refactoring, tests, docs, etc.)

Breaking Changes

  • This PR contains breaking changes

Testing

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed
  • No testing required (docs, internal refactor, etc.)

Additional Notes

Partially addresses #3110
REST API work still needed.

@copy-pr-bot

copy-pr-bot Bot commented Jul 13, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Summary by CodeRabbit

  • New Features
    • Added automatic VPC-backed network selection for instance interfaces.
    • Supports IPv4-only, IPv6-only, and dual-stack allocation modes.
    • Instance status now reports the resolved IPv4 and IPv6 VPC prefixes.
  • Bug Fixes
    • Improved concurrent network allocation to avoid conflicts and safely retry.
    • Improved reuse and cleanup of automatically generated network resources.
    • Added tenant-aware network allocation and validation.
  • Documentation
    • Clarified that instance configuration updates replace complete desired values rather than applying partial patches.

Walkthrough

Automatic VPC prefix selection is added to instance networking. RPC and internal models preserve selection intent, allocation resolves prefixes and segments in batches, status exposes resolved prefixes, and tests cover tenant scoping, concurrency, updates, reuse, and cleanup.

Changes

Automatic VPC Prefix Selection

Layer / File(s) Summary
Network contracts, model intent, and status projection
crates/rpc/proto/..., rest-api/proto/..., crates/rpc/src/model/..., crates/api-model/src/instance/..., crates/admin-cli/...
Adds automatic VPC selection schemas, family modes, resolved-prefix status, validation, intent-aware resource reuse, RPC conversions, and administrative output.
Prefix candidate selection and segment allocation
crates/api-db/src/vpc_prefix.rs, crates/api-core/src/network_segment/allocate.rs
Separates candidate discovery from locked allocation and replaces subnet enumeration with interval-based prefix selection using family-aware reserved capacity.
Instance allocation orchestration and generated-resource lifecycle
crates/api-core/src/instance/mod.rs, crates/api-core/src/handlers/instance.rs, crates/api-db/src/instance_address.rs, crates/machine-controller/src/handler.rs
Resolves prefix-backed interfaces in one ordered batch, propagates tenant context, and uses generated segment identities for persistence, readiness, and cleanup.
Automatic allocation and update validation
crates/api-core/src/tests/instance.rs, crates/api-core/src/tests/instance_config_update.rs, crates/api-core/src/tests/vpc_prefix.rs
Adds coverage for deterministic selection, tenant ownership, races, deletion, status projection, idempotent updates, resource reuse, and cleanup.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant InstanceAPI
  participant AllocationPlanner
  participant VpcPrefixDB
  participant PrefixAllocator
  participant InstanceStatus
  Client->>InstanceAPI: submit automatic VPC network intent
  InstanceAPI->>AllocationPlanner: pass tenant-scoped allocation request
  AllocationPlanner->>VpcPrefixDB: discover and lock candidates
  AllocationPlanner->>PrefixAllocator: allocate resolved prefixes and segments
  PrefixAllocator-->>AllocationPlanner: return generated resources
  AllocationPlanner-->>InstanceAPI: apply resolved network configuration
  InstanceAPI->>InstanceStatus: publish resolved VPC prefixes
  InstanceStatus-->>Client: return network status
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main feature: automatic prefix selection by VPC ID.
Description check ✅ Passed The description is clearly aligned with the changeset and covers the main feature and supporting work.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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 unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ast-grep (0.44.1)
rest-api/docs/index.html

ast-grep timed out on this file

crates/rpc/build.rs

ast-grep timed out on this file


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.

🧹 Nitpick comments (2)
crates/api-core/src/tests/instance.rs (1)

110-115: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consolidate the triplicated fixture_tenant_config() into a shared fixture. The identical helper now lives in three test modules; any future change to the fixture tenant contract must be applied in lockstep or the modules silently diverge. Extract a single definition into the existing crates/api-core/src/tests/common/api_fixtures module (alongside create_fixture_tenant) and import it in each site.

  • crates/api-core/src/tests/instance.rs#L110-L115: remove the local definition and import the shared helper.
  • crates/api-core/src/tests/instance_config_update.rs#L46-L51: remove the local definition and import the shared helper.
  • crates/api-core/src/tests/vpc_prefix.rs#L41-L46: remove the local definition and import the shared helper.
🤖 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 `@crates/api-core/src/tests/instance.rs` around lines 110 - 115, Consolidate
the duplicated fixture_tenant_config helper by adding one shared definition to
the existing api_fixtures module alongside create_fixture_tenant, then remove
the local definitions and import the shared helper in
crates/api-core/src/tests/instance.rs#L110-L115,
crates/api-core/src/tests/instance_config_update.rs#L46-L51, and
crates/api-core/src/tests/vpc_prefix.rs#L41-L46.
crates/machine-controller/src/handler.rs (1)

6437-6443: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider centralising the generated-segment projection. The identical expression interfaces.iter().filter_map(InstanceInterfaceConfig::generated_network_segment_id).collect_vec() now appears verbatim at three readiness/cleanup sites. Extracting a single helper (e.g. InstanceNetworkConfig::generated_network_segment_ids() or a free function over &[InstanceInterfaceConfig]) would keep the "which segments are generated VPC-prefix segments" contract in one place and guard against future divergence between readiness gating and cleanup.

  • crates/machine-controller/src/handler.rs#L6437-L6443: replace the inline filter_map(...).collect_vec() in InstanceState::WaitingForNetworkSegmentToBeReady with the shared helper.
  • crates/machine-controller/src/handler.rs#L7567-L7572: replace the identical expression in NetworkConfigUpdateState::WaitingForNetworkSegmentToBeReady with the same helper.
  • crates/machine-controller/src/handler.rs#L7929-L7932: replace the identical expression in release_network_segments_with_vpc_prefix with the same helper.
🤖 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 `@crates/machine-controller/src/handler.rs` around lines 6437 - 6443,
Centralize the generated network-segment projection in a shared helper, such as
InstanceNetworkConfig::generated_network_segment_ids(), preserving the existing
filter_map and collection behavior. Use that helper in
crates/machine-controller/src/handler.rs:6437-6443 within
InstanceState::WaitingForNetworkSegmentToBeReady, :7567-7572 within
NetworkConfigUpdateState::WaitingForNetworkSegmentToBeReady, and :7929-7932
within release_network_segments_with_vpc_prefix, replacing each inline
expression.
🤖 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.

Nitpick comments:
In `@crates/api-core/src/tests/instance.rs`:
- Around line 110-115: Consolidate the duplicated fixture_tenant_config helper
by adding one shared definition to the existing api_fixtures module alongside
create_fixture_tenant, then remove the local definitions and import the shared
helper in crates/api-core/src/tests/instance.rs#L110-L115,
crates/api-core/src/tests/instance_config_update.rs#L46-L51, and
crates/api-core/src/tests/vpc_prefix.rs#L41-L46.

In `@crates/machine-controller/src/handler.rs`:
- Around line 6437-6443: Centralize the generated network-segment projection in
a shared helper, such as InstanceNetworkConfig::generated_network_segment_ids(),
preserving the existing filter_map and collection behavior. Use that helper in
crates/machine-controller/src/handler.rs:6437-6443 within
InstanceState::WaitingForNetworkSegmentToBeReady, :7567-7572 within
NetworkConfigUpdateState::WaitingForNetworkSegmentToBeReady, and :7929-7932
within release_network_segments_with_vpc_prefix, replacing each inline
expression.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: cf68be2c-2460-4ede-bded-b2d185b58fe8

📥 Commits

Reviewing files that changed from the base of the PR and between f70eada and 1792f9d.

📒 Files selected for processing (18)
  • crates/admin-cli/src/instance/show/cmd.rs
  • crates/agent/src/tests/full.rs
  • crates/api-core/src/handlers/instance.rs
  • crates/api-core/src/instance/mod.rs
  • crates/api-core/src/network_segment/allocate.rs
  • crates/api-core/src/tests/instance.rs
  • crates/api-core/src/tests/instance_config_update.rs
  • crates/api-core/src/tests/vpc_prefix.rs
  • crates/api-db/src/instance_address.rs
  • crates/api-db/src/instance_network_config.rs
  • crates/api-db/src/vpc_prefix.rs
  • crates/api-model/src/instance/config/network.rs
  • crates/api-model/src/instance/status/network.rs
  • crates/machine-controller/src/handler.rs
  • crates/rpc/build.rs
  • crates/rpc/proto/forge.proto
  • crates/rpc/src/model/instance/config/network.rs
  • crates/rpc/src/model/instance/status/network.rs

@bcavnvidia bcavnvidia marked this pull request as ready for review July 14, 2026 13:45
@bcavnvidia bcavnvidia requested a review from a team as a code owner July 14, 2026 13:45
@bcavnvidia bcavnvidia marked this pull request as draft July 14, 2026 13:45
@github-actions

Copy link
Copy Markdown

🔐 TruffleHog Secret Scan

No secrets or credentials found!

Your code has been scanned for 700+ types of secrets and credentials. All clear! 🎉

🔗 View scan details

🕐 Last updated: 2026-07-14 13:47:57 UTC | Commit: 1792f9d

@bcavnvidia bcavnvidia force-pushed the auto-prefix-selection branch from 1792f9d to a3b6112 Compare July 14, 2026 13:59
@bcavnvidia bcavnvidia marked this pull request as ready for review July 14, 2026 13:59
@bcavnvidia bcavnvidia marked this pull request as draft July 14, 2026 13:59
@github-actions

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown

🔍 Container Scan Summary

Service Total Critical High Medium Low Other
boot-artifacts-aarch64 3 0 0 3 0 0
boot-artifacts-x86_64 3 0 0 3 0 0
forge-admin-cli-x86_64 259 13 30 78 7 131
machine-validation-runner 807 40 234 288 36 209
machine_validation 807 40 234 288 36 209
machine_validation-aarch64 807 40 234 288 36 209
nvmetal-carbide 807 40 234 288 36 209
TOTAL 3493 173 966 1236 151 967

Per-CVE detail lives in the per-service grype-* artifacts (JSON + SARIF). Severity counts only — no CVE IDs published here.

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

🧹 Nitpick comments (1)
crates/api-core/src/network_segment/allocate.rs (1)

470-492: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Prefer value_scenarios! over a manual table loop for this table-driven test.

The five cases are exactly the kind of input→output mapping carbide-test-support's value_scenarios! macro is meant for, consistent with how sibling tests (e.g. validate_inbound_vpc_selection_modes in crates/rpc/src/model/instance/config/network.rs) are written.

♻️ Suggested refactor
-    #[test]
-    fn find_first_unoccupied_linknet_index() {
-        // These cases cover gaps, overlapping occupied ranges, and complete
-        // exhaustion without constructing an address space proportional to IPv6.
-        let cases = [
-            ("empty", vec![], 0, 7, Some(0)),
-            ("leading occupied", vec![(0, 3)], 0, 7, Some(4)),
-            ("overlapping occupied", vec![(0, 3), (2, 6)], 0, 7, Some(7)),
-            ("gap", vec![(0, 1), (4, 7)], 0, 7, Some(2)),
-            ("exhausted", vec![(0, 7)], 0, 7, None),
-        ];
-
-        for (name, occupied, range_start, range_end, expected) in cases {
-            assert_eq!(
-                first_unoccupied_index(&occupied, range_start, range_end),
-                expected,
-                "case: {name}",
-            );
-        }
-    }
+    #[test]
+    fn find_first_unoccupied_linknet_index() {
+        value_scenarios!(
+            run = |(occupied, range_start, range_end): (Vec<(u128, u128)>, u128, u128)|
+                first_unoccupied_index(&occupied, range_start, range_end);
+            "empty" {
+                (vec![], 0, 7) => Some(0),
+            }
+            "leading occupied" {
+                (vec![(0, 3)], 0, 7) => Some(4),
+            }
+            "overlapping occupied" {
+                (vec![(0, 3), (2, 6)], 0, 7) => Some(7),
+            }
+            "gap" {
+                (vec![(0, 1), (4, 7)], 0, 7) => Some(2),
+            }
+            "exhausted" {
+                (vec![(0, 7)], 0, 7) => None,
+            }
+        );
+    }

As per coding guidelines, "In Rust tests, prefer carbide-test-support's scenarios!, value_scenarios!, check_cases, and check_values appropriately."

🤖 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 `@crates/api-core/src/network_segment/allocate.rs` around lines 470 - 492,
Replace the manual cases array and loop in find_first_unoccupied_linknet_index
with carbide-test-support’s value_scenarios! macro, expressing each
occupied-range and boundary input alongside its expected first_unoccupied_index
result. Preserve all five scenarios and their case labels, including the
exhaustion case.

Source: Coding guidelines

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

Nitpick comments:
In `@crates/api-core/src/network_segment/allocate.rs`:
- Around line 470-492: Replace the manual cases array and loop in
find_first_unoccupied_linknet_index with carbide-test-support’s value_scenarios!
macro, expressing each occupied-range and boundary input alongside its expected
first_unoccupied_index result. Preserve all five scenarios and their case
labels, including the exhaustion case.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: f2d916fc-2d34-42b4-b978-3449aeb01ef7

📥 Commits

Reviewing files that changed from the base of the PR and between 1792f9d and a3b6112.

⛔ Files ignored due to path filters (2)
  • rest-api/proto/core/gen/v1/nico_nico.pb.go is excluded by !**/*.pb.go, !**/gen/**, !rest-api/**/*.pb.go
  • rest-api/proto/core/gen/v1/nico_nico_grpc.pb.go is excluded by !**/*.pb.go, !**/gen/**, !rest-api/**/*.pb.go, !rest-api/**/*_grpc.pb.go
📒 Files selected for processing (20)
  • crates/admin-cli/src/instance/show/cmd.rs
  • crates/agent/src/tests/full.rs
  • crates/api-core/src/handlers/instance.rs
  • crates/api-core/src/instance/mod.rs
  • crates/api-core/src/network_segment/allocate.rs
  • crates/api-core/src/tests/instance.rs
  • crates/api-core/src/tests/instance_config_update.rs
  • crates/api-core/src/tests/vpc_prefix.rs
  • crates/api-db/src/instance_address.rs
  • crates/api-db/src/instance_network_config.rs
  • crates/api-db/src/vpc_prefix.rs
  • crates/api-model/src/instance/config/network.rs
  • crates/api-model/src/instance/status/network.rs
  • crates/machine-controller/src/handler.rs
  • crates/rpc/build.rs
  • crates/rpc/proto/forge.proto
  • crates/rpc/src/model/instance/config/network.rs
  • crates/rpc/src/model/instance/status/network.rs
  • rest-api/docs/index.html
  • rest-api/proto/core/src/v1/nico_nico.proto
🚧 Files skipped from review as they are similar to previous changes (16)
  • crates/api-db/src/instance_network_config.rs
  • crates/agent/src/tests/full.rs
  • crates/rpc/src/model/instance/status/network.rs
  • crates/api-db/src/instance_address.rs
  • crates/api-core/src/tests/vpc_prefix.rs
  • crates/api-core/src/handlers/instance.rs
  • crates/admin-cli/src/instance/show/cmd.rs
  • crates/api-db/src/vpc_prefix.rs
  • crates/machine-controller/src/handler.rs
  • crates/api-core/src/instance/mod.rs
  • crates/api-core/src/tests/instance_config_update.rs
  • crates/rpc/proto/forge.proto
  • crates/api-core/src/tests/instance.rs
  • crates/rpc/src/model/instance/config/network.rs
  • crates/api-model/src/instance/status/network.rs
  • crates/api-model/src/instance/config/network.rs

@bcavnvidia bcavnvidia force-pushed the auto-prefix-selection branch from a3b6112 to d8e5f86 Compare July 14, 2026 14:31
@bcavnvidia bcavnvidia marked this pull request as ready for review July 14, 2026 14:31
@bcavnvidia bcavnvidia marked this pull request as draft July 14, 2026 14:31

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

🧹 Nitpick comments (1)
crates/api-model/src/instance/status/network.rs (1)

1034-1070: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Make the resolved-prefix status test table-driven.

The new test covers only DualStack, while resolved_vpc_prefixes() has distinct IPv4-only, IPv6-only, and DualStack mappings. Parameterize this test over the supported modes so a family-key regression cannot pass unnoticed. As per coding guidelines, Rust tests for input-to-output or observable-result mappings should be table-driven.

🤖 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 `@crates/api-model/src/instance/status/network.rs` around lines 1034 - 1070,
Convert network_status_without_observations_includes_resolved_prefixes into a
table-driven test covering IPv4-only, IPv6-only, and DualStack modes. For each
mode, configure the corresponding interface family settings and assert the
expected resolved_vpc_prefixes mapping, while preserving the empty addresses
assertion and shared status construction.

Source: Coding guidelines

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

Nitpick comments:
In `@crates/api-model/src/instance/status/network.rs`:
- Around line 1034-1070: Convert
network_status_without_observations_includes_resolved_prefixes into a
table-driven test covering IPv4-only, IPv6-only, and DualStack modes. For each
mode, configure the corresponding interface family settings and assert the
expected resolved_vpc_prefixes mapping, while preserving the empty addresses
assertion and shared status construction.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: af826c87-1a04-417f-91f5-f0ef48bd9003

📥 Commits

Reviewing files that changed from the base of the PR and between a3b6112 and d8e5f86.

⛔ Files ignored due to path filters (2)
  • rest-api/proto/core/gen/v1/nico_nico.pb.go is excluded by !**/*.pb.go, !**/gen/**, !rest-api/**/*.pb.go
  • rest-api/proto/core/gen/v1/nico_nico_grpc.pb.go is excluded by !**/*.pb.go, !**/gen/**, !rest-api/**/*.pb.go, !rest-api/**/*_grpc.pb.go
📒 Files selected for processing (20)
  • crates/admin-cli/src/instance/show/cmd.rs
  • crates/agent/src/tests/full.rs
  • crates/api-core/src/handlers/instance.rs
  • crates/api-core/src/instance/mod.rs
  • crates/api-core/src/network_segment/allocate.rs
  • crates/api-core/src/tests/instance.rs
  • crates/api-core/src/tests/instance_config_update.rs
  • crates/api-core/src/tests/vpc_prefix.rs
  • crates/api-db/src/instance_address.rs
  • crates/api-db/src/instance_network_config.rs
  • crates/api-db/src/vpc_prefix.rs
  • crates/api-model/src/instance/config/network.rs
  • crates/api-model/src/instance/status/network.rs
  • crates/machine-controller/src/handler.rs
  • crates/rpc/build.rs
  • crates/rpc/proto/forge.proto
  • crates/rpc/src/model/instance/config/network.rs
  • crates/rpc/src/model/instance/status/network.rs
  • rest-api/docs/index.html
  • rest-api/proto/core/src/v1/nico_nico.proto
🚧 Files skipped from review as they are similar to previous changes (18)
  • crates/rpc/build.rs
  • crates/api-db/src/instance_network_config.rs
  • crates/agent/src/tests/full.rs
  • crates/api-core/src/tests/vpc_prefix.rs
  • crates/admin-cli/src/instance/show/cmd.rs
  • crates/api-db/src/instance_address.rs
  • crates/rpc/src/model/instance/status/network.rs
  • crates/rpc/proto/forge.proto
  • crates/api-core/src/instance/mod.rs
  • crates/api-db/src/vpc_prefix.rs
  • rest-api/proto/core/src/v1/nico_nico.proto
  • crates/api-core/src/handlers/instance.rs
  • crates/machine-controller/src/handler.rs
  • crates/rpc/src/model/instance/config/network.rs
  • crates/api-core/src/tests/instance.rs
  • crates/api-model/src/instance/config/network.rs
  • crates/api-core/src/tests/instance_config_update.rs
  • crates/api-core/src/network_segment/allocate.rs

@bcavnvidia bcavnvidia force-pushed the auto-prefix-selection branch from d8e5f86 to c280426 Compare July 14, 2026 15:22
@bcavnvidia bcavnvidia marked this pull request as ready for review July 14, 2026 15:22
@bcavnvidia bcavnvidia marked this pull request as draft July 14, 2026 15:22

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

🧹 Nitpick comments (1)
crates/admin-cli/src/instance/show/cmd.rs (1)

258-292: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Verbose enum string and triplicated match; extract the VPC selection once.

selection.family_mode().as_str_name() renders the raw proto constant (e.g. INSTANCE_INTERFACE_IP_FAMILY_MODE_IPV4_ONLY), which is far more verbose than the {:?} Debug-based short names (Virtual, Synced, ...) used for every other enum field in this same block — an inconsistent, harder-to-read CLI output. Additionally, if_config.and_then(|c| c.network_details.as_ref()) is matched three separate times (VPC PREFIX ID, REQUESTED VPC ID, REQUESTED IP FAMILY) for the same underlying value.

♻️ Proposed fix: match once, use Debug formatting for the enum
+                let vpc_selection = if_config
+                    .and_then(|c| c.network_details.as_ref())
+                    .and_then(|d| match d {
+                        forgerpc::instance_interface_config::NetworkDetails::Vpc(selection) => {
+                            Some(selection)
+                        }
+                        _ => None,
+                    });
                 let data: &[(&str, Cow<str>)] = &[
                     ...
                     (
                         "REQUESTED VPC ID",
-                        match if_config.and_then(|c| c.network_details.as_ref()) {
-                            Some(forgerpc::instance_interface_config::NetworkDetails::Vpc(
-                                selection,
-                            )) => selection
-                                .vpc_id
-                                .map(|vpc_id| vpc_id.to_string().into())
-                                .unwrap_or_else(|| "NA".into()),
-                            _ => "NA".into(),
-                        },
+                        vpc_selection
+                            .and_then(|s| s.vpc_id)
+                            .map(|vpc_id| vpc_id.to_string().into())
+                            .unwrap_or_else(|| "NA".into()),
                     ),
                     (
                         "REQUESTED IP FAMILY",
-                        match if_config.and_then(|c| c.network_details.as_ref()) {
-                            Some(forgerpc::instance_interface_config::NetworkDetails::Vpc(
-                                selection,
-                            )) => selection.family_mode().as_str_name().into(),
-                            _ => "NA".into(),
-                        },
+                        vpc_selection
+                            .map(|s| format!("{:?}", s.family_mode()).into())
+                            .unwrap_or_else(|| "NA".into()),
                     ),

Please confirm whether as_str_name() was intentionally chosen (e.g. to match wire/JSON field naming for scripting consumers) before switching to Debug formatting — this depends on the prost-generated enum API contract.

🤖 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 `@crates/admin-cli/src/instance/show/cmd.rs` around lines 258 - 292, Extract
if_config.and_then(|c| c.network_details.as_ref()) once and reuse the resulting
network details when producing VPC PREFIX ID, REQUESTED VPC ID, and REQUESTED IP
FAMILY. For the VPC selection’s family mode, use the same Debug-based short enum
formatting used by other enum fields instead of family_mode().as_str_name(),
unless this output intentionally serves a wire/JSON naming contract; preserve
the existing NA and other network-detail cases.
🤖 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.

Nitpick comments:
In `@crates/admin-cli/src/instance/show/cmd.rs`:
- Around line 258-292: Extract if_config.and_then(|c|
c.network_details.as_ref()) once and reuse the resulting network details when
producing VPC PREFIX ID, REQUESTED VPC ID, and REQUESTED IP FAMILY. For the VPC
selection’s family mode, use the same Debug-based short enum formatting used by
other enum fields instead of family_mode().as_str_name(), unless this output
intentionally serves a wire/JSON naming contract; preserve the existing NA and
other network-detail cases.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: f88858e3-6e84-40d7-924f-9b2af2157b9e

📥 Commits

Reviewing files that changed from the base of the PR and between d8e5f86 and c280426.

⛔ Files ignored due to path filters (2)
  • rest-api/proto/core/gen/v1/nico_nico.pb.go is excluded by !**/*.pb.go, !**/gen/**, !rest-api/**/*.pb.go
  • rest-api/proto/core/gen/v1/nico_nico_grpc.pb.go is excluded by !**/*.pb.go, !**/gen/**, !rest-api/**/*.pb.go, !rest-api/**/*_grpc.pb.go
📒 Files selected for processing (20)
  • crates/admin-cli/src/instance/show/cmd.rs
  • crates/agent/src/tests/full.rs
  • crates/api-core/src/handlers/instance.rs
  • crates/api-core/src/instance/mod.rs
  • crates/api-core/src/network_segment/allocate.rs
  • crates/api-core/src/tests/instance.rs
  • crates/api-core/src/tests/instance_config_update.rs
  • crates/api-core/src/tests/vpc_prefix.rs
  • crates/api-db/src/instance_address.rs
  • crates/api-db/src/instance_network_config.rs
  • crates/api-db/src/vpc_prefix.rs
  • crates/api-model/src/instance/config/network.rs
  • crates/api-model/src/instance/status/network.rs
  • crates/machine-controller/src/handler.rs
  • crates/rpc/build.rs
  • crates/rpc/proto/forge.proto
  • crates/rpc/src/model/instance/config/network.rs
  • crates/rpc/src/model/instance/status/network.rs
  • rest-api/docs/index.html
  • rest-api/proto/core/src/v1/nico_nico.proto
🚧 Files skipped from review as they are similar to previous changes (15)
  • crates/rpc/build.rs
  • crates/rpc/src/model/instance/status/network.rs
  • crates/agent/src/tests/full.rs
  • crates/api-db/src/instance_address.rs
  • crates/machine-controller/src/handler.rs
  • crates/api-core/src/tests/vpc_prefix.rs
  • crates/api-db/src/vpc_prefix.rs
  • crates/api-core/src/tests/instance_config_update.rs
  • rest-api/proto/core/src/v1/nico_nico.proto
  • crates/api-model/src/instance/status/network.rs
  • crates/api-core/src/instance/mod.rs
  • crates/rpc/src/model/instance/config/network.rs
  • crates/api-core/src/network_segment/allocate.rs
  • crates/api-core/src/tests/instance.rs
  • crates/api-model/src/instance/config/network.rs

@bcavnvidia bcavnvidia force-pushed the auto-prefix-selection branch from c280426 to bd0c7ba Compare July 14, 2026 16:45
@bcavnvidia bcavnvidia marked this pull request as ready for review July 14, 2026 16:45
@bcavnvidia bcavnvidia marked this pull request as draft July 14, 2026 16:46

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

🧹 Nitpick comments (2)
crates/api-db/src/vpc_prefix.rs (1)

155-183: 🚀 Performance & Scalability | 🔵 Trivial

Verify network_vpc_prefixes has index coverage for this hot allocation query.

find_allocation_candidates filters on vpc_id = ANY($1) AND deleted IS NULL plus computed family(prefix)/masklen(prefix) predicates, and now runs on every automatic VPC-prefix selection. If there's no partial index supporting vpc_id with deleted IS NULL (or a functional index on family(prefix)), this becomes a sequential scan as the table grows.

🤖 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 `@crates/api-db/src/vpc_prefix.rs` around lines 155 - 183, Verify the
schema/migration indexes used by find_allocation_candidates cover vpc_id for
rows where deleted IS NULL, and add or update a partial index if needed. Assess
whether the family(prefix)/masklen(prefix) predicates require functional or
otherwise appropriate index coverage for this hot query, while preserving the
existing filtering and ORDER BY vpc_id, id behavior.
crates/api-core/src/network_segment/allocate.rs (1)

303-394: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

next_free_prefix's new cursor/interval logic has no direct unit test.

The rewritten allocation core (next_free_prefix) no longer calls self.iter()/PrefixIterator — that machinery is now #[cfg(test)]-only and unused in production. The pre-existing test_next_iter* tests still pass, but they now only validate the old, unused iterator, not the actual algorithm (occupied-index-interval construction, next-fit start_index computation, and the two-part search with wraparound) that ships in production. Only first_unoccupied_index is unit-tested in isolation with tiny synthetic ranges (Lines 474-492); the u128 conversion of real overlapping IpNetwork prefixes into indices, and the wraparound-past-start_index behavior with realistic prefixes, is exercised only indirectly through higher-level allocation integration tests.

Given this is the load-bearing allocation path for both IPv4 and IPv6 linknets, consider adding a table-driven test directly against next_free_prefix (or a thin wrapper) covering: gaps left by soft-deleted/overlapping prefixes, cursor wraparound at the top of the VPC prefix, and IPv6 /48-scale prefixes to confirm no enumeration happens.

As per coding guidelines, "Use table-driven tests for functions mapping inputs to outputs, errors, or observable results," and "Avoid landing unused Rust code; when code is introduced incrementally, provide its intended usage where practical."

🤖 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 `@crates/api-core/src/network_segment/allocate.rs` around lines 303 - 394, Add
table-driven unit tests that invoke NetworkSegment::next_free_prefix directly,
rather than only testing PrefixIterator or first_unoccupied_index. Cover
overlapping and soft-deleted occupied prefixes, next-fit cursor wraparound at
the VPC boundary, and IPv6 /48-scale allocations to verify interval-based
behavior without enumeration. Reuse existing test setup/helpers and assert both
selected prefixes and expected exhaustion errors where applicable.

Source: Coding guidelines

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

Nitpick comments:
In `@crates/api-core/src/network_segment/allocate.rs`:
- Around line 303-394: Add table-driven unit tests that invoke
NetworkSegment::next_free_prefix directly, rather than only testing
PrefixIterator or first_unoccupied_index. Cover overlapping and soft-deleted
occupied prefixes, next-fit cursor wraparound at the VPC boundary, and IPv6
/48-scale allocations to verify interval-based behavior without enumeration.
Reuse existing test setup/helpers and assert both selected prefixes and expected
exhaustion errors where applicable.

In `@crates/api-db/src/vpc_prefix.rs`:
- Around line 155-183: Verify the schema/migration indexes used by
find_allocation_candidates cover vpc_id for rows where deleted IS NULL, and add
or update a partial index if needed. Assess whether the
family(prefix)/masklen(prefix) predicates require functional or otherwise
appropriate index coverage for this hot query, while preserving the existing
filtering and ORDER BY vpc_id, id behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 8ba0dece-1a22-4968-9c33-2c639b7bbaee

📥 Commits

Reviewing files that changed from the base of the PR and between c280426 and bd0c7ba.

⛔ Files ignored due to path filters (2)
  • rest-api/proto/core/gen/v1/nico_nico.pb.go is excluded by !**/*.pb.go, !**/gen/**, !rest-api/**/*.pb.go
  • rest-api/proto/core/gen/v1/nico_nico_grpc.pb.go is excluded by !**/*.pb.go, !**/gen/**, !rest-api/**/*.pb.go, !rest-api/**/*_grpc.pb.go
📒 Files selected for processing (22)
  • crates/admin-cli/src/instance/show/cmd.rs
  • crates/agent/src/tests/full.rs
  • crates/api-core/src/handlers/instance.rs
  • crates/api-core/src/instance/mod.rs
  • crates/api-core/src/network_segment/allocate.rs
  • crates/api-core/src/tests/instance.rs
  • crates/api-core/src/tests/instance_config_update.rs
  • crates/api-core/src/tests/vpc_prefix.rs
  • crates/api-db/src/instance_address.rs
  • crates/api-db/src/instance_network_config.rs
  • crates/api-db/src/vpc_prefix.rs
  • crates/api-integration-tests/tests/lib.rs
  • crates/api-model/src/instance/config/network.rs
  • crates/api-model/src/instance/status/network.rs
  • crates/api-test-helper/src/instance.rs
  • crates/machine-controller/src/handler.rs
  • crates/rpc/build.rs
  • crates/rpc/proto/forge.proto
  • crates/rpc/src/model/instance/config/network.rs
  • crates/rpc/src/model/instance/status/network.rs
  • rest-api/docs/index.html
  • rest-api/proto/core/src/v1/nico_nico.proto
🚧 Files skipped from review as they are similar to previous changes (17)
  • crates/api-db/src/instance_network_config.rs
  • crates/rpc/build.rs
  • crates/rpc/src/model/instance/status/network.rs
  • crates/agent/src/tests/full.rs
  • crates/api-db/src/instance_address.rs
  • crates/admin-cli/src/instance/show/cmd.rs
  • crates/machine-controller/src/handler.rs
  • crates/api-core/src/tests/vpc_prefix.rs
  • crates/api-core/src/handlers/instance.rs
  • rest-api/proto/core/src/v1/nico_nico.proto
  • crates/api-core/src/instance/mod.rs
  • crates/rpc/proto/forge.proto
  • crates/api-core/src/tests/instance.rs
  • crates/api-core/src/tests/instance_config_update.rs
  • crates/api-model/src/instance/status/network.rs
  • crates/api-model/src/instance/config/network.rs
  • crates/rpc/src/model/instance/config/network.rs

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

In REST we could add AutoSelectVpcPrefix flag on Interface model to capture user intent and differentiate from explicitly selected VPC Prefixes.

// requests are temporarily rejected until downstream DPU support is complete.
enum InstanceInterfaceIpFamilyMode {
// Invalid for an automatic VPC selection request.
INSTANCE_INTERFACE_IP_FAMILY_MODE_UNSPECIFIED = 0;

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.

I think within this object we don't need the INSTANCE_INTERFACE_IP_FAMILY_MODE prefix for each value.

@bcavnvidia bcavnvidia Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's per interface. If you say, "I want interface X to use VPC ID Y", that doesn't capture which IP family you want. You might only want a v4 address, or a v6, or both.

Misunderstood 🙃 Responded again further down.

@bcavnvidia bcavnvidia Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In REST we could add AutoSelectVpcPrefix flag on Interface model to capture user intent and differentiate from explicitly selected VPC Prefixes.

Yeah, I'm doing a separate PR for REST after this, but tracking the intent looks similar there. I have part of it already since I started out thinking we might be able to do all this initially as a pure REST implementation and defer the core work, until I quickly realized it just made too much sense to deal with it in core immediately.

@bcavnvidia bcavnvidia Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think within this object we don't need the INSTANCE_INTERFACE_IP_FAMILY_MODE prefix for each value

Oooooh, I just re-read what you said and realized what you meant. Without prefixes, protobuf scopes can lead to collisions.

In the generated Rust code, it becomes

InstanceInterfaceIpFamilyMode::Unspecified
InstanceInterfaceIpFamilyMode::Ipv4Only

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.

2 participants