Skip to content

feat(rest-api): expose dpfEnabled on expected-machine endpoints#2961

Open
hwadekar-nv wants to merge 4 commits into
NVIDIA:mainfrom
hwadekar-nv:fix/expose-dpf-enabled
Open

feat(rest-api): expose dpfEnabled on expected-machine endpoints#2961
hwadekar-nv wants to merge 4 commits into
NVIDIA:mainfrom
hwadekar-nv:fix/expose-dpf-enabled

Conversation

@hwadekar-nv

Copy link
Copy Markdown
Contributor

Summary

  • Add dpfEnabled to the Expected Machine REST API (GET, POST, PATCH, and batch create/update) so operators can manage per-host DPF eligibility without admin-cli.
  • Persist the flag in the cloud expected_machine table, forward it to Core via is_dpf_enabled on workflow proto, and reconcile it during site inventory sync.
  • Update OpenAPI spec and regenerate the standard SDK.

Test plan

  • go test ./db/pkg/db/model/... -run ExpectedMachine
  • go test ./api/pkg/api/model/... -run ExpectedMachine
  • go test ./api/pkg/api/handler/... -run ExpectedMachine
  • go test ./workflow/pkg/activity/expectedmachine/...
  • POST /expected-machine with "dpfEnabled": false and verify GET returns false
  • PATCH without dpfEnabled preserves existing value
  • Inventory sync reflects Core-side changes after admin-cli patch

@hwadekar-nv hwadekar-nv requested a review from a team as a code owner June 28, 2026 20:47
@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The head commit changed during the review from 6fd23b1 to a6fb40c.

Walkthrough

The change adds DpfEnabled as a nullable boolean field to the ExpectedMachine entity. It is wired end-to-end: DB model struct, EffectiveDpfEnabled helper, proto conversion, DAO create/update operations, a schema migration, API request/response models, single and batch HTTP handlers, workflow reconciliation activity, and the OpenAPI specification.

Changes

DpfEnabled field propagation for ExpectedMachine

Layer / File(s) Summary
DB model, proto mapping, and DAO operations
rest-api/db/pkg/db/model/expectedmachine.go, rest-api/db/pkg/db/model/expectedmachine_test.go
ExpectedMachine gains DpfEnabled *bool mapped to dpf_enabled; EffectiveDpfEnabled helper defaults nil to true; ToProto/FromProto extended; CreateMultiple and UpdateMultiple handle the new field; input structs updated; tests added for all paths.
DB migration
rest-api/db/pkg/migrations/20260628120000_expected_machine_dpf_enabled.go
Registers an up migration that executes ALTER TABLE expected_machine ADD COLUMN IF NOT EXISTS dpf_enabled BOOLEAN; down is a no-op.
API model conversion
rest-api/api/pkg/api/model/expectedmachine.go, rest-api/api/pkg/api/model/expectedmachine_test.go
Create and update request structs gain DpfEnabled *bool; response struct gains DpfEnabled bool; NewAPIExpectedMachine populates it via EffectiveDpfEnabled; unit tests verify nil/false/true mapping.
Handler wiring — single and batch
rest-api/api/pkg/api/handler/expectedmachine.go, rest-api/api/pkg/api/handler/expectedmachine_test.go
Single and batch Create/Update handlers forward DpfEnabled from the API request into DAO input structs; regression test asserts end-to-end propagation into the workflow request and response payload.
Workflow activity reconciliation
rest-api/workflow/pkg/activity/expectedmachine/expectedmachine.go
UpdateExpectedMachinesInDB populates DpfEnabled on create inputs, adds it to the field-differs condition, and includes it in update inputs.
OpenAPI spec
rest-api/openapi/spec.yaml
dpfEnabled schema descriptions refined; create/update schemas now accept boolean or null; example payloads updated with explicit true/false values.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~15 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% 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 clearly summarizes the main change: exposing dpfEnabled on expected-machine REST endpoints.
Description check ✅ Passed The description is directly aligned with the changeset, covering API, DB persistence, workflow propagation, and OpenAPI updates.
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.

@hwadekar-nv hwadekar-nv self-assigned this Jun 28, 2026
@github-actions

Copy link
Copy Markdown

@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-06-28 20:51:36 UTC | Commit: 5b93eb7

@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

🤖 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 `@rest-api/db/pkg/db/model/expectedmachine.go`:
- Line 244: `DpfEnabled` currently uses nil as both “no change” and “clear to
NULL,” which prevents the workflow from syncing inventory removals correctly.
Update the expected-machine update contract around `ExpectedMachine`,
`UpdateMultiple`, and the workflow reconciler so callers can explicitly
distinguish preserve-vs-clear semantics, using a presence flag or tri-state
field for `DpfEnabled`. Ensure the reconciler can mark `HasDpfEnabled` when
inventory should be reflected in the DB, and that the DAO applies NULL only when
that presence bit is set, keeping data-model compatibility for database changes.
🪄 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: cf7e790b-3b88-46e8-a908-7d2ab0991477

📥 Commits

Reviewing files that changed from the base of the PR and between 0082abd and 5b93eb7.

