Skip to content

feat: Added support for per-interface routing-profiles#591

Open
bcavnvidia wants to merge 1 commit into
NVIDIA:mainfrom
bcavnvidia:interface-profile
Open

feat: Added support for per-interface routing-profiles#591
bcavnvidia wants to merge 1 commit into
NVIDIA:mainfrom
bcavnvidia:interface-profile

Conversation

@bcavnvidia
Copy link
Copy Markdown
Contributor

Description

The Rust back-end now supports per-interface routing profiles to allow callers to further restrict anycast announcements between hosts and DPUs. This PR adds the related support to the REST API.

Type of Change

  • Feature - New feature or functionality (feat:)
  • Fix - Bug fixes (fix:)
  • Chore - Modification or removal of existing functionality (chore:)
  • Refactor - Refactoring of existing functionality (refactor:)
  • Docs - Changes in documentation or OpenAPI schema (docs:)
  • CI - Changes in GitHub workflows. Requires additional scrutiny (ci:)
  • Version - Issuing a new release version (version:)

Services Affected

  • API - API models or endpoints updated
  • Workflow - Workflow service updated
  • DB - DB DAOs or migrations updated
  • Site Manager - Site Manager updated
  • Cert Manager - Cert Manager updated
  • Site Agent - Site Agent updated
  • Flow - Flow service updated
  • Powershelf Manager - Powershelf Manager updated
  • NVSwitch Manager - NVSwitch Manager updated

Related Issues (Optional)

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

@bcavnvidia bcavnvidia requested a review from a team as a code owner May 30, 2026 01:20
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 30, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 513f1ef7-f73a-4b7e-9f6e-3855ac4df7f5

📥 Commits

Reviewing files that changed from the base of the PR and between 750f0bb and 941e092.

📒 Files selected for processing (6)
  • api/pkg/api/handler/instance.go
  • api/pkg/api/handler/instance_test.go
  • api/pkg/api/handler/instancebatch.go
  • api/pkg/api/handler/instancebatch_test.go
  • api/pkg/api/model/interface.go
  • api/pkg/api/model/interface_test.go
🚧 Files skipped from review as they are similar to previous changes (6)
  • api/pkg/api/handler/instancebatch_test.go
  • api/pkg/api/handler/instance.go
  • api/pkg/api/handler/instancebatch.go
  • api/pkg/api/model/interface.go
  • api/pkg/api/model/interface_test.go
  • api/pkg/api/handler/instance_test.go

Summary by CodeRabbit

  • New Features

    • Per-interface routing profile support (allowed anycast prefixes) across API, SDK models, DB, OpenAPI, instance create/update and batch flows, and controller propagation.
  • Bug Fixes

    • Improved file resource handling in the SDK client.
  • Migrations

    • Database migration to add a routing_profile JSONB column for interfaces.
  • Tests

    • Comprehensive tests covering routing profile behavior across creation, update, batch, and reconciliation paths.

Walkthrough

This pull request adds per-interface routing profile support (allowed anycast prefixes) end-to-end: API contract and validation, DB model + migration and DAO wiring, SDK model generation, instance handlers (single and batch), workflow reconciliation, OpenAPI updates, and tests.

Changes

Per-Interface Routing Profile Feature

Layer / File(s) Summary
API Interface Routing Profile Contract
api/pkg/api/model/interface.go, api/pkg/api/model/interface_test.go
Adds APIInterfaceRoutingProfile with CIDR validation, ToDBModel()/NewAPIInterfaceRoutingProfile(), integrates RoutingProfile into request/response models, and unit tests for validation and copy semantics.
Database Model and DAO Integration
db/pkg/db/model/interface.go, db/pkg/db/model/interface_test.go, db/pkg/migrations/20260529120000_interface_routing_profile.go
Adds InterfaceRoutingProfile DB type with proto converters; extends Interface, InterfaceCreateInput, InterfaceUpdateInput, InterfaceClearInput to persist/update/clear routing profiles; migration adds routing_profile JSONB; DAO code and tests updated for CRUD, batch-create, update, and clear semantics.
SDK Models
sdk/standard/model_interface_routing_profile.go, sdk/standard/model_interface.go, sdk/standard/model_interface_create_request.go
Generated SDK model InterfaceRoutingProfile plus nullable wrapper and accessors; Interface and InterfaceCreateRequest extended with RoutingProfile and generated accessor/mutator methods preserving explicit-nil semantics.
Instance Handlers (create/update & batch)
api/pkg/api/handler/instance.go, api/pkg/api/handler/instance_test.go, api/pkg/api/handler/instancebatch.go, api/pkg/api/handler/instancebatch_test.go
Handlers convert API RoutingProfile to DB model for interfaces, persist it via InterfaceCreateInput, and set proto RoutingProfile on InstanceInterfaceConfig when present; tests assert API responses, DB rows, and Site Controller/Temporal requests contain routing profile prefixes.
Workflow Reconciliation Activity
workflow/pkg/activity/instance/instance.go, workflow/pkg/activity/instance/instance_test.go
UpdateInstancesInDB now reconciles controller interface RoutingProfile: constructs proto->DB routingProfile, conditionally clears routing_profile via InterfaceClearInput, and includes it in InterfaceUpdateInput; tests validate persistence and clearing behavior.
OpenAPI Specification
openapi/spec.yaml
Adds InterfaceRoutingProfile schema and clarifies routingProfile and explicitly-requested IP rules apply only to VPC Prefix-based interfaces.
SDK Utilities & Formatting
sdk/standard/client.go, sdk/standard/model_*.go
Minor client multipart close refactor and generated model whitespace/formatting updates without functional changes.

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.77% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically summarizes the primary change: adding per-interface routing-profile support. It directly relates to the substantial changeset involving API models, DB layers, and workflow integration.
Description check ✅ Passed The description clearly articulates the feature intent, identifies it as adding REST API support for per-interface routing profiles, properly categorizes it as a Feature type change, and specifies affected services (API, Workflow, DB) with testing coverage indicated.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@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-05-30 01:21:24 UTC | Commit: 750f0bb

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
openapi/spec.yaml (2)

