Skip to content

Add per-VPC routing-profile overrides - #4411

Merged
bcavnvidia merged 1 commit into
NVIDIA:mainfrom
bcavnvidia:routing-profiles-overrides
Jul 31, 2026
Merged

Add per-VPC routing-profile overrides#4411
bcavnvidia merged 1 commit into
NVIDIA:mainfrom
bcavnvidia:routing-profiles-overrides

Conversation

@bcavnvidia

Copy link
Copy Markdown
Contributor

Adds create-time, per-VPC routing-profile overrides on top of named routing-profiles.

Each explicitly supplied override replaces the corresponding base-profile value, while omitted properties continue to inherit from the named profile. The operator-controlled internal and access_tier properties cannot be overridden at the VPC level.

The effective profile is resolved from the current API configuration and persisted VPC overrides rather than stored separately, so API responses reflect changes to the named base profile.

Related issues

#2624

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

#2624

@copy-pr-bot

copy-pr-bot Bot commented Jul 30, 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 30, 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
    • VPCs can now specify routing-profile overrides, including route targets, route leaking, communities, prefix filters, and anycast prefixes.
    • VPC details display configured overrides and the effective routing profile.
    • API responses report the resolved routing profile, including inherited settings.
  • Bug Fixes
    • Added validation for unsupported overrides, invalid profiles, missing configuration, and access-tier restrictions.
    • Preserved explicit empty and disabled override values during inheritance and resolution.
  • Documentation
    • Updated configuration guidance for routing-profile inheritance, defaults, and seeded VPC restrictions.

Walkthrough

VPC routing-profile overrides are added to RPC, REST, model, and database contracts. VPC creation resolves and persists overrides, startup validation rejects seeded overrides, networking consumes effective profiles, and CLI/web views display configured and effective values.

Changes

VPC routing-profile contracts and configuration

