Skip to content
This repository was archived by the owner on Jun 2, 2026. It is now read-only.

feat: Infer Provider/Tenant from caller's org across Tenant Account #603

Draft
parmani-nv wants to merge 1 commit into
NVIDIA:mainfrom
parmani-nv:feat/tenant-handler-inferId
Draft

feat: Infer Provider/Tenant from caller's org across Tenant Account #603
parmani-nv wants to merge 1 commit into
NVIDIA:mainfrom
parmani-nv:feat/tenant-handler-inferId

Conversation

@parmani-nv

Copy link
Copy Markdown
Contributor

…andlers

Description

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

@copy-pr-bot

copy-pr-bot Bot commented Jun 1, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: e84aa6cf-603a-4b2b-97f3-9fa2dc6c9319

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

This PR shifts API handlers, request models, and generated SDK code from explicit infrastructureProviderId/tenantId parameters to inferring Infrastructure Provider and Tenant from caller org membership. Tenant account creation now requires tenantOrg instead of infrastructureProviderId; instance models make tenantId optional. SDK pagination behavior refactored to avoid sending default pageNumber query parameters.

Changes

Tenant Account Handler & Model Refactoring

Layer / File(s) Summary
Handler authorization & listing logic
api/pkg/api/handler/tenantaccount.go
CreateTenantAccountHandler infers InfrastructureProviderID from org when omitted. GetAllTenantAccountHandler removes required-param validation, infers provider/tenant via common.IsProviderOrTenant, supports optional tenant narrowing, fetches from both perspectives, de-duplicates via mapset, and queries merged IDs. GetTenantAccountHandler removes org-validation block, uses explicit provider/tenant matching for authorization, and per-account allocation counting via AllocationDAO.GetCount.
Model validation & database filtering
api/pkg/api/model/tenantaccount.go, db/pkg/db/model/tenantaccount.go
APITenantAccountCreateRequest.Validate conditionally applies UUID validation only when InfrastructureProviderID is non-empty. TenantAccountFilterInput gains TenantAccountIDs field; DAO query builder applies single-ID or IN-clause filtering and sets tracer attributes.
Handler test fixtures & assertions
api/pkg/api/handler/tenantaccount_test.go, api/pkg/api/model/tenantaccount_test.go
Tests verify creation succeeds when infrastructureProviderId is omitted. Negative cases for missing/invalid query parameters removed. Authorization mismatches now expect 403 Forbidden. Test fixtures extended with second site and allocation. Validation test case confirms infrastructureProviderId omission is valid.

SDK Request Model Constructors & Field Types

Layer / File(s) Summary
Tenant account & instance request models
sdk/standard/model_tenant_account_create_request.go, sdk/standard/model_instance_create_request.go, sdk/standard/model_batch_instance_create_request.go
TenantAccountCreateRequest constructor drops infrastructureProviderId parameter; field type changed to *string with omitempty. InstanceCreateRequest and BatchInstanceCreateRequest drop tenantId from constructors, change fields to *string. Accessor methods updated for nil-safe pointer semantics. JSON marshaling/unmarshaling updated: conditional field inclusion and removed required-field checks.
SDK compatibility wrappers
sdk/standard/compat/instance_create.go
NewInstanceCreateRequestWithInterfaces and NewBatchInstanceCreateRequestWithInterfaces drop tenantId from constructor calls; conditionally apply tenantId via SetTenantId when provided, then set interfaces.

SDK API Deprecation Documentation & Pagination Refactoring

Layer / File(s) Summary
Handler & endpoint Swagger documentation
api/pkg/api/handler/ipblock.go
IP block handler endpoints mark infrastructureProviderId and tenantId query parameters as optional and deprecated.
SDK API client deprecation comments
sdk/standard/api_allocation.go, sdk/standard/api_instance_type.go, sdk/standard/api_ip_block.go, sdk/standard/api_site.go, sdk/standard/api_tenant_account.go
Request builder deprecation comments and operation descriptions updated across services to state Infrastructure Provider / Tenant is inferred from org membership.
SDK pagination query parameter behavior
sdk/standard/api_*.go (~30 files)
Across allocation, audit, DPU extension, expected machine/power shelf/rack/switch, infiniband, instance, instance type, IP block, machine, network security group, nvlink, operating system, rack, site, SKU, SSH key, SSH key group, subnet, tenant account, tray, VPC, VPC peering, VPC prefix services: when pageNumber (or activeOnly) is unset, defaults assigned to request fields only; no longer added to localVarQueryParams.

OpenAPI Specification & CLI Updates

