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 "encoding/json"
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 "github.com/carlosframework/platform/internal/registry"
15)
16
17func TestPlan14InventoryRequirementsRegistration(t *testing.T) {
18 t.Parallel()
19 for _, kind := range []string{"stateful", "service"} {
20 t.Run(kind, func(t *testing.T) {
21 f, root, q := plan14InstallRegistration(t, hostclaim.KindServing, "")
22 // Use the claim's canonical account/app, independently of fixture defaults.
23 h := f.read().Claim.Holder
24 rec, _, err := provision.GetRecordETag(t.Context(), f.claims, h.Account, h.App, q.Target.Host)
25 if err != nil {
26 t.Fatal(err)
27 }
28 if kind == "service" {
29 rec.Kind, rec.Addr = "service", "127.0.0.1:8080"
30 plan14PutRecord(t, f.claims, *rec)
31 _, q.RecordETag, err = f.claims.Get(t.Context(), q.RecordKey)
32 if err != nil {
33 t.Fatal(err)
34 }
35 }
36 _, initial := hostbox.RemoteJournals(func(ctx context.Context, prepared hostbox.JournalRequest) (hostbox.JournalResponse, error) {
37 q = prepared
38 return root.commitRootInventory(ctx, prepared)
39 })
40 if _, err := initial.WriteExpected(t.Context(), q.Inventory, hostbox.InventoryExpectation{RecordKey: q.RecordKey, RecordETag: q.RecordETag, Target: q.Target}); err != nil {
41 t.Fatal(err)
42 }
43 views, err := root.Stop.Coordinator.Guard.Root.GenerationInstallations(t.Context())
44 if err != nil || len(views) != 1 {
45 t.Fatal(views, err)
46 }
47 want := hostguard.InstallationArtifacts{Schema: 1, StateDirectory: kind == "stateful"}
48 if views[0].Installation.Artifacts != want {
49 t.Fatalf("root requirements: %+v want %+v", views[0].Installation.Artifacts, want)
50 }
51 if _, err := root.commitRootInventory(t.Context(), q); err != nil {
52 t.Fatal("replay", err)
53 }
54 rec.Kind, rec.Addr = "service", "127.0.0.1:8080"
55 plan14PutRecord(t, f.claims, *rec)
56 _, etag, err := f.claims.Get(t.Context(), q.RecordKey)
57 if err != nil {
58 t.Fatal(err)
59 }
60 _, client := hostbox.RemoteJournals(root.commitRootInventory)
61 if _, err := client.WriteExpected(t.Context(), q.Inventory, hostbox.InventoryExpectation{Revision: 1, RecordKey: q.RecordKey, RecordETag: etag, Target: q.Target}); err != nil {
62 t.Fatal(err)
63 }
64 views, err = root.Stop.Coordinator.Guard.Root.GenerationInstallations(t.Context())
65 if err != nil || views[0].Installation.Artifacts != want {
66 t.Fatalf("shape change erased history: %+v %v", views, err)
67 }
68 })
69 }
70}
71
72func TestPlan14InventoryRequirementsUnknownAndRatchet(t *testing.T) {
73 prior := hostguard.RootInstallation{}
74 row := registry.Route{DBPath: "/data/instances/tenant.example/state.db"}
75 in := hostbox.StopInventory{Host: "tenant.example", Entries: []hostbox.StopInventoryEntry{{Kind: "timer", RelativePath: "tenant.example/backup"}}}
76 if got, err := rootInventoryArtifacts(prior, row, in, 2); err != nil || got != (hostguard.InstallationArtifacts{}) {
77 t.Fatalf("unknown history initialized: %+v %v", got, err)
78 }
79 prior.Artifacts = hostguard.InstallationArtifacts{Schema: 1, StateDirectory: true, Timers: "backup"}
80 got, err := rootInventoryArtifacts(prior, registry.Route{}, hostbox.StopInventory{Host: in.Host}, 2)
81 if err != nil || got != prior.Artifacts {
82 t.Fatal("lost old requirements", got, err)
83 }
84 for _, bad := range []hostguard.InstallationArtifacts{{}, {Schema: 2}, {Schema: 1, Timers: "backup\nbackup"}, {Schema: 1, Timers: "z\na"}, {Schema: 1, Timers: "../other"}, {Schema: 1, Timers: "backup\n"}} {
85 if _, err := inventoryTimerNames(bad); err == nil {
86 t.Fatalf("accepted malformed requirements: %+v", bad)
87 }
88 }
89}
90
91func TestPlan14InventoryRequirementsHistoryIdentity(t *testing.T) {
92 in := hostguard.RootInstallation{Host: "tenant.example", Incarnation: "inc", Stamp: 3, Account: "bab", App: "shop", Record: "record", Box: "box", Enrollment: "en", Migration: 1}
93 // This is the pre-E37 wire shape, including its field order.
94 raw := []byte(`{"Registration":{"Op":"","Kind":"","Phase":"","RowID":"","Session":0},"Empty":false,"Host":"tenant.example","Incarnation":"inc","Account":"bab","App":"shop","Record":"record","Box":"box","Enrollment":"en","Stamp":3,"Migration":1,"InventoryRevision":0}`)
95 var check hostguard.RootInstallation
96 if err := json.Unmarshal(raw, &check); err != nil || check != in {
97 t.Fatal(check, err)
98 }
99 sum := sha256.Sum256(raw)
100 want := hex.EncodeToString(sum[:])
101 for _, a := range []hostguard.InstallationArtifacts{{}, {Schema: 1, StateDirectory: true, Timers: "backup"}} {
102 in.Artifacts = a
103 if got := rootHistoryInstallation(in); got != want {
104 t.Fatalf("installation identity changed: %s want %s", got, want)
105 }
106 }
107}
108