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 && rootrunner
2
3package host
4
5import (
6 "os"
7 "os/exec"
8 "path/filepath"
9 "strconv"
10 "testing"
11
12 "github.com/carlosframework/platform/internal/release"
13 "github.com/carlosframework/platform/internal/rootstate"
14)
15
16func TestPlan14GenerationKernelRetirementRootRunner(t *testing.T) {
17 dir := os.Getenv("PLAN14_E25_RETIRE_KERNEL_CHILD")
18 if dir == "" {
19 dir = generationRootRunnerDir(t)
20 cmd := exec.CommandContext(t.Context(), "unshare", "--mount", "--pid", "--fork", "--mount-proc", os.Args[0], "-test.run=^TestPlan14GenerationKernelRetirementRootRunner$", "-test.count=1")
21 cmd.Dir = dir
22 cmd.Env = append(os.Environ(), "PLAN14_E25_RETIRE_KERNEL_CHILD="+dir)
23 if out, err := cmd.CombinedOutput(); err != nil {
24 t.Fatalf("isolated root retirement: %v %s", err, out)
25 }
26 return
27 }
28 t.Setenv("CARLOS_OPT_DIR", dir)
29 path := release.VersionPath(dir, "bab", "v1", "shop")
30 if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
31 t.Fatal(err)
32 }
33 if err := os.WriteFile(path, []byte("retained generation"), 0644); err != nil {
34 t.Fatal(err)
35 }
36 identity := func(path string) rootstate.FileIdentity {
37 t.Helper()
38 file, err := os.Open(path)
39 if err != nil {
40 t.Fatal(err)
41 }
42 defer file.Close()
43 id, err := rootstate.Identity(file)
44 if err != nil {
45 t.Fatal(err)
46 }
47 return id
48 }
49 k := generationKernel{proc: "/proc"}
50 boot, err := k.boot()
51 if err != nil {
52 t.Fatal(err)
53 }
54 controller := exec.CommandContext(t.Context(), "/bin/sleep", "60")
55 controller.Dir = dir
56 if err := controller.Start(); err != nil {
57 t.Fatal(err)
58 }
59 joined := false
60 t.Cleanup(func() {
61 if !joined {
62 _ = controller.Process.Kill()
63 _ = controller.Wait()
64 }
65 })
66 raw, err := generationRead(filepath.Join("/proc", strconv.Itoa(controller.Process.Pid), "stat"))
67 if err != nil {
68 t.Fatal(err)
69 }
70 start, err := generationStart(raw)
71 if err != nil {
72 t.Fatal(err)
73 }
74 r := release.GenerationReservation{Binding: release.GenerationBinding{
75 Binding: release.HistoryBinding{Host: filepath.Base(dir) + ".example", Account: "bab", App: "shop"},
76 Target: release.GenerationOwner{BootID: boot}, Version: "v1", Path: path, Tree: filepath.Dir(path),
77 Executable: identity(path), TreeIdentity: identity(filepath.Dir(path)),
78 ControllerPID: controller.Process.Pid, ControllerStart: start,
79 }}
80 if _, err := productionGenerationAbsence(t.Context(), r); err == nil {
81 t.Fatal("live controller released")
82 }
83 if err := controller.Process.Kill(); err != nil {
84 t.Fatal(err)
85 }
86 _ = controller.Wait()
87 joined = true
88 if digest, err := productionGenerationAbsence(t.Context(), r); err != nil || len(digest) != 64 {
89 t.Fatalf("joined controller: %s %v", digest, err)
90 }
91 file, err := os.Open(path)
92 if err != nil {
93 t.Fatal(err)
94 }
95 if _, err := productionGenerationAbsence(t.Context(), r); err == nil {
96 file.Close()
97 t.Fatal("controller join erased an open reference")
98 }
99 file.Close()
100 if err := os.Rename(filepath.Dir(path), filepath.Dir(path)+".old"); err != nil {
101 t.Fatal(err)
102 }
103 if err := os.Mkdir(filepath.Dir(path), 0755); err != nil {
104 t.Fatal(err)
105 }
106 if err := os.WriteFile(path, []byte("replacement"), 0644); err != nil {
107 t.Fatal(err)
108 }
109 if _, err := productionGenerationAbsence(t.Context(), r); err == nil {
110 t.Fatal("replaced staged tree discharged the original identity")
111 }
112}
113