carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package host
2
3import (
4 "context"
5 "crypto/sha256"
6 "encoding/hex"
7 "github.com/carlosframework/platform/internal/rootparticipation"
8 "github.com/carlosframework/platform/internal/rootstate"
9 "io"
10 "os"
11 "strings"
12 "testing"
13 "time"
14
15 "github.com/carlosframework/platform/internal/hostbox"
16 "github.com/carlosframework/platform/internal/hostclaim"
17 "github.com/carlosframework/platform/internal/hostguard"
18 "github.com/carlosframework/platform/internal/instancectl"
19 "github.com/carlosframework/platform/internal/provision"
20 "github.com/carlosframework/platform/internal/release"
21)
22
23func TestPlan14FreshInstallRegistration(t *testing.T) {
24 t.Parallel()
25 for _, mode := range []string{"new", "writer", "relocation", "landing", "store-failure", "replay", "deleted-history"} {
26 t.Run(mode, func(t *testing.T) {
27 kind, phase := hostclaim.KindServing, ""
28 if mode == "relocation" {
29 kind, phase = hostclaim.KindRelocating, hostclaim.PhaseInstalling
30 }
31 if mode == "landing" {
32 kind, phase = hostclaim.KindLanding, provision.LandChecking
33 }
34 f, root, q := plan14InstallRegistration(t, kind, phase)
35 if mode == "writer" {
36 o, err := hostclaim.Update(t.Context(), f.claims, f.read(), func(c *hostclaim.Claim) error { c.Holder.WriterBox = "box-1"; c.Holder.Session = 1; return nil })
37 if err != nil {
38 t.Fatal(err)
39 }
40 q.Target.ClaimETag, q.Target.Session = o.ETag, 1
41 q = plan14PreparedInventory(t, root, q)
42 }
43 disk := &rollbackDisk{dir: t.TempDir()}
44 history := &release.RootHistory{Store: disk}
45 calls := 0
46 root.history = func(ctx context.Context, fn func(*release.RootHistory) error) error {
47 calls++
48 if mode == "store-failure" {
49 return os.ErrPermission
50 }
51 return fn(history)
52 }
53 out, err := root.commitRootInventory(t.Context(), q)
54 if mode == "store-failure" {
55 if err == nil {
56 t.Fatal("registration ignored history failure")
57 }
58 if _, err = root.Stop.Coordinator.Guard.Capture(q.Target.Host); err == nil {
59 t.Fatal("registered before release exclusion")
60 }
61 return
62 }
63 if err != nil {
64 t.Fatal(err)
65 }
66 if out.Revision != 1 || calls != 1 {
67 t.Fatalf("out=%+v calls=%d", out, calls)
68 }
69 in, err := root.Stop.Coordinator.Guard.Root.View(t.Context(), q.Target.Host, hostguard.Captured{Incarnation: q.Target.Incarnation, Stamp: q.Target.Stamp})
70 if err != nil {
71 t.Fatal(err)
72 }
73 b := release.HistoryBinding{Host: in.Installation.Host, Account: in.Installation.Account, App: in.Installation.App}
74 id := rootHistoryInstallation(in.Installation)
75 if mode == "replay" || mode == "deleted-history" {
76 if mode == "deleted-history" {
77 names, e := disk.Names()
78 if e != nil {
79 t.Fatal(e)
80 }
81 for _, name := range names {
82 if e = disk.Remove(name); e != nil {
83 t.Fatal(e)
84 }
85 }
86 }
87 if _, err = root.commitRootInventory(t.Context(), q); err != nil {
88 t.Fatal(err)
89 }
90 }
91 fresh, err := history.FreshInstallation(b, id)
92 want := mode == "new" || mode == "replay"
93 if want && (err != nil || !fresh) {
94 t.Fatalf("new creation not recorded: %v %v", fresh, err)
95 }
96 if !want && err == nil && fresh {
97 t.Fatal("old installation became fresh")
98 }
99 })
100 }
101}
102
103func TestPlan14FreshInstallLaunchObservation(t *testing.T) {
104 for _, mode := range []string{"ready", "not-ready", "history-failure", "record-failure"} {
105 t.Run(mode, func(t *testing.T) {
106 f := newLaunchFixture(t, servingOp())
107 f.claims.set(func(c *hostclaim.Claim) {
108 c.Holder.Account = "bab"
109 c.Holder.App = "app"
110 c.Holder.Key = "record"
111 c.Holder.Admissions = []hostclaim.AdmissionRecord{{Box: f.target.Box, Region: f.target.Region, Session: f.target.Session, Generation: c.Holder.Generation}}
112 })
113 f.root.Guard.Root = hostguard.NewRootAuthority(&rollbackDisk{dir: t.TempDir()})
114 in := hostguard.RootInstallation{Host: f.target.Host, Account: "bab", App: "app", Record: "record", Incarnation: f.target.Incarnation, Stamp: f.target.Stamp, Box: f.target.Box, Enrollment: f.target.Enrollment, Migration: 1, InventoryRevision: 1}
115 if err := f.root.Guard.EstablishRoot(t.Context(), in, func(*hostclaim.Claim) error { return nil }); err != nil {
116 t.Fatal(err)
117 }
118 h := &release.RootHistory{Store: &rollbackDisk{dir: t.TempDir()}}
119 b := release.HistoryBinding{Host: in.Host, Account: in.Account, App: in.App}
120 if err := h.RecordCreation(b, rootHistoryInstallation(in)); err != nil {
121 t.Fatal(err)
122 }
123 f.root.history = func(ctx context.Context, fn func(*release.RootHistory) error) error {
124 if mode == "history-failure" {
125 return os.ErrPermission
126 }
127 return fn(h)
128 }
129 observed := 0
130 f.root.installedProgram = func(context.Context, hostbox.RoleLaunchRequest, instancectl.ClaimUnitStarted, ClaimLaunchObserved) (string, error) {
131 observed++
132 if mode == "record-failure" {
133 return "", os.ErrPermission
134 }
135 return "actual/program", nil
136 }
137 if mode == "not-ready" {
138 f.kernel.observeErr = os.ErrPermission
139 }
140 _, err := f.root.Serve(t.Context(), f.peer, f.req)
141 if (err == nil) != (mode == "ready") {
142 t.Fatalf("launch: %v", err)
143 }
144 programs, e := h.Programs(b)
145 if e != nil {
146 t.Fatal(e)
147 }
148 if mode == "ready" {
149 if len(programs) != 1 || programs[0] != "actual/program" {
150 t.Fatalf("programs: %v", programs)
151 }
152 } else if len(programs) != 0 {
153 t.Fatal("unobserved program recorded", programs)
154 }
155 fresh, e := h.FreshInstallation(b, rootHistoryInstallation(in))
156 if e != nil || fresh != (mode == "history-failure") {
157 t.Fatalf("fresh after attempt: %v %v", fresh, e)
158 }
159 if mode == "not-ready" && observed != 0 {
160 t.Fatal("recorded unready launch")
161 }
162 })
163 }
164}
165
166func TestPlan14InstalledLaunchProgramEvidence(t *testing.T) {
167 path, err := os.Executable()
168 if err != nil {
169 t.Fatal(err)
170 }
171 file, err := os.Open(path)
172 if err != nil {
173 t.Fatal(err)
174 }
175 id, err := rootstate.Identity(file)
176 if err != nil {
177 t.Fatal(err)
178 }
179 raw, err := io.ReadAll(file)
180 file.Close()
181 if err != nil {
182 t.Fatal(err)
183 }
184 digest := sha256.Sum256(raw)
185 for _, mode := range []string{"observed", "staged-only", "digest", "inode", "process", "unit", "authorization"} {
186 t.Run(mode, func(t *testing.T) {
187 f := newLaunchFixture(t, servingOp())
188 f.req.Executable = path
189 f.req.Spec.Digest = hex.EncodeToString(digest[:])
190 f.req.Reservation.Executable = hostbox.LaunchFile{Device: id.Device, Inode: id.Inode}
191 seen := f.kernel.observed
192 seen.Executable = f.req.Reservation.Executable
193 seen.Running = seen.Executable
194 f.kernel.observed = seen
195 switch mode {
196 case "staged-only":
197 seen.TenantPID = 0
198 f.kernel.observed = seen
199 case "digest":
200 f.req.Spec.Digest = strings.Repeat("0", 64)
201 case "inode":
202 f.req.Reservation.Executable.Inode++
203 case "process":
204 f.kernel.observed.TenantStart = "successor"
205 case "unit":
206 f.units.sameErr = os.ErrPermission
207 case "authorization":
208 f.root.ValidateExecutable = func(string, string, string) error { return os.ErrPermission }
209 }
210 program, err := f.root.rootInstalledProgram(t.Context(), f.req, f.units.started, seen)
211 if mode == "observed" {
212 if err != nil || program != release.FileProgram(path) {
213 t.Fatalf("program=%q: %v", program, err)
214 }
215 } else if err == nil {
216 t.Fatal("accepted", mode)
217 }
218 })
219 }
220}
221
222func TestPlan14FreshInstallCanonicalIdentity(t *testing.T) {
223 t.Parallel()
224 for _, mode := range []string{"canonical", "account", "app", "host", "record", "census", "inventory", "service-files"} {
225 t.Run(mode, func(t *testing.T) {
226 f := newRestartConsumptionFixture(t)
227 rt, err := f.e.root.reg.Get(f.claim.Host)
228 if err != nil {
229 t.Fatal(err)
230 }
231 id, err := f.p.source.creation(t.Context(), *rt)
232 if err != nil || id == "" {
233 t.Fatal(id, err)
234 }
235 switch mode {
236 case "account":
237 rt.Account = "bap"
238 case "app":
239 rt.App = "other"
240 case "host":
241 rt.Host = "other.example"
242 case "record":
243 rec, err := provision.GetRecord(t.Context(), f.e.store, rt.Account, rt.App, rt.Host)
244 if err != nil {
245 t.Fatal(err)
246 }
247 rec.CreatedAt = rec.CreatedAt.Add(time.Second)
248 plan14PutRecord(t, f.e.store, *rec)
249 case "census":
250 f.p.source.census = func() (rootparticipation.Census, error) { return rootparticipation.Census{}, os.ErrPermission }
251 case "inventory":
252 if err := f.p.source.state.Remove(rt.Host + ".json"); err != nil {
253 t.Fatal(err)
254 }
255 case "service-files":
256 if err := f.e.root.reg.Delete(rt.Host); err != nil {
257 t.Fatal(err)
258 }
259 rt.Caps = "host-role"
260 rt.GoodVersion = "invented"
261 rt.Unit = "forged.service"
262 }
263 got, err := f.p.source.creation(t.Context(), *rt)
264 if mode == "canonical" || mode == "service-files" {
265 if err != nil || got != id {
266 t.Fatalf("canonical identity changed: %q %v", got, err)
267 }
268 } else if err == nil {
269 t.Fatal("accepted", mode)
270 }
271 })
272 }
273}
274