carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1//go:build linux
2
3package host
4
5import (
6 "os"
7 "path/filepath"
8 "testing"
9
10 "github.com/carlosframework/platform/internal/activator"
11 "github.com/carlosframework/platform/internal/registry"
12 "github.com/carlosframework/platform/internal/release"
13)
14
15// The wired LocalSeedID and RemoveLocal are Plan 4's marker read and purge
16// (preflight M12), through instancefs: the marker names the seed, and the
17// removal takes the database, its WAL and SHM, the marker and the seed
18// fetch leftovers, and leaves anything else in the directory.
19func TestWiredRollbackReadsAndRemovesTheLocalSeed(t *testing.T) {
20 h := wiredSeedHooks(t, &fakeFence{gens: map[string]uint64{}}, restartTestRegistry(t),
21 release.NewDirStore(t.TempDir()), release.NewDirStore(t.TempDir()))
22 const id = "sd_aaaaaaaaaaaaaaaaaaaaaaaaaa"
23 dir := filepath.Join(t.TempDir(), "shop-1.example.com")
24 if err := os.MkdirAll(dir, 0o700); err != nil {
25 t.Fatal(err)
26 }
27 db := filepath.Join(dir, "shop-1.example.com.db")
28 gone := []string{db, db + "-wal", db + "-shm", db + activator.SeedMarkerSuffix, filepath.Join(dir, ".seed-sd_x.tmp")}
29 for _, p := range gone {
30 body := "data"
31 if p == db+activator.SeedMarkerSuffix {
32 body = id + "\n"
33 }
34 if err := os.WriteFile(p, []byte(body), 0o600); err != nil {
35 t.Fatal(err)
36 }
37 }
38 kept := filepath.Join(dir, "uploads.txt")
39 if err := os.WriteFile(kept, []byte("keep"), 0o600); err != nil {
40 t.Fatal(err)
41 }
42
43 if got, err := h.LocalSeedID(db); err != nil || got != id {
44 t.Fatalf("LocalSeedID = %q, %v; want %q", got, err, id)
45 }
46 if err := h.RemoveLocal(registry.Route{Host: "shop-1.example.com", Kind: "instance", DBPath: db}); err != nil {
47 t.Fatal(err)
48 }
49 for _, p := range gone {
50 if _, err := os.Lstat(p); !os.IsNotExist(err) {
51 t.Errorf("%s survived the removal (%v)", p, err)
52 }
53 }
54 if _, err := os.Stat(kept); err != nil {
55 t.Errorf("an unrelated file went: %v", err)
56 }
57 if got, err := h.LocalSeedID(db); err != nil || got != "" {
58 t.Fatalf("LocalSeedID after the removal = %q, %v", got, err)
59 }
60 if err := h.RemoveLocal(registry.Route{Host: "shop-1.example.com", Kind: "instance", DBPath: db}); err != nil {
61 t.Fatalf("a second removal: %v", err)
62 }
63}
64
65// Merge review S1: the wired EnvBefore and RetireKey are the activator's
66// read of the host's own env file and its retirement of the import's key.
67// A file the import created goes; a key that was there before stays.
68func TestWiredSwapAndRollbackKnowTheImportsInstanceKey(t *testing.T) {
69 h := wiredSeedHooks(t, &fakeFence{gens: map[string]uint64{}}, restartTestRegistry(t),
70 release.NewDirStore(t.TempDir()), release.NewDirStore(t.TempDir()))
71 const host = "shop-1.example.com"
72 dir := filepath.Join(t.TempDir(), host)
73 if err := os.MkdirAll(dir, 0o700); err != nil {
74 t.Fatal(err)
75 }
76 db, env := filepath.Join(dir, host+".db"), filepath.Join(dir, host+".env")
77 if got, err := h.EnvBefore(db, host); err != nil || got != registry.EnvBeforeAbsent {
78 t.Fatalf("EnvBefore with no file = %q, %v", got, err)
79 }
80 body := activator.InstanceKeyVar + "=minted-by-the-import\n"
81 if err := os.WriteFile(env, []byte(body), 0o600); err != nil {
82 t.Fatal(err)
83 }
84 if got, err := h.EnvBefore(db, host); err != nil || got != registry.EnvBeforeKey {
85 t.Fatalf("EnvBefore with a key = %q, %v", got, err)
86 }
87 if err := h.RetireKey(db, host, registry.EnvBeforeKey); err != nil {
88 t.Fatal(err)
89 }
90 if got, err := os.ReadFile(env); err != nil || string(got) != body {
91 t.Fatalf("a key that predated the import was touched: %q, %v", got, err)
92 }
93 if err := h.RetireKey(db, host, registry.EnvBeforeAbsent); err != nil {
94 t.Fatal(err)
95 }
96 if _, err := os.Lstat(env); !os.IsNotExist(err) {
97 t.Fatalf("the env file the import created survived (%v)", err)
98 }
99}
100