carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package steering
2
3import (
4 "context"
5 "encoding/json"
6 "strings"
7 "testing"
8
9 "github.com/carlosframework/platform/internal/registry"
10)
11
12// edgesBody renders one box's edges file the way internal/host's
13// edgesFilePass writes it (schema v1) — the bytes the housekeeper duty reads
14// out of control/edges/<box>.json and hands to ConvergeDeployment verbatim.
15func edgesBody(t *testing.T, box, eip, region string) []byte {
16 t.Helper()
17 body, err := json.Marshal(map[string]any{
18 "v": 1,
19 "box": box,
20 "eip": eip,
21 "region": region,
22 "generation": "2026-08-23T09:00:00Z",
23 "hosts": map[string]any{"app.example.com": map[string]any{"role": "home"}},
24 })
25 if err != nil {
26 t.Fatal(err)
27 }
28 return body
29}
30
31// TestConvergeDeploymentFoldsAndConverges is the entry point's whole job: two
32// boxes' edges files plus one steered route become the four latency records
33// (2 names x 2 edges) the zone should hold.
34func TestConvergeDeploymentFoldsAndConverges(t *testing.T) {
35 captureLog(t)
36 f := newFake()
37
38 err := ConvergeDeployment(context.Background(), f, testZone,
39 []registry.Route{steeredRoute("app.example.com")},
40 [][]byte{
41 edgesBody(t, "dublin", "1.2.3.4", "eu-west-1"),
42 edgesBody(t, "oregon", "5.6.7.8", "us-west-2"),
43 },
44 "example.com")
45 if err != nil {
46 t.Fatalf("ConvergeDeployment: %v", err)
47 }
48
49 want := []string{
50 "app.example.com.|A|dublin",
51 "app.example.com.|A|oregon",
52 "edge.example.com.|A|dublin",
53 "edge.example.com.|A|oregon",
54 }
55 got := recordNames(f.records)
56 if len(got) != len(want) {
57 t.Fatalf("records = %v, want %v", got, want)
58 }
59 for i := range want {
60 if got[i] != want[i] {
61 t.Fatalf("records = %v, want %v", got, want)
62 }
63 }
64 if f.nCreateCheck != 2 {
65 t.Errorf("health checks created = %d, want one per distinct EIP (2)", f.nCreateCheck)
66 }
67}
68
69// TestConvergeDeploymentSkipsUnparseableEdgesFiles: a file that LISTS and
70// READS but does not PARSE is a content problem the fold tolerates — it is
71// skipped, named in the log, and the pass converges on the rest. (A file that
72// fails to READ is a different class entirely and never reaches here: the
73// duty fails closed before calling this function at all — see
74// internal/host/steering_loop.go's loadEdgesFileBodies.)
75func TestConvergeDeploymentSkipsUnparseableEdgesFiles(t *testing.T) {
76 logs := captureLog(t)
77 f := newFake()
78
79 err := ConvergeDeployment(context.Background(), f, testZone,
80 []registry.Route{steeredRoute("app.example.com")},
81 [][]byte{
82 []byte("{not json at all"),
83 edgesBody(t, "dublin", "1.2.3.4", "eu-west-1"),
84 []byte(`{"box":"ancient","eip":"9.9.9.9","region":"eu-west-1"}`), // no "v" — unversioned
85 },
86 "example.com")
87 if err != nil {
88 t.Fatalf("ConvergeDeployment: %v", err)
89 }
90
91 // Only dublin folded in: 2 names x 1 edge.
92 if got := recordNames(f.records); len(got) != 2 {
93 t.Fatalf("records = %v, want the 2 dublin records only", got)
94 }
95 out := logs.String()
96 if !strings.Contains(out, "skipping edges file") {
97 t.Fatalf("log = %q, want a skip line naming the unparseable files", out)
98 }
99 if strings.Count(out, "skipping edges file") != 2 {
100 t.Fatalf("log = %q, want exactly 2 skip lines (bad json + unversioned)", out)
101 }
102}
103
104// TestConvergeDeploymentAllEdgesUnparseableRefusesTeardown is the composition
105// that matters most: every edges file unreadable-as-content folds to an EMPTY
106// desired set, and converge's empty-set refusal must catch it. A pass that
107// obeyed it would delete the deployment's entire managed record set because
108// of a schema problem.
109func TestConvergeDeploymentAllEdgesUnparseableRefusesTeardown(t *testing.T) {
110 logs := captureLog(t)
111 f := newFake()
112 // Seed the zone with a managed record so a teardown would be visible.
113 mustConverge(t, f, []desiredRecord{dublinRec})
114 before := len(f.records)
115 writesBefore := f.writes()
116
117 err := ConvergeDeployment(context.Background(), f, testZone,
118 []registry.Route{steeredRoute("app.example.com")},
119 [][]byte{[]byte("garbage"), []byte("{}")},
120 "example.com")
121 if err != nil {
122 t.Fatalf("ConvergeDeployment: %v", err)
123 }
124 if len(f.records) != before {
125 t.Fatalf("records = %d, want %d — an empty fold must never tear the zone down", len(f.records), before)
126 }
127 if f.writes() != writesBefore {
128 t.Fatalf("writes = %d, want %d (zero new writes)", f.writes(), writesBefore)
129 }
130 if !strings.Contains(logs.String(), "refusing to remove any record") {
131 t.Fatalf("log = %q, want the empty-set refusal", logs.String())
132 }
133}
134
135// TestConvergeDeploymentRefusesBadZoneID: the zone-id gate is converge's, and
136// the entry point must not paper over it — a malformed id returns an error
137// (which the duty logs) rather than converging against something else.
138func TestConvergeDeploymentRefusesBadZoneID(t *testing.T) {
139 captureLog(t)
140 f := newFake()
141 err := ConvergeDeployment(context.Background(), f, "/hostedzone/Z0ABC",
142 []registry.Route{steeredRoute("app.example.com")},
143 [][]byte{edgesBody(t, "dublin", "1.2.3.4", "eu-west-1")},
144 "example.com")
145 if err == nil {
146 t.Fatal("ConvergeDeployment accepted a non-bare hosted-zone id")
147 }
148 if f.writes() != 0 {
149 t.Fatalf("writes = %d, want 0", f.writes())
150 }
151}
152