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/hostbox"
11 "github.com/carlosframework/platform/internal/hostclaim"
12 "github.com/carlosframework/platform/internal/hostguard"
13 "github.com/carlosframework/platform/internal/provision"
14)
15
16func TestPlan14EmptyCensusRootSibling(t *testing.T) {
17 for _, fault := range []string{"none", "missing-root", "wrong-revision", "rename", "unclassified", "selected-host", "private-alias-substitution", "private-alias-symlink"} {
18 t.Run(fault, func(t *testing.T) {
19 f, _, _ := generationLaunchFixture(t)
20 root := t.TempDir()
21 rel := filepath.Join("instances", provision.InstanceID(f.target.Host))
22 path := filepath.Join(root, rel)
23 if err := os.MkdirAll(path, 0700); err != nil {
24 t.Fatal(err)
25 }
26 if err := os.WriteFile(filepath.Join(path, "app.db"), []byte("live sibling"), 0600); err != nil {
27 t.Fatal(err)
28 }
29 id, err := hostbox.CaptureInventoryIdentity(root, rel)
30 if err != nil {
31 t.Fatal(err)
32 }
33 service, err := hostbox.NewJournalService(f.journal)
34 if err != nil {
35 t.Fatal(err)
36 }
37 in := hostbox.StopInventory{Complete: true, Host: f.target.Host, Incarnation: f.target.Incarnation, InstallationStamp: f.target.Stamp, Box: f.target.Box, Enrollment: f.target.Enrollment, DirectoryRevision: "1", Entries: []hostbox.StopInventoryEntry{{Kind: "path", ManagedRoot: "data", RelativePath: rel, ArtifactID: "state", Ownership: "owner", Materialization: "materialized", Device: id.Device, Inode: id.Inode, Type: 0040000, Identity: id}}}
38 if err := service.Inventory.WriteStopInventory(t.Context(), in); err != nil {
39 t.Fatal(err)
40 }
41 reg := restartTestRegistry(t)
42 c := hostbox.EmptyInstallationCensus{Inventory: service.Inventory, Registry: reg, Launches: f.journal, Box: f.target.Box, Enrollment: f.target.Enrollment, DirectoryRevision: "1", Roots: map[string]string{"data": root, "opt": t.TempDir(), "units": t.TempDir()}}
43 h := ClaimRootHTTP{Launches: f.journal, Roots: c.Roots, Stop: ClaimStopHTTP{Coordinator: ClaimStopCoordinator{Guard: f.root.Guard}}}
44 c.OtherPath = h.rootSiblingPath
45 switch fault {
46 case "missing-root":
47 h.Stop.Coordinator.Guard.Root = hostguard.NewRootAuthority(&rollbackDisk{dir: t.TempDir()})
48 c.OtherPath = h.rootSiblingPath
49 case "wrong-revision":
50 if err := service.Inventory.WriteStopInventory(t.Context(), in); err != nil {
51 t.Fatal(err)
52 }
53 case "rename":
54 if err := os.Rename(path, path+"-old"); err != nil {
55 t.Fatal(err)
56 }
57 if err := os.Mkdir(path, 0700); err != nil {
58 t.Fatal(err)
59 }
60 case "private-alias-substitution", "private-alias-symlink":
61 private := filepath.Join(root, ".instances", provision.InstanceID(f.target.Host))
62 if err := os.MkdirAll(filepath.Dir(private), 0700); err != nil {
63 t.Fatal(err)
64 }
65 if fault == "private-alias-symlink" {
66 if err := os.Symlink(path, private); err != nil {
67 t.Fatal(err)
68 }
69 } else {
70 if err := os.Mkdir(private, 0700); err != nil {
71 t.Fatal(err)
72 }
73 }
74 case "unclassified":
75 if err := os.WriteFile(filepath.Join(root, "unknown"), []byte("x"), 0600); err != nil {
76 t.Fatal(err)
77 }
78 }
79 selected := "new.example"
80 if fault == "selected-host" {
81 selected = f.target.Host
82 }
83 obs := hostclaim.Observed{Host: selected, Claim: &hostclaim.Claim{Holder: &hostclaim.Holder{Incarnation: "new", Stamp: 1}}}
84 if fault == "none" {
85 c.OtherPath = nil
86 if err := c.CheckLocal(t.Context(), obs, hostbox.RecordSelection{Host: selected, Incarnation: "new"}); err == nil {
87 t.Fatal("unclassified sibling unexpectedly admitted")
88 }
89 c.OtherPath = h.rootSiblingPath
90 }
91 err = c.CheckLocal(t.Context(), obs, hostbox.RecordSelection{Host: selected, Incarnation: "new"})
92 if (err == nil) != (fault == "none") {
93 t.Fatal("empty census", fault, err)
94 }
95
96 })
97 }
98}
99