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 "database/sql"
5 "errors"
6 "github.com/carlosframework/platform/internal/hostclaim"
7 "github.com/carlosframework/platform/internal/hostguard"
8 "github.com/carlosframework/platform/internal/provision"
9 "testing"
10 "time"
11)
12
13func TestPlan14Fix2InventoryReceiptPruned(t *testing.T) {
14 f, root, q := plan14InstallRegistration(t, hostclaim.KindLanding, provision.LandChecking)
15 state := &plan14RegistrationCrash{rollbackDisk: &rollbackDisk{dir: t.TempDir()}}
16 root.Stop.Coordinator.Guard.Root = hostguard.NewRootAuthority(state)
17 if _, err := root.commitRootInventory(t.Context(), q); err == nil {
18 t.Fatal("missing crash")
19 }
20 db, err := sql.Open("sqlite", f.journalPath)
21 if err != nil {
22 t.Fatal(err)
23 }
24 defer db.Close()
25 if _, err = db.Exec("DELETE FROM journal_requests"); err != nil {
26 t.Fatal(err)
27 }
28 if err := root.recoverRootInventory(t.Context()); err != nil {
29 t.Fatal(err)
30 }
31 view, err := root.Stop.Coordinator.Guard.Root.View(t.Context(), q.Target.Host, hostguard.Captured{Incarnation: q.Target.Incarnation, Stamp: q.Target.Stamp})
32 if err != nil || view.Installation.InventoryRevision != 1 {
33 t.Fatalf("root commit not recovered: %+v %v", view, err)
34 }
35}
36func TestPlan14Fix2OldInventoryRequestLeavesNoIntent(t *testing.T) {
37 _, root, q := plan14InstallRegistration(t, hostclaim.KindLanding, provision.LandChecking)
38 q.IssuedAt = time.Now().Add(-time.Hour).UnixNano()
39 if _, err := root.commitRootInventory(t.Context(), q); err == nil {
40 t.Fatal("old request accepted")
41 }
42 pending, err := root.Stop.Coordinator.Guard.Root.PendingInstallations()
43 if err != nil || len(pending) != 0 {
44 t.Fatal("old request fenced host", pending, err)
45 }
46}
47func TestPlan14Fix2CommittedInventoryAfterETagChange(t *testing.T) {
48 t.Parallel()
49 f, root, q := plan14InstallRegistration(t, hostclaim.KindLanding, provision.LandChecking)
50 state := &plan14RegistrationCrash{rollbackDisk: &rollbackDisk{dir: t.TempDir()}}
51 root.Stop.Coordinator.Guard.Root = hostguard.NewRootAuthority(state)
52 if _, err := root.commitRootInventory(t.Context(), q); err == nil {
53 t.Fatal("missing crash")
54 }
55 // Change the claim without changing its holder tuple.
56 obs := f.read()
57 obs.Claim.Op.Journal["fix2"] = "changed"
58 if _, err := hostclaim.Update(t.Context(), f.claims, f.read(), func(c *hostclaim.Claim) error { c.Op.Journal["fix2"] = "changed"; return nil }); err != nil {
59 t.Fatal(err)
60 }
61 // The committed request still completes after an ETag-only change.
62 if err := root.recoverRootInventory(t.Context()); err != nil {
63 t.Fatal(err)
64 }
65 _, err := root.Stop.Coordinator.Guard.Root.PendingInstallations()
66 if err != nil && !errors.Is(err, hostguard.ErrFenced) {
67 t.Fatal(err)
68 }
69}
70
71func TestPlan14Fix2SupersededInventoryIntentAbandoned(t *testing.T) {
72 f, root, q := plan14InstallRegistration(t, hostclaim.KindLanding, provision.LandChecking)
73 state := &rollbackDisk{dir: t.TempDir()}
74 root.Stop.Coordinator.Guard.Root = hostguard.NewRootAuthority(state)
75 state.afterWrite = func(string, []byte) { state.afterWrite = nil; _ = root.Reconcile.Registry.Close() }
76 if _, err := root.commitRootInventory(t.Context(), q); err == nil {
77 t.Fatal("closed registry accepted commit")
78 }
79 pending, err := root.Stop.Coordinator.Guard.Root.PendingInstallations()
80 if err != nil || len(pending) != 1 {
81 t.Fatal("missing pending intent", pending, err)
82 }
83 if _, err := hostclaim.Update(t.Context(), f.claims, f.read(), func(c *hostclaim.Claim) error { c.Op.Journal["fix2"] = "changed"; return nil }); err != nil {
84 t.Fatal(err)
85 }
86 if err := root.recoverRootInventory(t.Context()); err != nil {
87 t.Fatal(err)
88 }
89 pending, err = root.Stop.Coordinator.Guard.Root.PendingInstallations()
90 if err != nil || len(pending) != 0 {
91 t.Fatal("superseded intent survived", pending, err)
92 }
93 _, err = root.Stop.Coordinator.Guard.Root.View(t.Context(), q.Target.Host, hostguard.Captured{Incarnation: q.Target.Incarnation, Stamp: q.Target.Stamp})
94 if !errors.Is(err, hostguard.ErrFenced) {
95 t.Fatal("abandon removed quarantine", err)
96 }
97}
98