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 "sync"
7
8 "github.com/carlosframework/platform/internal/activator"
9 "github.com/carlosframework/platform/internal/hostbox"
10 "github.com/carlosframework/platform/internal/hostclaim"
11 "github.com/carlosframework/platform/internal/hostguard"
12 "github.com/carlosframework/platform/internal/hostwrite"
13 "github.com/carlosframework/platform/internal/lbhealth"
14 "github.com/carlosframework/platform/internal/provision"
15 "github.com/carlosframework/platform/internal/schedule"
16)
17
18// ClaimProviders contains deployment providers after identity, floor and
19// quarantine verification. Build must fail if any of those gates is unknown.
20type RegionalLoop interface {
21 Loop(context.Context, <-chan struct{}, func(error)) error
22}
23
24type ClaimProviders struct {
25 guard hostguard.Guard
26 registerLanding func(context.Context, hostclaim.Observed) error
27 moveTargetFence func(context.Context, hostclaim.Observed) (hostclaim.ReturnFence, error)
28 moveParks *claimMoveParks
29 Delivery schedule.DeliveryAdmission
30 Selector hostwrite.Selector
31 Wake *activator.ClaimRuntime
32 Regional RegionalLoop
33 Stop *ClaimStopCoordinator
34 Provision func(*provision.ReconcileConfig)
35 Close func(context.Context) error
36}
37type ClaimFactory func(context.Context) (ClaimProviders, error)
38
39type ClaimWiring struct {
40 Writes hostwrite.Config
41 Providers ClaimProviders
42 cancel context.CancelFunc
43 joined chan struct{}
44 once sync.Once
45}
46
47func newClaimWiring(ctx context.Context, getenv func(string) string, build ClaimFactory) (*ClaimWiring, error) {
48 w := &ClaimWiring{}
49 cfg, err := hostbox.Startup(ctx, getenv, func(ctx context.Context) (hostwrite.Selector, error) {
50 if build == nil {
51 return nil, hostwrite.ErrUnavailable
52 }
53 providers, err := build(ctx)
54 if err != nil {
55 return nil, err
56 }
57 if providers.Selector == nil || providers.Wake == nil || providers.Regional == nil || providers.Stop == nil {
58 return nil, hostwrite.ErrUnavailable
59 }
60 w.Providers = providers
61 return providers.Selector, nil
62 })
63 w.Writes = cfg
64 return w, err
65}
66
67func (w *ClaimWiring) configure(cfg *activator.Config, runner *schedule.Runner, converger *schedule.Converger) error {
68 if w == nil || cfg == nil || runner == nil || converger == nil {
69 return hostwrite.ErrUnavailable
70 }
71 if !w.Writes.Enabled {
72 return nil
73 }
74 if w.Writes.Selector == nil || w.Providers.Wake == nil {
75 return hostwrite.ErrUnavailable
76 }
77 cfg.HostWrites = w.Writes
78 cfg.Claims = w.Providers.Wake
79 runner.HostWrites = w.Writes
80 runner.StartDelivery = w.Providers.Delivery
81 converger.HostWrites = w.Writes
82 return nil
83}
84func (w *ClaimWiring) startRegional(ctx context.Context, serial <-chan struct{}, report func(error)) error {
85 if w == nil {
86 return hostwrite.ErrUnavailable
87 }
88 if !w.Writes.Enabled {
89 return nil
90 }
91 if w.Providers.Regional == nil || w.joined != nil {
92 return hostwrite.ErrUnavailable
93 }
94 workerCtx, cancel := context.WithCancel(ctx)
95 w.cancel = cancel
96 w.joined = make(chan struct{})
97 // The load balancer's hosting condition (region HA spec 2 §5, §6) is
98 // this process's mode, as RunAgent's gate chose it (agentHosting):
99 // the claim agent of an enrolled box with an armed guard. It is set
100 // before the worker starts and cleared when the worker ends, so a box
101 // whose claim worker has stopped never answers healthy.
102 hosting := agentHosting.Load()
103 lbhealth.Default.SetHosting(hosting)
104 go func() {
105 defer close(w.joined)
106 defer lbhealth.Default.SetHosting(false)
107 w.Providers.Regional.Loop(workerCtx, serial, report)
108 }()
109 return nil
110}
111func (w *ClaimWiring) close(ctx context.Context) error {
112 if w == nil {
113 return nil
114 }
115 w.once.Do(func() {
116 if w.cancel != nil {
117 w.cancel()
118 }
119 })
120 if w.joined == nil {
121 if w.Providers.Close != nil {
122 return w.Providers.Close(ctx)
123 }
124 return nil
125 }
126 select {
127 case <-w.joined:
128 if w.Providers.Close != nil {
129 return w.Providers.Close(ctx)
130 }
131 return nil
132 case <-ctx.Done():
133 return errors.Join(ctx.Err(), hostwrite.ErrUnavailable)
134 }
135}
136