package ssh import ( "strings" "testing" "github.com/dtoro/oikos/internal/core/ports" ) // TestResolveTemplate — moved from httpapi/pct_create_test.go with the // pct flow it belongs to. func TestResolveTemplate(t *testing.T) { avail := []string{ "debian-12-standard_12.7-1_amd64.tar.zst", "debian-13-standard_13.0-1_amd64.tar.zst", "ubuntu-24.04-standard_24.04-2_amd64.tar.zst", } cases := []struct { requested string want string }{ {"debian-13-standard_13.0-1_amd64.tar.zst", "debian-13-standard_13.0-1_amd64.tar.zst"}, // exact {"debian-13", "debian-13-standard_13.0-1_amd64.tar.zst"}, // prefix {"", "debian-13-standard_13.0-1_amd64.tar.zst"}, // auto newest debian {"debian-99", "debian-13-standard_13.0-1_amd64.tar.zst"}, // miss prefix → auto debian {"ubuntu-24", "ubuntu-24.04-standard_24.04-2_amd64.tar.zst"}, {"alpine", "debian-13-standard_13.0-1_amd64.tar.zst"}, // miss → auto debian } for _, c := range cases { if got := ResolveTemplate(c.requested, avail); got != c.want { t.Errorf("ResolveTemplate(%q) = %q, want %q", c.requested, got, c.want) } } if got := ResolveTemplate("debian", nil); got != "" { t.Errorf("ResolveTemplate with no cache = %q, want empty", got) } } func TestGatewayPreflightPassed(t *testing.T) { cases := []struct { in string want bool }{ {"PREFLIGHT_OK", true}, {"PREFLIGHT_OK\n", true}, {" PREFLIGHT_OK ", true}, {"PREFLIGHT_FAIL", false}, {"UNREACHABLE", false}, // the original substring bug {"", false}, } for _, c := range cases { if got := GatewayPreflightPassed(c.in); got != c.want { t.Errorf("GatewayPreflightPassed(%q) = %v, want %v", c.in, got, c.want) } } } func TestBuildPctCreateCmd(t *testing.T) { base := ports.LXCInput{ VMID: 137, Hostname: "grafana", Cores: 2, MemoryMB: 1024, DiskGB: 12, IP: "192.168.8.55", GW: "192.168.8.2", Bridge: "vmbr1", Storage: "local-lvm", Template: "debian-13-standard_13.0-1_amd64.tar.zst", Nameserver: "192.168.8.2", Searchdomain: "hubris.network", } got := BuildPctCreateCmd(base) for _, want := range []string{ "pct create 137 /var/lib/vz/template/cache/debian-13-standard_13.0-1_amd64.tar.zst", "--hostname grafana", "--cores 2", "--memory 1024", "--rootfs local-lvm:12", "--unprivileged 1", "--net0 name=eth0,bridge=vmbr1,ip=192.168.8.55,gw=192.168.8.2", "--start 1", "--nameserver 192.168.8.2", "--searchdomain hubris.network", } { if !strings.Contains(got, want) { t.Errorf("cmd missing %q:\n%s", want, got) } } if strings.Contains(got, "--features") { t.Errorf("unprivileged non-nested should have no features flag:\n%s", got) } nested := base nested.Nesting = true nested.Privileged = true nested.IP = "dhcp" got = BuildPctCreateCmd(nested) if !strings.Contains(got, "--features nesting=1,keyctl=1") { t.Errorf("privileged+nesting features missing:\n%s", got) } if !strings.Contains(got, "--unprivileged 0") { t.Errorf("privileged should pass --unprivileged 0:\n%s", got) } if !strings.Contains(got, "ip=dhcp") || strings.Contains(got, "gw=") { t.Errorf("dhcp must omit gateway:\n%s", got) } }