Files
mesh-host/internal/link/messages_test.go
T
jschoubben a9a0f7b4e0 Say the node's facts in its haves alone, and enrol through the seat alone
The CONTROL stream the facts, the enrolment and the overlay rekey were published into was the controller's, which ended
by its unassignment (issue 1126) and whose stream is removed after group B's delivery: a publish there would fail every
facts event before its haves are written. The facts go into the haves as they did after the report, the enrolment goes
through mesh-enrolment alone, and overlay take is refused because no seat takes a rekey now.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 11:27:28 +01:00

68 lines
3.6 KiB
Go

package link
import (
"encoding/json"
"testing"
)
func TestTheWireFormatIsExactlyTheseFieldNames(t *testing.T) {
// The contract with the control plane, which defines these separately. A matching test lives
// there; rename a field on either side and both fail.
for _, c := range []struct {
value any
expect []string
}{
{Report{Node: "n", Applied: []string{"a"}, Failed: map[string]string{"k": "v"}, Refused: "r"},
[]string{"node", "applied", "failed", "refused"}},
// novox/hq ADR 0100: what an adopted node holds, the firewall it was found with, and what
// is reachable on it.
{Report{Node: "n", Held: []Held{{ID: "i"}}, Firewall: "ufw", Reachable: []Reach{{Port: 1}}},
[]string{"node", "held", "firewall", "reachable"}},
{Held{ID: "i", Module: "m", Kind: "file", Target: "/t", Changed: "rewritten", Kept: "/k"},
[]string{"id", "module", "kind", "target", "since", "changed", "kept"}},
{Reach{Protocol: "tcp", Address: "0.0.0.0", Port: 8080, By: "c", Published: true, ContainerPort: 80},
[]string{"protocol", "address", "port", "by", "published", "container-port"}},
// novox/hq to-be 45 §8: a witness's verdicts, said on every report while they stand, and the
// witness contract this host keeps.
{Report{Node: "n", Rollbacks: []Rollback{{Component: ComponentNodeTools}}, Witness: WitnessContract},
[]string{"node", "rollbacks", "witness"}},
{Rollback{Component: ComponentNodeTools, From: "sha256:b", To: "sha256:a", Outcome: RolledBack, Why: "w"},
[]string{"component", "from", "to", "outcome", "why", "at"}},
// novox/hq ADR 0240: every long-running resource's health, in every report and in its own event.
{Report{Node: "n", Health: &Health{Contract: LivenessContract}}, []string{"node", "health"}},
{Health{Contract: LivenessContract, Resources: []ResourceHealth{}}, []string{"contract", "at", "resources"}},
{ResourceHealth{Module: "m", Resource: "m.r", Kind: "container", Target: "t", State: StateUnhealthy,
Reason: ReasonRestarting, Streak: 2, Restarts: 3, Check: "http", Needs: "postgres-database"},
[]string{"module", "resource", "kind", "target", "state", "reason", "since", "streak", "restarts",
"check", "needs"}},
{HealthSaid{Node: "n"}, []string{"node", "health"}},
// novox/hq ADR 0266: an account judged for whether it can become root without a person.
{ResourceHealth{Module: "m", Resource: "m.agent", Kind: KindAccount, Account: "agent", Root: "never"},
[]string{"module", "resource", "kind", "target", "state", "since", "account", "root"}},
// novox/hq ADR 0241: the machine's own networking, beside its resources.
{Health{Contract: ReadinessContract, Resources: []ResourceHealth{}, Network: &NetworkHealth{State: "unhealthy",
Parts: []NetworkPart{}}}, []string{"contract", "at", "resources", "network"}},
{NetworkHealth{State: "unhealthy", Parts: []NetworkPart{}}, []string{"state", "since", "parts"}},
{NetworkPart{Part: "resolv-conf", State: "unhealthy", Reason: "r", Said: "s", Writer: "w", Owner: "o",
Toward: []string{"hub"}, Streak: 2}, []string{"part", "state", "reason", "said", "writer", "owner", "toward",
"since", "streak"}},
} {
raw, err := json.Marshal(c.value)
if err != nil {
t.Fatal(err)
}
var fields map[string]any
if err := json.Unmarshal(raw, &fields); err != nil {
t.Fatal(err)
}
for _, want := range c.expect {
if _, ok := fields[want]; !ok {
t.Errorf("%T has no %q field; the control plane uses that name", c.value, want)
}
}
if len(fields) != len(c.expect) {
t.Errorf("%T has %d fields, expected %d: %v", c.value, len(fields), len(c.expect), fields)
}
}
}