Skip to content

Phase 7: apply engine (Proxmox writes, NetBox write-back, audit log)

Aiho Tehisaru requested to merge feature/apply-engine into trunk

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 a DeviceSpec, preserving hand-maintained content (BGP sessions etc.) after the RAX:MANAGED:END sentinel. diff.Compute now produces a set_notes Action and a notes_migration Warning.
  • 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 order diff.Compute produced them in. Stops at the first failure, records the rest as skipped. Generates a MAC only for a brand-new NIC with no pinned primary_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.ProxmoxEnvironment gains VMIDRangeLow/VMIDRangeHigh/DiskStorage/ISOStorage (needed for create_vm/attach_iso, previously missing from the settings UI), plus new audit_plans/audit_actions tables.
  • 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 per remove_nic action, 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 yetCreateVM/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 in internal/notes, internal/apply (ordering, MAC generation/pinning, VMID allocation incl. IPv6-only-from-top, stop-on-failure), internal/proxmox/internal/netbox write methods (httptest), internal/store audit CRUD, and internal/web apply-handler integration tests (success, stale plan hash, blocked plan, missing remove_nic confirmation, unbound rack, partial failure)

🤖 Generated with Claude Code

https://claude.ai/code/session_01U9buZPRQy7YXLodkSPFFik

Merge request reports

Loading