The user list is a file in a directory the bus's container mounts, so it read as moving data and held every new credential for a person's yes, against ADR 0539 clause 7; mesh-sdk's UserListOnly lets the assigner write such a revision at once.
109 lines
4.3 KiB
Go
109 lines
4.3 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
"git.novox.be/novox/mesh-sdk/go/compose"
|
|
sdkdelivery "git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
// natsComposedWith is the bus module's composition on novox with the given user list: the catalogue's nats manifest as
|
|
// captured (testdata/beside/mesh-catalog/modules/nats/module.json.captured), its archives, which only a registration
|
|
// turns into references, left out, and its container's built image given as a reference.
|
|
func natsComposedWith(t *testing.T, users string) sdkdelivery.Composed {
|
|
t.Helper()
|
|
raw, err := os.ReadFile("../../testdata/beside/mesh-catalog/modules/nats/module.json.captured")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var m catalogue.Manifest
|
|
if err := json.Unmarshal(raw, &m); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var kept []map[string]any
|
|
for _, r := range m.Resources {
|
|
if _, templated := r["template"]; templated {
|
|
continue // a template is rendered from the build's templates archive, which only a registration fetches
|
|
}
|
|
switch r["type"] {
|
|
case "archive":
|
|
continue
|
|
case "container":
|
|
// Its image is named by a build's artifact, which only a registration records: given here as a reference.
|
|
delete(r, "artifact")
|
|
r["image"] = "nats@sha256:" + strings.Repeat("1", 64)
|
|
}
|
|
kept = append(kept, r)
|
|
}
|
|
m.Resources = kept
|
|
key := base64.StdEncoding.EncodeToString(make([]byte, 32))
|
|
in := compose.Input{Catalogue: map[string]catalogue.Manifest{m.Module: m}, BusUsers: users,
|
|
OwnSecrets: []compose.OwnSecretRow{{Node: "novox", Module: m.Module, Name: "broker", Origin: "made", SealedTo: key,
|
|
Sealed: "SEALED-BY-THE-TEST"}},
|
|
Nodes: []compose.Node{{Name: "novox", Assigned: []string{m.Module}, Stated: true, SealingKey: key,
|
|
Capabilities: map[string]bool{"container-runtime": true, "systemd": true}}}}
|
|
fp := sdkdelivery.SourcePrefix2 + strings.Repeat("e", 64)
|
|
all, _, err := compose.Compositions(in, "novox", map[string]string{m.Module: fp}, compose.Foreseeing)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
k, _ := sdkdelivery.ComposedKey("novox", m.Module, fp)
|
|
c, ok := all[k]
|
|
if !ok {
|
|
t.Fatalf("no composition of %s: %v", m.Module, all)
|
|
}
|
|
return c
|
|
}
|
|
|
|
// 1945/AC12 and the review's A2 (ADR 0539 clause 7): a revision of the bus module's composition that changes only its
|
|
// user list, a file in a directory its container mounts, is judged neither and said to change only the user list, so
|
|
// a new credential never waits for a person's yes; a revision that changes anything else beside it is judged as any.
|
|
func TestARevisionOfOnlyTheUserListMovesNothing(t *testing.T) {
|
|
at, _, _, haves := aPlace(t, "novox")
|
|
ctx := context.Background()
|
|
before := natsComposedWith(t, "authorization { users = [ {user: a} ] }\n")
|
|
after := natsComposedWith(t, "authorization { users = [ {user: a}, {user: b} ] }\n")
|
|
if d1, _ := sdkdelivery.ComposedDigestOf(before); d1 == func() string { d, _ := sdkdelivery.ComposedDigestOf(after); return d }() {
|
|
t.Fatal("the two user lists composed the same")
|
|
}
|
|
key, _ := sdkdelivery.ComposedKey("novox", before.Module, before.FP)
|
|
if _, err := writeComposed(ctx, at, key, before); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
runs, _ := sdkdelivery.ComposedDigestOf(before)
|
|
haves[before.Module] = sdkdelivery.Have{FP: before.FP, Composed: runs, Phase: sdkdelivery.PhaseRunning, Health: sdkdelivery.HealthOK}
|
|
digest, _ := sdkdelivery.ComposedDigestOf(after)
|
|
v, err := judgeMove(ctx, at, key, after, digest)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if v.Judgement != sdkdelivery.JudgedNeither || !v.UserListOnly || v.Against != runs {
|
|
t.Errorf("a user-list-only revision is judged %+v", v)
|
|
}
|
|
// The user list and a container's image beside it: judged as any move, and not user-list-only.
|
|
other := after
|
|
other.Resources = append([]json.RawMessage{}, after.Resources...)
|
|
for i, r := range other.Resources {
|
|
var head map[string]any
|
|
_ = json.Unmarshal(r, &head)
|
|
if head["type"] == "container" {
|
|
head["image"] = "nats@sha256:" + strings.Repeat("9", 64)
|
|
other.Resources[i], _ = json.Marshal(head)
|
|
}
|
|
}
|
|
d2, _ := sdkdelivery.ComposedDigestOf(other)
|
|
v, err = judgeMove(ctx, at, key, other, d2)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if v.UserListOnly || v.Judgement != sdkdelivery.JudgedRecreates {
|
|
t.Errorf("a new image beside the user list is judged %+v", v)
|
|
}
|
|
}
|