Files
oikos/internal/adapters/ssh/provisioner_test.go
dtoro 60c0432d8b feat: Phase 7 — SeedService, SecretsService, ProvisioningService + ssh Provisioner
Seed ingest/export moves behind ports.SeedRepository (SeedRepo in the
postgres adapter; knowledge ingest absorbed from internal/knowledge,
package deleted). pct_create flow (defaults, template/VMID/gateway
pre-flights, pct create, graph registration) moves from httpapi's
approved-execution path into app.ProvisioningService + the ssh
provisioner adapter; CLI seed/export/secret become adapters over the
services. EntityCreateInput gains EnrolledAt. Plan status corrected:
phases 0-7 shipped, 8 + 9 gates open. VERSION 0.34.1.
2026-08-16 09:11:26 +02:00

101 lines
3.2 KiB
Go

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)
}
}