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 "errors"
6 "os"
7
8 "github.com/carlosframework/platform/internal/instancectl"
9)
10
11// Placement comes from retained root state. Configuration may deny a new
12// start, but removing it cannot retarget cleanup to the ordinary run unit.
13type claimUnitDispatch struct {
14 base instancectl.ClaimUnits
15 bindings *claimUnitBindings
16 shapes func() (map[string]claimUnitShape, error)
17 definition func(claimUnitShape) error
18 effective func(context.Context, claimUnitShape) error
19}
20
21func (d claimUnitDispatch) selected(host string) (instancectl.ClaimUnits, error) {
22 u := d.base
23 if d.bindings == nil || d.shapes == nil {
24 return u, os.ErrPermission
25 }
26 b, err := d.bindings.read(host)
27 if err == nil {
28 u.BoundHost, u.BoundUnit, u.BoundAddr = host, b.Shape.Unit, b.Shape.Addr
29 return u, nil
30 }
31 if !errors.Is(err, os.ErrNotExist) {
32 return u, err
33 }
34
35 return u, nil
36}
37
38func (d claimUnitDispatch) forStart(ctx context.Context, host string) (instancectl.ClaimUnits, error) {
39 u, err := d.selected(host)
40 if err != nil {
41 return u, err
42 }
43 if u.BoundUnit == "" {
44 shapes, e := d.shapes()
45 if e != nil {
46 return u, e
47 }
48 if e == nil {
49 if _, configured := shapes[host]; configured {
50 return u, os.ErrPermission
51 }
52 }
53 if d.effective == nil {
54 return u, os.ErrPermission
55 }
56 if err := d.effective(ctx, claimUnitShape{Host: host, Unit: instancectl.UnitName(instancectl.RoleRun, host)}); err != nil {
57 return u, err
58 }
59 }
60 if u.BoundUnit != "" {
61 shapes, err := d.shapes()
62 if err != nil {
63 return u, err
64 }
65 b, err := d.bindings.check(ctx, host, nil)
66 if err != nil {
67 return u, err
68 }
69 if shapes[host] != b.Shape {
70 return u, os.ErrPermission
71 }
72 if d.definition == nil {
73 return u, os.ErrPermission
74 }
75 if err := d.definition(b.Shape); err != nil {
76 return u, err
77 }
78 if d.effective != nil {
79 if err := d.effective(ctx, b.Shape); err != nil {
80 return u, err
81 }
82 }
83 }
84 return u, nil
85}
86
87func (d claimUnitDispatch) Placement(host string) (string, string, error) {
88 u, err := d.selected(host)
89 if err != nil {
90 return "", "", err
91 }
92 return u.Placement(host)
93}
94
95func (d claimUnitDispatch) StartReserved(ctx context.Context, in instancectl.ClaimUnit, l instancectl.Launch, p instancectl.ClaimExecPermit, check func() error) (instancectl.ClaimUnitStarted, error) {
96 u, err := d.forStart(ctx, in.Host)
97 if err != nil {
98 return instancectl.ClaimUnitStarted{}, err
99 }
100 if check == nil {
101 return instancectl.ClaimUnitStarted{}, os.ErrPermission
102 }
103 return u.StartReserved(ctx, in, l, p, func() error {
104 again, err := d.forStart(ctx, in.Host)
105 if err != nil {
106 return err
107 }
108 if again.BoundHost != u.BoundHost || again.BoundUnit != u.BoundUnit {
109 return os.ErrPermission
110 }
111 return check()
112 })
113}
114
115func (d claimUnitDispatch) Same(ctx context.Context, started instancectl.ClaimUnitStarted) error {
116 // The caller retained the selected placement in the launch grant. Same
117 // checks that exact invocation without taking a new route from the registry.
118 return d.base.Same(ctx, started)
119}
120
121func (d claimUnitDispatch) Stop(context.Context, string) error {
122 // Dispatch cannot guess which invocation a bare host means.
123 return os.ErrPermission
124}
125
126func (d claimUnitDispatch) StopInvocation(ctx context.Context, host, invocation string) error {
127 u, err := d.selected(host)
128 if err != nil {
129 return err
130 }
131 return u.StopInvocation(ctx, host, invocation)
132}
133
134func (d claimUnitDispatch) Gone(ctx context.Context, host, invocation string) error {
135 u, err := d.selected(host)
136 if err != nil {
137 return err
138 }
139 return u.Gone(ctx, host, invocation)
140}
141