Files
egress-proxies-operator/internal/provider/config_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

204 lines
4.3 KiB
Go

package provider
import (
"strings"
"testing"
)
func TestLoadConfig_valid(t *testing.T) {
t.Parallel()
data := []byte(`
providers:
- name: kubernetes
type: kubernetes
kubernetes:
image: ubuntu/squid:6.6-24.04_edge
- name: gcp-eu
type: gcp
gcp:
project: my-project
network: custom-net
`)
cfg, err := LoadConfig(data)
if err != nil {
t.Fatalf("LoadConfig() error = %v, want nil", err)
}
if len(cfg.Providers) != 2 {
t.Fatalf("len(cfg.Providers) = %d, want 2", len(cfg.Providers))
}
if cfg.Providers[0].Kubernetes == nil || cfg.Providers[0].Kubernetes.Image != "ubuntu/squid:6.6-24.04_edge" {
t.Errorf("providers[0].kubernetes = %+v, want Image=ubuntu/squid:6.6-24.04_edge", cfg.Providers[0].Kubernetes)
}
if cfg.Providers[1].GCP == nil || cfg.Providers[1].GCP.Project != "my-project" {
t.Errorf("providers[1].gcp = %+v, want Project=my-project", cfg.Providers[1].GCP)
}
}
func TestLoadConfig_invalid(t *testing.T) {
t.Parallel()
tests := []struct {
name string
yaml string
wantErrSub string
}{
{
name: "empty providers list",
yaml: `providers: []`,
wantErrSub: "at least one provider",
},
{
name: "missing name",
yaml: `
providers:
- type: kubernetes`,
wantErrSub: "name is required",
},
{
name: "duplicate name",
yaml: `
providers:
- name: kubernetes
type: kubernetes
- name: kubernetes
type: kubernetes`,
wantErrSub: "duplicate provider name",
},
{
name: "unknown type",
yaml: `
providers:
- name: p1
type: azure`,
wantErrSub: `unknown provider type "azure"`,
},
{
name: "missing type",
yaml: `
providers:
- name: p1`,
wantErrSub: "type is required",
},
{
name: "gcp missing project",
yaml: `
providers:
- name: gcp-eu
type: gcp`,
wantErrSub: "gcp.project is required",
},
{
name: "gcp with empty project",
yaml: `
providers:
- name: gcp-eu
type: gcp
gcp:
project: ""`,
wantErrSub: "gcp.project is required",
},
{
name: "kubernetes type with gcp block",
yaml: `
providers:
- name: p1
type: kubernetes
gcp:
project: my-project`,
wantErrSub: "type is kubernetes but a gcp block is set",
},
{
name: "gcp type with kubernetes block",
yaml: `
providers:
- name: p1
type: gcp
gcp:
project: my-project
kubernetes:
image: custom-image`,
wantErrSub: "type is gcp but a kubernetes block is set",
},
{
name: "kvm type with kvm2 block",
yaml: `
providers:
- name: p1
type: kvm
kvm2:
sshKeyFile: /key`,
wantErrSub: "type is kvm but a kvm2 block is set",
},
{
name: "kvm2 type with kvm block",
yaml: `
providers:
- name: p1
type: kvm2
kvm:
sshKeyFile: /key`,
wantErrSub: "type is kvm2 but a kvm block is set",
},
{
name: "proxmox type with kvm block",
yaml: `
providers:
- name: p1
type: proxmox
kvm:
sshKeyFile: /key`,
wantErrSub: "type is proxmox but a kvm block is set",
},
{
name: "kvm type with proxmox block",
yaml: `
providers:
- name: p1
type: kvm
proxmox:
url: https://pve:8006`,
wantErrSub: "type is kvm but a proxmox block is set",
},
{
name: "strict mode rejects unknown top-level key",
yaml: `
providers:
- name: p1
type: kubernetes
extraneous: true`,
wantErrSub: "parsing providers config",
},
{
name: "strict mode rejects unknown provider key",
yaml: `
providers:
- name: p1
type: kubernetes
bogus: true`,
wantErrSub: "parsing providers config",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
_, err := LoadConfig([]byte(tc.yaml))
if err == nil {
t.Fatalf("LoadConfig() error = nil, want error containing %q", tc.wantErrSub)
}
if !strings.Contains(err.Error(), tc.wantErrSub) {
t.Errorf("LoadConfig() error = %q, want substring %q", err.Error(), tc.wantErrSub)
}
})
}
}
func TestLoadConfigFile_missingFile(t *testing.T) {
t.Parallel()
_, err := LoadConfigFile("/nonexistent/providers.yaml")
if err == nil {
t.Fatal("LoadConfigFile() error = nil, want error")
}
if !strings.Contains(err.Error(), "reading providers config") {
t.Errorf("LoadConfigFile() error = %q, want substring %q", err.Error(), "reading providers config")
}
}