package preflight import ( "context" "os" "strconv" "strings" "testing" "time" "gitea.mynodes.xyz/ilker/llmgw/internal/onboard" ) func facts(over map[string]string) map[string]string { f := map[string]string{ "os": "ubuntu", "version": "24.04", "pretty": "Ubuntu 24.04.3 LTS", "arch": "x86_64", "cpus": "2", "mem_mb": "3900", "disk_gb": "35", "ntp": "yes", "listening": "22 53", "sudo": "yes", "apt": "yes", "internet": "yes", "now": strconv.FormatFloat(float64(time.Now().UnixNano())/1e9, 'f', 3, 64), } for k, v := range over { f[k] = v } return f } func levelOf(fs []Finding, check string) (Level, string) { for _, f := range fs { if f.Check == check { return f.Level, f.Detail } } return -1, "" } func TestAMachineFitForItsRoleHasNothingWrong(t *testing.T) { fs := Evaluate(Machine{Name: "pg01", Roles: []Role{RoleDatabase}}, facts(nil), time.Now()) if r := (Report{Findings: fs}); r.Worst() != OK { t.Errorf("%+v", fs) } } func TestEachProblemIsFoundAndSaysWhatToDo(t *testing.T) { m := Machine{Name: "x", Roles: []Role{RoleDatabase, RoleControl}} cases := []struct { over map[string]string check string want Level }{ {map[string]string{"os": "centos", "version": "9"}, "system", Fail}, {map[string]string{"version": "20.04"}, "system", Warn}, {map[string]string{"arch": "riscv64"}, "architecture", Fail}, {map[string]string{"sudo": "no"}, "sudo", Warn}, {map[string]string{"mem_mb": "1000"}, "memory", Fail}, {map[string]string{"disk_gb": "20"}, "disk", Warn}, {map[string]string{"ntp": "no"}, "time sync", Warn}, {map[string]string{"listening": "22 5432"}, "ports", Warn}, {map[string]string{"internet": "no"}, "internet", Fail}, {map[string]string{"now": strconv.FormatFloat(float64(time.Now().Add(-30*time.Second).UnixNano())/1e9, 'f', 3, 64)}, "clock", Fail}, } for _, c := range cases { fs := Evaluate(m, facts(c.over), time.Now()) got, detail := levelOf(fs, c.check) if got != c.want { t.Errorf("%v: %s is %v (%s), want %v", c.over, c.check, got, detail, c.want) } for _, f := range fs { if f.Level != OK && f.Fix == "" { t.Errorf("%s: %s says nothing about what to do", c.check, f.Check) } } } // This machine is run as root; sudo is not its question. if l, _ := levelOf(Evaluate(Machine{Name: "here", Local: true}, facts(map[string]string{"sudo": "no"}), time.Now()), "sudo"); l != -1 { t.Error("the local machine was asked about sudo") } } func TestAMachineThatCannotReachAnotherIsCalledOut(t *testing.T) { fs := evaluateReach(Machine{Name: "a"}, "reach 10.0.0.2 yes\nreach 10.0.0.3 no\n") if fs[0].Level != Fail || !strings.Contains(fs[0].Detail, "10.0.0.3") { t.Errorf("%+v", fs) } } // TestAgainstRealMachines runs the probe over ssh when LLMGW_TEST_PREFLIGHT // names user@host,user@host: the scripts are shell, and only a real machine // says whether they parse. func TestAgainstRealMachines(t *testing.T) { targets := os.Getenv("LLMGW_TEST_PREFLIGHT") if targets == "" { t.Skip("set LLMGW_TEST_PREFLIGHT=user@host,user@host to run against machines") } var ms []Machine for _, tgt := range strings.Split(targets, ",") { user, host, _ := strings.Cut(tgt, "@") ms = append(ms, Machine{Name: host, Addr: host, Roles: []Role{RoleDatabase}, Remote: &onboard.GoSSH{Addr: host, User: user, UseAgent: true}}) } rep := Run(context.Background(), ms) for _, f := range rep.Findings { t.Logf("%-12s %-12s %-5s %s", f.Machine, f.Check, f.Level, f.Detail) } for _, f := range rep.Findings { if f.Check == "login" && f.Level != OK { t.Fatalf("could not log in: %s", f.Detail) } } }