package cli import ( "archive/tar" "compress/gzip" "io" "os" "path/filepath" "strings" "testing" "time" "gitea.mynodes.xyz/ilker/llmgw/internal/store" ) func TestABackupHoldsTheStoreAndTheConfiguration(t *testing.T) { tmp := t.TempDir() dbPath := filepath.Join(tmp, "store.db") db, err := store.Open(t.Context(), dbPath) if err != nil { t.Fatal(err) } secret, err := db.ClusterSecret(t.Context(), "engine-key") if err != nil { t.Fatal(err) } _ = db.Close() etc := filepath.Join(tmp, "etc") _ = os.MkdirAll(filepath.Join(etc, "pki"), 0o700) _ = os.WriteFile(filepath.Join(etc, "server.yaml"), []byte("listen: :8080\n"), 0o644) _ = os.WriteFile(filepath.Join(etc, "pki", "ca-key.pem"), []byte("KEY"), 0o600) out := filepath.Join(tmp, "backups") path, err := writeBackup(t.Context(), dbPath, etc, out) if err != nil { t.Fatal(err) } info, _ := os.Stat(path) if info.Mode().Perm() != 0o600 { t.Errorf("the archive holds the CA's key and is %v", info.Mode().Perm()) } files := map[string][]byte{} f, _ := os.Open(path) defer f.Close() gz, err := gzip.NewReader(f) if err != nil { t.Fatal(err) } tr := tar.NewReader(gz) for { h, err := tr.Next() if err == io.EOF { break } if err != nil { t.Fatal(err) } b, _ := io.ReadAll(tr) files[h.Name] = b } for _, want := range []string{"MANIFEST", "store.sqlite", "etc/llmgw/server.yaml", "etc/llmgw/pki/ca-key.pem"} { if _, ok := files[want]; !ok { t.Errorf("%s is not in the archive", want) } } // And the store in it is a working store, with what was in it. restored := filepath.Join(tmp, "restored.db") _ = os.WriteFile(restored, files["store.sqlite"], 0o600) rdb, err := store.Open(t.Context(), restored) if err != nil { t.Fatalf("the backed-up store does not open: %v", err) } defer rdb.Close() if got, _ := rdb.ClusterSecret(t.Context(), "engine-key"); got != secret { t.Error("the restored store lost the engine key secret; every engine would be locked out") } } func TestOldBackupsArePrunedAndTheNewestIsFound(t *testing.T) { dir := t.TempDir() for i, stamp := range []string{"20260101T000000Z", "20260102T000000Z", "20260103T000000Z"} { p := filepath.Join(dir, backupPrefix+"h-"+stamp+".tar.gz") _ = os.WriteFile(p, []byte("x"), 0o600) mt := time.Date(2026, 1, 1+i, 0, 0, 0, 0, time.UTC) _ = os.Chtimes(p, mt, mt) } _ = os.WriteFile(filepath.Join(dir, "someone-elses-file"), []byte("x"), 0o600) _ = os.WriteFile(filepath.Join(dir, backupPrefix+"h-20260104T000000Z.tar.gz.part"), []byte("x"), 0o600) removed, err := pruneBackups(dir, 2) if err != nil || removed != 1 { t.Fatalf("removed %d, %v", removed, err) } if _, err := os.Stat(filepath.Join(dir, "someone-elses-file")); err != nil { t.Error("a file the backup did not write was removed") } newest := NewestBackup(dir) if !newest.Equal(time.Date(2026, 1, 3, 0, 0, 0, 0, time.UTC)) { t.Errorf("newest %v; an interrupted .part must not count", newest) } if !NewestBackup(filepath.Join(dir, "none")).IsZero() { t.Error("a missing directory reported a backup") } } func TestABackupDirectoryTheControlPlaneCannotListIsSaid(t *testing.T) { dir := t.TempDir() _ = os.Chmod(dir, 0o700) if unlistable(dir) == "" { t.Error("a directory only its owner can list was taken as visible") } _ = os.Chmod(dir, 0o755) if why := unlistable(dir); why != "" { t.Errorf("a listable directory: %s", why) } } func TestNoScratchCopyOfTheStoreIsLeftBehind(t *testing.T) { // The snapshot is made before it is archived. Made straight into the // listable archive directory, it was readable by anyone for that time. tmp := t.TempDir() dbPath := filepath.Join(tmp, "store.db") db, err := store.Open(t.Context(), dbPath) if err != nil { t.Fatal(err) } _ = db.Close() out := filepath.Join(tmp, "backups") if _, err := writeBackup(t.Context(), dbPath, t.TempDir(), out); err != nil { t.Fatal(err) } entries, _ := os.ReadDir(out) for _, e := range entries { if strings.HasPrefix(e.Name(), ".store") { t.Errorf("a scratch copy of the store was left behind: %s", e.Name()) } } } func TestAStoreOfSeveralHostsIsGivenToPgDumpAsLibpqLists(t *testing.T) { // The address of a Patroni cluster: url.Parse read its host as one name, // and pg_dump reached the database only by falling through to the second. env, err := pgEnv("postgres://llmgw:s3cret@10.0.0.149:5432,10.0.0.150/llmgw?sslmode=disable&target_session_attrs=read-write") if err != nil { t.Fatal(err) } got := strings.Join(env, " ") for _, want := range []string{"PGHOST=10.0.0.149,10.0.0.150", "PGPORT=5432,5432", "PGUSER=llmgw", "PGPASSWORD=s3cret", "PGDATABASE=llmgw", "PGSSLMODE=disable", "PGTARGETSESSIONATTRS=prefer-standby"} { if !strings.Contains(got, want) { t.Errorf("%s is not in %s", want, got) } } one, err := pgEnv("postgres://u:p@db.internal:6432/llmgw") if err != nil || !strings.Contains(strings.Join(one, " "), "PGHOST=db.internal PGPORT=6432") { t.Errorf("one host: %v, %v", one, err) } if _, err := pgEnv("postgres://u:p@a:5432,:5432/x"); err == nil { t.Error("an empty host in the list was accepted") } }