package console // claim_invariant_probes_worker_test.go is the probe table for the recorded // workers that are not doors. A worker answers nothing, so the proof is its // work: a bucket object, a SQL row or the line it logs, read from the world // after one bounded run. A run that did nothing (no pointer to expire, no // alert to send, no box to report on) is not coverage. import ( "context" "encoding/json" "strings" "testing" "time" "github.com/carlosframework/platform/internal/economics" "github.com/carlosframework/platform/internal/geoip" "github.com/carlosframework/platform/internal/hostfloor" "github.com/carlosframework/platform/internal/hostops" "github.com/carlosframework/platform/internal/infraview" "github.com/carlosframework/platform/internal/metrics" "github.com/carlosframework/platform/internal/moves" "github.com/carlosframework/platform/internal/plans" "github.com/carlosframework/platform/internal/provision" "github.com/carlosframework/platform/internal/registry" "github.com/carlosframework/platform/internal/release" "github.com/carlosframework/platform/internal/usage" ) // claimLogWorkerProbe runs a worker that only logs, and answers the log: the // reply's body is what the worker said, so the probe's markers are the lines // it must have said about a real finding. func claimLogWorkerProbe(name string, setup func(*testing.T, *claimCase), want ...string) claimProbe { return claimProbe{ serial: "captures the process-wide log output (captureLogTo): another case's log lines would land in its answer", setup: setup, do: func(t *testing.T, cx *claimCase) claimReply { claimMustRunAlone(t, "log worker probe "+name) var logs strings.Builder restore := captureLogTo(&logs) reply := claimWorkerReply(name)(t, cx) restore() reply.Body = logs.String() return reply }, body: want, } } // claimRegionalApp is app blog homed in uk with a no-region instance record // created after it: the shape a console rolled below the floor writes, which // the placement check lists as a discrepancy candidate. func claimRegionalApp(t *testing.T, cx *claimCase) { t.Helper() scope := []claimSQLScope{{AccountID: OpsAccountID, App: "blog", AppID: "claim-bab-blog", Mode: claimModeEffect}} err := cx.st.withClaimSQL(gateCtx(t), scope, allowAllClaimSQL, func(v *Store) error { if _, err := v.CreateAppInRegion(OpsAccountID, "blog", claimFxOwner, "uk", "chosen", time.Now().Add(-time.Hour)); err != nil { return err } return v.BindClaimAppIdentity(OpsAccountID, "blog", "claim-bab-blog") }) if err != nil { t.Fatalf("stage the regional app: %v", err) } cx.putAdmission(t, "bab", "blog", hostops.AppAdmission{V: 1, AppID: "claim-bab-blog", Revision: 1, Epoch: 1, State: "open", Registrations: map[string]hostops.Registration{}, Effects: map[string]hostops.Effect{}}) rec := provision.Record{Schema: 1, Host: "drift.go.tito.io", App: "blog", Account: release.OpsAccount, Channel: "stable", CreatedAt: time.Now()} if err := provision.CreateRecord(context.Background(), cx.rel, rec); err != nil { t.Fatalf("stage the drifting record: %v", err) } } var claimWorkerProbes = map[string]claimProbe{ // ---- reads: they say what they found ---- "worker ReportApexSquats": claimLogWorkerProbe("ReportApexSquats", func(t *testing.T, cx *claimCase) { // A route at titogo's platform apex that belongs to another app. cx.addRoute(t, registry.Route{Host: "titogo.bab.oncarlos.com", Kind: "instance", Status: "ready", App: "kass", Account: "bab", Addr: "127.0.0.1:9301"}) }, "apex squat", "titogo.bab.oncarlos.com"), "worker StartRunSweep": claimLogWorkerProbe("StartRunSweep", nil, "run sweep", "host-claim console"), "worker StartSeedsPass": claimLogWorkerProbe("StartSeedsPass", nil, "seeds pass", "host-claim console"), "worker LogPlacementDiscrepancies": claimLogWorkerProbe("LogPlacementDiscrepancies", claimRegionalApp, msgPlacementDiscrepancy("drift.go.tito.io", "blog", "uk")), // ---- nonApp: they write deployment state ---- "worker PublishMovesConsole": { setup: func(t *testing.T, cx *claimCase) { cx.srv.cfg.MovesEnabled = true }, do: claimWorkerReply("PublishMovesConsole"), effect: func(t *testing.T, cx *claimCase, r claimReply) string { var rec moves.ConsoleRecord if !cx.bucketJSON(moves.ConsoleKey, &rec) { return "no " + moves.ConsoleKey + " was published" } if rec.V != 1 || rec.Protocol != moves.ProtocolVersion || rec.At.IsZero() { return "the published moves console record is not this console's" } return "" }, }, "worker StartAlertWatcher": { setup: func(t *testing.T, cx *claimCase) { // One box with a disk alert firing; the owner holds a Keymail grant // (they signed in), so the watcher can mail them and must record it. now := time.Now().UTC() state := metrics.AlertState{V: 1, Box: "box1", UpdatedAt: now, Rules: map[string]metrics.RuleState{"disk": {Firing: true, FiredAt: now, Value: 91}}} body, err := json.Marshal(state) if err != nil { t.Fatal(err) } if _, err := cx.rel.Put(context.Background(), metrics.AlertKey("box1"), body, ""); err != nil { t.Fatal(err) } }, do: claimWorkerReply("StartAlertWatcher"), effect: func(t *testing.T, cx *claimCase, r claimReply) string { if cx.sqlCount(t, `SELECT COUNT(*) FROM alert_seen`) == 0 { return "no operator was told about the firing alert (alert_seen is empty)" } return "" }, }, "worker StartEconomicsPass": { setup: func(t *testing.T, cx *claimCase) { // The bill pull is the one stage that would reach AWS: a seam answers it. cx.srv.ceCosts = func(context.Context, time.Time, time.Time) (map[string]float64, error) { return map[string]float64{"AmazonEC2": 1}, nil } }, do: claimWorkerReply("StartEconomicsPass"), effect: func(t *testing.T, cx *claimCase, r claimReply) string { day := usage.DayOf(time.Now()) var census usage.CensusDay if !cx.bucketJSON(usage.CensusDayKey(day), &census) || census.Date != day { return "no census day was written for " + day } var bill economics.Bill if !cx.bucketJSON(economics.BillKey(time.Now().UTC().Format("2006-01")), &bill) || bill.TotalUSD != 1 { return "no bill was pulled for the month" } return "" }, }, "worker StartGeoipJobs": { setup: func(t *testing.T, cx *claimCase) { // A blob no pointer names: the orphan a crashed publish leaves. if _, err := cx.rel.Put(context.Background(), geoip.BlobKey(strings.Repeat("a", 64)), []byte("x"), ""); err != nil { t.Fatal(err) } }, do: claimWorkerReply("StartGeoipJobs"), effect: func(t *testing.T, cx *claimCase, r claimReply) string { if cx.bucketHas(geoip.BlobKey(strings.Repeat("a", 64))) { return "the orphan blob survived the sweep" } return "" }, }, "worker StartHostReports": { serial: "swaps the package variable hostRunningImage", setup: func(t *testing.T, cx *claimCase) { claimMustRunAlone(t, "worker StartHostReports") // The box's guard files are not here; the seam says what this // process is running, as the guard would. prev := hostRunningImage hostRunningImage = func() (hostfloor.Running, error) { return hostfloor.Running{ReleaseTag: "v1.0.0", Hash: claimFxConsoleSHA, Protocol: 1, BootID: "claim-fixture-boot", GuardReady: true}, nil } t.Cleanup(func() { hostRunningImage = prev }) }, do: claimWorkerReply("StartHostReports"), effect: func(t *testing.T, cx *claimCase, r claimReply) string { var report struct { Actor string `json:"actor"` Component string `json:"component"` } if !cx.bucketJSON("status/consoles/"+claimFxConsole+".json", &report) { return "this console's census report was not written" } if report.Actor != claimFxConsole || report.Component != "console" { return "the census report is not this console's" } return "" }, }, "worker StartInfraPass": { setup: claimInventorySeam, do: claimWorkerReply("StartInfraPass"), effect: func(t *testing.T, cx *claimCase, r claimReply) string { var inv infraview.Inventory if !cx.bucketJSON(infraview.InventoryKey, &inv) || inv.Provider != "aws" { return "no inventory snapshot was stored" } return "" }, }, "worker PublishPlansMarker": { setup: func(t *testing.T, cx *claimCase) { cx.srv.cfg.PlanCatalog = examplePlanCatalog(t) }, do: claimWorkerReply("PublishPlansMarker"), effect: func(t *testing.T, cx *claimCase, r claimReply) string { var m plans.Marker if !cx.bucketJSON(plans.MarkerKey(), &m) || !m.Enabled { return "no enabled plans marker was published" } return "" }, }, "worker StartPlanLimitsPass": { setup: func(t *testing.T, cx *claimCase) { cx.srv.cfg.PlanCatalog = examplePlanCatalog(t) }, do: claimWorkerReply("StartPlanLimitsPass"), effect: func(t *testing.T, cx *claimCase, r claimReply) string { var rec plans.Record if !cx.bucketJSON(plans.LimitsKey("bab"), &rec) { return "no limits record was published for bab" } if rec.Plan != "free" || rec.Limits.RunningThings != 3 { return "the published limits record is not the default plan's" } return "" }, }, }