Layer / File(s) Summary
OpenAPI endpoint & schema definitions
openapi/spec.yaml
Query parameters infrastructureProviderId and tenantId marked deprecated across tenant accounts, allocations, sites, instance types, IP blocks endpoints with "inferred from org membership" descriptions. Tenant account create request schema: infrastructureProviderId deprecated, new tenantOrg field added (pattern/minLength) and required. Instance/batch-instance schemas: tenantId deprecated and removed from required lists.
CLI tenant account creation
cli/tui/commands.go
cmdTenantAccountCreate now prompts only for tenantOrg; infrastructureProviderId prompt and body entry removed.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

The PR spans multiple layers of significant behavioral changes: handler authorization logic refactoring with org-membership inference, request model constructor signature changes affecting API contracts, widespread pagination behavior refactoring across ~30 SDK generated files, and comprehensive OpenAPI specification updates. While many individual SDK pagination changes are repetitive, the handler logic (especially GetAllTenantAccountHandler merging logic) and model changes require careful validation of pointer semantics, nil handling, and backward compatibility. The substantial cross-cutting impact on authorization flows and request validation demands careful review.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 53.85% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description field contains only an empty PR template with unchecked boxes and no substantive details about the implementation, testing, or impact. Provide a meaningful description documenting the implementation approach, affected endpoints, validation changes, deprecation strategy, and testing methodology for stakeholder context.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main feature: inferring Provider/Tenant context from the caller's organization across Tenant Account handlers. This aligns well with the extensive changeset.
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.

@parmani-nv

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@parmani-nv

Copy link
Copy Markdown
Contributor Author

/ok to test 0e16f06

@github-actions

github-actions Bot commented Jun 2, 2026

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-06-02 00:04:04 UTC | Commit: 0e16f06

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

Caution

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

⚠️ Outside diff range comments (1)
sdk/standard/client.go (1)

588-605: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

File closed before being read; multipart uploads will fail.

The refactored error handling closes the file at line 593, but io.Copy(part, file) at line 602 attempts to read from the closed file descriptor. This will cause all multipart file uploads to fail with a "file already closed" or "bad file descriptor" error.

🔧 Proposed fix: Move close after io.Copy
 func addFile(w *multipart.Writer, fieldName, path string) error {
 	file, err := os.Open(filepath.Clean(path))
 	if err != nil {
 		return err
 	}
-	err = file.Close()
-	if err != nil {
-		return err
-	}
+	defer file.Close()
 
 	part, err := w.CreateFormFile(fieldName, filepath.Base(path))
 	if err != nil {
 		return err
 	}
 	_, err = io.Copy(part, file)
 
 	return err
 }
🤖 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 `@sdk/standard/client.go` around lines 588 - 605, The file is being closed
before it is read in addFile; move the file.Close so the file remains open for
io.Copy(part, file) (e.g., open the file in addFile, defer file.Close()
immediately after successful open or call Close after io.Copy completes) and
ensure error handling still returns any errors from io.Copy, referencing the
addFile function, the multipart.Writer usage, w.CreateFormFile, io.Copy, and
file.Close.
🧹 Nitpick comments (2)
api/pkg/api/handler/tenantaccount_test.go (1)

780-941: ⚡ Quick win

Add a dual-role org-membership case for this auth refactor.

The updated handlers now depend on combined provider/tenant visibility, but the suite still only exercises single-role callers. Please add a case where the same caller is authorized through both paths, especially for GetAll, so a regression back to first-match short-circuiting is caught. Based on learnings: "RBAC should not short-circuit on the first matching role ... Evaluate both authorization paths independently ... Add tests covering mixed-role scenarios ..."

Also applies to: 1114-1497

🤖 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 `@api/pkg/api/handler/tenantaccount_test.go` around lines 780 - 941, Add a test
case exercising a dual-role org membership (caller authorized as both provider
and tenant) to the tests table used by the GetAll/Get handlers: create or use a
user that has both provider and tenant roles (e.g., a new dualRoleUser composed
from ipUser and tnUser roles), add an entry in the tests slice with that user,
set reqOrgName to the org that gives both visibilities (e.g., ipOrg1/tnOrg1 as
appropriate), provide the same expected success fields as the single-role
success cases (expectedStatus http.StatusOK, expectedID ta11.ID.String(),
expectedTenantOrg/expectedInfrastructureProviderOrg, expectedTenantContact,
expectedAllocationCount, verifyChildSpanner where applicable), and replicate the
same dual-role test addition in the other table blocks referenced (lines
1114-1497) so mixed-role authorization regressions are caught.
cli/tui/commands.go (1)

2313-2321: ⚡ Quick win

Make the org-based inference explicit in the prompt.

