From 84af0ed1805b4767819f4507643dd0a1f78822e7 Mon Sep 17 00:00:00 2001 From: jochen Date: Sun, 18 Oct 2026 02:37:28 +0200 Subject: [PATCH] Guard that the bus storage stays declared as data with a backup (issue 1098) --- .../cmd/nats-tools/backup_declared_test.go | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 modules/nats/cmd/nats-tools/backup_declared_test.go diff --git a/modules/nats/cmd/nats-tools/backup_declared_test.go b/modules/nats/cmd/nats-tools/backup_declared_test.go new file mode 100644 index 00000000..4cacebe8 --- /dev/null +++ b/modules/nats/cmd/nats-tools/backup_declared_test.go @@ -0,0 +1,72 @@ +package main + +import ( + "encoding/json" + "os" + "strings" + "testing" +) + +// The bus's storage stays declared as data protected by a backup (novox/hq ADR 0408 clause 7; issue 1098): the +// assignments, rollouts and builds now live in the bus's buckets, so a manifest that stopped saying so would leave +// the one copy of them unprotected. The storage directory is declared as valuable data with a dump into the +// snapshots directory, which is itself declared. +func TestTheBusStorageIsDeclaredAsDataProtectedByABackup(t *testing.T) { + raw, err := os.ReadFile("../../module.json") + if err != nil { + t.Fatal(err) + } + var m struct { + Data struct { + Own []struct { + ID string `json:"id"` + Path string `json:"path"` + Class string `json:"class"` + Backup *struct { + Dump string `json:"dump"` + Into string `json:"into"` + } `json:"backup"` + } `json:"own"` + } `json:"data"` + Resources []struct { + ID string `json:"id"` + Type string `json:"type"` + } `json:"resources"` + } + if err := json.Unmarshal(raw, &m); err != nil { + t.Fatal(err) + } + var storage, snapshots bool + for _, d := range m.Data.Own { + switch d.ID { + case "jetstream": + if d.Path != "${dir:jetstream-data}" || d.Class != "valuable" { + t.Errorf("the bus's storage is declared as %q, class %q", d.Path, d.Class) + } + if d.Backup == nil || strings.TrimSpace(d.Backup.Dump) == "" || d.Backup.Into != "snapshots" { + t.Errorf("the bus's storage has no dump into the snapshots: %+v", d.Backup) + } + storage = true + case "snapshots": + snapshots = true + } + } + if !storage || !snapshots { + t.Errorf("the bus's storage declared: %v, and its snapshots: %v", storage, snapshots) + } + var dirs []string + for _, r := range m.Resources { + if r.Type == "directory" { + dirs = append(dirs, r.ID) + } + } + for _, want := range []string{"jetstream-data", "snapshots"} { + found := false + for _, id := range dirs { + found = found || id == want + } + if !found { + t.Errorf("the directory %s is not a declared resource (directories: %v)", want, dirs) + } + } +}