16646-16651: 💤 Low value

Align description terminology with the Interface schema.

The descriptions for requestedIpAddress and routingProfile in InterfaceCreateRequest use "cannot be specified for Subnet-based interfaces", while the corresponding fields in the Interface component schema (hunk 1, lines 16582 and 16587) use "not valid for Subnet-based interfaces" and "Only valid for VPC Prefix-based interfaces". Consistent terminology across request and response schemas improves clarity.

📝 Suggested alignment
-          description: Explicitly requested IP address for the interface. It cannot be specified for Subnet-based interfaces. The least-significant host bit must be 1.
+          description: Explicitly requested IP address for the interface. This is only used for VPC Prefix-based interfaces and is not valid for Subnet-based interfaces. The least-significant host bit must be 1.
-          description: Interface-local routing profile options. It cannot be specified for Subnet-based interfaces.
+          description: Interface-local routing profile options. Only valid for VPC Prefix-based interfaces.
🤖 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 `@openapi/spec.yaml` around lines 16646 - 16651, The descriptions in
InterfaceCreateRequest for requestedIpAddress and routingProfile are
inconsistent with the Interface component; update the description text for
requestedIpAddress and routingProfile inside the InterfaceCreateRequest schema
to match the terminology used in the Interface component (e.g., use "not valid
for Subnet-based interfaces" for requestedIpAddress and "Only valid for VPC
Prefix-based interfaces" or equivalent for routingProfile) so both request and
response schemas use the same phrases and meaning.

16613-16619: ⚡ Quick win

Add pattern validation for CIDR prefixes.

The allowedAnycastPrefixes array items lack format or pattern constraints. Without a pattern, clients may submit invalid CIDR strings, leading to runtime validation failures. Consider adding a pattern constraint to guide client-side validation.

📐 Proposed enhancement with CIDR pattern validation
         allowedAnycastPrefixes:
           type: array
           description: CIDR prefixes this interface is allowed to announce as anycast routes.
           default: []
           items:
             type: string
+            pattern: '^([0-9]{1,3}\.){3}[0-9]{1,3}/([0-9]|[1-2][0-9]|3[0-2])$'
             example: 192.0.2.0/24

Alternatively, if the pattern becomes complex (e.g., to enforce valid IPv4 octets), add a description note:

         allowedAnycastPrefixes:
           type: array
-          description: CIDR prefixes this interface is allowed to announce as anycast routes.
+          description: CIDR prefixes this interface is allowed to announce as anycast routes. Each prefix must be a valid IPv4 CIDR notation (e.g., 192.0.2.0/24). Server-side validation enforces CIDR format compliance.
           default: []
           items:
             type: string
             example: 192.0.2.0/24
🤖 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 `@openapi/spec.yaml` around lines 16613 - 16619, The items of the
allowedAnycastPrefixes array lack validation; add a pattern constraint under
allowedAnycastPrefixes -> items to validate CIDR strings (e.g., a regex that
enforces IPv4 octets and a /prefix length like
^((25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\/([0-9]|[12][0-9]|3[0-2])$),
and update the items description to mention the required CIDR format so clients
can do client-side validation before sending values to allowedAnycastPrefixes.
🤖 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 `@api/pkg/api/model/interface.go`:
- Around line 67-75: The validation currently stops at the first bad prefix and
returns a capitalized error string; replace the manual loop over
rp.AllowedAnycastPrefixes with ozzo-validation's validation.Each combined with
validation.By so every element is validated (using netip.ParsePrefix) and
aggregated, and change the error text to start lowercase (e.g. "invalid anycast
prefix `%s`") while keeping the field key "allowedAnycastPrefixes" to match
tests; update the validation logic referenced by rp.AllowedAnycastPrefixes to
use validation.Each(validation.By(...)) that calls netip.ParsePrefix and returns
the lowercase error message for each invalid element.

In `@sdk/standard/model_interface_routing_profile.go`:
- Around line 1-7: The file sdk/standard/model_interface_routing_profile.go is
missing the SPDX-FileCopyrightText header present in other generated model files
(e.g., model_interface.go and model_interface_create_request.go); rebase onto
the latest main and re-run the SDK generator (make generate-sdk) so the SPDX
header injection script adds the header to model_interface_routing_profile.go,
then verify the header matches the other model files and commit the regenerated
SDK.

---

Nitpick comments:
In `@openapi/spec.yaml`:
- Around line 16646-16651: The descriptions in InterfaceCreateRequest for
requestedIpAddress and routingProfile are inconsistent with the Interface
component; update the description text for requestedIpAddress and routingProfile
inside the InterfaceCreateRequest schema to match the terminology used in the
Interface component (e.g., use "not valid for Subnet-based interfaces" for
requestedIpAddress and "Only valid for VPC Prefix-based interfaces" or
equivalent for routingProfile) so both request and response schemas use the same
phrases and meaning.
- Around line 16613-16619: The items of the allowedAnycastPrefixes array lack
validation; add a pattern constraint under allowedAnycastPrefixes -> items to
validate CIDR strings (e.g., a regex that enforces IPv4 octets and a /prefix
length like
^((25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\/([0-9]|[12][0-9]|3[0-2])$),
and update the items description to mention the required CIDR format so clients
can do client-side validation before sending values to allowedAnycastPrefixes.
🪄 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: f988646a-5096-4478-b39f-4fa7c4224d3a

📥 Commits

Reviewing files that changed from the base of the PR and between 0451d4c and 750f0bb.

⛔ Files ignored due to path filters (2)
  • workflow-schema/schema/site-agent/workflows/v1/nico_nico.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • workflow-schema/site-agent/workflows/v1/nico_nico.proto is excluded by !workflow-schema/site-agent/workflows/v1/*_nico.proto
📒 Files selected for processing (36)
  • api/pkg/api/handler/instance.go
  • api/pkg/api/handler/instance_test.go
  • api/pkg/api/handler/instancebatch.go
  • api/pkg/api/handler/instancebatch_test.go
  • api/pkg/api/model/interface.go
  • api/pkg/api/model/interface_test.go
  • db/pkg/db/model/interface.go
  • db/pkg/db/model/interface_test.go
  • db/pkg/migrations/20260529120000_interface_routing_profile.go
  • docs/index.html
  • openapi/spec.yaml
  • sdk/standard/client.go
  • sdk/standard/model_expected_machine.go
  • sdk/standard/model_expected_machine_create_request.go
  • sdk/standard/model_expected_machine_update_request.go
  • sdk/standard/model_expected_power_shelf.go
  • sdk/standard/model_expected_power_shelf_create_request.go
  • sdk/standard/model_expected_power_shelf_update_request.go
  • sdk/standard/model_expected_rack.go
  • sdk/standard/model_expected_rack_create_request.go
  • sdk/standard/model_expected_rack_update_request.go
  • sdk/standard/model_expected_switch.go
  • sdk/standard/model_expected_switch_create_request.go
  • sdk/standard/model_expected_switch_update_request.go
  • sdk/standard/model_infini_band_partition.go
  • sdk/standard/model_infini_band_partition_create_request.go
  • sdk/standard/model_infini_band_partition_update_request.go
  • sdk/standard/model_interface.go
  • sdk/standard/model_interface_create_request.go
  • sdk/standard/model_interface_routing_profile.go
  • sdk/standard/model_machine_update_request.go
  • sdk/standard/model_vpc.go
  • sdk/standard/model_vpc_create_request.go
  • sdk/standard/model_vpc_update_request.go
  • workflow/pkg/activity/instance/instance.go
  • workflow/pkg/activity/instance/instance_test.go

Comment thread api/pkg/api/model/interface.go Outdated
Comment thread sdk/standard/model_interface_routing_profile.go
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 30, 2026

🔍 Container Scan Summary

Service Total Critical High Medium Low Other
nico-flow 66 4 34 18 2 8
nico-nsm 82 2 28 43 9 0
nico-psm 67 4 35 18 2 8
nico-rest-api 100 6 53 30 3 8
nico-rest-cert-manager 65 4 34 18 1 8
nico-rest-db 66 4 34 18 2 8
nico-rest-site-agent 65 4 34 18 1 8
nico-rest-site-manager 65 4 34 18 1 8
nico-rest-workflow 67 4 35 18 2 8
TOTAL 643 36 321 199 23 64

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

@bcavnvidia bcavnvidia force-pushed the interface-profile branch from 750f0bb to 941e092 Compare May 30, 2026 02:02
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.

1 participant