Layer / File(s) Summary
Contracts and effective configuration
rest-api/proto/core/src/v1/nico_nico.proto, crates/rpc/proto/*, crates/api-model/src/vpc/*, crates/api-core/src/cfg/*
Optional override models and effective-profile messages are added. FNN profile fields now preserve unset values for inheritance and defaulting.
Persistence and RPC wiring
crates/api-db/migrations/*, crates/api-db/src/vpc.rs, crates/rpc/src/model/vpc.rs, crates/admin-cli/src/*, crates/machine-a-tron/src/api_client.rs
Overrides are stored as nullable JSON and converted across API boundaries. VPC creation clients initialize absent overrides explicitly.
Runtime resolution and networking
crates/api-core/src/handlers/vpc.rs, crates/api-core/src/ethernet_virtualization.rs
VPC creation and retrieval resolve effective profiles from named profiles and inline overrides. Networking validation uses the resolved profile.
Seed validation and startup handling
crates/api-core/src/db_init.rs, crates/api-core/src/setup.rs, crates/api-model/src/lib.rs
Initial VPC definitions reject inline overrides before database mutation. Startup validation reports dedicated configuration errors.
Routing profile compatibility coverage
crates/api-core/src/tests/*, crates/api-core/src/cfg/file.rs, crates/api-core/src/setup.rs
Tests cover inheritance, explicit overrides, persistence, profile transitions, anycast behavior, and seeded-VPC rejection.
CLI and web presentation
crates/admin-cli/src/vpc/show/cmd.rs, crates/api-web/src/vpc.rs, crates/api-web/templates/vpc_detail.html
CLI and web output show routing-profile type, configured overrides, and the effective profile with absent-value fallbacks.

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

Sequence Diagram(s)

sequenceDiagram
  participant VpcClient
  participant VpcHandler
  participant FnnConfig
  participant VpcDatabase
  VpcClient->>VpcHandler: Submit VPC creation request with overrides
  VpcHandler->>FnnConfig: Resolve base profile and apply overrides
  FnnConfig-->>VpcHandler: Return effective routing profile
  VpcHandler->>VpcDatabase: Persist VPC and overrides
  VpcDatabase-->>VpcHandler: Return stored VPC
  VpcHandler-->>VpcClient: Return VPC status with effective profile
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding per-VPC routing-profile overrides.
Description check ✅ Passed The description directly explains the routing-profile override behavior, inheritance rules, restrictions, resolution model, and testing.
Docstring Coverage ✅ Passed Docstring coverage is 83.02% 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

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

🧹 Nitpick comments (3)
crates/api-core/src/setup.rs (1)

2141-2146: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Prefer variant-based classification over message substring matching.

Two concerns with this arm: the "routing_profile_overrides" substring couples the table to error prose that the repository's error-message lint may reword, and the else branch labels every other ConfigValidationError as InvalidNetwork — a future non-network validation failure would be silently misattributed even though ResolveFailure::Unexpected exists for exactly that case.

♻️ Suggested refactor to keep unknown failures distinguishable
                 if let Some(error) = error.downcast_ref::<model::ConfigValidationError>() {
-                    return if error.to_string().contains("routing_profile_overrides") {
-                        Err(ResolveFailure::InvalidVpcOverrides)
-                    } else {
-                        Err(ResolveFailure::InvalidNetwork)
-                    };
+                    let message = error.to_string();
+                    return match error {
+                        model::ConfigValidationError::InvalidValue(_)
+                            if message.contains("test-vpc") =>
+                        {
+                            Err(ResolveFailure::InvalidVpcOverrides)
+                        }
+                        model::ConfigValidationError::InvalidValue(_) => {
+                            Err(ResolveFailure::InvalidNetwork)
+                        }
+                        _ => Err(ResolveFailure::Unexpected(message)),
+                    };
                 }
🤖 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/setup.rs` around lines 2141 - 2146, Update the
ConfigValidationError classification in the surrounding resolver to match its
concrete error variant or structured field for routing_profile_overrides instead
of inspecting error.to_string(). Map only the known network-related variants to
InvalidVpcOverrides or InvalidNetwork, and route any other ConfigValidationError
to ResolveFailure::Unexpected rather than treating it as a network failure.
crates/api-core/src/tests/vpc.rs (1)

605-637: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider a table-driven form for these two same-operation inputs.

Both requests invoke create_vpc with a single differing field and share one expectation — the case the repository reserves for the carbide-test-support helpers. Beyond convention, check_cases/scenarios! labels each input, so a regression on only the second request is reported directly instead of surfacing as an anonymous loop iteration. Naming the scenarios "routing_profile_type" and "routing_profile_overrides" would suffice.

As per coding guidelines, "Use tables whenever multiple tests call the same operation with different inputs, but keep genuinely distinct tests as standalone tests."

🤖 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/vpc.rs` around lines 605 - 637, Replace the
anonymous requests loop in the VPC creation test with the repository’s
table-driven test helper, such as check_cases/scenarios!, using cases named
"routing_profile_type" and "routing_profile_overrides". Keep each existing
request input and shared create_vpc error assertion unchanged so failures
identify the specific scenario.

Source: Coding guidelines

crates/api-core/src/handlers/vpc.rs (1)

705-882: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add unit coverage for vpc_profile_overrides in resolve_vpc_routing.

Every test call in this module (updated or new) passes None for the new vpc_profile_overrides parameter. Two branches introduced by this parameter are consequently unverified at the unit level:

  • (None, None) with overrides present must fall through to the "no tenant/profile-type found" error.
  • FNN-disabled + overrides-present (with no explicit request_profile_type) must be rejected via the "FNN configuration required" error.

Adding two focused cases would close this gap and guard the new validation logic against regressions.

🧪 Suggested additional test cases
#[test]
fn overrides_without_tenant_or_request_profile_is_rejected() {
    let err = resolve_vpc_routing(
        VpcVirtualizationType::Fnn,
        None,
        Some(&VpcRoutingProfileOverrides::default()),
        None,
        None,
        "test-org",
    )
    .expect_err("overrides without any named profile must be rejected");
    assert!(matches!(err, CarbideError::FailedPrecondition(_)));
}

#[test]
fn fnn_disabled_with_overrides_only_is_rejected() {
    let tenant = tenant_with_profile(Some("INTERNAL"));
    let err = resolve_vpc_routing(
        VpcVirtualizationType::Fnn,
        None,
        Some(&VpcRoutingProfileOverrides::default()),
        Some(&tenant),
        None,
        "test-org",
    )
    .expect_err("overrides require FNN configuration even without an explicit request");
    assert!(matches!(err, CarbideError::FailedPrecondition(_)));
}
🤖 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/handlers/vpc.rs` around lines 705 - 882, Add two focused
unit tests for the vpc_profile_overrides branches in resolve_vpc_routing: verify
overrides without a tenant or requested profile returns FailedPrecondition, and
verify FNN-disabled routing with tenant profile plus overrides but no request
also returns FailedPrecondition. Use VpcRoutingProfileOverrides::default() and
preserve the existing error assertions.
🤖 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 `@crates/api-core/src/ethernet_virtualization.rs`:
- Around line 179-190: Extract the duplicated base-profile lookup and VPC
override application into an FnnConfig helper such as resolve_effective_profile,
returning the existing Cow-based Result and preserving the current Internal and
NotFoundError cases. Replace the inline resolution in
validate_instance_interface_routing_profiles
(crates/api-core/src/ethernet_virtualization.rs#L179-L190) and tenant_network
(crates/api-core/src/ethernet_virtualization.rs#L673-L683) with the helper and
propagate via ?. Replace the inline lookup in vpc_to_rpc
(crates/api-core/src/handlers/vpc.rs#L395-L431) with the helper and convert its
Result using .ok() to retain graceful missing-profile handling.

---

Nitpick comments:
In `@crates/api-core/src/handlers/vpc.rs`:
- Around line 705-882: Add two focused unit tests for the vpc_profile_overrides
branches in resolve_vpc_routing: verify overrides without a tenant or requested
profile returns FailedPrecondition, and verify FNN-disabled routing with tenant
profile plus overrides but no request also returns FailedPrecondition. Use
VpcRoutingProfileOverrides::default() and preserve the existing error
assertions.

In `@crates/api-core/src/setup.rs`:
- Around line 2141-2146: Update the ConfigValidationError classification in the
surrounding resolver to match its concrete error variant or structured field for
routing_profile_overrides instead of inspecting error.to_string(). Map only the
known network-related variants to InvalidVpcOverrides or InvalidNetwork, and
route any other ConfigValidationError to ResolveFailure::Unexpected rather than
treating it as a network failure.

In `@crates/api-core/src/tests/vpc.rs`:
- Around line 605-637: Replace the anonymous requests loop in the VPC creation
test with the repository’s table-driven test helper, such as
check_cases/scenarios!, using cases named "routing_profile_type" and
"routing_profile_overrides". Keep each existing request input and shared
create_vpc error assertion unchanged so failures identify the specific scenario.
🪄 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: 6e28a912-fc52-4473-9b45-594ffe36e988

📥 Commits

Reviewing files that changed from the base of the PR and between 56b4379 and c080aa4.

📒 Files selected for processing (26)
  • crates/admin-cli/src/rpc.rs
  • crates/admin-cli/src/vpc/create/args.rs
  • crates/admin-cli/src/vpc/show/cmd.rs
  • crates/api-core/src/cfg/README.md
  • crates/api-core/src/cfg/file.rs
  • crates/api-core/src/db_init.rs
  • crates/api-core/src/ethernet_virtualization.rs
  • crates/api-core/src/handlers/vpc.rs
  • crates/api-core/src/setup.rs
  • crates/api-core/src/tests/common/api_fixtures/mod.rs
  • crates/api-core/src/tests/instance_allocate.rs
  • crates/api-core/src/tests/instance_config_update.rs
  • crates/api-core/src/tests/machine_network.rs
  • crates/api-core/src/tests/network_segment.rs
  • crates/api-core/src/tests/vpc.rs
  • crates/api-db/migrations/20260728120000_vpc_routing_profile_overrides.sql
  • crates/api-db/src/vpc.rs
  • crates/api-model/src/vpc/capability.rs
  • crates/api-model/src/vpc/mod.rs
  • crates/api-model/src/vpc/routing_profile.rs
  • crates/api-web/src/vpc.rs
  • crates/api-web/templates/vpc_detail.html
  • crates/machine-a-tron/src/api_client.rs
  • crates/rpc/build.rs
  • crates/rpc/proto/forge.proto
  • crates/rpc/src/model/vpc.rs

Comment thread crates/api-core/src/ethernet_virtualization.rs Outdated
@bcavnvidia
bcavnvidia force-pushed the routing-profiles-overrides branch from c080aa4 to 862a21d Compare July 30, 2026 21:32

@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/rpc/src/model/vpc.rs (1)

112-221: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract shared helpers to eliminate the repeated route-target/prefix conversion logic.

The TryFrom/From impls for VpcRoutingProfileOverrides repeat the same two shapes of logic four times each: the RouteTargetConfig list mapping (route_target_imports / route_targets_on_exports) and the PrefixFilterPolicyEntry list mapping (accepted_leaks_from_underlay / allowed_anycast_prefixes). Any future field tweak (e.g., adding validation) risks being applied to only one of the four copies.

Extracting small conversion helpers keeps this DRY and easier to maintain.

♻️ Proposed refactor sketch
+fn route_targets_from_rpc(targets: rpc::forge::RouteTargets) -> Vec<RouteTargetConfig> {
+    targets
+        .values
+        .into_iter()
+        .map(|target| RouteTargetConfig {
+            asn: target.asn,
+            vni: target.vni,
+        })
+        .collect()
+}
+
+fn prefix_entries_from_rpc(
+    entries: rpc::forge::PrefixFilterPolicyEntries,
+) -> Result<Vec<PrefixFilterPolicyEntry>, RpcDataConversionError> {
+    entries
+        .values
+        .into_iter()
+        .map(|entry| Ok(PrefixFilterPolicyEntry { prefix: entry.prefix.parse()? }))
+        .collect()
+}
+
 impl TryFrom<rpc::forge::VpcRoutingProfileOverrides> for VpcRoutingProfileOverrides {
     type Error = RpcDataConversionError;

     fn try_from(profile: rpc::forge::VpcRoutingProfileOverrides) -> Result<Self, Self::Error> {
         Ok(Self {
-            route_target_imports: profile.route_target_imports.map(|targets| {
-                targets.values.into_iter().map(|target| RouteTargetConfig {
-                    asn: target.asn,
-                    vni: target.vni,
-                }).collect()
-            }),
-            route_targets_on_exports: profile.route_targets_on_exports.map(|targets| { /* same */ }),
+            route_target_imports: profile.route_target_imports.map(route_targets_from_rpc),
+            route_targets_on_exports: profile.route_targets_on_exports.map(route_targets_from_rpc),
             ...
