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 "path/filepath"
8 "slices"
9
10 "github.com/carlosframework/platform/internal/activator"
11 "github.com/carlosframework/platform/internal/cgroup"
12 "github.com/carlosframework/platform/internal/hostbox"
13 "github.com/carlosframework/platform/internal/hostwrite"
14 "github.com/carlosframework/platform/internal/instancectl"
15 "github.com/carlosframework/platform/internal/provision"
16 "github.com/carlosframework/platform/internal/registry"
17 "github.com/carlosframework/platform/internal/release"
18)
19
20func (h *ClaimLaunchRoot) boundInputs(ctx context.Context, rt registry.Route) (*hostbox.UnitLaunchInputs, error) {
21 if h.unitBindings == nil || h.unitProgram == nil {
22 return nil, os.ErrPermission
23 }
24 var result *hostbox.UnitLaunchInputs
25 err := func() error {
26 b, err := h.unitBindings.read(rt.Host)
27 if errors.Is(err, os.ErrNotExist) {
28 if _, e := h.unitBindings.canonical(ctx, rt.Host); e == nil {
29 return os.ErrPermission
30 }
31 if rt.Unit != "" || rt.Backing != "" || rt.Tunnel != "" {
32 return hostbox.ErrUnsupported
33 }
34 return nil
35 }
36 if err != nil {
37 return err
38 }
39 b, err = h.unitBindings.check(ctx, rt.Host, &rt)
40 if err != nil {
41 return err
42 }
43 p, err := h.unitProgram(b.Shape)
44 if err != nil {
45 return err
46 }
47 result = &hostbox.UnitLaunchInputs{Unit: b.Shape.Unit, Socket: b.Shape.Socket, Addr: b.Shape.Addr, DBPath: b.Shape.DBPath, Program: b.Shape.Program, Args: append([]string(nil), p.Args...), Env: append([]string(nil), p.Env...)}
48 return nil
49 }()
50 return result, err
51}
52
53type claimUnitInputReader func(context.Context, registry.Route) (*hostbox.UnitLaunchInputs, error)
54
55func claimBoundSnapshot(ctx context.Context, backend *activator.ExecBackend, rt registry.Route, read claimUnitInputReader) (ClaimServingLaunch, error) {
56 var out ClaimServingLaunch
57 unit, err := read(ctx, rt)
58 if err != nil {
59 return out, err
60 }
61 if unit == nil {
62 return out, hostbox.ErrUnsupported
63 }
64 if err = validateClaimUnitInputs(rt.Host, unit); err != nil {
65 return out, err
66 }
67 id, err := release.ResolveLive(backend.OptDir, rt.Host)
68 if err != nil {
69 return out, err
70 }
71 if id.Version == "" || !claimHexDigest(id.Digest) {
72 return out, hostbox.ErrChanged
73 }
74 out = ClaimServingLaunch{Unit: unit, Identity: hostwrite.Identity{Config: unit.Program, Release: id.Digest}, Executable: release.LiveLink(backend.OptDir, rt.Host), ExecutableSHA256: id.Digest, Args: unit.Args, Env: unit.Env, Version: id.Version, Staged: id, Limit: cgroup.TierDefault, Roles: []string{"main"}}
75 return out, nil
76}
77
78func validateClaimUnitInputs(host string, in *hostbox.UnitLaunchInputs) error {
79 if in == nil || !claimHexDigest(in.Program) || !provision.ValidHostShape(host) || filepath.Dir(in.DBPath) != provision.InstanceDir("/data", host) {
80 return hostbox.ErrRoleLaunchShape
81 }
82 if !instancectl.ValidBoundClaimUnit(in.Unit) || (in.Socket == "") == (in.Addr == "") || filepath.Clean(in.DBPath) != in.DBPath {
83 return hostbox.ErrRoleLaunchShape
84 }
85 if in.Socket != "" && in.Socket != provision.NestedSocket(host) && !claimFlatSocket(claimUnitShape{Socket: in.Socket}) {
86 return hostbox.ErrRoleLaunchShape
87 }
88 return nil
89}
90
91func claimBoundInputMatch(host string, in ClaimLaunchInputs) error {
92 if err := validateClaimUnitInputs(host, in.Unit); err != nil {
93 return err
94 }
95 if in.DBPath != in.Unit.DBPath || in.Identity.Config != in.Unit.Program || !slices.Equal(in.Args, in.Unit.Args) || !slices.Equal(in.Env, in.Unit.Env) {
96 return hostbox.ErrRoleLaunchShape
97 }
98 return nil
99}
100