carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package hostguard
2
3import (
4 "context"
5 "errors"
6 "github.com/carlosframework/platform/internal/hostclaim"
7)
8
9func (g Guard) RetireInstallationWith(ctx context.Context, host string, captured Captured, check func(*hostclaim.Claim) error, fn func() error) error {
10 return g.retireInstallationWith(ctx, host, captured, check, fn, nil)
11}
12
13// persist is injected by package tests to interrupt the record's durable write.
14func (g Guard) retireInstallationWith(ctx context.Context, host string, captured Captured, check func(*hostclaim.Claim) error, fn func() error, persist func(*recordDir, record) error) error {
15 if captured.Stamp == 0 || check == nil || fn == nil {
16 return ErrInvalidInput
17 }
18 return g.locked(ctx, host, func(d *recordDir) error {
19 c, err := g.fresh(ctx, host)
20 if err != nil {
21 return err
22 }
23 if c.Holder.Incarnation != captured.Incarnation {
24 return ErrClaimIncarnation
25 }
26 if err := check(c); err != nil {
27 return err
28 }
29 r, err := d.read(host)
30 if err != nil {
31 return err
32 }
33 if r.Incarnation != captured.Incarnation {
34 return ErrRecordIncarnation
35 }
36 if r.ActiveStamp != 0 {
37 if r.ActiveStamp != captured.Stamp {
38 return ErrStampMismatch
39 }
40 r.retire()
41 if persist == nil {
42 persist = (*recordDir).write
43 }
44 } else {
45 n := len(r.RetiredStamps)
46 if n == 0 || r.RetiredStamps[n-1] != captured.Stamp {
47 return ErrStampMismatch
48 }
49 if persist == nil {
50 persist = func(d *recordDir, _ record) error { return d.sync(host) }
51 }
52 }
53 if err := ctx.Err(); err != nil {
54 return err
55 }
56 // An inactive record can be visible after rename without being durable.
57 // Sync it on retries before the callback may move any artifact.
58 if err := persist(d, r); err != nil {
59 return err
60 }
61 if err := ctx.Err(); err != nil {
62 return err
63 }
64 return fn()
65 })
66}
67
68func (g Guard) WithNoInstallation(ctx context.Context, host, incarnation string, check func(*hostclaim.Claim) error, fn func() error) error {
69 if incarnation == "" || check == nil || fn == nil {
70 return ErrInvalidInput
71 }
72 return g.locked(ctx, host, func(d *recordDir) error {
73 c, err := g.fresh(ctx, host)
74 if err != nil {
75 return err
76 }
77 if c.Holder.Incarnation != incarnation {
78 return ErrClaimIncarnation
79 }
80 if err := check(c); err != nil {
81 return err
82 }
83 if g.Root != nil {
84 captured := Captured{Incarnation: incarnation, Stamp: c.Holder.Stamp}
85 view, err := g.Root.viewLocked(host, captured)
86 if err != nil {
87 return err
88 }
89 if err = view.admit(host, captured, c.Holder.Session); err != nil {
90 return err
91 }
92 if !view.Installation.Empty || view.Installation.Account != c.Holder.Account || view.Installation.App != c.Holder.App {
93 return ErrStampMismatch
94 }
95 return fn()
96 }
97 _, err = d.read(host)
98 if !errors.Is(err, ErrNoRecord) {
99 if err != nil {
100 return err
101 }
102 return ErrStampMismatch
103 }
104 if err := ctx.Err(); err != nil {
105 return err
106 }
107 return fn()
108 })
109}
110