carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package hostbox
2
3import (
4 "context"
5 "errors"
6 "github.com/carlosframework/platform/internal/hostclaim"
7 "github.com/carlosframework/platform/internal/lease/leasetest"
8 "github.com/carlosframework/platform/internal/park"
9 "github.com/carlosframework/platform/internal/release"
10 "strings"
11 "testing"
12 "time"
13)
14
15type plan12Renewable struct {
16 lost chan struct{}
17 err error
18 releases int
19}
20
21func (r *plan12Renewable) Err() error { return r.err }
22func (r *plan12Renewable) Lost() <-chan struct{} { return r.lost }
23func (r *plan12Renewable) Release(context.Context) error { r.releases++; return nil }
24func TestPlan12LandingResidueParkUnderItsOwnLease(t *testing.T) {
25 for _, mode := range []string{"ok", "wrong-host", "wrong-location", "wrong-bucket", "lost", "authorization"} {
26 t.Run(mode, func(t *testing.T) {
27 ctx := t.Context()
28 host := "app.example"
29 inc := strings.Repeat("a", 64)
30 loc := "instances/" + host + "/" + inc
31 now := time.Date(2026, 10, 10, 12, 0, 0, 0, time.UTC)
32 claims := release.NewDirStore(t.TempDir())
33 _, err := hostclaim.Update(ctx, claims, hostclaim.Observed{Host: host, Absent: true}, func(c *hostclaim.Claim) error {
34 c.Op = hostclaim.Op{Kind: hostclaim.KindParking, ID: "op", Intent: map[string]string{"park_sweep": "v1"}}
35 c.Obligations = []hostclaim.Obligation{{ID: "chore", Op: "op", Kind: "park-replica", Region: "ie", Owner: "region:ie", Retirement: "ret", Park: &hostclaim.ParkScope{Location: loc, Incarnation: inc, EvidenceAt: now.Add(-time.Hour), RequestLimit: RequestLimit}}}
36 return nil
37 })
38 if err != nil {
39 t.Fatal(err)
40 }
41 data := leasetest.NewVersionedBucket()
42 data.AddBucket("data")
43 data.Put("data", loc+"/db", []byte("residue"))
44 r := &plan12Renewable{lost: make(chan struct{})}
45 acquires := 0
46 leases := RenewingLeases{Region: "eu-west-1", Open: func(context.Context, string, string, string) (Renewable, error) {
47 acquires++
48 if acquires > 1 {
49 return nil, errors.New("already held")
50 }
51 return r, nil
52 }}
53 bucket, scope := "data", loc
54 switch mode {
55 case "wrong-host":
56 scope = "instances/other.example/" + inc
57 case "wrong-location":
58 scope = "instances/" + host
59 case "wrong-bucket":
60 bucket = "other"
61 }
62 own, err := leases.Acquire(ctx, bucket, scope)
63 if err != nil {
64 t.Fatal(err)
65 }
66 defer own.Close()
67 if mode == "lost" {
68 r.err = errors.New("lost")
69 }
70 authorized := 0
71 engine := park.Engine{Claims: claims, Store: data, Bucket: "data", Region: "ie", Leases: AggregateLeases{Leases: leases, Resolve: ReplicaParkLeaseSet}, Now: func() time.Time { return now }, NewID: func() string { return "next" }, View: func(_ context.Context, o hostclaim.Observed) (park.View, error) {
72 return park.View{ClaimETag: o.ETag, Region: "ie"}, nil
73 }, Authorize: func(context.Context, hostclaim.Observed, hostclaim.Obligation) error {
74 authorized++
75 if mode == "authorization" {
76 return park.ErrUnsafe
77 }
78 return nil
79 }}
80 err = engine.RunHeld(ctx, park.Work{Host: host, ID: "chore", Op: "op"}, own)
81 if mode == "ok" {
82 if err != nil && !errors.Is(err, park.ErrPending) {
83 t.Fatal(err)
84 }
85 if authorized == 0 {
86 t.Fatal("authorizer bypassed")
87 }
88 versions, e := data.ListVersions(ctx, "data", loc+"/")
89 if e != nil || len(versions) != 0 {
90 t.Fatal("residue not parked", e, versions)
91 }
92 } else if err == nil {
93 t.Fatal("accepted", mode)
94 }
95 if acquires != 1 || r.releases != 0 {
96 t.Fatalf("acquires=%d releases=%d", acquires, r.releases)
97 }
98 if mode != "lost" && own.Check(ctx) != nil {
99 t.Fatal("caller lease lost")
100 }
101 })
102 }
103}
104func TestPlan12LeaseSetSemantics(t *testing.T) {
105 for _, scope := range []string{"moves/app.example/op", "moves/app.example", "instances/app.example", "instances/app.example/" + strings.Repeat("a", 64)} {
106 got, err := ReplicaParkLeaseSet(t.Context(), "data", scope)
107 if err != nil || len(got) != 1 || got[0] != scope {
108 t.Fatalf("%s: %v %v", scope, got, err)
109 }
110 }
111 for _, scope := range []string{"control/staging-leases/ie/app.example", "s3://deployment/moves/app.example/op", "instances/app.example/not-an-incarnation", "moves/other/../op"} {
112 if _, err := ReplicaParkLeaseSet(t.Context(), "data", scope); err == nil {
113 t.Fatal(scope)
114 }
115 }
116}
117