// Command mesh-bootstrap brings a mesh into existence on a bare machine. // // Tier 0, beside `mesh-host` and not inside it. Bootstrapping is done by hand and it changes a // machine, which is what tier 0 is (novox/hq 03-DESIGN/01-to-be/05-the-node-host.md) — but // `mesh-host` states of itself that it connects to nothing and listens on nothing and that what it // applies comes from a file, and that is the whole reason an always-running root daemon can be // audited by reading one page. An installer that loads images and interrogates a control plane // cannot be folded into it without making that sentence false. Same tier, same repository, // different program. // // What it does not do is enrol this machine, register modules or assign them. It stops at a // running substrate with a control plane that answers, which is a mesh of one node. package main import ( "context" "encoding/json" "flag" "fmt" "net" "os" "os/signal" "syscall" "time" "github.com/novox/mesh-host/internal/apply" "github.com/novox/mesh-host/internal/bootstrap" "github.com/novox/mesh-host/internal/store" ) // version is stamped at build time. Unset in a development build, and said so rather than // defaulted to something that looks like a release. var version = "development build" const ( defaultTemplate = "substrate.lock" defaultOut = "/var/lib/mesh-host/substrate.lock" ) const usage = `mesh-bootstrap — make a bare machine into a mesh bootstrap preflight, load, bundle, apply, verify (the default) version --bundle the substrate template to build this machine's bundle from (default ` + defaultTemplate + `) --out where the produced bundle is written, for a person to read (default ` + defaultOut + `) --state where this node records what it has applied (default ` + store.DefaultPath + `) --system which operating system this is; by default it is asked --timeout how long any single probe may take (default 30s) --wait how long a thing that is merely starting is given (default 3m) --dry-run everything that does not change the machine --json machine-readable output It carries the control plane's image and applies a substrate. Every step is idempotent: run it again after fixing whatever it named, and the steps that already succeeded say so. ` func main() { // Ctrl-C must stop the installer, not be swallowed by whatever it is waiting for — and it // waits on pulls, on a runtime starting, and on a control plane opening its stores. ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() command, opts, jsonOut, err := parseArgs(os.Args[1:]) if err == nil { err = run(ctx, command, opts, jsonOut) } if err != nil { fmt.Fprintf(os.Stderr, "mesh-bootstrap: %v\n", err) os.Exit(1) } } // parseArgs takes an optional subcommand first, then its flags. // // Parsed in a loop for the reason `mesh-host` records: the standard library stops 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. That fault has been paid for twice in this repository and is // not being paid for a third time. func parseArgs(args []string) (string, bootstrap.Options, bool, error) { opts := bootstrap.Options{ Template: defaultTemplate, Out: defaultOut, State: store.DefaultPath, // Longer than the host's 10s: these probes reach a container runtime that may be busy // pulling, and a probe that times out on a working machine is a false refusal. Timeout: 30 * time.Second, // A socket-activated runtime queued behind the network, and a control plane running its // first `initdb`-shaped wait, are both minutes rather than seconds. Wait: 3 * time.Minute, } var jsonOut bool command := "bootstrap" if len(args) > 0 && len(args[0]) > 0 && args[0][0] != '-' { command = args[0] args = args[1:] } set := newFlagSet(&opts, &jsonOut) var positionals []string rest := args for { if err := set.Parse(rest); err != nil { return "", opts, false, err } rest = set.Args() if len(rest) == 0 { break } positionals = append(positionals, rest[0]) rest = rest[1:] } // Refused rather than ignored: a mistyped argument that changes nothing and reports success is // worse than an error, and this program's whole job is to change a machine. if len(positionals) > 0 { return "", opts, false, fmt.Errorf( "unexpected argument %q — try `mesh-bootstrap help`", positionals[0]) } return command, opts, jsonOut, nil } func newFlagSet(opts *bootstrap.Options, jsonOut *bool) *flag.FlagSet { set := flag.NewFlagSet("mesh-bootstrap", flag.ContinueOnError) set.SetOutput(os.Stderr) set.Usage = func() { fmt.Fprint(os.Stderr, usage) } set.StringVar(&opts.Template, "bundle", opts.Template, "the substrate template to build from") set.StringVar(&opts.Out, "out", opts.Out, "where the produced bundle is written") set.StringVar(&opts.State, "state", opts.State, "where this node records what it has applied") set.StringVar(&opts.System, "system", opts.System, "which operating system this is") set.DurationVar(&opts.Timeout, "timeout", opts.Timeout, "how long any single probe may take") set.DurationVar(&opts.Wait, "wait", opts.Wait, "how long something merely starting is given") set.BoolVar(&opts.DryRun, "dry-run", false, "everything that does not change the machine") set.BoolVar(jsonOut, "json", false, "machine-readable output") return set } func run(ctx context.Context, command string, opts bootstrap.Options, jsonOut bool) error { switch command { case "bootstrap": say := func(line string) { if !jsonOut { fmt.Println(line) } } result, err := bootstrap.Run(ctx, opts, bootstrap.Deps{ Run: apply.ExecRunner, Dial: dial, }, say) // Printed whichever way it went. What the installer got through before it stopped is on // the machine either way, and a report that only exists on success describes a machine // nobody has (novox/hq ADR 0018). if jsonOut { encoder := json.NewEncoder(os.Stdout) encoder.SetIndent("", " ") if encodeErr := encoder.Encode(result); encodeErr != nil && err == nil { return encodeErr } } return err case "version": fmt.Println(version) return nil case "help", "-h", "--help": fmt.Fprint(os.Stderr, usage) return nil default: return fmt.Errorf("unknown command %q — try `mesh-bootstrap help`", command) } } // dial answers whether a TCP address responds. // // A connection rather than a ping or a name lookup: what has to work is a pull, and a pull opens a // connection to exactly this address. A machine whose DNS resolves and whose route is missing // passes a lookup and fails the thing that matters. func dial(ctx context.Context, address string) error { var dialer net.Dialer conn, err := dialer.DialContext(ctx, "tcp", address) if err != nil { return err } return conn.Close() }