-            accepted_leaks_from_underlay: profile.accepted_leaks_from_underlay.map(|entries| { /* parse loop */ }).transpose()?,
-            allowed_anycast_prefixes: profile.allowed_anycast_prefixes.map(|entries| { /* parse loop */ }).transpose()?,
+            accepted_leaks_from_underlay: profile.accepted_leaks_from_underlay.map(prefix_entries_from_rpc).transpose()?,
+            allowed_anycast_prefixes: profile.allowed_anycast_prefixes.map(prefix_entries_from_rpc).transpose()?,
         })
     }
 }

A symmetric pair of helpers (route_targets_to_rpc, prefix_entries_to_rpc) would similarly simplify the reverse From impl.

🤖 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/rpc/src/model/vpc.rs` around lines 112 - 221, Extract shared helpers
for converting route-target collections and prefix-filter entries, then reuse
them in both VpcRoutingProfileOverrides TryFrom and From implementations.
Replace the duplicated mappings for
route_target_imports/route_targets_on_exports with the route-target helper, and
accepted_leaks_from_underlay/allowed_anycast_prefixes with the prefix-entry
helper, including parsing and RPC serialization 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.

Nitpick comments:
In `@crates/rpc/src/model/vpc.rs`:
- Around line 112-221: Extract shared helpers for converting route-target
collections and prefix-filter entries, then reuse them in both
VpcRoutingProfileOverrides TryFrom and From implementations. Replace the
duplicated mappings for route_target_imports/route_targets_on_exports with the
route-target helper, and accepted_leaks_from_underlay/allowed_anycast_prefixes
with the prefix-entry helper, including parsing and RPC serialization behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d9e604f1-5cbc-40b7-a3e3-fde91a25fdda

📥 Commits

Reviewing files that changed from the base of the PR and between c080aa4 and 862a21d.

📒 Files selected for processing (27)
  • crates/admin-cli/src/rpc.rs
  • crates/admin-cli/src/vpc/create/args.rs
  • crates/admin-cli/src/vpc/show/cmd.rs
  • crates/api-core/src/cfg/README.md
  • crates/api-core/src/cfg/file.rs
  • crates/api-core/src/db_init.rs
  • crates/api-core/src/ethernet_virtualization.rs
  • crates/api-core/src/handlers/vpc.rs
  • crates/api-core/src/setup.rs
  • crates/api-core/src/tests/common/api_fixtures/mod.rs
  • crates/api-core/src/tests/instance_allocate.rs
  • crates/api-core/src/tests/instance_config_update.rs
  • crates/api-core/src/tests/machine_network.rs
  • crates/api-core/src/tests/network_segment.rs
  • crates/api-core/src/tests/vpc.rs
  • crates/api-db/migrations/20260728120000_vpc_routing_profile_overrides.sql
  • crates/api-db/src/vpc.rs
  • crates/api-model/src/lib.rs
  • crates/api-model/src/vpc/capability.rs
  • crates/api-model/src/vpc/mod.rs
  • crates/api-model/src/vpc/routing_profile.rs
  • crates/api-web/src/vpc.rs
  • crates/api-web/templates/vpc_detail.html
  • crates/machine-a-tron/src/api_client.rs
  • crates/rpc/build.rs
  • crates/rpc/proto/forge.proto
  • crates/rpc/src/model/vpc.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • crates/api-core/src/cfg/README.md
  • crates/api-core/src/tests/instance_config_update.rs
  • crates/api-core/src/tests/network_segment.rs

@bcavnvidia
bcavnvidia marked this pull request as ready for review July 30, 2026 21:47
@bcavnvidia
bcavnvidia requested a review from a team as a code owner July 30, 2026 21:47
@bcavnvidia
bcavnvidia marked this pull request as draft July 30, 2026 21:47
@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-30 21:53:32 UTC | Commit: 862a21d

@bcavnvidia
bcavnvidia force-pushed the routing-profiles-overrides branch 3 times, most recently from c1f801c to 2392f2f Compare July 31, 2026 01:02
@bcavnvidia
bcavnvidia marked this pull request as ready for review July 31, 2026 01:02
@bcavnvidia
bcavnvidia marked this pull request as draft July 31, 2026 01:02
@github-actions

Copy link
Copy Markdown

@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)
crates/api-core/src/db_init.rs (1)

68-114: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Inconsistent trailing-dot normalization when matching the configured domain.

forward_domains classification trims a trailing . before checking reverse-zone suffixes (line 86), but the configured-domain equality check on line 96 compares the raw, untrimmed domain.name against domain_name. If a forward domain row is stored as an FQDN with a trailing dot (as seen for reverse zones in this file's own test fixtures, e.g. "0.0.ip6.arpa."), while initial_domain_name in config is typically entered without one, the exact match silently fails and the function falls through to the ambiguous/fallback path instead of correctly selecting the configured domain. This edge case isn't covered by the new table-driven tests.

🐛 Proposed fix
     if let Some(domain_name) = configured_domain_name {
         let configured_domains = forward_domains
             .iter()
-            .filter(|domain| domain.name == domain_name)
+            .filter(|domain| domain.name.trim_end_matches('.') == domain_name)
             .collect_vec();
🤖 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/db_init.rs` around lines 68 - 114, Normalize trailing
dots consistently in select_seed_network_domain when matching
configured_domain_name: compare the domain name after removing its trailing dot
against the configured value using the same normalization applied during
forward-domain classification. Preserve the existing single-match selection and
fallback behavior, and add coverage for a stored forward domain with a trailing
dot and an undotted configured name.
🧹 Nitpick comments (5)
crates/api-core/src/cfg/file.rs (1)