⛔ Files ignored due to path filters (31)
  • rest-api/sdk/standard/client.go is excluded by !rest-api/sdk/standard/client.go
  • rest-api/sdk/standard/model_batch_instance_create_request.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_expected_machine.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_expected_machine_create_request.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_expected_machine_update_request.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_expected_power_shelf.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_expected_power_shelf_create_request.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_expected_power_shelf_update_request.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_expected_rack.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_expected_rack_create_request.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_expected_rack_update_request.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_expected_switch.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_expected_switch_create_request.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_expected_switch_update_request.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_infini_band_partition.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_infini_band_partition_create_request.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_infini_band_partition_update_request.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_instance.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_instance_create_request.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_instance_type.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_instance_type_create_request.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_instance_type_update_request.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_instance_update_request.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_machine.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_machine_update_request.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_network_security_group.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_network_security_group_create_request.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_network_security_group_update_request.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_vpc.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_vpc_create_request.go is excluded by !rest-api/sdk/standard/model_*.go
  • rest-api/sdk/standard/model_vpc_update_request.go is excluded by !rest-api/sdk/standard/model_*.go
📒 Files selected for processing (9)
  • rest-api/api/pkg/api/handler/expectedmachine.go
  • rest-api/api/pkg/api/handler/expectedmachine_test.go
  • rest-api/api/pkg/api/model/expectedmachine.go
  • rest-api/api/pkg/api/model/expectedmachine_test.go
  • rest-api/db/pkg/db/model/expectedmachine.go
  • rest-api/db/pkg/db/model/expectedmachine_test.go
  • rest-api/db/pkg/migrations/20260628120000_expected_machine_dpf_enabled.go
  • rest-api/openapi/spec.yaml
  • rest-api/workflow/pkg/activity/expectedmachine/expectedmachine.go

TrayIdx *int32
HostID *int32
Labels map[string]string
DpfEnabled *bool

@coderabbitai coderabbitai Bot Jun 28, 2026

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.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

DpfEnabled cannot be cleared back to NULL.

UpdateMultiple treats nil as “leave unchanged”, but the workflow reconciliation now compares cur.DpfEnabled against reported.DpfEnabled and forwards reported.DpfEnabled directly. When Site inventory stops sending is_dpf_enabled, the diff remains true forever while the DAO never clears dpf_enabled, so the DB value stays stale and this row will be “updated” on every sync. Please introduce an explicit presence bit / tri-state update contract so callers can distinguish “preserve existing” from “set column to NULL”. As per path instructions, review database changes for data-model compatibility.

Proposed direction
 type ExpectedMachineUpdateInput struct {
 	ExpectedMachineID        uuid.UUID
 	...
 	DpfEnabled               *bool
+	HasDpfEnabled            bool
 }

-	if input.DpfEnabled != nil {
+	if input.HasDpfEnabled {
 		em.DpfEnabled = input.DpfEnabled
 		columnsSet["dpf_enabled"] = true
 	}

The workflow reconciler can then set HasDpfEnabled: true whenever DB state must match inventory, even when reported.DpfEnabled is nil.

Also applies to: 684-687

🤖 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 `@rest-api/db/pkg/db/model/expectedmachine.go` at line 244, `DpfEnabled`
currently uses nil as both “no change” and “clear to NULL,” which prevents the
workflow from syncing inventory removals correctly. Update the expected-machine
update contract around `ExpectedMachine`, `UpdateMultiple`, and the workflow
reconciler so callers can explicitly distinguish preserve-vs-clear semantics,
using a presence flag or tri-state field for `DpfEnabled`. Ensure the reconciler
can mark `HasDpfEnabled` when inventory should be reflected in the DB, and that
the DAO applies NULL only when that presence bit is set, keeping data-model
compatibility for database changes.

Source: Path instructions

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

In proto, DpfEnabled is going to be deprecated, instead isDpfEnabled use, how for readable purpose we kept 'DpfEnabled' in model. However, HasDpfEnabled looks correct but we will stick with DpfEnabled, we can ingnore

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.

@hwadekar-nv Acknowledged — keeping DpfEnabled in the model for readability while the proto transitions toward isDpfEnabled makes sense.

My concern was specifically about the update semantics rather than the field name: today nil still means both “preserve existing value” and “clear DB column to NULL”, so inventory removals cannot be reflected in expected_machine.dpf_enabled. That said, if you’re choosing to defer that behavior change for this PR, I’m fine to leave it there and move on.

If you want, I can open a small follow-up issue for the tri-state/presence-bit cleanup separately.


✏️ Learnings added
Learnt from: hwadekar-nv
Repo: NVIDIA/infra-controller PR: 2961
File: rest-api/db/pkg/db/model/expectedmachine.go:235-235
Timestamp: 2026-06-28T22:19:15.745Z
Learning: In the NVIDIA infra-controller ExpectedMachine flow, the workflow proto is moving away from `DpfEnabled` toward `isDpfEnabled`, but the Go model layer keeps the field name `DpfEnabled` for readability.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Allow operators to read and set per-host DPF eligibility via the REST API,
persisting the flag in the cloud DB and forwarding it to Core through the
existing expected-machine workflows and inventory sync.

Signed-off-by: Hitesh Wadekar <hwadekar@nvidia.com>
@hwadekar-nv hwadekar-nv force-pushed the fix/expose-dpf-enabled branch from 6fd23b1 to a6fb40c Compare June 28, 2026 21:19
@github-actions

github-actions Bot commented Jun 28, 2026

Copy link
Copy Markdown

🔍 Container Scan Summary

Service Total Critical High Medium Low Other
nico-flow 43 3 21 9 2 8
nico-nsm 49 0 10 31 8 0
nico-psm 43 3 21 9 2 8
nico-rest-api 43 3 21 9 2 8
nico-rest-cert-manager 42 3 21 9 1 8
nico-rest-db 43 3 21 9 2 8
nico-rest-site-agent 42 3 21 9 1 8
nico-rest-site-manager 42 3 21 9 1 8
nico-rest-workflow 43 3 21 9 2 8
TOTAL 390 24 178 103 21 64

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

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