mesh/delivery merged: source.main moved to novox/mesh-sdk@095d41fa3e81
mesh/delivery-group group fix/1945-memberships merged: every member is merged
mesh/check failed: integration: github.com/novox/mesh-controller/cmd/mesh-controller.TestTheDeclarationsStreamGoesOnceEveryNodeRunsTheNewEngine: with …
The grants part reads each module's last membership before it publishes, so it needs the direct get on every membership subject, as the controller's composer now grants (fix/1945-mesh-grants-publishes-memberships). The equality test compares every membership the fixtures issue with the controller's MembershipFor, written by its own code.
117 lines
4.5 KiB
Go
117 lines
4.5 KiB
Go
package buscompose
|
|
|
|
// The fixtures the copied bus composer is held to (issue 1377, ADR 0547 §5): the same source is compiled into the
|
|
// controller's internal/broker to write the expected lists, and into mesh-sdk's buscompose to compare against them.
|
|
|
|
// UserListFixture is one mesh's records, and the hashes its accounts carry.
|
|
type UserListFixture struct {
|
|
Name string
|
|
Records Records
|
|
// Hashless are users given no hash, so they are left out and named.
|
|
Hashless []string
|
|
}
|
|
|
|
func fixtureTelegramSeat() Seat {
|
|
return Seat{Name: "telegram-sender", Accepts: []string{"send"}, Emits: []string{"delivered", "failed"}}
|
|
}
|
|
|
|
// UserListFixtures are the meshes, from the controller's own tests' records outward.
|
|
func UserListFixtures() []UserListFixture {
|
|
return []UserListFixture{
|
|
{Name: "empty"},
|
|
{Name: "the controller's someRecords", Records: Records{
|
|
Nodes: []string{"two", "one"},
|
|
Assigned: map[string][]Declared{
|
|
"one": {{Module: "telegram", Serves: []string{"status"}}},
|
|
"two": {{Module: "shop", Emits: []string{"order.placed"}}},
|
|
},
|
|
Enrolling: []string{"three"},
|
|
People: map[string][]string{"ada": {"mesh-catalog.catalog_tools"}},
|
|
}},
|
|
{Name: "seats, consumers, people and a hashless user", Hashless: []string{"two.audit"}, Records: Records{
|
|
Nodes: []string{"one", "two"},
|
|
Assigned: map[string][]Declared{
|
|
"one": {
|
|
{Module: "telegram", Holds: []Seat{fixtureTelegramSeat()}, Serves: []string{"status"}},
|
|
{Module: "nats", SnapshotsTheBus: true, Serves: []string{"nats_streams"}},
|
|
{Module: "mesh-watchman"},
|
|
{Module: "mesh-grants", Emits: []string{"membership-changed"}},
|
|
},
|
|
"two": {
|
|
{Module: "shop", Uses: []Seat{fixtureTelegramSeat()}, Emits: []string{"order.placed"}},
|
|
{Module: "audit", Consumes: []string{"shop.order.placed"}},
|
|
},
|
|
},
|
|
People: map[string][]string{"ada": {"*"}, "bob": {"shop.status"}},
|
|
Interchangeable: map[string]bool{"shop": true},
|
|
}},
|
|
{Name: "state, logs, streams, queues and processes", Records: Records{
|
|
Nodes: []string{"ace", "novox"},
|
|
Assigned: map[string][]Declared{
|
|
"novox": {
|
|
{Module: "mesh-delivery-builder", Emits: []string{"built"},
|
|
State: []Bucket{{Module: "mesh-delivery-builder", Name: "steps", History: 5},
|
|
{Module: "mesh-delivery-builder", Name: "presence", PerMachine: true, KeyTTL: true, TTLSeconds: 60}},
|
|
Logs: []Log{{Module: "mesh-delivery-builder", Name: "builds", MaxMiB: 64}},
|
|
Streams: []ModuleStream{{Module: "mesh-delivery-builder", Name: "asks", Events: []string{"ask"}, MaxAgeDays: 7, MaxMiB: 32, WorkQueue: true}},
|
|
Queues: []QueueOwner{{Process: "worker", Stream: "asks", MaxDeliver: 5}},
|
|
Processes: []ProcessPrincipal{{Process: "worker", Emits: []string{"built"},
|
|
Queues: []QueueOwner{{Process: "worker", Stream: "asks", MaxDeliver: 5}},
|
|
State: []string{"steps"}, Invokes: []string{"gitea.gitea_commit"}}},
|
|
Invokes: []string{"gitea.gitea_commit"},
|
|
},
|
|
{Module: "mesh-delivery-view", Reads: []string{"mesh-delivery-builder.steps"},
|
|
KeyedReads: []KeyedRead{{Read: "mesh-delivery-builder.presence", Key: "novox"}}},
|
|
},
|
|
"ace": {
|
|
{Module: "plex", Serves: []string{"plex_status"}, Checks: []string{"plex.plex_status"}},
|
|
{Module: "silent", NoAccount: true},
|
|
},
|
|
},
|
|
RootFree: map[string]bool{"ace": true},
|
|
}},
|
|
}
|
|
}
|
|
|
|
// HashOf is the stand-in hash a fixture's user carries.
|
|
func HashOf(user string) string {
|
|
h := "$2a$11$"
|
|
for len(h) < 29 {
|
|
h += user
|
|
}
|
|
return h[:29] + "fixturefixturefixturefixture00"
|
|
}
|
|
|
|
// ComposedFor is a fixture's user list as the composer writes it, and the users left out.
|
|
func ComposedFor(f UserListFixture) (string, []string, error) {
|
|
users, err := Users(f.Records)
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
hashes := map[string]string{}
|
|
skip := map[string]bool{}
|
|
for _, u := range f.Hashless {
|
|
skip[u] = true
|
|
}
|
|
for _, u := range users {
|
|
if !skip[u.Username()] {
|
|
hashes[u.Username()] = HashOf(u.Username())
|
|
}
|
|
}
|
|
filled, missing := WithPasswords(users, hashes)
|
|
list, err := ComposeAccounts(filled)
|
|
return list, missing, err
|
|
}
|
|
|
|
// MembershipsFor is every membership a fixture's records issue, by `<node>.<module>`, as the composer makes them.
|
|
func MembershipsFor(f UserListFixture) map[string]Membership {
|
|
where := PlacementsOf(f.Records, f.Records.Interchangeable)
|
|
out := map[string]Membership{}
|
|
for node, ds := range f.Records.Assigned {
|
|
for _, d := range ds {
|
|
out[node+"."+d.Module] = MembershipFor(node, d, where)
|
|
}
|
|
}
|
|
return out
|
|
}
|