This flow intentionally omits infrastructureProviderId, but the interactive text does not say that the provider is inferred from the current org. A short note here would make the changed workflow self-explanatory for operators.

♻️ Proposed tweak
 func cmdTenantAccountCreate(s *Session, _ []string) error {
-	tenantOrg, err := PromptText("Tenant org", true)
+	tenantOrg, err := PromptText("Tenant org (infrastructure provider inferred from current org)", true)
 	if err != nil {
 		return err
 	}

As per coding guidelines, "Document when you have intentionally omitted code that the reader might otherwise expect to be present".

🤖 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 `@cli/tui/commands.go` around lines 2313 - 2321, Update the interactive prompt
in cmdTenantAccountCreate to explicitly state that the infrastructure provider
is inferred from the current org: change the PromptText call and/or its prompt
string (the "Tenant org" prompt passed to PromptText) to include a short note
like "(infrastructure provider will be inferred from current org)" so operators
know why infrastructureProviderId is omitted; keep the same trimming and LogCmd
usage but ensure the new prompt text is used when constructing the body and
logging.
🤖 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/handler/ipblock.go`:
- Around line 269-270: Update the Swagger param descriptions for the query
params infrastructureProviderId and tenantId in api/pkg/api/handler/ipblock.go
to state that these params are deprecated and are ignored for authorization
because the handler now derives Provider/Tenant context from the org claim
(i.e., authorization is based on org-derived context, not these query params);
adjust the same deprecated text for the other occurrence in this file (the other
param block) and ensure the OpenAPI schema files under the openapi/ directory
(and any api*.go swagger comments) are updated to reflect that org-based
inference is used instead of these query params.

In `@api/pkg/api/handler/tenantaccount.go`:
- Around line 399-413: The per-row call to aDAO.GetCount inside the loop causes
N DB round-trips; instead, collect all (InfrastructureProviderID, TenantID)
pairs for rows where TenantID != nil while iterating over tas, call a new or
existing batched DAO method (e.g., Add/GetCountsForTenantPairs or GetCounts(ctx,
nil, []AllocationFilterInput)) once to return a map keyed by
(infrastructure_provider_id,tenant_id) -> count, then in the loop look up
allocCount from that map and pass it to model.NewAPITenantAccount; update or add
the DAO method signature and its call-site to accept the slice of filter inputs
and return the counts mapping, and use ssdMap[ta.ID.String()] and
tmpTa.ID/tenant fields unchanged when mapping results back.
- Around line 340-372: The current handler materializes all matching
tenant-account IDs by calling taDAO.GetAll up to twice then merging IDs in
memory (mergedTenantAccountIDs), causing full scans before pagination; instead,
extend the DAO query to perform the provider/tenant union in SQL and call
taDAO.GetAll only once. Update the TenantAccountFilterInput (and its use in
taDAO.GetAll) to accept an InfrastructureProviderID and/or TenantID (or a
combined flag) and implement the SQL logic in the DAO to apply an OR/UNION
between provider-scoped and tenant-scoped rows so count and LIMIT/OFFSET are
executed by the database; remove the in-handler loops and mergedTenantAccountIDs
usage and pass the new combined filter into taDAO.GetAll with
pageRequest.ConvertToDB() and qIncludeRelations so pagination and total are
computed in SQL. Ensure existing callers of taDAO.GetAll remain compatible or
are updated to the new filter fields.

In `@openapi/spec.yaml`:
- Around line 536-540: The tenantId query parameter is declared as a scalar
string but the description says it may be supplied multiple times; update the
parameter definition to be an array: replace the scalar schema with schema:
type: array, items: { type: string, format: uuid } and add query serialization
metadata (e.g., style: form and explode: true) so repeated tenantId query params
are modeled correctly; locate the parameter by the name "tenantId" in the
OpenAPI parameter block and modify its schema and serialization settings
accordingly.
- Around line 13122-13126: The tenantOrg schema's regex pattern
'^[A-Za-z0-9-_]+$' can treat '-' as a range operator; update the pattern in
openapi/spec.yaml for the tenantOrg property to make the hyphen literal (e.g.,
move '-' to the end or escape it) so it becomes something like
'^[A-Za-z0-9_-]+$' ensuring only letters, digits, underscore, and hyphen are
allowed.

In `@sdk/standard/api_site.go`:
- Around line 304-312: The generated setter doc comments emit a standalone "//
Deprecated" line which Go tooling ignores; update the OpenAPI
generator/template/spec so the doc-comment paragraph for setters like
ApiGetAllSiteRequest.InfrastructureProviderId (and the Tenant ID setter) begins
with "Deprecated:" followed by the message (e.g., "Deprecated: Infrastructure
Provider is now inferred...") instead of a separate "// Deprecated" line; modify
the template that renders method comments to prepend "Deprecated: " to the
deprecation sentence so the full paragraph starts with "Deprecated:".

In `@sdk/standard/compat/instance_create.go`:
- Around line 19-50: The compat layer is missing shims for the removed/changed
exported constructors (notably NewTenantAccountCreateRequest) so callers relying
on old arities break; add deprecated wrapper functions in sdk/standard/compat
that preserve the old signatures and delegate to the new constructors (similar
to NewInstanceCreateRequestWithInterfaces and
NewBatchInstanceCreateRequestWithInterfaces): implement
NewTenantAccountCreateRequest(oldTenantOrg string) that calls the new
standard.NewTenantAccountCreateRequest(...) API or constructs a
standard.TenantAccountCreateRequest and sets fields as needed, and if you
removed any other overloaded constructors restore them as deprecated wrappers
that call standard.NewInstanceCreateRequest,
standard.NewBatchInstanceCreateRequest, etc., and apply any missing SetX methods
(e.g., SetTenantId, SetInterfaces) so existing callers continue to work while
marking these shims deprecated.

---

Outside diff comments:
In `@sdk/standard/client.go`:
- Around line 588-605: The file is being closed before it is read in addFile;
move the file.Close so the file remains open for io.Copy(part, file) (e.g., open
the file in addFile, defer file.Close() immediately after successful open or
call Close after io.Copy completes) and ensure error handling still returns any
errors from io.Copy, referencing the addFile function, the multipart.Writer
usage, w.CreateFormFile, io.Copy, and file.Close.

---

Nitpick comments:
In `@api/pkg/api/handler/tenantaccount_test.go`:
- Around line 780-941: Add a test case exercising a dual-role org membership
(caller authorized as both provider and tenant) to the tests table used by the
GetAll/Get handlers: create or use a user that has both provider and tenant
roles (e.g., a new dualRoleUser composed from ipUser and tnUser roles), add an
entry in the tests slice with that user, set reqOrgName to the org that gives
both visibilities (e.g., ipOrg1/tnOrg1 as appropriate), provide the same
expected success fields as the single-role success cases (expectedStatus
http.StatusOK, expectedID ta11.ID.String(),
expectedTenantOrg/expectedInfrastructureProviderOrg, expectedTenantContact,
expectedAllocationCount, verifyChildSpanner where applicable), and replicate the
same dual-role test addition in the other table blocks referenced (lines
1114-1497) so mixed-role authorization regressions are caught.

In `@cli/tui/commands.go`:
- Around line 2313-2321: Update the interactive prompt in cmdTenantAccountCreate
to explicitly state that the infrastructure provider is inferred from the
current org: change the PromptText call and/or its prompt string (the "Tenant
org" prompt passed to PromptText) to include a short note like "(infrastructure
provider will be inferred from current org)" so operators know why
infrastructureProviderId is omitted; keep the same trimming and LogCmd usage but
ensure the new prompt text is used when constructing the body and logging.
🪄 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: 360f474d-add4-4dc8-b414-0f27673e2d27

📥 Commits

Reviewing files that changed from the base of the PR and between d3a07c6 and 0e16f06.

📒 Files selected for processing (60)
  • api/pkg/api/handler/ipblock.go
  • api/pkg/api/handler/tenantaccount.go
  • api/pkg/api/handler/tenantaccount_test.go
  • api/pkg/api/model/tenantaccount.go
  • api/pkg/api/model/tenantaccount_test.go
  • cli/tui/commands.go
  • db/pkg/db/model/tenantaccount.go
  • docs/index.html
  • openapi/spec.yaml
  • sdk/standard/api_allocation.go
  • sdk/standard/api_audit.go
  • sdk/standard/api_dpu_extension_service.go
  • sdk/standard/api_expected_machine.go
  • sdk/standard/api_expected_power_shelf.go
  • sdk/standard/api_expected_rack.go
  • sdk/standard/api_expected_switch.go
  • sdk/standard/api_infini_band_partition.go
  • sdk/standard/api_instance.go
  • sdk/standard/api_instance_type.go
  • sdk/standard/api_ip_block.go
  • sdk/standard/api_machine.go
  • sdk/standard/api_network_security_group.go
  • sdk/standard/api_nv_link_logical_partition.go
  • sdk/standard/api_operating_system.go
  • sdk/standard/api_rack.go
  • sdk/standard/api_site.go
  • sdk/standard/api_sku.go
  • sdk/standard/api_ssh_key.go
  • sdk/standard/api_ssh_key_group.go
  • sdk/standard/api_subnet.go
  • sdk/standard/api_tenant_account.go
  • sdk/standard/api_tray.go
  • sdk/standard/api_vpc.go
  • sdk/standard/api_vpc_peering.go
  • sdk/standard/api_vpc_prefix.go
  • sdk/standard/client.go
  • sdk/standard/compat/instance_create.go
  • sdk/standard/model_batch_instance_create_request.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_instance_create_request.go
  • sdk/standard/model_instance_update_request.go
  • sdk/standard/model_machine_update_request.go
  • sdk/standard/model_tenant_account_create_request.go
  • sdk/standard/model_vpc.go
  • sdk/standard/model_vpc_create_request.go
  • sdk/standard/model_vpc_update_request.go
💤 Files with no reviewable changes (21)
  • sdk/standard/api_expected_power_shelf.go
  • sdk/standard/api_operating_system.go
  • sdk/standard/api_expected_machine.go
  • sdk/standard/api_dpu_extension_service.go
  • sdk/standard/api_ssh_key.go
  • sdk/standard/api_vpc.go
  • sdk/standard/api_nv_link_logical_partition.go
  • sdk/standard/api_expected_switch.go
  • sdk/standard/api_sku.go
  • sdk/standard/api_vpc_prefix.go
  • sdk/standard/api_rack.go
  • sdk/standard/api_ssh_key_group.go
  • sdk/standard/api_vpc_peering.go
  • sdk/standard/api_infini_band_partition.go
  • sdk/standard/api_expected_rack.go
  • sdk/standard/api_machine.go
  • sdk/standard/api_subnet.go
  • sdk/standard/api_tray.go
  • sdk/standard/api_network_security_group.go
  • sdk/standard/api_instance.go
  • sdk/standard/api_audit.go

Comment thread api/pkg/api/handler/ipblock.go Outdated
Comment on lines +269 to +270
// @Param infrastructureProviderId query string false "Deprecated: ID of Infrastructure Provider"
// @Param tenantId query string false "Deprecated: ID of Tenant"

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Document org-based inference in these deprecated query params.

These descriptions only say the params are deprecated, but the handler now derives Provider/Tenant context from org and ignores these query params for authorization. Please spell that out here as well so the generated Swagger is unambiguous.

As per coding guidelines, {**/*api*.go,openapi/**/*.{yml,yaml,json}}: Update OpenAPI schema whenever API endpoints are added or updated.

Also applies to: 747-748

🤖 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 `@api/pkg/api/handler/ipblock.go` around lines 269 - 270, Update the Swagger
param descriptions for the query params infrastructureProviderId and tenantId in
api/pkg/api/handler/ipblock.go to state that these params are deprecated and are
ignored for authorization because the handler now derives Provider/Tenant
context from the org claim (i.e., authorization is based on org-derived context,
not these query params); adjust the same deprecated text for the other
occurrence in this file (the other param block) and ensure the OpenAPI schema
files under the openapi/ directory (and any api*.go swagger comments) are
updated to reflect that org-based inference is used instead of these query
params.

Comment on lines +340 to +372
mergedTenantAccountIDs := mapset.NewSet[uuid.UUID]()
totalLimitPage := cdbp.PageInput{Limit: cdb.GetIntPtr(cdbp.TotalLimit)}

if provider != nil {
providerFilter := sharedFilter
providerFilter.InfrastructureProviderID = &provider.ID
providerFilter.TenantIDs = filterTenantIDs
tenantAccountsFromProviderPerspective, _, err := taDAO.GetAll(ctx, nil, providerFilter, totalLimitPage, nil)
if err != nil {
logger.Error().Err(err).Msg("error getting TenantAccounts from Provider perspective")
return cutil.NewAPIErrorResponse(c, http.StatusInternalServerError, "Failed to retrieve TenantAccounts, DB error", nil)
}
for _, tenantAccount := range tenantAccountsFromProviderPerspective {
mergedTenantAccountIDs.Add(tenantAccount.ID)
}
}

filter := cdbm.TenantAccountFilterInput{
InfrastructureProviderID: infrastructureProviderID,
TenantIDs: tenantIDs,
Statuses: statuses,
SearchQuery: searchQuery,
if tenant != nil {
tenantFilter := sharedFilter
tenantFilter.TenantIDs = []uuid.UUID{tenant.ID}
tenantAccountsFromTenantPerspective, _, err := taDAO.GetAll(ctx, nil, tenantFilter, totalLimitPage, nil)
if err != nil {
logger.Error().Err(err).Msg("error getting TenantAccounts from Tenant perspective")
return cutil.NewAPIErrorResponse(c, http.StatusInternalServerError, "Failed to retrieve TenantAccounts, DB error", nil)
}
for _, tenantAccount := range tenantAccountsFromTenantPerspective {
mergedTenantAccountIDs.Add(tenantAccount.ID)
}
}

tas, total, err := taDAO.GetAll(ctx, nil, filter, cdbp.PageInput{
Offset: pageRequest.Offset,
Limit: pageRequest.Limit,
OrderBy: pageRequest.OrderBy,
}, qIncludeRelations)
tas, total, err := taDAO.GetAll(ctx, nil, cdbm.TenantAccountFilterInput{
TenantAccountIDs: mergedTenantAccountIDs.ToSlice(),
}, pageRequest.ConvertToDB(), qIncludeRelations)

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.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Push the provider/tenant union into SQL before paginating.

This path now does up to three GetAll calls and materializes every matching tenant-account ID before the page limit is applied. Large orgs will pay the full scan and memory cost even for page 1. Please move the provider/tenant union into the DAO query so count and pagination happen in SQL.

🤖 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 `@api/pkg/api/handler/tenantaccount.go` around lines 340 - 372, The current
handler materializes all matching tenant-account IDs by calling taDAO.GetAll up
to twice then merging IDs in memory (mergedTenantAccountIDs), causing full scans
before pagination; instead, extend the DAO query to perform the provider/tenant
union in SQL and call taDAO.GetAll only once. Update the
TenantAccountFilterInput (and its use in taDAO.GetAll) to accept an
InfrastructureProviderID and/or TenantID (or a combined flag) and implement the
SQL logic in the DAO to apply an OR/UNION between provider-scoped and
tenant-scoped rows so count and LIMIT/OFFSET are executed by the database;
remove the in-handler loops and mergedTenantAccountIDs usage and pass the new
combined filter into taDAO.GetAll with pageRequest.ConvertToDB() and
qIncludeRelations so pagination and total are computed in SQL. Ensure existing
callers of taDAO.GetAll remain compatible or are updated to the new filter
fields.

Comment on lines 399 to +413
for _, ta := range tas {
tmpTa := ta
// Check for Allocation for Tenant
total := 0
allocCount := 0
if tmpTa.TenantID != nil {
total = allocationCountByTenantIDMap[*tmpTa.TenantID]
cnt, cerr := aDAO.GetCount(ctx, nil, cdbm.AllocationFilterInput{
InfrastructureProviderID: &tmpTa.InfrastructureProviderID,
TenantIDs: []uuid.UUID{*tmpTa.TenantID},
})
if cerr != nil {
logger.Error().Err(cerr).Msg("error retrieving allocation count for Tenant Account from DB")
return cutil.NewAPIErrorResponse(c, http.StatusInternalServerError, "Failed to retrieve Allocations to determine total Allocation count for Tenants", nil)
}
allocCount = cnt
}
apiTa := model.NewAPITenantAccount(&tmpTa, ssdMap[ta.ID.String()], total)
apiTa := model.NewAPITenantAccount(&tmpTa, ssdMap[ta.ID.String()], allocCount)

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.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Avoid the per-row allocation count query.

AllocationDAO.GetCount(...) inside the loop turns one list request into 1+N database round trips. That will scale poorly as page size grows. Please batch these counts in one DAO call keyed by (infrastructure_provider_id, tenant_id) and map them back in memory.

🤖 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 `@api/pkg/api/handler/tenantaccount.go` around lines 399 - 413, The per-row
call to aDAO.GetCount inside the loop causes N DB round-trips; instead, collect
all (InfrastructureProviderID, TenantID) pairs for rows where TenantID != nil
while iterating over tas, call a new or existing batched DAO method (e.g.,
Add/GetCountsForTenantPairs or GetCounts(ctx, nil, []AllocationFilterInput))
once to return a map keyed by (infrastructure_provider_id,tenant_id) -> count,
then in the loop look up allocCount from that map and pass it to
model.NewAPITenantAccount; update or add the DAO method signature and its
call-site to accept the slice of filter inputs and return the counts mapping,
and use ssdMap[ta.ID.String()] and tmpTa.ID/tenant fields unchanged when mapping
results back.

Comment thread openapi/spec.yaml Outdated
Comment on lines +536 to +540
type: string
format: uuid
in: query
name: tenantId
description: Filter TenantAccounts by Tenant ID
description: 'Filter TenantAccounts by Tenant ID (Provider role only; for Tenant role the tenant is inferred from org membership and this param is ignored). Can be specified multiple times to filter on more than one Tenant ID.'

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Model tenantId as an array if it can be repeated.

The description says this query parameter may be supplied multiple times, but the schema is still a scalar string. That will generate incorrect SDKs/docs for the provider-side narrowing flow.

Suggested OpenAPI fix
         - schema:
-            type: string
-            format: uuid
+            type: array
+            items:
+              type: string
+              format: uuid
           in: query
           name: tenantId
+          style: form
+          explode: true
           description: 'Filter TenantAccounts by Tenant ID (Provider role only; for Tenant role the tenant is inferred from org membership and this param is ignored). Can be specified multiple times to filter on more than one Tenant ID.'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
type: string
format: uuid
in: query
name: tenantId
description: Filter TenantAccounts by Tenant ID
description: 'Filter TenantAccounts by Tenant ID (Provider role only; for Tenant role the tenant is inferred from org membership and this param is ignored). Can be specified multiple times to filter on more than one Tenant ID.'
type: array
items:
type: string
format: uuid
in: query
name: tenantId
style: form
explode: true
description: 'Filter TenantAccounts by Tenant ID (Provider role only; for Tenant role the tenant is inferred from org membership and this param is ignored). Can be specified multiple times to filter on more than one Tenant ID.'
🤖 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 536 - 540, The tenantId query parameter is
declared as a scalar string but the description says it may be supplied multiple
times; update the parameter definition to be an array: replace the scalar schema
with schema: type: array, items: { type: string, format: uuid } and add query
serialization metadata (e.g., style: form and explode: true) so repeated
tenantId query params are modeled correctly; locate the parameter by the name
"tenantId" in the OpenAPI parameter block and modify its schema and
serialization settings accordingly.

Comment thread openapi/spec.yaml
Comment thread sdk/standard/api_site.go Outdated
Comment on lines +304 to +312
// Filter Sites by Infrastructure Provider ID. Deprecated: Infrastructure Provider is now inferred from the org's membership.
// Deprecated
func (r ApiGetAllSiteRequest) InfrastructureProviderId(infrastructureProviderId string) ApiGetAllSiteRequest {
r.infrastructureProviderId = &infrastructureProviderId
return r
}

// Filter Sites by Tenant ID
// Filter Sites by Tenant ID. Deprecated: Tenant is now inferred from the org's membership.
// Deprecated

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

For Go doc comments, does a deprecated symbol need a paragraph beginning with Deprecated:for tools like godoc/pkg.go.dev/gopls to recognize it, or is// Deprecated without the colon sufficient?

💡 Result:

For Go doc comments, the deprecation convention recognized by Go doc tooling is to include a paragraph that begins exactly with Deprecated: (with the colon). Go’s official doc comment guidelines state: “To signal that an identifier should not be used, add a paragraph to its doc comment that begins with Deprecated: …” [1]. The same convention is reiterated in the Go wiki: “add a paragraph … that begins with Deprecated:” [2]. Therefore, // Deprecated without the colon is not the stated convention; to ensure tools recognize the deprecation notice, use // Deprecated: ... as the first text of a paragraph in the doc comment [1][2].

Citations:


Fix Go deprecation doc comments in generated setters

In sdk/standard/api_site.go (lines ~304-312), the doc comments emit a standalone // Deprecated line. Go doc tooling recognizes deprecations only when a doc-comment paragraph begins with Deprecated: (with the colon). Update the OpenAPI generator/template/spec so these setters render Deprecated: ... rather than // Deprecated.

🤖 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 `@sdk/standard/api_site.go` around lines 304 - 312, The generated setter doc
comments emit a standalone "// Deprecated" line which Go tooling ignores; update
the OpenAPI generator/template/spec so the doc-comment paragraph for setters
like ApiGetAllSiteRequest.InfrastructureProviderId (and the Tenant ID setter)
begins with "Deprecated:" followed by the message (e.g., "Deprecated:
Infrastructure Provider is now inferred...") instead of a separate "//
Deprecated" line; modify the template that renders method comments to prepend
"Deprecated: " to the deprecation sentence so the full paragraph starts with
"Deprecated:".

Comment on lines 19 to 50
// NewInstanceCreateRequestWithInterfaces preserves the pre-`auto`
// `NewInstanceCreateRequest` signature, which took an explicit
// `interfaces` argument before that field became optional on the
// `NewInstanceCreateRequest` signature, which took explicit `tenantId`
// and `interfaces` arguments before those fields became optional on the
// REST API. Callers should migrate to
// `standard.NewInstanceCreateRequest(name, tenantId, vpcId)` followed
// by `SetInterfaces` (or `SetAutoNetwork` for zero-DPU instances).
// `standard.NewInstanceCreateRequest(name, vpcId)`, optionally
// `SetTenantId`, then `SetInterfaces` (or `SetAutoNetwork` for zero-DPU
// instances).
//
// Deprecated: use `standard.NewInstanceCreateRequest` + `SetInterfaces`.
func NewInstanceCreateRequestWithInterfaces(name, tenantID, vpcID string, interfaces []standard.InterfaceCreateRequest) *standard.InstanceCreateRequest {
req := standard.NewInstanceCreateRequest(name, tenantID, vpcID)
req := standard.NewInstanceCreateRequest(name, vpcID)
if tenantID != "" {
req.SetTenantId(tenantID)
}
req.SetInterfaces(interfaces)
return req
}

// NewBatchInstanceCreateRequestWithInterfaces preserves the pre-`auto`
// `NewBatchInstanceCreateRequest` signature, which took an explicit
// `interfaces` argument before that field became optional. Callers
// should migrate to `standard.NewBatchInstanceCreateRequest(...)`
// followed by `SetInterfaces` (or `SetAutoNetwork` for zero-DPU batches).
// `NewBatchInstanceCreateRequest` signature, which took explicit `tenantId`
// and `interfaces` arguments before those fields became optional. Callers
// should migrate to `standard.NewBatchInstanceCreateRequest(...)`, optionally
// `SetTenantId`, then `SetInterfaces` (or `SetAutoNetwork` for zero-DPU batches).
//
// Deprecated: use `standard.NewBatchInstanceCreateRequest` + `SetInterfaces`.
func NewBatchInstanceCreateRequestWithInterfaces(namePrefix string, count int32, tenantID, instanceTypeID, vpcID string, interfaces []standard.InterfaceCreateRequest) *standard.BatchInstanceCreateRequest {
req := standard.NewBatchInstanceCreateRequest(namePrefix, count, tenantID, instanceTypeID, vpcID)
req := standard.NewBatchInstanceCreateRequest(namePrefix, count, instanceTypeID, vpcID)
if tenantID != "" {
req.SetTenantId(tenantID)
}
req.SetInterfaces(interfaces)
return req

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.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Generated exported constructors:\n'
rg -n '^func New(TenantAccountCreateRequest|InstanceCreateRequest|BatchInstanceCreateRequest)\(' sdk/standard

printf '\nCompat constructors present in this PR:\n'
rg -n '^func New.*CreateRequest' sdk/standard/compat

Repository: NVIDIA/infra-controller-rest

Length of output: 1048


Major: sdk/standard/compat shims don’t cover the exported constructor breaking arity changes

The exported constructors in sdk/standard now have reduced signatures:

  • NewTenantAccountCreateRequest(tenantOrg string) (sdk/standard/model_tenant_account_create_request.go)
  • NewInstanceCreateRequest(name string, vpcId string) (sdk/standard/model_instance_create_request.go)
  • NewBatchInstanceCreateRequest(namePrefix string, count int32, instanceTypeId string, vpcId string) (sdk/standard/model_batch_instance_create_request.go)

But sdk/standard/compat only adds NewInstanceCreateRequestWithInterfaces and NewBatchInstanceCreateRequestWithInterfaces (sdk/standard/compat/instance_create.go), with no tenant-account compat shim and no adapter that preserves the old call patterns for standard.New*CreateRequest without forcing callers onto the *WithInterfaces functions.

If this is not an intentional breaking change, restore backward compatibility by keeping the old exported constructor signatures (deprecated) and adding the new ones; otherwise, provide a complete, documented migration/versioning plan.

🤖 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 `@sdk/standard/compat/instance_create.go` around lines 19 - 50, The compat
layer is missing shims for the removed/changed exported constructors (notably
NewTenantAccountCreateRequest) so callers relying on old arities break; add
deprecated wrapper functions in sdk/standard/compat that preserve the old
signatures and delegate to the new constructors (similar to
NewInstanceCreateRequestWithInterfaces and
NewBatchInstanceCreateRequestWithInterfaces): implement
NewTenantAccountCreateRequest(oldTenantOrg string) that calls the new
standard.NewTenantAccountCreateRequest(...) API or constructs a
standard.TenantAccountCreateRequest and sets fields as needed, and if you
removed any other overloaded constructors restore them as deprecated wrappers
that call standard.NewInstanceCreateRequest,
standard.NewBatchInstanceCreateRequest, etc., and apply any missing SetX methods
(e.g., SetTenantId, SetInterfaces) so existing callers continue to work while
marking these shims deprecated.

…andlers

Signed-off-by: Parham Armani <parmani@nvidia.com>
@parmani-nv parmani-nv force-pushed the feat/tenant-handler-inferId branch from 0e16f06 to 49ee436 Compare June 2, 2026 00:56
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant