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 "encoding/json"
7 "os"
8 "path/filepath"
9 "testing"
10 "time"
11
12 "github.com/carlosframework/platform/internal/hostclaim"
13 "github.com/carlosframework/platform/internal/hostguard"
14 "github.com/carlosframework/platform/internal/provision"
15 "github.com/carlosframework/platform/internal/release"
16 "github.com/carlosframework/platform/internal/rollout"
17 "github.com/carlosframework/platform/internal/rootparticipation"
18 "github.com/carlosframework/platform/internal/rootstate"
19)
20
21func TestPlan14RootFailureProductionOpener(t *testing.T) {
22 if os.Geteuid() != 0 {
23 t.Fatal("root required")
24 }
25 for _, path := range []string{"/var/lib/carlos-claims", "/var/lib/carlos-release", rootRetryProjection} {
26 if err := os.Mkdir(path, 0755); err != nil {
27 t.Fatal("existing fixture", path, err)
28 }
29 path := path
30 t.Cleanup(func() { os.RemoveAll(path) })
31 }
32 state, err := rootstate.Open(rootparticipation.Namespace, true, false)
33 if err != nil {
34 t.Fatal(err)
35 }
36 c := rootparticipation.Census{Schema: 1, Box: "box", Enrollment: "en", Migration: 1, Revision: 1, LaunchRevision: 1, Complete: true}
37 raw, _ := json.Marshal(c)
38 if err = state.Write("census.json", raw); err != nil {
39 t.Fatal(err)
40 }
41 state.Close()
42 failures, err := rootstate.Open(rollout.RootFailuresDir, true, false)
43 if err != nil {
44 t.Fatal(err)
45 }
46 defer failures.Close()
47 book, err := rollout.InitializeRootFailures(failures, rootUpdatesMigration(c), nil)
48 if err != nil {
49 t.Fatal(err)
50 }
51 rec := provision.Record{Schema: 1, Host: "h.example.com", Account: "bab", App: "km", Channel: "canary/x", Pin: "v1", CreatedAt: time.Now().UTC()}
52 if _, err = book.Record(rollout.FailureRecord{Account: rec.Account, App: rec.App, Host: rec.Host, Build: "v1", HeldDown: []string{rec.Host}}); err != nil {
53 t.Fatal(err)
54 }
55 inc, _ := hostclaim.Incarnation(rec.Account, rec.App, rec.Host, rec.CreatedAt)
56 fences, err := rootstate.Open("/var/lib/carlos-claims/authority/fences", true, false)
57 if err != nil {
58 t.Fatal(err)
59 }
60 defer fences.Close()
61 in := hostguard.RootInstallation{Host: rec.Host, Account: rec.Account, App: rec.App, Record: provision.RecordKey(rec.Account, rec.App, rec.Host), Incarnation: inc, Stamp: 1, Box: c.Box, Enrollment: c.Enrollment, Migration: c.Migration, InventoryRevision: 1}
62 if err = hostguard.NewRootAuthority(fences).RetainMigrationDeny(t.Context(), in, 1); err != nil {
63 t.Fatal(err)
64 }
65 store := release.NewDirStore(t.TempDir())
66 plan14PutRecord(t, store, rec)
67 claim := hostclaim.Claim{V: 2, Host: rec.Host, Gen: 1, Holder: &hostclaim.Holder{Family: "instance", Key: in.Record, Account: rec.Account, App: rec.App, Incarnation: inc, CreatedAt: rec.CreatedAt, Location: "instances/" + rec.Host, Stamp: 1, Session: 1, WriterBox: c.Box}, Op: hostclaim.Op{Kind: hostclaim.KindServing, Exec: c.Box}}
68 if err = claim.Validate(); err != nil {
69 t.Fatal(err)
70 }
71 key, _ := hostclaim.Key(rec.Host)
72 raw, _ = json.Marshal(claim)
73 if _, err = store.Put(t.Context(), key, raw, ""); err != nil {
74 t.Fatal(err)
75 }
76 seed, public, _ := release.GenerateKey()
77 priv, _ := release.ParseSigningKey(seed, "test")
78 pub, _ := release.ParsePublicKey(public, "test")
79 m := release.Manifest{Schema: 1, App: rec.App, Version: "v1", Kind: "binary", Artifacts: map[string]release.Artifact{runtimePlatform(): {}}}
80 if err = release.Ship(t.Context(), store, rec.Account, m, map[string][]byte{runtimePlatform(): []byte("v1")}); err != nil {
81 t.Fatal(err)
82 }
83 if err = release.Promote(t.Context(), store, priv, rec.Account, rec.App, rec.Channel, "v1"); err != nil {
84 t.Fatal(err)
85 }
86 data, opt := t.TempDir(), t.TempDir()
87 if err = os.Mkdir(filepath.Join(data, rollout.FailureFile), 0700); err != nil {
88 t.Fatal(err)
89 }
90 rt := provision.RouteFor(rec, data, "", false, nil)
91 rt.Account, rt.App, rt.Channel, rt.GoodVersion = "bad", "foreign", "forged", "forged"
92 reg := openReg(t, rt)
93 if err = release.Pass(t.Context(), reg, store, pub, opt, nil, updatesPassOption(data, true)); err != nil {
94 t.Fatal(err)
95 }
96 if v, _ := release.LiveVersion(opt, rec.Host); v != "v1" {
97 t.Fatal("sticky or legacy state held production adoption", v)
98 }
99 opened, err := productionRootUpdates(data)(t.Context(), store, pub)
100 if err != nil || opened == nil {
101 t.Fatal(err)
102 }
103 resolved, err := opened.Resolve(t.Context(), rec.Host)
104 if err != nil || resolved.Route.Account != rec.Account || resolved.Route.App != rec.App || resolved.Failed("v1") {
105 t.Fatal("canonical activation policy", resolved, err)
106 }
107 opened.Close()
108 wire, err := release.SignHostRetry(release.RootSigner(priv), rec.Account, rec.App, rec.Host, "v1", book.ID(), book.PublishedEpoch(rec.Account, rec.App, "v1", rec.Host), time.Now())
109 if err != nil {
110 t.Fatal(err)
111 }
112 retries := release.ScopedRestartGeneration{Schema: 1, Requests: []release.RestartRequest{{ID: "retry", RequestedAt: time.Now().UTC().Format(time.RFC3339), Scope: release.RestartScope{Kind: release.RestartScopeRetry, Value: rec.Host, Signed: wire}}}}
113 raw, _ = json.Marshal(retries)
114 if _, err = store.Put(t.Context(), release.HostRetryKey(rec.Account, rec.App), raw, ""); err != nil {
115 t.Fatal(err)
116 }
117 opened, err = productionRootUpdates(data)(t.Context(), store, pub)
118 if err != nil {
119 t.Fatal(err)
120 }
121 if _, err = opened.Resolve(t.Context(), rec.Host); err != nil {
122 t.Fatal(err)
123 }
124 opened.Close()
125 book, err = rollout.OpenRootFailures(failures, rootUpdatesMigration(c))
126 if err != nil || book.HeldDown(rec.Account, rec.App, "v1", rec.Host) {
127 t.Fatal("production retry not settled", err)
128 }
129 _, etag, _ := store.Get(t.Context(), key)
130 claim.Op.Exec = "foreign"
131 raw, _ = json.Marshal(claim)
132 if _, err = store.Put(t.Context(), key, raw, etag); err != nil {
133 t.Fatal(err)
134 }
135 opened, err = productionRootUpdates(data)(t.Context(), store, pub)
136 if err != nil {
137 t.Fatal(err)
138 }
139 defer opened.Close()
140 if _, err = opened.Resolve(t.Context(), rec.Host); err == nil {
141 t.Fatal("foreign controller authority accepted")
142 }
143}
144