2078-2084: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Align the not-found resource kind with the existing routing-profile lookup.

resolve_vpc_routing_profile reports kind: "routing_profile_type", whereas the equivalent lookup in crates/api-core/src/handlers/vpc.rs (resolve_vpc_routing) reports kind: "routing_profile" for the very same fnn.routing_profiles miss. Operators therefore see two different resource names for one failure mode.

♻️ Suggested alignment
                 .ok_or_else(|| CarbideError::NotFoundError {
-                    kind: "routing_profile_type",
+                    kind: "routing_profile",
                     id: profile_type.to_string(),
                 })?;

Note the assertion in vpc_routing_profile_resolution_reports_consistent_errors (Line 3754) needs the matching update.

🤖 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/cfg/file.rs` around lines 2078 - 2084, Update the
NotFoundError construction in resolve_vpc_routing_profile to use kind
"routing_profile", matching resolve_vpc_routing for the same routing_profiles
lookup, and update the expected kind in
vpc_routing_profile_resolution_reports_consistent_errors accordingly.
crates/rpc/src/model/vpc.rs (2)

175-219: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Collapse the four repeated collection mappings into reusable conversions.

The route-target and prefix-entry mappings are duplicated in both directions (eight near-identical closures across TryFrom and From). Dedicated From/TryFrom impls for RouteTargetsVec<RouteTargetConfig> and PrefixFilterPolicyEntriesVec<PrefixFilterPolicyEntry> would keep the override conversion declarative and prevent the two directions from drifting.

♻️ Sketch
impl From<Vec<RouteTargetConfig>> for rpc::forge::RouteTargets {
    fn from(targets: Vec<RouteTargetConfig>) -> Self {
        Self {
            values: targets
                .into_iter()
                .map(|target| rpc::common::RouteTarget { asn: target.asn, vni: target.vni })
                .collect(),
        }
    }
}

The override conversion then reduces to profile.route_target_imports.map(Into::into), with the mirrored From<rpc::forge::RouteTargets> used on the inbound side.

As per coding guidelines: "Prefer From/TryFrom and FromStr conversions over bespoke conversion methods".

🤖 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/rpc/src/model/vpc.rs` around lines 175 - 219, Extract the duplicated
route-target and prefix-entry collection mappings into reusable From/TryFrom
implementations for rpc::forge::RouteTargets and
rpc::forge::PrefixFilterPolicyEntries with their corresponding Vec configuration
types. Update both outbound and inbound conversions in the relevant TryFrom/From
implementations to use map(Into::into) or the established conversion path,
preserving prefix parsing errors and existing field values.

