proxmox: config block, IDs, marks, state mapping, classify, registration
Phase 2 of the proxmox provider plan. Adds the proxmox: config block with its validation, registers the type in the config allow-list and the constructor map, and starts internal/provider/proxmox: the api seam and its data types, providerIDs (vms/<vmid>/<name>) with the UID-derived VMID, the description mark, state mapping, and error classification. Tests read the responses captured from pv1-1 in Phase 0 rather than repeating Proxmox's wording, and every matcher is run against every captured error so none fires on the wrong message. The contract methods are Transient stubs until Phases 5 to 7. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
package proxmox
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// capture is one response recorded from the real host in Phase 0: the
|
||||
// status, the reason phrase after the status code, and the raw body.
|
||||
type capture struct {
|
||||
Status int `json:"status"`
|
||||
Reason string `json:"reason"`
|
||||
Body string `json:"body"`
|
||||
}
|
||||
|
||||
// readCapture loads testdata/<name>.json and fails the test when it is
|
||||
// missing, so every string a test relies on is backed by a real response.
|
||||
func readCapture(t *testing.T, name string) capture {
|
||||
t.Helper()
|
||||
raw, err := os.ReadFile(filepath.Join("testdata", name+".json"))
|
||||
if err != nil {
|
||||
t.Fatalf("reading capture %s: %v", name, err)
|
||||
}
|
||||
var c capture
|
||||
if err := json.Unmarshal(raw, &c); err != nil {
|
||||
t.Fatalf("parsing capture %s: %v", name, err)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// loadAPIError turns an error capture into the apiError the client builds.
|
||||
func loadAPIError(t *testing.T, name string) *apiError {
|
||||
t.Helper()
|
||||
c := readCapture(t, name)
|
||||
if c.Status < 400 {
|
||||
t.Fatalf("capture %s has status %d, want an error status", name, c.Status)
|
||||
}
|
||||
return newAPIError(c.Status, c.Reason, []byte(c.Body))
|
||||
}
|
||||
|
||||
// decodeData decodes the "data" member of a successful capture into T.
|
||||
func decodeData[T any](t *testing.T, name string) T {
|
||||
t.Helper()
|
||||
c := readCapture(t, name)
|
||||
if c.Status != 200 {
|
||||
t.Fatalf("capture %s has status %d, want 200", name, c.Status)
|
||||
}
|
||||
var env struct {
|
||||
Data T `json:"data"`
|
||||
}
|
||||
if err := json.Unmarshal([]byte(c.Body), &env); err != nil {
|
||||
t.Fatalf("decoding capture %s: %v", name, err)
|
||||
}
|
||||
return env.Data
|
||||
}
|
||||
Reference in New Issue
Block a user