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 "strings"
9 "testing"
10 "time"
11
12 "github.com/carlosframework/platform/internal/hostbox"
13 "github.com/carlosframework/platform/internal/hostguard"
14 "github.com/carlosframework/platform/internal/instancectl"
15 "github.com/carlosframework/platform/internal/release"
16)
17
18func TestPlan14RetiredGenerationBoundary(t *testing.T) {
19 for _, mode := range []string{"retired", "active sibling", "live installation", "pending pin", "open pin", "named", "legacy process", "open writers", "pending unit", "foreign receipt", "bad receipt", "barrier", "missing installation", "missing launches", "missing reservation"} {
20 t.Run(mode, func(t *testing.T) {
21 target := hostguard.FenceTarget{Host: "shop.example", Incarnation: "inc", Stamp: 3, Session: 4, Box: "box", Enrollment: "en", BootID: "boot", ControllerID: "controller", FenceID: "fence", Op: "delete", ObligationID: "park", RosterRevision: 1}
22 at := time.Now().UTC()
23 s := StopReceipt{Kind: "stopped", DirectoryRevision: testReceiptNumeral(target), Host: target.Host, Incarnation: target.Incarnation, InstallationStamp: target.Stamp, WriterSession: target.Session, Box: target.Box, Enrollment: target.Enrollment, BootID: target.BootID, ControllerID: target.ControllerID, FenceID: target.FenceID, OperationID: target.Op, ObligationID: target.ObligationID, EvidenceAt: at}
24 view := hostguard.FenceView{Host: target.Host, Installation: hostguard.RootInstallation{Host: target.Host, Incarnation: target.Incarnation, Stamp: target.Stamp}, Retired: []hostguard.Captured{{Incarnation: target.Incarnation, Stamp: target.Stamp}}, Receipts: []hostguard.FenceReceipt{{Target: target, Bytes: mustMarshalStopReceipt(s), EvidenceAt: at}}}
25 inv := generationInventory{Installations: []hostguard.FenceView{view}, Launches: []hostbox.LaunchInventory{{Target: target, WritersClosed: true, Reservations: []hostbox.LaunchReservation{{Target: target, State: hostbox.UnitSettled, Group: hostbox.LaunchGroup{RelativePath: instancectl.ClaimUnitControlGroup(target.Host)}}}}}}
26 records := []release.GenerationReservation{{Binding: release.GenerationBinding{Target: generationOwner(target)}, Closed: true, Retirement: strings.Repeat("a", 64)}}
27 switch mode {
28 case "active sibling":
29 sibling := hostguard.FenceView{Host: "sibling.example", Installation: hostguard.RootInstallation{Host: "sibling.example", Incarnation: "sibling", Stamp: 1}}
30 inv.Installations = append(inv.Installations, sibling)
31 inv.Launches = append(inv.Launches, hostbox.LaunchInventory{Target: hostguard.FenceTarget{Host: "sibling.example", Incarnation: "sibling", Stamp: 1}})
32 records = append(records, release.GenerationReservation{Binding: release.GenerationBinding{Target: release.GenerationOwner{Host: "sibling.example", Incarnation: "sibling", Stamp: 1}}})
33 case "live installation":
34 inv.Installations[0].Retired = nil
35 case "pending pin":
36 records[0].Retirement = ""
37 case "open pin":
38 records[0].Closed = false
39 case "named":
40 records[0].Binding.Unit = "console.service"
41 case "legacy process":
42 records[0].Process.PID = 10
43 case "open writers":
44 inv.Launches[0].WritersClosed = false
45 case "pending unit":
46 inv.Launches[0].Reservations[0].State = hostbox.UnitIntended
47 case "foreign receipt":
48 inv.Installations[0].Receipts[0].Target.Session++
49 case "bad receipt":
50 inv.Installations[0].Receipts[0].Bytes = []byte("{}")
51 case "barrier":
52 inv.Installations[0].Barrier = &target
53 case "missing installation":
54 inv.Installations = nil
55 case "missing launches":
56 inv.Launches = nil
57 case "missing reservation":
58 records = nil
59 }
60 if got := retiredGenerationSnapshot(t.Context(), inv, records); got != (mode == "retired" || mode == "active sibling") {
61 t.Fatalf("boundary = %v", got)
62 }
63 })
64 }
65}
66
67func TestPlan14RetiredGenerationGroups(t *testing.T) {
68 root := filepath.Join(t.TempDir(), "groups")
69 if err := emptyGenerationGroups(t.Context(), root); err != nil {
70 t.Fatal(err)
71 }
72 if err := os.MkdirAll(filepath.Join(root, "unknown"), 0700); err != nil {
73 t.Fatal(err)
74 }
75 for _, group := range []string{root, filepath.Join(root, "unknown")} {
76 if err := os.WriteFile(filepath.Join(group, "cgroup.procs"), nil, 0600); err != nil {
77 t.Fatal(err)
78 }
79 }
80 if err := emptyGenerationGroups(t.Context(), root); err != nil {
81 t.Fatal(err)
82 }
83 path := filepath.Join(root, "unknown", "cgroup.procs")
84 if err := os.WriteFile(path, []byte("42\n"), 0600); err != nil {
85 t.Fatal(err)
86 }
87 if err := emptyGenerationGroups(t.Context(), root); err == nil {
88 t.Fatal("unrecorded managed process ignored")
89 }
90 if err := os.Remove(path); err != nil {
91 t.Fatal(err)
92 }
93 if err := emptyGenerationGroups(t.Context(), root); err == nil {
94 t.Fatal("missing kernel evidence accepted")
95 }
96}
97
98func TestPlan14GenerationEarlyBootStart(t *testing.T) {
99 for _, start := range []string{"0", "1", "-1", "not-a-number", "18446744073709551616"} {
100 got, err := generationStart([]byte("1 (init) S " + strings.Repeat("0 ", 18) + start))
101 if start == "0" || start == "1" {
102 if err != nil || got != start {
103 t.Fatalf("start %s: %s %v", start, got, err)
104 }
105 } else if err == nil {
106 t.Fatalf("invalid start accepted: %s", start)
107 }
108 }
109}
110