Source: Coding guidelines


140-167: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Preserve prefix context in parse errors

The existing ? resolves through RpcDataConversionError::NetworkParseError, but the resulting message omits the profile field and raw prefix. Map each parse failure to a lowercase InvalidArgument containing the field name, offending prefix, and parser error; apply this to both lists.

🤖 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/rpc/src/model/vpc.rs` around lines 140 - 167, Update both prefix
parsing closures in the profile conversion to map parse failures into lowercase
InvalidArgument errors instead of relying on the existing RpcDataConversionError
conversion. Include the corresponding profile field name, raw prefix value, and
parser error in each message, preserving the current successful conversion and
collection behavior for accepted_leaks_from_underlay and
allowed_anycast_prefixes.
crates/api-core/src/handlers/vpc.rs (1)

698-920: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider consolidating the resolve_vpc_routing cases into a table, and cover the FNN-enabled + overrides success path.

Thirteen tests now invoke the same function with only argument variations, which is precisely the shape the repository reserves for table-driven scenarios. A scenarios!-style table keyed on (virt type, requested profile, overrides, tenant, FNN) would also make the one currently untested branch obvious: overrides supplied with FNN enabled and a tenant profile, asserting the resolved profile_type and inherited internal flag. Today only the rejection paths for overrides are asserted at this level.

As per coding guidelines, "Use tables whenever multiple tests call the same operation with different inputs, but keep genuinely distinct tests as standalone tests," and "prefer table-driven tests using carbide-test-support scenarios such as scenarios! / value_scenarios!".

🤖 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/handlers/vpc.rs` around lines 698 - 920, Consolidate the
repetitive `resolve_vpc_routing` tests into a `carbide-test-support`
`scenarios!` or equivalent table-driven scenario covering their varied inputs
and expected results, while keeping genuinely distinct assertions standalone.
Add a successful FNN-enabled overrides scenario with a tenant profile, asserting
the resolved `profile_type` and inherited `internal` flag alongside the existing
rejection and default cases.

Source: Coding guidelines

crates/admin-cli/src/vpc/show/cmd.rs (1)

184-252: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

CLI "nice" output omits the effective routing profile shown by the web view.

The PR-stack description for this cohort states the CLI and web views both display "serialized routing overrides and effective routing profiles when available," and crates/api-web/src/vpc.rs's VpcDetail does add an effective-profile section in this same PR. This function only adds ROUTING PROFILE TYPE / ROUTING PROFILE OVERRIDES rows — vpc.status.effective_routing_profile (already available on the same Vpc value) is never surfaced here. If there isn't a separate raw/JSON output path that already covers this for vpc show, operators lose visibility into the resolved effective profile from the primary human-readable output.

♻️ Suggested addition for parity with the web detail view
         (
             "ROUTING PROFILE OVERRIDES",
             routing_profile_overrides.into(),
         ),
+        (
+            "EFFECTIVE ROUTING PROFILE",
+            vpc.status
+                .as_ref()
+                .and_then(|status| status.effective_routing_profile.as_ref())
+                .map(serde_json::to_string_pretty)
+                .transpose()?
+                .unwrap_or_else(|| "Not applicable or unavailable".to_string())
+                .into(),
+        ),
     ];
