Phase 7: apply engine (Proxmox writes, NetBox write-back, audit log)
Summary
Implements Phase 7 of the build plan — the apply engine that actually writes to Proxmox, gated behind explicit operator approval of a specific computed Plan (re-validated fresh at apply time, never trusted as a standing intent).
-
internal/notes(new — sketched in the plan but never built in earlier phases): renders/regenerates the managed VM-notes block from aDeviceSpec, preserving hand-maintained content (BGP sessions etc.) after theRAX:MANAGED:ENDsentinel.diff.Computenow produces aset_notesAction and anotes_migrationWarning. -
internal/apply(new): executes an approved Plan's Actions against Proxmox in a fixed safe order (create_vm → grow_disk → NIC changes → resizes → tags → ISO → notes), independent of the orderdiff.Computeproduced them in. Stops at the first failure, records the rest as skipped. Generates a MAC only for a brand-new NIC with no pinnedprimary_mac_address; a generated VMID/MAC is written back to NetBox only after the corresponding Proxmox change actually succeeded. -
proxmox.Client:CreateVM/UpdateConfig/DeleteConfigKeys/ResizeDisk/ListISOs. -
netbox.Client:SetDeviceVMID/SetInterfaceMAC. -
store.ProxmoxEnvironmentgainsVMIDRangeLow/VMIDRangeHigh/DiskStorage/ISOStorage(needed forcreate_vm/attach_iso, previously missing from the settings UI), plus newaudit_plans/audit_actionstables. -
model.Plan.Hash()— the web layer re-checks a freshly recomputed Plan's hash against what the operator approved before applying (closes the gap between viewing the approval page and clicking Apply). -
POST /devices/{id}/apply: re-fetches NetBox+Proxmox fresh, recomputes the Plan, bounces back on a stale hash or any Blocker, requires an explicit checkbox perremove_nicaction, then executes and records the audit trail. The approval page has a live Apply button and shows exactly what applied/failed/was skipped on partial failure.
Not verified against a live PVE 9.2.3 node yet — CreateVM/UpdateConfig/ResizeDisk's JSON body shape and the exact resize param syntax were flagged as open items in the build plan. First live apply should target a low-risk action (set_tags/set_notes) on an already-existing VM before trusting create_vm or NIC-changing actions.
Test plan
-
go build ./...,go vet ./...,gofmt -l .clean -
go test ./...green — new coverage ininternal/notes,internal/apply(ordering, MAC generation/pinning, VMID allocation incl. IPv6-only-from-top, stop-on-failure),internal/proxmox/internal/netboxwrite methods (httptest),internal/storeaudit CRUD, andinternal/webapply-handler integration tests (success, stale plan hash, blocked plan, missing remove_nic confirmation, unbound rack, partial failure)