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 unix
2
3package host
4
5import (
6 "errors"
7 "os"
8 "path/filepath"
9 "testing"
10 "time"
11
12 "github.com/carlosframework/platform/internal/hostbox"
13 "github.com/carlosframework/platform/internal/hostclaim"
14 "github.com/carlosframework/platform/internal/provision"
15 "github.com/carlosframework/platform/internal/registry"
16 "github.com/carlosframework/platform/internal/release"
17)
18
19// Astra round 2 finding 8, ruling 61: an empty installation initialises with
20// a previous relocation's journals present under relocate/ (N9 classifies
21// the directory as the claim classifies its own journals); without the
22// classification the same tree refuses, which is the defect.
23func TestCensusInitializesWithOldRelocationJournals(t *testing.T) {
24 t.Parallel()
25 censusWithSharedFiles(t, "relocate", map[string]string{
26 "relocate/ops/op-old/install.json": `{"v":1,"host":"old.example","op":"op-old"}`,
27 "relocate/ops/op-old/attempts.json": `{"v":1,"host":"old.example","op":"op-old"}`,
28 "relocate/release/op-old.json": `{"v":1,"request":{"Host":"old.example"}}`,
29 "relocate/build/op-old/old.example.db": "scratch",
30 })
31}
32
33// censusWithSharedFiles plants files under a production box's data root
34// and checks an empty installation of another host initialises with them,
35// and refuses once the shared entry named classified is taken out of
36// claimGlobalSharedPaths.
37func censusWithSharedFiles(t *testing.T, classified string, files map[string]string) {
38 t.Helper()
39 ctx := t.Context()
40 r := claimCensusBox(t)
41 reg, err := registry.Open(filepath.Join(r.DataDir, "registry.db"))
42 if err != nil {
43 t.Fatal(err)
44 }
45 defer reg.Close()
46 inventory, err := openLegacyInventory(t, filepath.Join(r.DataDir, ".hostclaims", "inventory.db"))
47 if err != nil {
48 t.Fatal(err)
49 }
50 defer inventory.Close()
51 launches, err := hostbox.OpenLaunchJournal(filepath.Join(r.DataDir, ".hostclaims", "launches.db"))
52 if err != nil {
53 t.Fatal(err)
54 }
55 defer launches.Close()
56 for path, body := range files {
57 full := filepath.Join(r.DataDir, filepath.FromSlash(path))
58 if err := os.MkdirAll(filepath.Dir(full), 0o700); err != nil {
59 t.Fatal(err)
60 }
61 if err := os.WriteFile(full, []byte(body), 0o600); err != nil {
62 t.Fatal(err)
63 }
64 }
65 store := release.NewDirStore(t.TempDir())
66 created := time.Date(2026, 10, 7, 0, 0, 0, 0, time.UTC)
67 record := provision.Record{Schema: 1, Host: "shop.example", Slug: "shop", App: "app", Account: "acct", Region: "ie", Channel: "stable", CreatedAt: created}
68 if err := provision.CreateRecord(ctx, store, record); err != nil {
69 t.Fatal(err)
70 }
71 key := provision.RecordKey(record.Account, record.App, record.Host)
72 obs, err := hostclaim.Read(ctx, store, record.Host)
73 if err != nil {
74 t.Fatal(err)
75 }
76 obs, err = hostclaim.Update(ctx, store, obs, hostclaim.Adopt(hostclaim.NewHolder{Family: "instance", Key: key, Account: record.Account, App: record.App, Host: record.Host, Region: record.Region, CreatedAt: created}, "box", nil, nil, "adopt", func() string { return "id" }))
77 if err != nil {
78 t.Fatal(err)
79 }
80 selected := hostbox.RecordSelection{Host: record.Host, Incarnation: obs.Claim.Holder.Incarnation}
81 census := hostbox.EmptyInstallationCensus{Inventory: inventory, Registry: reg, Launches: launches, Box: "box", Enrollment: "enrollment", DirectoryRevision: "1",
82 Roots: map[string]string{"data": r.DataDir, "opt": r.OptDir, "units": r.UnitsDir}, SharedPaths: claimGlobalSharedPaths(r)}
83 unclassified := census
84 unclassified.SharedPaths = map[string][]string{}
85 for root, entries := range claimGlobalSharedPaths(r) {
86 for _, e := range entries {
87 if e != classified {
88 unclassified.SharedPaths[root] = append(unclassified.SharedPaths[root], e)
89 }
90 }
91 }
92 if err := unclassified.Initialize(ctx, obs, selected); !errors.Is(err, hostbox.ErrTypedInventory) {
93 t.Fatalf("without %s classified the files were accepted: %v", classified, err)
94 }
95 if err := census.Initialize(ctx, obs, selected); err != nil {
96 t.Fatalf("initialisation with %s present: %v", classified, err)
97 }
98}
99