🤖 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/vpc/show/cmd.rs` around lines 184 - 252, Update
convert_vpc_to_nice_format to include vpc.status.effective_routing_profile in
the human-readable rows, alongside ROUTING PROFILE TYPE and ROUTING PROFILE
OVERRIDES. Serialize or format the effective profile consistently with the web
detail view, handling its absence as an unavailable/empty value, while
preserving the existing output fields.
🤖 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 `@crates/api-core/src/db_init.rs`:
- Around line 68-114: Normalize trailing dots consistently in
select_seed_network_domain when matching configured_domain_name: compare the
domain name after removing its trailing dot against the configured value using
the same normalization applied during forward-domain classification. Preserve
the existing single-match selection and fallback behavior, and add coverage for
a stored forward domain with a trailing dot and an undotted configured name.

---

Nitpick comments:
In `@crates/admin-cli/src/vpc/show/cmd.rs`:
- Around line 184-252: Update convert_vpc_to_nice_format to include
vpc.status.effective_routing_profile in the human-readable rows, alongside
ROUTING PROFILE TYPE and ROUTING PROFILE OVERRIDES. Serialize or format the
effective profile consistently with the web detail view, handling its absence as
an unavailable/empty value, while preserving the existing output fields.

In `@crates/api-core/src/cfg/file.rs`:
- Around line 2078-2084: Update the NotFoundError construction in
resolve_vpc_routing_profile to use kind "routing_profile", matching
resolve_vpc_routing for the same routing_profiles lookup, and update the
expected kind in vpc_routing_profile_resolution_reports_consistent_errors
accordingly.

In `@crates/api-core/src/handlers/vpc.rs`:
- Around line 698-920: Consolidate the repetitive `resolve_vpc_routing` tests
into a `carbide-test-support` `scenarios!` or equivalent table-driven scenario
covering their varied inputs and expected results, while keeping genuinely
distinct assertions standalone. Add a successful FNN-enabled overrides scenario
with a tenant profile, asserting the resolved `profile_type` and inherited
`internal` flag alongside the existing rejection and default cases.

In `@crates/rpc/src/model/vpc.rs`:
- Around line 175-219: Extract the duplicated route-target and prefix-entry
collection mappings into reusable From/TryFrom implementations for
rpc::forge::RouteTargets and rpc::forge::PrefixFilterPolicyEntries with their
corresponding Vec configuration types. Update both outbound and inbound
conversions in the relevant TryFrom/From implementations to use map(Into::into)
or the established conversion path, preserving prefix parsing errors and
existing field values.
- Around line 140-167: Update both prefix parsing closures in the profile
conversion to map parse failures into lowercase InvalidArgument errors instead
of relying on the existing RpcDataConversionError conversion. Include the
corresponding profile field name, raw prefix value, and parser error in each
message, preserving the current successful conversion and collection behavior
for accepted_leaks_from_underlay and allowed_anycast_prefixes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 4428bff3-4a0b-4726-aaca-a6c7b5cc3579

📥 Commits

Reviewing files that changed from the base of the PR and between 862a21d and 2392f2f.

📒 Files selected for processing (27)
  • crates/admin-cli/src/rpc.rs
  • crates/admin-cli/src/vpc/create/args.rs
  • crates/admin-cli/src/vpc/show/cmd.rs
  • crates/api-core/src/cfg/README.md
  • crates/api-core/src/cfg/file.rs
  • crates/api-core/src/db_init.rs
  • crates/api-core/src/ethernet_virtualization.rs
  • crates/api-core/src/handlers/vpc.rs
  • crates/api-core/src/setup.rs
  • crates/api-core/src/tests/common/api_fixtures/mod.rs
  • crates/api-core/src/tests/instance_allocate.rs
  • crates/api-core/src/tests/instance_config_update.rs
  • crates/api-core/src/tests/machine_network.rs
  • crates/api-core/src/tests/network_segment.rs
  • crates/api-core/src/tests/vpc.rs
  • crates/api-db/migrations/20260728120000_vpc_routing_profile_overrides.sql
  • crates/api-db/src/vpc.rs
  • crates/api-model/src/lib.rs
  • crates/api-model/src/vpc/capability.rs
  • crates/api-model/src/vpc/mod.rs
  • crates/api-model/src/vpc/routing_profile.rs
  • crates/api-web/src/vpc.rs
  • crates/api-web/templates/vpc_detail.html
  • crates/machine-a-tron/src/api_client.rs
  • crates/rpc/build.rs
  • crates/rpc/proto/forge.proto
  • crates/rpc/src/model/vpc.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/api-core/src/cfg/README.md

@bcavnvidia
bcavnvidia force-pushed the routing-profiles-overrides branch from 2392f2f to 8244e44 Compare July 31, 2026 14:08
@bcavnvidia
bcavnvidia marked this pull request as ready for review July 31, 2026 14:16
@bcavnvidia
bcavnvidia marked this pull request as draft July 31, 2026 14:16

@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

🧹 Nitpick comments (5)
crates/api-core/src/handlers/vpc.rs (3)

826-847: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add a scenario for an unset access_tier.

Line 640 and Line 641 both rely on unwrap_or_default() to map an absent access_tier to tier 0, the broadest tier. profile() always sets access_tier: Some(..), so no scenario pins that fallback. A profile that omits access_tier in configuration becomes maximally broad as a base and maximally restrictive as a tenant profile, which is a consequential default to leave untested.

💚 Suggested scenario addition
                 } => FailsWith(FailedPrecondition),
+                RoutingResolutionInput {
+                    network_virtualization_type: Fnn,
+                    requested_profile_type: Some("UNSET_TIER"),
+                    routing_profile_overrides: None,
+                    tenant: Some(tenant_with_profile(Some("EXTERNAL"))),
+                    fnn_config: Some(fnn_with_profiles(&[
+                        ("EXTERNAL", profile(false, 2)),
+                        ("UNSET_TIER", FnnRoutingProfileConfig {
+                            internal: Some(false),
+                            ..Default::default()
+                        }),
+                    ])),
+                    // An unset access tier resolves to the broadest tier `0`.
+                } => FailsWith(FailedPrecondition),
             }
🤖 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/handlers/vpc.rs` around lines 826 - 847, Add a
routing-resolution test scenario in the existing profile-access-tier cases
covering a profile with access_tier unset. Construct the relevant
profile/configuration without profile()’s explicit tier value, and assert the
resulting behavior verifies unwrap_or_default() maps the missing tier to 0 for
both base and tenant-profile resolution as applicable.

405-428: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider logging the discarded resolution error.

vpc_to_rpc discards the error from resolve_vpc_routing_profile with .ok(). Two distinct conditions collapse into the same empty result: a named profile removed from the configuration, and an FNN VPC persisted without routing_profile_type. Neither leaves a trace. A structured warning keeps the response contract unchanged and makes the condition observable.

