|
|
|
@@ -1,10 +1,12 @@
|
|
|
|
|
package broker
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"slices"
|
|
|
|
|
"strings"
|
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
|
|
|
"github.com/nats-io/nats.go/jetstream"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// 1945/AC1: a node's composition bucket keeps five revisions of a key and is named for its node; the bucket of digests
|
|
|
|
@@ -147,3 +149,55 @@ func TestTheOperatorWritesTheHandPath(t *testing.T) {
|
|
|
|
|
t.Errorf("the controller may not say bucket-deleted")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 1945 (the review's A1): the bus's user list today's controller composes, which is the one the bus runs after release
|
|
|
|
|
// 6's switch, already grants every subject the new controller, every new node-engine and the assigner use: the
|
|
|
|
|
// controller writes each node's compositions and the digests; a node-engine reads its own compositions and wants, asks
|
|
|
|
|
// its own backup holder and hears its word, and nothing of another node's; the assigner reads the digests, announced
|
|
|
|
|
// readable.
|
|
|
|
|
func TestTheUserListGrantsWhatReleaseSixUses(t *testing.T) {
|
|
|
|
|
controller, err := PermissionsFor(Principal{Kind: KindController, PasswordHash: "x", FilesFor: []string{"ace", "g14"}})
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
for _, s := range []string{"$KV.composed-ace.>", "$KV.composed-g14.>", "$KV.mesh-controller_composed.>",
|
|
|
|
|
"mesh.seat.mesh-controller.event.bucket-deleted"} {
|
|
|
|
|
has(t, controller.Publish, s)
|
|
|
|
|
}
|
|
|
|
|
node, err := PermissionsFor(Principal{Kind: KindNode, Node: "ace", PasswordHash: "x"})
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
for _, s := range []string{
|
|
|
|
|
"$JS.API.STREAM.INFO.KV_composed-ace", "$JS.API.DIRECT.GET.KV_composed-ace.>", "$JS.API.CONSUMER.CREATE.KV_composed-ace.>",
|
|
|
|
|
"$JS.API.DIRECT.GET.KV_mesh-delivery-assigner_wants.$KV.mesh-delivery-assigner_wants.want.ace.>",
|
|
|
|
|
"$JS.API.CONSUMER.CREATE.KV_mesh-delivery-assigner_wants.*.$KV.mesh-delivery-assigner_wants.want.ace.>",
|
|
|
|
|
"mesh.seat.node-backup.tool.now.ace", "mesh.seat.node-backup.tool.backed-up.ace",
|
|
|
|
|
} {
|
|
|
|
|
has(t, node.Publish, s)
|
|
|
|
|
}
|
|
|
|
|
has(t, node.Subscribe, "mesh.mod.restic.event.backed-up")
|
|
|
|
|
for _, p := range node.Publish {
|
|
|
|
|
if strings.Contains(p, "composed-g14") || strings.Contains(p, "mesh-controller_composed") || strings.Contains(p, "want.g14") ||
|
|
|
|
|
strings.HasPrefix(p, "$KV.composed-") || strings.HasSuffix(p, "node-backup.tool.now.*") {
|
|
|
|
|
t.Errorf("a node-engine of ace may publish %s", p)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if !slices.Contains(controllerReadableStates(), ControllerComposed) ||
|
|
|
|
|
!slices.Contains(ControllerBuckets(), delivery.ControllerComposedBucket) || !IsControllerBucket(delivery.ControllerComposedBucket) {
|
|
|
|
|
t.Fatalf("the digests are not announced readable among the controller's buckets")
|
|
|
|
|
}
|
|
|
|
|
if !ControllerAnnouncement("novox").Readable(ControllerComposed) {
|
|
|
|
|
t.Fatalf("the controller does not announce %s readable", ControllerComposed)
|
|
|
|
|
}
|
|
|
|
|
assigner, err := PermissionsFor(Principal{Kind: KindModule, Node: "novox", Module: "mesh-delivery-assigner", PasswordHash: "x",
|
|
|
|
|
Reads: []string{"mesh-controller.composed"}})
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
has(t, assigner.Publish, "$JS.API.STREAM.INFO.KV_mesh-controller_composed")
|
|
|
|
|
has(t, assigner.Publish, "$JS.API.CONSUMER.CREATE.KV_mesh-controller_composed.>")
|
|
|
|
|
if c := ComposedDigestsConfig(); c.Bucket != "mesh-controller_composed" || c.History != 5 || c.Storage != jetstream.FileStorage {
|
|
|
|
|
t.Errorf("the digests' bucket is %+v", c)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|