feat(api): Added support for automatic prefix selection by VPC ID#3456
feat(api): Added support for automatic prefix selection by VPC ID#3456bcavnvidia wants to merge 1 commit into
Conversation
|
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. |
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
Summary by CodeRabbit
WalkthroughAutomatic 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. ChangesAutomatic VPC Prefix Selection
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
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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.htmlast-grep timed out on this file crates/rpc/build.rsast-grep timed out on this file Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
crates/api-core/src/tests/instance.rs (1)
110-115: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsolidate 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 existingcrates/api-core/src/tests/common/api_fixturesmodule (alongsidecreate_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 valueConsider 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 inlinefilter_map(...).collect_vec()inInstanceState::WaitingForNetworkSegmentToBeReadywith the shared helper.crates/machine-controller/src/handler.rs#L7567-L7572: replace the identical expression inNetworkConfigUpdateState::WaitingForNetworkSegmentToBeReadywith the same helper.crates/machine-controller/src/handler.rs#L7929-L7932: replace the identical expression inrelease_network_segments_with_vpc_prefixwith 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
📒 Files selected for processing (18)
crates/admin-cli/src/instance/show/cmd.rscrates/agent/src/tests/full.rscrates/api-core/src/handlers/instance.rscrates/api-core/src/instance/mod.rscrates/api-core/src/network_segment/allocate.rscrates/api-core/src/tests/instance.rscrates/api-core/src/tests/instance_config_update.rscrates/api-core/src/tests/vpc_prefix.rscrates/api-db/src/instance_address.rscrates/api-db/src/instance_network_config.rscrates/api-db/src/vpc_prefix.rscrates/api-model/src/instance/config/network.rscrates/api-model/src/instance/status/network.rscrates/machine-controller/src/handler.rscrates/rpc/build.rscrates/rpc/proto/forge.protocrates/rpc/src/model/instance/config/network.rscrates/rpc/src/model/instance/status/network.rs
🔐 TruffleHog Secret Scan✅ No secrets or credentials found! Your code has been scanned for 700+ types of secrets and credentials. All clear! 🎉 🕐 Last updated: 2026-07-14 13:47:57 UTC | Commit: 1792f9d |
1792f9d to
a3b6112
Compare
|
🌿 Preview your docs: https://nvidia-preview-pull-request-3456.docs.buildwithfern.com/infra-controller |
🔍 Container Scan Summary
Per-CVE detail lives in the per-service |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
crates/api-core/src/network_segment/allocate.rs (1)
470-492: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winPrefer
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'svalue_scenarios!macro is meant for, consistent with how sibling tests (e.g.validate_inbound_vpc_selection_modesincrates/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
⛔ Files ignored due to path filters (2)
rest-api/proto/core/gen/v1/nico_nico.pb.gois excluded by!**/*.pb.go,!**/gen/**,!rest-api/**/*.pb.gorest-api/proto/core/gen/v1/nico_nico_grpc.pb.gois 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.rscrates/agent/src/tests/full.rscrates/api-core/src/handlers/instance.rscrates/api-core/src/instance/mod.rscrates/api-core/src/network_segment/allocate.rscrates/api-core/src/tests/instance.rscrates/api-core/src/tests/instance_config_update.rscrates/api-core/src/tests/vpc_prefix.rscrates/api-db/src/instance_address.rscrates/api-db/src/instance_network_config.rscrates/api-db/src/vpc_prefix.rscrates/api-model/src/instance/config/network.rscrates/api-model/src/instance/status/network.rscrates/machine-controller/src/handler.rscrates/rpc/build.rscrates/rpc/proto/forge.protocrates/rpc/src/model/instance/config/network.rscrates/rpc/src/model/instance/status/network.rsrest-api/docs/index.htmlrest-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
a3b6112 to
d8e5f86
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
crates/api-model/src/instance/status/network.rs (1)
1034-1070: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winMake the resolved-prefix status test table-driven.
The new test covers only
DualStack, whileresolved_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
⛔ Files ignored due to path filters (2)
rest-api/proto/core/gen/v1/nico_nico.pb.gois excluded by!**/*.pb.go,!**/gen/**,!rest-api/**/*.pb.gorest-api/proto/core/gen/v1/nico_nico_grpc.pb.gois 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.rscrates/agent/src/tests/full.rscrates/api-core/src/handlers/instance.rscrates/api-core/src/instance/mod.rscrates/api-core/src/network_segment/allocate.rscrates/api-core/src/tests/instance.rscrates/api-core/src/tests/instance_config_update.rscrates/api-core/src/tests/vpc_prefix.rscrates/api-db/src/instance_address.rscrates/api-db/src/instance_network_config.rscrates/api-db/src/vpc_prefix.rscrates/api-model/src/instance/config/network.rscrates/api-model/src/instance/status/network.rscrates/machine-controller/src/handler.rscrates/rpc/build.rscrates/rpc/proto/forge.protocrates/rpc/src/model/instance/config/network.rscrates/rpc/src/model/instance/status/network.rsrest-api/docs/index.htmlrest-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
d8e5f86 to
c280426
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
crates/admin-cli/src/instance/show/cmd.rs (1)
258-292: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winVerbose 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 theprost-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
⛔ Files ignored due to path filters (2)
rest-api/proto/core/gen/v1/nico_nico.pb.gois excluded by!**/*.pb.go,!**/gen/**,!rest-api/**/*.pb.gorest-api/proto/core/gen/v1/nico_nico_grpc.pb.gois 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.rscrates/agent/src/tests/full.rscrates/api-core/src/handlers/instance.rscrates/api-core/src/instance/mod.rscrates/api-core/src/network_segment/allocate.rscrates/api-core/src/tests/instance.rscrates/api-core/src/tests/instance_config_update.rscrates/api-core/src/tests/vpc_prefix.rscrates/api-db/src/instance_address.rscrates/api-db/src/instance_network_config.rscrates/api-db/src/vpc_prefix.rscrates/api-model/src/instance/config/network.rscrates/api-model/src/instance/status/network.rscrates/machine-controller/src/handler.rscrates/rpc/build.rscrates/rpc/proto/forge.protocrates/rpc/src/model/instance/config/network.rscrates/rpc/src/model/instance/status/network.rsrest-api/docs/index.htmlrest-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
c280426 to
bd0c7ba
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (2)
crates/api-db/src/vpc_prefix.rs (1)
155-183: 🚀 Performance & Scalability | 🔵 TrivialVerify
network_vpc_prefixeshas index coverage for this hot allocation query.
find_allocation_candidatesfilters onvpc_id = ANY($1) AND deleted IS NULLplus computedfamily(prefix)/masklen(prefix)predicates, and now runs on every automatic VPC-prefix selection. If there's no partial index supportingvpc_idwithdeleted IS NULL(or a functional index onfamily(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 callsself.iter()/PrefixIterator— that machinery is now#[cfg(test)]-only and unused in production. The pre-existingtest_next_iter*tests still pass, but they now only validate the old, unused iterator, not the actual algorithm (occupied-index-interval construction, next-fitstart_indexcomputation, and the two-part search with wraparound) that ships in production. Onlyfirst_unoccupied_indexis unit-tested in isolation with tiny synthetic ranges (Lines 474-492); the u128 conversion of real overlappingIpNetworkprefixes into indices, and the wraparound-past-start_indexbehavior 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
⛔ Files ignored due to path filters (2)
rest-api/proto/core/gen/v1/nico_nico.pb.gois excluded by!**/*.pb.go,!**/gen/**,!rest-api/**/*.pb.gorest-api/proto/core/gen/v1/nico_nico_grpc.pb.gois 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.rscrates/agent/src/tests/full.rscrates/api-core/src/handlers/instance.rscrates/api-core/src/instance/mod.rscrates/api-core/src/network_segment/allocate.rscrates/api-core/src/tests/instance.rscrates/api-core/src/tests/instance_config_update.rscrates/api-core/src/tests/vpc_prefix.rscrates/api-db/src/instance_address.rscrates/api-db/src/instance_network_config.rscrates/api-db/src/vpc_prefix.rscrates/api-integration-tests/tests/lib.rscrates/api-model/src/instance/config/network.rscrates/api-model/src/instance/status/network.rscrates/api-test-helper/src/instance.rscrates/machine-controller/src/handler.rscrates/rpc/build.rscrates/rpc/proto/forge.protocrates/rpc/src/model/instance/config/network.rscrates/rpc/src/model/instance/status/network.rsrest-api/docs/index.htmlrest-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
left a comment
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
I think within this object we don't need the INSTANCE_INTERFACE_IP_FAMILY_MODE prefix for each value.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
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.
Related issues
#3110
Type of Change
Breaking Changes
Testing
Additional Notes
Partially addresses #3110
REST API work still needed.