♻️ Suggested refactor to record the suppressed error
         fnn_config.and_then(|fnn| {
             // A persisted VPC can outlive its named runtime profile. In that
             // case the status remains available without an effective profile.
             fnn.resolve_vpc_routing_profile(&vpc.config)
-                .ok()
+                .inspect_err(|error| {
+                    tracing::warn!(
+                        vpc_id = %vpc.id,
+                        %error,
+                        "Effective routing profile unresolved for VPC"
+                    );
+                })
+                .ok()
                 .map(|profile| rpc::VpcEffectiveRoutingProfile::from(profile.as_ref()))
         })
🤖 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/handlers/vpc.rs` around lines 405 - 428, Update
vpc_to_rpc’s resolve_vpc_routing_profile handling to preserve the existing None
response behavior while recording a structured warning when resolution returns
an error. Distinguish the error path from a successful resolution and include
sufficient VPC/profile context in the warning; leave successful profile
conversion and unsupported-network handling unchanged.

625-647: 🗄️ Data Integrity & Integration | 🔵 Trivial | 💤 Low value

Align the NotFoundError kind with the configuration resolver.

These lookups report kind: "routing_profile". FnnConfig::resolve_vpc_routing_profile in crates/api-core/src/cfg/file.rs reports kind: "routing_profile_type" for the same missing-profile condition, as does the VNI release path at Line 322 of this file. A client that keys on kind observes two different values for one failure mode. Select one identifier and use it in all three sites.

🤖 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/handlers/vpc.rs` around lines 625 - 647, Align the
missing-profile error identifiers in the VPC handler with the established value
used by FnnConfig::resolve_vpc_routing_profile and the VNI release path. Update
both NotFoundError constructions in the Some(fnn) branch to use the same kind
value, preserving their existing profile IDs and lookup behavior.
crates/api-core/src/tests/vpc.rs (2)

639-653: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Carry the error message into the expectation.

The closure collapses the error to a bool. When this test regresses, the report states only that true was expected and false was produced. The actual gRPC message is discarded, so the failure gives no diagnostic value. Map the error to its message and assert on the fragment so the report contains the observed text.

♻️ Suggested refactor for a self-describing failure
         |request| {
             let api = env.api.clone();
             async move {
                 api.create_vpc(request)
                     .await
                     .map(drop)
-                    .map_err(|error| {
-                        error.message().contains(
-                            "`routing_profile_type` and `routing_profile_overrides` fields are FNN-only",
-                        )
-                    })
+                    .map_err(|error| error.message().to_string())
             }
         },

Then assert the fragment in each Case expectation, for example with a helper that checks containment against the returned message.

🤖 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/vpc.rs` around lines 639 - 653, Update the
create_vpc error handling in the test closure to return the actual gRPC error
message, rather than collapsing it to a boolean via
error.message().contains(...). Adjust the corresponding Case expectations to
assert that the returned message contains the required “routing_profile_type”
and “routing_profile_overrides” fragment, preserving self-describing failure
output.

759-839: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add coverage for named-profile changes.

Create a VPC with a named profile, change that profile in the API configuration, then assert that find_vpcs_by_ids and update_vpc return the new effective_routing_profile. Existing assertions use one fixed profile configuration.

🤖 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/vpc.rs` around lines 759 - 839, Extend the test
around the existing VPC create/find/update flow to use a named routing profile,
then modify that profile through the API configuration before calling
find_vpcs_by_ids and update_vpc. Assert both responses expose the updated
effective_routing_profile rather than the original fixed expected profile, while
preserving the existing override and virtualization-transition assertions.
🤖 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 `@crates/api-core/src/handlers/vpc.rs`:
- Around line 598-602: Update the FailedPrecondition message in the (_, None)
match arm to accurately cover requests containing routing_profile_overrides as
well as a requested profile type, and replace “routing profile-type” with
“routing profile type.”

---

Nitpick comments:
In `@crates/api-core/src/handlers/vpc.rs`:
- Around line 826-847: Add a routing-resolution test scenario in the existing
profile-access-tier cases covering a profile with access_tier unset. Construct
the relevant profile/configuration without profile()’s explicit tier value, and
assert the resulting behavior verifies unwrap_or_default() maps the missing tier
to 0 for both base and tenant-profile resolution as applicable.
- Around line 405-428: Update vpc_to_rpc’s resolve_vpc_routing_profile handling
to preserve the existing None response behavior while recording a structured
warning when resolution returns an error. Distinguish the error path from a
successful resolution and include sufficient VPC/profile context in the warning;
leave successful profile conversion and unsupported-network handling unchanged.
- Around line 625-647: Align the missing-profile error identifiers in the VPC
handler with the established value used by
FnnConfig::resolve_vpc_routing_profile and the VNI release path. Update both
NotFoundError constructions in the Some(fnn) branch to use the same kind value,
preserving their existing profile IDs and lookup behavior.

In `@crates/api-core/src/tests/vpc.rs`:
- Around line 639-653: Update the create_vpc error handling in the test closure
to return the actual gRPC error message, rather than collapsing it to a boolean
via error.message().contains(...). Adjust the corresponding Case expectations to
assert that the returned message contains the required “routing_profile_type”
and “routing_profile_overrides” fragment, preserving self-describing failure
output.
- Around line 759-839: Extend the test around the existing VPC
create/find/update flow to use a named routing profile, then modify that profile
through the API configuration before calling find_vpcs_by_ids and update_vpc.
Assert both responses expose the updated effective_routing_profile rather than
the original fixed expected profile, while preserving the existing override and
virtualization-transition assertions.
🪄 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: 9251bbb3-b75a-4cf6-822e-d972df99613f

📥 Commits

Reviewing files that changed from the base of the PR and between 2392f2f and 8244e44.

