A live restart of the system bus during an upgrade hung every login on a workstation until a reboot. The module owns the bus's packages, declares the bus running with no restart or reload trigger, publishes only curated events (health, services, denials; never traffic) and serves tools to look at both buses.
160 lines
4.6 KiB
Go
160 lines
4.6 KiB
Go
package main
|
|
|
|
// The dbus module's shape (novox/hq ADR 0215): it holds node-message-bus, owns the bus's packages,
|
|
// declares the bus running and never restarts or reloads it, and publishes only its curated events.
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"reflect"
|
|
"regexp"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
type manifestShape struct {
|
|
Module string `json:"module"`
|
|
Capabilities []string `json:"capabilities"`
|
|
Claims []map[string]any `json:"claims"`
|
|
Emits []string `json:"emits"`
|
|
Consumes []string `json:"consumes"`
|
|
Tools []string `json:"tools"`
|
|
Resources []map[string]any `json:"resources"`
|
|
Build struct {
|
|
Artifacts []map[string]any `json:"artifacts"`
|
|
} `json:"build"`
|
|
}
|
|
|
|
func manifest(t *testing.T) (manifestShape, string) {
|
|
t.Helper()
|
|
raw, err := os.ReadFile("../../module.json")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var m manifestShape
|
|
if err := json.Unmarshal(raw, &m); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return m, string(raw)
|
|
}
|
|
|
|
func TestItHoldsTheMessageBusSeatWithOnlyWhatItNeeds(t *testing.T) {
|
|
m, _ := manifest(t)
|
|
if m.Module != "dbus" || len(m.Claims) != 1 || m.Claims[0]["name"] != "node-message-bus" || m.Claims[0]["scope"] != "node" {
|
|
t.Fatalf("claims: %+v", m.Claims)
|
|
}
|
|
if _, serves := m.Claims[0]["serves"]; serves {
|
|
t.Error("the seat receives nothing yet (ADR 0215 §4) and serves no verbs")
|
|
}
|
|
if !reflect.DeepEqual(m.Capabilities, []string{"package-manager", "service-manager"}) {
|
|
t.Fatalf("capabilities: %v", m.Capabilities)
|
|
}
|
|
}
|
|
|
|
func TestItOwnsTheBusImplementationsPackages(t *testing.T) {
|
|
m, _ := manifest(t)
|
|
var pkgs []string
|
|
for _, r := range m.Resources {
|
|
if r["type"] == "package" {
|
|
pkgs = append(pkgs, r["package"].(string))
|
|
if r["absent"] == true {
|
|
t.Errorf("%v is declared absent", r["package"])
|
|
}
|
|
}
|
|
}
|
|
sort.Strings(pkgs)
|
|
if !reflect.DeepEqual(pkgs, Packages) {
|
|
t.Fatalf("packages %v, the check reads %v", pkgs, Packages)
|
|
}
|
|
}
|
|
|
|
// TestTheBusIsNeverRestartedOrReloaded is ADR 0215 §2: the bus is declared running, with no trigger
|
|
// that would restart or reload it, and no boot state: dbus.service is an alias and dbus-broker.service
|
|
// is started at boot through dbus.socket, so enabling would write an alias link the machines do not
|
|
// have today.
|
|
func TestTheBusIsNeverRestartedOrReloaded(t *testing.T) {
|
|
m, raw := manifest(t)
|
|
if strings.Contains(raw, "restart-on") || strings.Contains(raw, "reload-on") {
|
|
t.Fatal("the manifest carries a restart or reload trigger")
|
|
}
|
|
var services []map[string]any
|
|
for _, r := range m.Resources {
|
|
if r["type"] == "service" {
|
|
services = append(services, r)
|
|
}
|
|
}
|
|
if len(services) != 1 {
|
|
t.Fatalf("services: %v", services)
|
|
}
|
|
s := services[0]
|
|
if s["unit"] != SystemUnit || s["state"] != "running" {
|
|
t.Fatalf("%v", s)
|
|
}
|
|
if _, ok := s["boot"]; ok {
|
|
t.Fatal("a boot state on the bus would have the host enable it")
|
|
}
|
|
for k := range s {
|
|
if k != "id" && k != "type" && k != "unit" && k != "state" {
|
|
t.Errorf("the bus's service carries %q", k)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestItEmitsTheCuratedEventsAndConsumesNothing(t *testing.T) {
|
|
m, _ := manifest(t)
|
|
if !reflect.DeepEqual(m.Emits, Emits) {
|
|
t.Fatalf("emits %v, the watcher publishes %v", m.Emits, Emits)
|
|
}
|
|
if len(m.Consumes) != 0 {
|
|
t.Fatalf("consumes %v", m.Consumes)
|
|
}
|
|
}
|
|
|
|
func TestToolsAreTheManifests(t *testing.T) {
|
|
m, _ := manifest(t)
|
|
served := map[string]bool{}
|
|
for _, tool := range Tools(testMachine(t, nil), nil) {
|
|
if served[tool.Name] {
|
|
t.Errorf("%s is served twice", tool.Name)
|
|
}
|
|
served[tool.Name] = true
|
|
if !strings.HasPrefix(tool.Name, "dbus_") {
|
|
t.Errorf("%s is not named dbus_<verb>", tool.Name)
|
|
}
|
|
}
|
|
for _, want := range m.Tools {
|
|
if !served[want] {
|
|
t.Errorf("the manifest lists %s and the bundle does not serve it", want)
|
|
}
|
|
delete(served, want)
|
|
}
|
|
for extra := range served {
|
|
t.Errorf("the bundle serves %s, which the manifest does not list", extra)
|
|
}
|
|
}
|
|
|
|
func TestTheBundleIsTheBuildersShape(t *testing.T) {
|
|
m, _ := manifest(t)
|
|
if len(m.Build.Artifacts) != 1 {
|
|
t.Fatalf("%v", m.Build.Artifacts)
|
|
}
|
|
a := m.Build.Artifacts[0]
|
|
for k, v := range map[string]string{"kind": "bundle", "language": "go", "system": "arch", "from": "cmd/dbus-tools", "binary": "dbus-tools"} {
|
|
if a[k] != v {
|
|
t.Errorf("%s is %v, want %s", k, a[k], v)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestNothingInstallationSpecific holds the manifest to the catalogue's rule: no node names, domains
|
|
// or home paths.
|
|
func TestNothingInstallationSpecific(t *testing.T) {
|
|
_, raw := manifest(t)
|
|
for _, re := range []*regexp.Regexp{regexp.MustCompile(`/home/`), regexp.MustCompile(`\.(be|internal|com)\b`)} {
|
|
if loc := re.FindString(raw); loc != "" {
|
|
t.Errorf("the manifest carries %q", loc)
|
|
}
|
|
}
|
|
}
|