Files
egress-proxies-operator/internal/provider/proxmox/api_test.go
T
kacerrandClaude Opus 5.5 6e996ae2c7 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>
2026-09-23 09:42:46 +00:00

98 lines
3.5 KiB
Go

package proxmox
import (
"strings"
"testing"
)
// TestAPITypes_decodeCaptures decodes the Phase 0 responses into the seam's
// types, so a misspelled JSON tag fails here and not in a later phase.
func TestAPITypes_decodeCaptures(t *testing.T) {
t.Parallel()
t.Run("version", func(t *testing.T) {
t.Parallel()
if v := decodeData[versionInfo](t, "version"); v.Version != "9.2.20" || v.Release != "9.2" || v.RepoID == "" {
t.Errorf("version = %+v", v)
}
})
t.Run("node status", func(t *testing.T) {
t.Parallel()
n := decodeData[nodeStatus](t, "node_status")
if !strings.HasPrefix(n.PVEVersion, "pve-manager/9.2.20") || n.CurrentKernel.Release != "7.0.14-17-pve" {
t.Errorf("node status = %+v", n)
}
})
t.Run("storage status", func(t *testing.T) {
t.Parallel()
s := decodeData[storageStatus](t, "storage_status")
if s.Type != "dir" || !strings.Contains(s.Content, "iso") || s.Active != 1 || s.Avail <= 0 || s.Total < s.Avail {
t.Errorf("storage status = %+v", s)
}
})
t.Run("cluster resources", func(t *testing.T) {
t.Parallel()
rs := decodeData[[]vmResource](t, "cluster_resources")
byID := map[int]vmResource{}
for _, r := range rs {
byID[r.VMID] = r
}
if r := byID[9001]; r.Name != "debian-13-template" || r.Template != 1 || r.Node != "pv1-1" || r.Type != "qemu" || r.Status != "stopped" {
t.Errorf("resources[9001] = %+v", r)
}
if r := byID[100]; r.Template != 0 || r.Name != "ubuntu-vm-1" {
t.Errorf("resources[100] = %+v", r)
}
})
t.Run("cluster resources during clone", func(t *testing.T) {
t.Parallel()
for _, r := range decodeData[[]vmResource](t, "cluster_resources_during_clone") {
if r.VMID != 199999 {
continue
}
if r.Name != "" || r.Lock != "clone" || r.Status != "unknown" {
t.Errorf("mid-clone entry = %+v, want no name, lock clone, status unknown", r)
}
return
}
t.Error("no entry for VMID 199999 in the mid-clone capture")
})
t.Run("cluster resources tags", func(t *testing.T) {
t.Parallel()
for _, r := range decodeData[[]vmResource](t, "cluster_resources_during_destroy") {
if r.VMID == 199999 && r.Tags != "proxy_operator" {
t.Errorf("tags = %q, want proxy_operator", r.Tags)
}
}
})
t.Run("status current", func(t *testing.T) {
t.Parallel()
if s := decodeData[vmStatus](t, "status_current_paused"); s.Status != "running" || s.QMPStatus != "paused" {
t.Errorf("paused status = %+v", s)
}
if s := decodeData[vmStatus](t, "status_current_stopped"); s.Status != "stopped" || s.QMPStatus != "stopped" {
t.Errorf("stopped status = %+v", s)
}
})
t.Run("task status", func(t *testing.T) {
t.Parallel()
if s := decodeData[taskStatus](t, "task_status_stopped_error"); s.Status != "stopped" || s.ExitStatus != "shrinking disks is not supported" || s.Type != "resize" {
t.Errorf("failed task = %+v", s)
}
if s := decodeData[taskStatus](t, "task_status_running"); s.Status != "running" || s.ExitStatus != "" || s.Node != "pv1-1" {
t.Errorf("running task = %+v", s)
}
if s := decodeData[taskStatus](t, "task_status_volume_missing"); s.ExitStatus != "OK" {
t.Errorf("deleting a missing volume = %+v, want exitstatus OK", s)
}
})
t.Run("UPID responses", func(t *testing.T) {
t.Parallel()
for _, c := range []string{"clone_response", "start_response", "stop_response", "destroy_response", "resize_response", "upload_response", "content_delete_response"} {
if upid := decodeData[string](t, c); !strings.HasPrefix(upid, "UPID:pv1-1:") {
t.Errorf("%s = %q, want a UPID of node pv1-1", c, upid)
}
}
})
}