⛔ Files ignored due to path filters (1)
  • rest-api/proto/core/gen/v1/nico_nico.pb.go is excluded by !**/*.pb.go, !**/gen/**, !rest-api/**/*.pb.go
📒 Files selected for processing (28)
  • crates/admin-cli/src/rpc.rs
  • crates/admin-cli/src/vpc/create/args.rs
  • crates/admin-cli/src/vpc/show/cmd.rs
  • crates/api-core/src/cfg/README.md
  • crates/api-core/src/cfg/file.rs
  • crates/api-core/src/db_init.rs
  • crates/api-core/src/ethernet_virtualization.rs
  • crates/api-core/src/handlers/vpc.rs
  • crates/api-core/src/setup.rs
  • crates/api-core/src/tests/common/api_fixtures/mod.rs
  • crates/api-core/src/tests/instance_allocate.rs
  • crates/api-core/src/tests/instance_config_update.rs
  • crates/api-core/src/tests/machine_network.rs
  • crates/api-core/src/tests/network_segment.rs
  • crates/api-core/src/tests/vpc.rs
  • crates/api-db/migrations/20260728120000_vpc_routing_profile_overrides.sql
  • crates/api-db/src/vpc.rs
  • crates/api-model/src/lib.rs
  • crates/api-model/src/vpc/capability.rs
  • crates/api-model/src/vpc/mod.rs
  • crates/api-model/src/vpc/routing_profile.rs
  • crates/api-web/src/vpc.rs
  • crates/api-web/templates/vpc_detail.html
  • crates/machine-a-tron/src/api_client.rs
  • crates/rpc/build.rs
  • crates/rpc/proto/forge.proto
  • crates/rpc/src/model/vpc.rs
  • rest-api/proto/core/src/v1/nico_nico.proto
🚧 Files skipped from review as they are similar to previous changes (22)
  • crates/admin-cli/src/vpc/create/args.rs
  • crates/api-core/src/tests/instance_config_update.rs
  • crates/api-model/src/vpc/capability.rs
  • crates/api-db/src/vpc.rs
  • crates/api-web/src/vpc.rs
  • crates/api-model/src/lib.rs
  • crates/api-core/src/tests/network_segment.rs
  • crates/rpc/src/model/vpc.rs
  • crates/admin-cli/src/vpc/show/cmd.rs
  • crates/admin-cli/src/rpc.rs
  • crates/api-core/src/setup.rs
  • crates/api-core/src/tests/machine_network.rs
  • crates/api-core/src/db_init.rs
  • crates/machine-a-tron/src/api_client.rs
  • crates/api-core/src/tests/instance_allocate.rs
  • crates/api-db/migrations/20260728120000_vpc_routing_profile_overrides.sql
  • crates/api-web/templates/vpc_detail.html
  • crates/rpc/build.rs
  • crates/api-core/src/cfg/file.rs
  • crates/api-model/src/vpc/routing_profile.rs
  • crates/api-model/src/vpc/mod.rs
  • crates/api-core/src/ethernet_virtualization.rs

Comment thread crates/api-core/src/handlers/vpc.rs
@bcavnvidia
bcavnvidia force-pushed the routing-profiles-overrides branch 2 times, most recently from efc8039 to 9297f4f Compare July 31, 2026 16:33
@bcavnvidia
bcavnvidia marked this pull request as ready for review July 31, 2026 16:33
@bcavnvidia
bcavnvidia force-pushed the routing-profiles-overrides branch from 9297f4f to 3b24ed9 Compare July 31, 2026 16:40
@bcavnvidia
bcavnvidia enabled auto-merge (squash) July 31, 2026 17:25
@bcavnvidia
bcavnvidia force-pushed the routing-profiles-overrides branch from 3b24ed9 to 28d8f6b Compare July 31, 2026 17:35
@bcavnvidia
bcavnvidia merged commit 8b9e44f into NVIDIA:main Jul 31, 2026
172 of 174 checks passed
@bcavnvidia
bcavnvidia deleted the routing-profiles-overrides branch July 31, 2026 19:20
polarweasel pushed a commit to polarweasel/infra-controller that referenced this pull request Jul 31, 2026
Adds create-time, per-VPC routing-profile overrides on top of named
routing-profiles.

Each explicitly supplied override replaces the corresponding
base-profile value, while omitted properties continue to inherit from
the named profile. The operator-controlled `internal` and `access_tier`
properties cannot be overridden at the VPC level.

The effective profile is resolved from the current API configuration and
persisted VPC overrides rather than stored separately, so API responses
reflect changes to the named base profile.

## Related issues
NVIDIA#2624

## Type of Change

- [x] **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

- [x] Unit tests added/updated
- [x] Integration tests added/updated
- [ ] Manual testing performed
- [ ] No testing required (docs, internal refactor, etc.)

## Additional Notes
NVIDIA#2624
Signed-off-by: Alex Ball <aball@nvidia.com>
bcavnvidia added a commit that referenced this pull request Aug 1, 2026
#4411 allows
routing-profiles overrides for VPC creation.

This PR continues the support through VPC updates. Similarly, each
explicitly supplied override replaces the corresponding base-profile
value, while omitted properties continue to inherit from the named
profile. The operator-controlled internal and access_tier properties
cannot be overridden at the VPC level.

Agent also has a minor update to include interface-level profiles in the
additional hashing it does to detect config changes.

## Related issues
#2624

## Type of Change
- [x] **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
- [x] Unit tests added/updated
- [ ] Integration tests added/updated
- [ ] Manual testing performed
- [ ] No testing required (docs, internal refactor, etc.)

## Additional Notes
#2624
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