carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package console
2
3import (
4 "context"
5 "crypto/ed25519"
6 "crypto/rand"
7 "encoding/json"
8 "strings"
9 "testing"
10 "time"
11
12 "github.com/carlosframework/platform/internal/hostactors"
13 "github.com/carlosframework/platform/internal/hostclaim"
14 "github.com/carlosframework/platform/internal/hostops"
15 "github.com/carlosframework/platform/internal/release"
16)
17
18func TestClaimHoldRecoveryInvalidatesUnusedStartAndPreservesActiveHold(t *testing.T) {
19 for _, active := range []bool{false, true} {
20 t.Run(map[bool]string{false: "unused", true: "active"}[active], func(t *testing.T) {
21 ctx := context.Background()
22 store := release.NewDirStore(t.TempDir())
23 pub, key, err := ed25519.GenerateKey(rand.Reader)
24 if err != nil {
25 t.Fatal(err)
26 }
27 signer := release.RootSigner(key)
28 enrollment := strings.Repeat("a", 32)
29 before, err := hostclaim.Read(ctx, store, "app.example")
30 if err != nil {
31 t.Fatal(err)
32 }
33 roster := hostactors.Roster{V: 1, Revision: 1, DeploymentBucket: "bucket", Boxes: map[string]hostactors.Box{"box": {Enrollment: enrollment, Namespace: "platform", BoxID: "box", Label: "box", Region: "ie", Pool: "default", Cloud: hostactors.Cloud{Provider: "aws", Account: "123", Region: "eu-west-1", InstanceID: "i-box"}, EvidenceSHA256: strings.Repeat("b", 64), State: "active"}}, Consoles: map[string]hostactors.Console{}, Holds: map[string]hostactors.Reservation{"hold": {ID: "hold", Host: before.Host, OpID: "op", ExpectedClaimETag: before.ETag, FloorSHA256: strings.Repeat("f", 64), Actors: map[string]string{"box:box": enrollment}, Releases: map[string]hostactors.Report{"box:box": {Enrollment: enrollment}}}}, Activations: map[string]hostactors.Reservation{}}
34 wire, err := release.SignRootEnvelope(signer, roster)
35 if err != nil {
36 t.Fatal(err)
37 }
38 if _, err = store.Put(ctx, hostactors.Key, wire, ""); err != nil {
39 t.Fatal(err)
40 }
41 if active {
42 if _, err = hostclaim.Update(ctx, store, before, func(c *hostclaim.Claim) error {
43 now := time.Now().UTC()
44 n := hostclaim.NewHolder{Family: "instance", Key: "apps/bab/app/instances/app.example.json", Account: "bab", App: "app", Host: before.Host, Region: "ie", CreatedAt: now}
45 body, _ := json.Marshal(map[string]any{"host": before.Host, "account": "bab", "app": "app", "created_at": now})
46 if err := hostclaim.BeginCreate(n, body, "op", "test", now)(c); err != nil {
47 return err
48 }
49 c.Op.Intent["actors_hold"] = "hold"
50 return nil
51 }); err != nil {
52 t.Fatal(err)
53 }
54 }
55 directory := hostactors.Directory{Store: store, PublicKey: pub, Bucket: "bucket"}
56 s := &Server{cfg: Config{HostClaim: true, ClaimAuthority: &hostops.ProductionAuthority{Store: store, Directory: directory, Signer: signer}}}
57 if err = s.SweepClaimHolds(ctx); err != nil {
58 t.Fatal(err)
59 }
60 after, err := directory.Read(ctx)
61 if err != nil {
62 t.Fatal(err)
63 }
64 _, exists := after.Roster.Holds["hold"]
65 if exists != active {
66 t.Fatalf("hold exists=%v active=%v", exists, active)
67 }
68 if !active {
69 if _, err = hostclaim.Update(ctx, store, before, func(*hostclaim.Claim) error { return nil }); err == nil {
70 t.Fatal("unused start observation remained usable")
71 }
72 }
73 })
74 }
75}
76