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 "database/sql"
6 "errors"
7 "fmt"
8 "os"
9 "reflect"
10 "slices"
11
12 "github.com/carlosframework/platform/internal/hostbox"
13 "github.com/carlosframework/platform/internal/hostclaim"
14 execlease "github.com/carlosframework/platform/internal/hostexec"
15 "github.com/carlosframework/platform/internal/hostguard"
16 "github.com/carlosframework/platform/internal/park"
17 "github.com/carlosframework/platform/internal/rootparticipation"
18)
19
20var errReinstallRetired = errors.New("hostname was retired on this box; reinstalling it is not yet supported")
21
22func (h ClaimRootHTTP) executionAuthority(ctx context.Context, q execlease.ExecutionRequest, _ execlease.ControllerProcess) (execlease.ExecutionAuthority, error) {
23 var out execlease.ExecutionAuthority
24 if h.InventoryActor == nil || h.Stop.Coordinator.Guard.Root == nil || h.Reconcile.Census == nil || h.Journals == nil {
25 return out, hostbox.ErrUnsupported
26 }
27 actor, err := h.InventoryActor(ctx)
28 if err != nil {
29 return out, err
30 }
31 if h.RequireNewWork != nil {
32 if err = h.RequireNewWork(ctx); err != nil {
33 return out, err
34 }
35 }
36 obs, err := hostclaim.Read(ctx, h.Stop.Coordinator.Evidence, q.Host)
37 if err != nil {
38 return out, err
39 }
40 c := obs.Claim
41 if obs.Absent || c == nil || c.Holder == nil || c.Validate() != nil || c.Host != q.Host || c.Holder.Incarnation != q.Incarnation || c.Holder.Stamp != q.Stamp || c.Holder.Session != q.Session || c.Op.ID != q.Op || slices.Contains(c.Lost, actor.Box) {
42 return out, hostbox.ErrChanged
43 }
44 if c.Op.Kind != hostclaim.KindServing && !slices.Contains(c.Op.Participants, actor.Box) {
45 return out, hostbox.ErrChanged
46 }
47 if c.Op.Kind == hostclaim.KindServing && execlease.PreinstallationParticipant(c, actor.Box, actor.Enrollment) != nil {
48 return out, hostbox.ErrChanged
49 }
50 retirement := c.Op.Kind == hostclaim.KindDeleting || c.Op.Kind == hostclaim.KindParking
51 if retirement {
52 home, homeErr := park.VerifiedHome(actor.FleetHomeRegion, actor.HomeRegion, actor.Region, c.Op.Intent["home_region"])
53 if homeErr != nil || actor.FleetHomeRegion == "" || actor.Region != actor.FleetHomeRegion || c.Holder.Family != "instance" || c.Holder.Location != "instances/"+c.Host+"/"+c.Holder.Incarnation || c.Op.Exec != actor.Box || c.Op.Intent["key"] != c.Holder.Key || c.Op.Intent["etag"] == "" {
54 return out, hostbox.ErrChanged
55 }
56 for _, admission := range c.Holder.Admissions {
57 if admission.Box != actor.Box || !park.SameRegion(home, admission.Region, actor.Region) || (admission.PredecessorRegion != "" && !park.SameRegion(home, admission.PredecessorRegion, actor.Region)) {
58 return out, hostbox.ErrChanged
59 }
60 }
61 }
62 _, etag, err := rootClaimRecord(ctx, h.Stop.Coordinator.Evidence, c, h.Roots["data"])
63 if retirement && (c.Op.Kind == hostclaim.KindParking || errors.Is(err, os.ErrNotExist)) {
64 if !errors.Is(err, os.ErrNotExist) {
65 return out, hostbox.ErrChanged
66 }
67 if _, _, absent := h.Stop.Coordinator.Evidence.Get(ctx, c.Holder.Key); !errors.Is(absent, os.ErrNotExist) {
68 return out, hostbox.ErrChanged
69 }
70 etag, err = c.Op.Intent["etag"], nil
71 }
72 if err != nil {
73 return out, err
74 }
75 if retirement && etag != c.Op.Intent["etag"] {
76 return out, hostbox.ErrChanged
77 }
78 out = execlease.ExecutionAuthority{Box: actor.Box, Enrollment: actor.Enrollment, Account: c.Holder.Account, App: c.Holder.App, ClaimRevision: obs.ETag, RecordRevision: etag, DirectoryRevision: actor.Binding, Kind: c.Op.Kind, Phase: c.Op.Phase}
79 captured := hostguard.Captured{Incarnation: q.Incarnation, Stamp: q.Stamp}
80 view, err := h.Stop.Coordinator.Guard.Root.View(ctx, q.Host, captured)
81 if retirement && err != nil {
82 return out, err
83 }
84 if errors.Is(err, hostguard.ErrStampMismatch) {
85 if execlease.PreinstallationParticipant(c, actor.Box, actor.Enrollment) == nil {
86 retired, checkErr := h.Stop.Coordinator.Guard.Root.HostRetired(ctx, q.Host)
87 if checkErr != nil {
88 return out, checkErr
89 }
90 if retired {
91 return out, fmt.Errorf("%s: %w", q.Host, errReinstallRetired)
92 }
93 }
94 return h.retainedExecutionSource(ctx, q, actor, c, out)
95 }
96 if errors.Is(err, hostguard.ErrFenced) {
97 in, raw, pendingErr := h.Stop.Coordinator.Guard.Root.PendingInstallation(ctx, q.Host)
98 if pendingErr != nil {
99 return out, pendingErr
100 }
101 var pending hostbox.JournalRequest
102 if rootparticipation.Decode(raw, &pending) != nil || pending.Op != "inventory-write" || pending.Revision != 0 || pending.RecordKey != c.Holder.Key || pending.RecordETag != etag || pending.Target.ClaimETag != obs.ETag || pending.Target.Host != q.Host || pending.Target.Incarnation != q.Incarnation || pending.Target.Stamp != q.Stamp || pending.Target.Session != q.Session || pending.Target.Op != q.Op || pending.Target.Phase != c.Op.Phase || pending.Target.Box != actor.Box || pending.Target.Enrollment != actor.Enrollment || in.Host != q.Host || in.Incarnation != q.Incarnation || in.Stamp != q.Stamp || in.Account != out.Account || in.App != out.App || in.Record != c.Holder.Key || in.Box != actor.Box || in.Enrollment != actor.Enrollment || in.Migration == 0 {
103 return out, hostbox.ErrChanged
104 }
105 if err := execlease.PreinstallationParticipant(c, actor.Box, actor.Enrollment); err != nil {
106 return out, err
107 }
108 inventory, revision, err := h.Journals.Inventory.Snapshot(ctx, q.Host, captured)
109 if err != nil {
110 return out, err
111 }
112 if revision == 0 {
113 selected := hostbox.RecordSelection{Host: q.Host, Key: c.Holder.Key, ETag: etag, Incarnation: q.Incarnation, Family: c.Holder.Family}
114 if err := h.rootEmptyCensus().CheckLocal(ctx, obs, selected); err != nil {
115 return out, err
116 }
117 } else {
118 expected := pending.Inventory
119 if c.Op.Kind == hostclaim.KindLanding {
120 expected.Entries = []hostbox.StopInventoryEntry{rootLandingEntry(pending, c, actor)}
121 }
122 if revision != in.InventoryRevision || !reflect.DeepEqual(inventory, expected) {
123 return out, hostbox.ErrTypedInventory
124 }
125 }
126 out.ParticipationOnly = true
127 out.Migration = in.Migration
128 out.Installation = fmt.Sprintf("%s/%d/%s/%s", in.Incarnation, in.Stamp, in.Box, in.Enrollment)
129 return out, nil
130 }
131 if errors.Is(err, hostguard.ErrNoRecord) {
132 if err = execlease.PreinstallationParticipant(c, actor.Box, actor.Enrollment); err != nil {
133 return out, err
134 }
135 // An orphan journal is not a root registration, even when its complete bit is set.
136 if _, err = h.Journals.Inventory.ReadStopInventory(ctx, q.Host); !errors.Is(err, sql.ErrNoRows) {
137 return out, hostbox.ErrTypedInventory
138 }
139 selected := hostbox.RecordSelection{Host: q.Host, Key: c.Holder.Key, ETag: etag, Incarnation: q.Incarnation, Family: c.Holder.Family}
140 if err = h.rootEmptyCensus().CheckLocal(ctx, obs, selected); err != nil {
141 return out, err
142 }
143 out.ParticipationOnly = true
144 return out, nil
145 }
146 if err != nil {
147 return out, err
148 }
149 in := view.Installation
150 if in.Host != q.Host || in.Incarnation != q.Incarnation || in.Stamp != q.Stamp || in.Account != out.Account || in.App != out.App || in.Record != c.Holder.Key || in.Box != actor.Box || in.Enrollment != actor.Enrollment || in.Migration == 0 || in.InventoryRevision == 0 {
151 return out, hostbox.ErrChanged
152 }
153 if view.Barrier != nil || (slices.Contains(view.Retired, captured) && !(retirement && c.Op.Kind == hostclaim.KindParking)) {
154 return out, hostguard.ErrFenced
155 }
156 denied := func(t hostguard.FenceTarget) bool {
157 return t.Incarnation == q.Incarnation && t.Stamp == q.Stamp && t.Session == q.Session
158 }
159 if view.Pending != nil && denied(*view.Pending) {
160 completed := false
161 if retirement {
162 for _, receipt := range view.Receipts {
163 if receipt.Target == *view.Pending && verifyRetirementReceipt(ctx, receipt) == nil {
164 completed = true
165 }
166 }
167 }
168 if !completed {
169 return out, hostguard.ErrFenced
170 }
171 }
172 for _, receipt := range view.Receipts {
173 if denied(receipt.Target) && !retirement {
174 return out, hostguard.ErrFenced
175 }
176 }
177 _, revision, err := h.Journals.Inventory.Snapshot(ctx, q.Host, captured)
178 if err != nil {
179 return out, err
180 }
181 if revision != in.InventoryRevision {
182 return out, hostbox.ErrChanged
183 }
184 out.ParticipationOnly = retirement
185 out.Migration = in.Migration
186 out.Installation = fmt.Sprintf("%s/%d/%s/%s", in.Incarnation, in.Stamp, in.Box, in.Enrollment)
187 return out, nil
188}
189