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 "bytes"
5 "encoding/base64"
6 "os"
7 "testing"
8
9 "github.com/carlosframework/platform/internal/registry"
10 "github.com/carlosframework/platform/internal/release"
11 "github.com/carlosframework/platform/internal/rollout"
12)
13
14// Final review round 1, finding 2 (Astra): a real claims move launch (a
15// moves probe or a landing) runs on a row the move holds ("landing",
16// "restoring", movesprobeowners heldRoute), and Managed reads every held
17// status as not managed. The declined box's restriction must not depend on
18// that passing status: a held row the book restricts is refused at the
19// claims move launch exactly as its ready row is, for a hold-down and for a
20// hold-ran marker. Move authorization is the moves package's own check, and
21// stays separate.
22func TestDeclinedBoxGatesAClaimsMoveLaunchOfAHeldRow(t *testing.T) {
23 for _, status := range []string{"landing", "restoring"} {
24 for _, kind := range []string{"hold-down", "marker"} {
25 t.Run(status+", "+kind, func(t *testing.T) {
26 f := newAdminTokenFixture(t, "box-1")
27 if err := os.WriteFile(f.envPath(), []byte("CARLOS_ADMIN_TOKEN=tok-0123456789abcdef0123456789abcdef\n"), 0o600); err != nil {
28 t.Fatal(err)
29 }
30 t.Setenv("CARLOS_SECRETS_KEY", base64.StdEncoding.EncodeToString(bytes.Repeat([]byte{7}, 32)))
31 rt := f.rt
32 rt.Kind, rt.Status, rt.HoldOp, rt.Channel, rt.Account, rt.App, rt.Hibernate, rt.Version = "instance", status, "op-1", "edge", "bab", "jam", true, "v1"
33 acct := release.RouteAccount(rt)
34 svc, reg, dd := rolloutFixture(t, false)
35 var want string
36 switch kind {
37 case "hold-down":
38 // v1 failed in hold mode on this instance: it stays down.
39 rt.GoodVersion, rt.GoodDigest = "v0", "sha256:v0"
40 writeFailureBook(t, dd, []rollout.FailureRecord{{Account: acct, App: "jam", Build: "v1", Host: rt.Host, Mode: "hold", HeldDown: []string{rt.Host}}}, nil)
41 want = rollout.HeldDownRefusal("v1")
42 case "marker":
43 // A hold build v2 ran here: the good build v1, which the
44 // launch would exec, is barred until a signed rollback.
45 rt.GoodVersion, rt.GoodDigest = "v1", "sha256:v1"
46 b, err := rollout.OpenFailureBook(dd)
47 if err != nil {
48 t.Fatal(err)
49 }
50 if err := b.MarkHoldRan(rt.Host, rollout.HoldRan{Account: acct, App: "jam", Build: "v2"}); err != nil {
51 t.Fatal(err)
52 }
53 want = rollout.HeldDownRefusal("v2")
54 }
55 declineWithBook(t, svc, reg, dd)
56 if _, _, err := claimMoveLaunchSource(f.backend)(t.Context(), rt); err == nil || err.Error() != want {
57 t.Fatalf("move launch of a %s row = %v, want %q", status, err, want)
58 }
59 })
60 }
61 }
62}
63
64// Finding 2's second half (Task 10's deferred minor): a signed retry that
65// arrives while the instance's row is held by a move ("moving") is applied,
66// not consumed and dropped: the restart leg reads each request once.
67func TestADeclinedBoxAppliesARetryWhileTheRowIsMoving(t *testing.T) {
68 t.Setenv("CARLOS_OPT_DIR", t.TempDir())
69 svc, reg, dd := rolloutFixture(t, false)
70 const host = "h.example.com"
71 rt := heldRouteIn(t, reg, host, "v2", "v1")
72 acct := release.RouteAccount(rt)
73 writeFailureBook(t, dd, []rollout.FailureRecord{{
74 Account: acct, App: "blog", Build: "v2", Host: "sib.example.com", Mode: "hold", Reason: "health", HeldDown: []string{host},
75 }}, nil)
76 declineWithBook(t, svc, reg, dd)
77 hr, ok := declinedHostReport(t, host)
78 if !ok || hr.HeldBy != "v2" {
79 t.Fatalf("published %+v (%v), want v2 holding %s", hr, ok, host)
80 }
81 if err := reg.SetHold(host, "moving", "op-1"); err != nil {
82 t.Fatal(err)
83 }
84 moving, err := reg.Get(host)
85 if err != nil || moving == nil || !registry.IsHold(moving.Status) {
86 t.Fatalf("row %+v (%v): want it held by the move", moving, err)
87 }
88 if !heldHolds().retryHost(host, "v2", hr.HeldBook, hr.HeldEpoch) {
89 t.Fatal("a grant that arrived while the row was moving cleared nothing")
90 }
91 if heldHolds().book.HeldDown(acct, "blog", "v2", host) {
92 t.Fatal("the hold-down survived the grant")
93 }
94}
95