The only complete written-down copy of how a mesh is stood up was an integration test in the lab. That is why every bootstrap gap kept being found late: an install procedure that lives as a test fixture is exercised by whoever writes tests, never by whoever installs. This is that procedure. A separate binary, not a mesh-host subcommand. mesh-host says of itself that it connects to nothing and listens on nothing and that what it applies comes from a file, and that sentence is what makes an always-running root daemon auditable. An installer loads images and interrogates a control plane. Same tier, different program. The control plane's image is carried, not built and not fetched. The forge that holds its source runs on the mesh, so a bootstrap that had to fetch it would need a mesh in order to raise one. Embedding breaks that cycle the way the carried bundle breaks "copy it onto a machine and run it". The image id is read out of the saved tar before the runtime is asked anything, which is what makes the load idempotent: the installer can ask whether the machine already holds exactly this. Five steps, each idempotent and each saying whether it found or changed something, because this is run over and over by somebody getting a machine working. It stops at a running substrate with a control plane that replies — enrolment, the module catalogue and assignment are the next stage and are deliberately absent. Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
114 lines
4.0 KiB
Go
114 lines
4.0 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/novox/mesh-host/internal/bootstrap"
|
|
"github.com/novox/mesh-host/internal/store"
|
|
)
|
|
|
|
// Argument handling gets tests for the reason `mesh-host` records: the standard library stops
|
|
// parsing at the first non-flag argument, so a flag sitting after one is silently dropped and the
|
|
// command exits zero having ignored what it was asked. Here that would mean `--dry-run` ignored on
|
|
// a program whose whole job is to change a machine.
|
|
|
|
func TestBootstrapIsWhatItDoesWithNoCommand(t *testing.T) {
|
|
// Running the installer with nothing but flags must install, not print usage: the command is
|
|
// the reason the binary exists, and making somebody type its name twice buys nothing.
|
|
command, opts, _, err := parseArgs([]string{"--dry-run"})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if command != "bootstrap" {
|
|
t.Errorf("command = %q, want bootstrap", command)
|
|
}
|
|
if !opts.DryRun {
|
|
t.Error("--dry-run before any subcommand was ignored")
|
|
}
|
|
}
|
|
|
|
func TestFlagsAreReadWhereverTheySit(t *testing.T) {
|
|
for _, args := range [][]string{
|
|
{"bootstrap", "--dry-run", "--bundle", "s.lock", "--json"},
|
|
{"bootstrap", "--json", "--bundle=s.lock", "--dry-run"},
|
|
{"--bundle", "s.lock", "--dry-run", "--json"},
|
|
} {
|
|
_, opts, jsonOut, err := parseArgs(args)
|
|
if err != nil {
|
|
t.Errorf("%v: unexpected error: %v", args, err)
|
|
continue
|
|
}
|
|
if !opts.DryRun || !jsonOut || opts.Template != "s.lock" {
|
|
t.Errorf("%v parsed as dry-run=%v json=%v bundle=%q",
|
|
args, opts.DryRun, jsonOut, opts.Template)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAMistypedFlagIsRefusedNotIgnored(t *testing.T) {
|
|
// Asymmetric cost: an error is a moment's annoyance, and a silently dropped --dry-run is a
|
|
// machine changed by somebody who asked for it not to be.
|
|
if _, _, _, err := parseArgs([]string{"bootstrap", "--dry-runn"}); err == nil {
|
|
t.Fatal("a mistyped flag was accepted")
|
|
}
|
|
}
|
|
|
|
func TestAnUnexpectedArgumentIsRefused(t *testing.T) {
|
|
if _, _, _, err := parseArgs([]string{"bootstrap", "substrate.lock"}); err == nil {
|
|
t.Fatal("a stray argument was ignored rather than refused — the bundle is --bundle")
|
|
}
|
|
}
|
|
|
|
func TestTheDefaultsAreTheDocumentedOnes(t *testing.T) {
|
|
// The usage text is a promise. A default that drifts from what is printed is a small lie that
|
|
// costs somebody an afternoon in front of a machine that will not come up.
|
|
_, opts, jsonOut, err := parseArgs(nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if opts.Template != defaultTemplate {
|
|
t.Errorf("default bundle is %q; the usage text says %q", opts.Template, defaultTemplate)
|
|
}
|
|
if opts.Out != defaultOut {
|
|
t.Errorf("default out is %q; the usage text says %q", opts.Out, defaultOut)
|
|
}
|
|
if opts.State != store.DefaultPath {
|
|
t.Errorf("default state is %q; the host's own default is %q", opts.State, store.DefaultPath)
|
|
}
|
|
if opts.Timeout != 30*time.Second {
|
|
t.Errorf("default timeout is %s; the usage text says 30s", opts.Timeout)
|
|
}
|
|
if opts.Wait != 3*time.Minute {
|
|
t.Errorf("default wait is %s; the usage text says 3m", opts.Wait)
|
|
}
|
|
if opts.DryRun || jsonOut || opts.System != "" {
|
|
t.Error("something is on by default that the usage text describes as a flag")
|
|
}
|
|
}
|
|
|
|
// Every flag the usage text promises must exist, and every flag that exists must be in the usage
|
|
// text. The two drifting apart is how a program acquires a feature nobody can find and a
|
|
// documented option that does nothing.
|
|
func TestTheUsageTextAndTheFlagsAgree(t *testing.T) {
|
|
var opts bootstrap.Options
|
|
var jsonOut bool
|
|
set := newFlagSet(&opts, &jsonOut)
|
|
|
|
declared := map[string]bool{}
|
|
set.VisitAll(func(f *flag.Flag) { declared[f.Name] = true })
|
|
|
|
for name := range declared {
|
|
if !strings.Contains(usage, "--"+name) {
|
|
t.Errorf("--%s exists and the usage text does not mention it", name)
|
|
}
|
|
}
|
|
for _, promised := range []string{"bundle", "out", "state", "system", "timeout", "wait", "dry-run", "json"} {
|
|
if !declared[promised] {
|
|
t.Errorf("the usage text promises --%s and no such flag exists", promised)
|
|
}
|
|
}
|
|
}
|