Files
Ilker ManapandClaude Opus 5.5 32c3942040 The firewall turns off and on with the cluster's settings; llmgw wipe
firewall.enabled (default true) is a cluster setting, applied live: the
leader sends a Firewall message to every agent when it registers and when
the setting or firewall_networks changes, and the agent (root) takes llmgw's
nft table out or installs it. A control plane writes the state to
/var/lib/llmgw/firewall.json, which llmgw-firewall-sync.path applies as root
with `llmgw firewall sync`; server init and server add install the units,
`llmgw firewall sync --install` on one set up before. node add and server
add put no firewall on a machine while the setting is off.

`llmgw wipe` removes llmgw from a machine after listing what goes and asking
for its name: units, engines' processes, the nft table, /etc/llmgw,
/var/lib/llmgw, the agent's state, the sudo grant, the CA from the trust
store, keepalived's configuration when llmgw wrote it, and the users.
--models, --store (Patroni member, etcd, or the local database) and --all
take more. The console has it under Do.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-06 08:00:06 +02:00

107 lines
3.9 KiB
Go

package cli
import (
"os"
"path/filepath"
"strings"
"testing"
)
func wipeFixture(t *testing.T) string {
t.Helper()
root := t.TempDir()
for p, body := range map[string]string{
"/etc/llmgw/server.yaml": "listen: :8080\n",
"/etc/llmgw/pki/ca-key.pem": "key",
"/var/lib/llmgw/admin-token": "t",
"/var/lib/llmgw-agent/control-planes.json": "[]",
"/etc/systemd/system/llmgw-server.service": "[Unit]",
"/etc/systemd/system/llmgw-agent.service": "[Unit]",
"/etc/sudoers.d/llmgw-setup": "x",
"/etc/keepalived/keepalived.conf": "# llmgw: the gateway's floating address\n",
"/etc/passwd": "root:x:0:0::/root:/bin/sh\nllmgw:x:999:999::/var/lib/llmgw:/usr/sbin/nologin\nllmgw-engine:x:998:998::/:/usr/sbin/nologin\n",
"/srv/models/qwen/v1/q.gguf": "w",
"/opt/llmgw/engines/llamacpp/b1/llama-server": "e",
"/etc/patroni/config.yml": "scope: llmgw\n",
"/var/lib/postgresql/16/llmgw/PG_VERSION": "16",
"/etc/default/etcd": "ETCD_INITIAL_CLUSTER_TOKEN=llmgw\n",
"/var/lib/etcd/default/member/snap": "s",
"/usr/local/bin/llmgw": "bin",
} {
full := filepath.Join(root, p)
if err := os.MkdirAll(filepath.Dir(full), 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(full, []byte(body), 0o600); err != nil {
t.Fatal(err)
}
}
return root
}
func TestWipeRemovesTheConfigurationAndKeepsWhatWasNotAsked(t *testing.T) {
root := wipeFixture(t)
var ran []string
w := &wiper{root: root, run: func(name string, args ...string) error {
ran = append(ran, name+" "+strings.Join(args, " "))
return nil
}}
for _, s := range w.plan() {
if err := s.do(); err != nil {
t.Fatalf("%s: %v", s.what, err)
}
}
for _, gone := range []string{"/etc/llmgw", "/var/lib/llmgw", "/var/lib/llmgw-agent",
"/etc/systemd/system/llmgw-server.service", "/etc/sudoers.d/llmgw-setup", "/etc/keepalived/keepalived.conf"} {
if _, err := os.Stat(filepath.Join(root, gone)); err == nil {
t.Errorf("%s is still there", gone)
}
}
for _, kept := range []string{"/srv/models/qwen/v1/q.gguf", "/opt/llmgw/engines", "/etc/patroni/config.yml",
"/var/lib/postgresql/16/llmgw", "/var/lib/etcd/default", "/usr/local/bin/llmgw"} {
if _, err := os.Stat(filepath.Join(root, kept)); err != nil {
t.Errorf("%s was removed without being asked", kept)
}
}
all := strings.Join(ran, "\n")
for _, want := range []string{"systemctl disable --now llmgw-server.service", "pkill -KILL -u llmgw-engine",
"nft delete table inet llmgw", "systemctl disable --now keepalived", "userdel llmgw-engine", "userdel llmgw"} {
if !strings.Contains(all, want) {
t.Errorf("did not run %q:\n%s", want, all)
}
}
if strings.Contains(all, "patroni") {
t.Error("the store was touched without --store")
}
}
func TestWipeAllTakesTheStoreAndTheModelsToo(t *testing.T) {
root := wipeFixture(t)
w := &wiper{root: root, all: true, run: func(string, ...string) error { return nil }}
for _, s := range w.plan() {
if err := s.do(); err != nil {
t.Fatalf("%s: %v", s.what, err)
}
}
for _, gone := range []string{"/srv/models", "/opt/llmgw", "/etc/patroni", "/var/lib/postgresql/16/llmgw",
"/var/lib/etcd/default", "/etc/default/etcd", "/usr/local/bin/llmgw"} {
if _, err := os.Stat(filepath.Join(root, gone)); err == nil {
t.Errorf("%s is still there", gone)
}
}
}
func TestWipeLeavesAKeepalivedItDidNotWrite(t *testing.T) {
root := t.TempDir()
p := filepath.Join(root, "/etc/keepalived/keepalived.conf")
_ = os.MkdirAll(filepath.Dir(p), 0o755)
_ = os.WriteFile(p, []byte("vrrp_instance site_vip {}\n"), 0o600)
w := &wiper{root: root, run: func(string, ...string) error { return nil }}
for _, s := range w.plan() {
_ = s.do()
}
if _, err := os.Stat(p); err != nil {
t.Error("someone else's keepalived configuration was removed")
}
}