Z4 zfs-manifest-bus: the events stream, states and ledger by template, the keeper as the module's one process bus account
The three root processes declare no bus and reach the keeper's socket; the module invokes the service manager's start. The judge refuses the keeper's bus emits and state until the validator accepts what the module asks for in requires (A-38). Builds: design 42 zfs-owns-zfs §25, §26, §27, §28, A-6, A-19, A-36, A-37, A-38
This commit is contained in:
@@ -76,8 +76,8 @@ func TestTheManifestNamesTheToolsTheBundleServesAndWhatEachReplaces(t *testing.T
|
||||
if len(m.Claims) != 0 {
|
||||
t.Errorf("the module claims no seat: %v", m.Claims)
|
||||
}
|
||||
if strings.Join(m.Emits, ",") != "snapshot.taken,"+ScrubEvent {
|
||||
t.Errorf("emits %v", m.Emits)
|
||||
if len(m.Emits) != 0 {
|
||||
t.Errorf("the events are asked for by template in requires: emits %v", m.Emits)
|
||||
}
|
||||
if hit := regexp.MustCompile(`\b(g14|novox|ace|shanks|jochen)\b|/home/`).FindString(strings.ReplaceAll(raw, "novox/hq", "")); hit != "" {
|
||||
t.Errorf("the manifest says %q", hit)
|
||||
@@ -459,3 +459,84 @@ func TestTheBundleRunsOnlyTheFormsOfADR0679(t *testing.T) {
|
||||
t.Errorf("found %d call sites; the test no longer sees them", sites)
|
||||
}
|
||||
}
|
||||
|
||||
// §25, §26 (A-19, A-36), A-37, A-38, §28: one events stream by template, 30 days, every kind of §25; the states applied,
|
||||
// schedule and findings; the ledger snapshots of A-36 with a fixed cap and no index; the keeper alone holds the process bus, as a user of
|
||||
// the module's own, naming the module's events and states and invoking the three; the three root processes declare no bus and
|
||||
// reach the keeper's socket; the module invokes the service manager's start; the tools list holds §28's.
|
||||
func TestTheManifestsBusStateKeeperAndTools(t *testing.T) {
|
||||
tree, byID, _ := manifestOf(t)
|
||||
reqs := map[string]map[string]any{}
|
||||
for _, r := range tree["requires"].([]any) {
|
||||
e := r.(map[string]any)
|
||||
reqs[e["name"].(string)] = e
|
||||
}
|
||||
ev := reqs["events"]
|
||||
opts, _ := ev["options"].(map[string]any)
|
||||
var kinds []string
|
||||
for _, k := range opts["events"].([]any) {
|
||||
kinds = append(kinds, k.(string))
|
||||
}
|
||||
if ev["storage"] != "stream" || ev["template"] != "events" || opts["max-age-days"] != float64(30) || strings.Join(kinds, ",") != strings.Join(EventKinds, ",") {
|
||||
t.Errorf("the events stream: %v", ev)
|
||||
}
|
||||
for _, n := range []string{"applied", "schedule", "findings"} {
|
||||
if e := reqs[n]; e == nil || e["storage"] != "key-value" || e["template"] != "state" {
|
||||
t.Errorf("the state %s: %v", n, e)
|
||||
}
|
||||
}
|
||||
if reqs["findings"]["options"] != nil {
|
||||
t.Errorf("findings declares no stream of its own (A-32): %v", reqs["findings"])
|
||||
}
|
||||
l := reqs[LedgerName]
|
||||
lo, _ := l["options"].(map[string]any)
|
||||
types, _ := l["types"].([]any)
|
||||
if l["storage"] != "ledger" || l["template"] != "ledger" || lo["max-mib"] == nil || len(types) != 1 {
|
||||
t.Fatalf("the ledger: %v", l)
|
||||
}
|
||||
ty := types[0].(map[string]any)
|
||||
ops, _ := json.Marshal(ty["operations"])
|
||||
if ty["name"] != "snapshot" || ty["indexes"] != nil ||
|
||||
string(ops) != `[{"effect":"set-entry","fields":["dataset","name","kind","at"],"into":"taken","key":"name","name":"taken"},{"effect":"remove","into":"taken","key":"name","name":"removed"}]` {
|
||||
t.Errorf("the ledger's type: %v", ty)
|
||||
}
|
||||
k := byID["keeper"]
|
||||
bus, _ := k["bus"].(map[string]any)
|
||||
acct := byID["keeper-account"]
|
||||
if k["user"] != "zfs-keeper" || acct["type"] != "user" || acct["name"] != "zfs-keeper" || bus == nil ||
|
||||
fmt.Sprint(bus["state"]) != "[applied schedule findings]" ||
|
||||
fmt.Sprint(bus["invokes"]) != "["+ToolRecord+" "+ToolSchedule+" seat:node-service-manager.start]" {
|
||||
t.Errorf("the keeper: %v %v", k, acct)
|
||||
}
|
||||
if got := fmt.Sprint(bus["emits"]); strings.Contains(got, ScrubEvent) || !strings.Contains(got, EventApplied) || !strings.Contains(got, EventTakenSchedule) {
|
||||
t.Errorf("the keeper's events: %v", got)
|
||||
}
|
||||
for _, id := range []string{"apply", "events", "run"} {
|
||||
r := byID[id]
|
||||
if r["bus"] != nil || fmt.Sprint(r["env"]) != "map["+KeeperSocketEnv+":${dir:keeper-state}/keeper.sock]" {
|
||||
t.Errorf("%s declares a bus or does not reach the keeper's socket: %v", id, r)
|
||||
}
|
||||
}
|
||||
for _, id := range []string{"watch", "keeper-state"} {
|
||||
if byID[id]["bus"] != nil {
|
||||
t.Errorf("%s", id)
|
||||
}
|
||||
}
|
||||
if byID["keeper-state"]["owner"] != "zfs-keeper" {
|
||||
t.Errorf("the keeper's folder: %v", byID["keeper-state"])
|
||||
}
|
||||
if fmt.Sprint(tree["invokes"]) != "[seat:node-service-manager.start]" {
|
||||
t.Errorf("invokes: %v", tree["invokes"])
|
||||
}
|
||||
m, _ := readManifest(t)
|
||||
for _, tool := range []string{"zfs_config", "zfs_config_apply", "zfs_snapshots_schedule", "zfs_snapshots_run_now", "zfs_snapshots_prune_now", "zfs_snapshots_pause",
|
||||
"zfs_snapshots_resume", "zfs_module_events", "zfs_snapshots_check", "zfs_findings", "zfs_snapshots_record"} {
|
||||
found := false
|
||||
for _, x := range m.Tools {
|
||||
found = found || x == tool
|
||||
}
|
||||
if !found {
|
||||
t.Errorf("%s is not in tools", tool)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+164
-5
@@ -5,9 +5,103 @@
|
||||
"package-manager",
|
||||
"service-manager"
|
||||
],
|
||||
"emits": [
|
||||
"snapshot.taken",
|
||||
"scrub.requested"
|
||||
"invokes": [
|
||||
"seat:node-service-manager.start"
|
||||
],
|
||||
"own-secrets": {
|
||||
"broker-keeper": {
|
||||
"path": "${dir:keeper-state}/broker-keeper.secret",
|
||||
"owner": "zfs-keeper"
|
||||
}
|
||||
},
|
||||
"requires": [
|
||||
{
|
||||
"name": "events",
|
||||
"storage": "stream",
|
||||
"template": "events",
|
||||
"options": {
|
||||
"events": [
|
||||
"config.applied",
|
||||
"config.refused",
|
||||
"config.waiting",
|
||||
"snapshot.taken.person",
|
||||
"snapshot.taken.schedule",
|
||||
"snapshot.removed.person",
|
||||
"snapshot.removed.schedule",
|
||||
"snapshot.skipped.person",
|
||||
"snapshot.skipped.schedule",
|
||||
"run.skipped",
|
||||
"scrub.requested"
|
||||
],
|
||||
"max-age-days": 30,
|
||||
"max-mib": 16
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "applied",
|
||||
"storage": "key-value",
|
||||
"template": "state"
|
||||
},
|
||||
{
|
||||
"name": "schedule",
|
||||
"storage": "key-value",
|
||||
"template": "state"
|
||||
},
|
||||
{
|
||||
"name": "findings",
|
||||
"storage": "key-value",
|
||||
"template": "state"
|
||||
},
|
||||
{
|
||||
"name": "snapshots",
|
||||
"storage": "ledger",
|
||||
"template": "ledger",
|
||||
"options": {
|
||||
"max-mib": 64
|
||||
},
|
||||
"types": [
|
||||
{
|
||||
"name": "snapshot",
|
||||
"schema": {
|
||||
"dataset": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"type": "string"
|
||||
},
|
||||
"at": {
|
||||
"type": "string"
|
||||
},
|
||||
"taken": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"operations": [
|
||||
{
|
||||
"name": "taken",
|
||||
"effect": "set-entry",
|
||||
"into": "taken",
|
||||
"key": "name",
|
||||
"fields": [
|
||||
"dataset",
|
||||
"name",
|
||||
"kind",
|
||||
"at"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "removed",
|
||||
"effect": "remove",
|
||||
"into": "taken",
|
||||
"key": "name"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"pool": {
|
||||
@@ -260,6 +354,20 @@
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "keeper-account",
|
||||
"type": "user",
|
||||
"name": "zfs-keeper",
|
||||
"shell": "/usr/bin/nologin"
|
||||
},
|
||||
{
|
||||
"id": "keeper-state",
|
||||
"type": "directory",
|
||||
"mode": "0711",
|
||||
"owner": "zfs-keeper",
|
||||
"place": "mesh",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "config-dir",
|
||||
"type": "directory",
|
||||
@@ -432,6 +540,48 @@
|
||||
"zed=off"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "keeper",
|
||||
"type": "process",
|
||||
"name": "zfs-keeper",
|
||||
"artifact": "tools",
|
||||
"run": [
|
||||
"./zfs-tools",
|
||||
"keeper"
|
||||
],
|
||||
"user": "zfs-keeper",
|
||||
"env": {
|
||||
"MESH_BROKER_FILE": "${dir:keeper-state}/broker-keeper.secret",
|
||||
"ZFS_KEEPER_SOCKET": "${dir:keeper-state}/keeper.sock"
|
||||
},
|
||||
"bus": {
|
||||
"state": [
|
||||
"applied",
|
||||
"schedule",
|
||||
"findings"
|
||||
],
|
||||
"emits": [
|
||||
"config.applied",
|
||||
"config.refused",
|
||||
"config.waiting",
|
||||
"snapshot.taken.person",
|
||||
"snapshot.taken.schedule",
|
||||
"snapshot.removed.person",
|
||||
"snapshot.removed.schedule",
|
||||
"snapshot.skipped.person",
|
||||
"snapshot.skipped.schedule",
|
||||
"run.skipped"
|
||||
],
|
||||
"invokes": [
|
||||
"zfs.zfs_snapshots_record",
|
||||
"zfs.zfs_snapshots_schedule",
|
||||
"seat:node-service-manager.start"
|
||||
]
|
||||
},
|
||||
"health": {
|
||||
"kind": "unit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "apply",
|
||||
"type": "process",
|
||||
@@ -444,7 +594,10 @@
|
||||
"run-once": true,
|
||||
"restart-on": [
|
||||
"config"
|
||||
]
|
||||
],
|
||||
"env": {
|
||||
"ZFS_KEEPER_SOCKET": "${dir:keeper-state}/keeper.sock"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "watch",
|
||||
@@ -476,6 +629,9 @@
|
||||
],
|
||||
"health": {
|
||||
"kind": "unit"
|
||||
},
|
||||
"env": {
|
||||
"ZFS_KEEPER_SOCKET": "${dir:keeper-state}/keeper.sock"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -487,7 +643,10 @@
|
||||
"./zfs-tools",
|
||||
"run"
|
||||
],
|
||||
"schedule": "0,15,30,45 * * * *"
|
||||
"schedule": "0,15,30,45 * * * *",
|
||||
"env": {
|
||||
"ZFS_KEEPER_SOCKET": "${dir:keeper-state}/keeper.sock"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "distribution-weekly",
|
||||
|
||||
Reference in New Issue
Block a user