Taking a module off a node takes it off the machine
The half of the module system that was built and never proved. Unassigning i3 removed i3's file AND xorg's, because xorg was only there to satisfy i3 -- the node's own record agrees, and the resolution the mesh sends no longer mentions either. That works because a declaration removes what the mesh previously declared and nothing else, which is 04-ISSUES/010's fix carrying its weight here: the substrate the machine raised for itself is untouched by any of it. Tests for the storage layer, which had none. The ones worth naming: A module a machine is running cannot be forgotten -- not a fault, it means the mesh would lose the ability to describe what is on that machine. Removing a node DOES take its assignments, and the asymmetry is deliberate: a node that is gone cannot be running anything. A node that has never reported has NO capabilities rather than all of them. That refuses anything needing one, which is wrong but visible -- where assuming it can do everything would assign work it cannot do and find out on the machine. And a capability the node reported as ABSENT is not counted: reading the list without the verdict would let a module onto a machine that said no. `overlay push` is gone, replaced by `push`, which sends a node its network and its modules as one declaration. Two commands that overlap is how a mesh ends up half-configured by whichever was run. The old name answers with where to go, and answers before opening a database -- needing one would turn a redirect into a connection error.
This commit is contained in:
+11
-47
@@ -113,7 +113,6 @@ func usage() {
|
||||
declare <node> <file> send a node a signed declaration
|
||||
overlay place <node> [flags] say where a node is and how it is reached
|
||||
overlay show the private network, as the mesh computes it
|
||||
overlay push send every node its part of the private network
|
||||
module add <file> register a module from its manifest
|
||||
module list what modules this mesh knows about
|
||||
module forget <name> remove one, unless a node is running it
|
||||
@@ -497,7 +496,14 @@ func overlayCIDR() string {
|
||||
|
||||
func overlayCommand(ctx context.Context, args []string) error {
|
||||
if len(args) == 0 {
|
||||
return errors.New("overlay place <node> [flags], overlay show, or overlay push")
|
||||
return errors.New("overlay place <node> [flags], or overlay show")
|
||||
}
|
||||
// Answered before anything is opened. A message about which command to use should not need a
|
||||
// database to say so, and needing one turns a redirect into a connection error.
|
||||
if args[0] == "push" {
|
||||
return errors.New("`overlay push` is now `push`, which sends a node its network AND " +
|
||||
"what its assignments resolve to — the two are computed from one picture of the " +
|
||||
"mesh, and sending them separately would let them disagree")
|
||||
}
|
||||
inv, err := openInventory(ctx)
|
||||
if err != nil {
|
||||
@@ -510,10 +516,9 @@ func overlayCommand(ctx context.Context, args []string) error {
|
||||
return overlayPlace(ctx, inv, args[1:])
|
||||
case "show":
|
||||
return overlayShow(ctx, inv)
|
||||
case "push":
|
||||
return overlayPush(ctx, inv)
|
||||
|
||||
default:
|
||||
return fmt.Errorf("overlay has no %q; it has place, show and push", args[0])
|
||||
return fmt.Errorf("overlay has no %q; it has place and show", args[0])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -611,47 +616,6 @@ func overlayShow(ctx context.Context, inv *inventory.Inventory) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func overlayPush(ctx context.Context, inv *inventory.Inventory) error {
|
||||
nodes, computed, err := graph(ctx, inv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ident, err := openIdentity(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer ident.Close()
|
||||
|
||||
server, err := link.Connect(nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer server.Close()
|
||||
|
||||
sent := 0
|
||||
for _, n := range nodes {
|
||||
peers, ok := computed[n.Name]
|
||||
if !ok {
|
||||
// Skipped, and said. A node with no key or address is not on the network yet, and
|
||||
// sending it an empty configuration would take down the one it may already have.
|
||||
fmt.Printf("%s is not on the overlay yet — skipped\n", n.Name)
|
||||
continue
|
||||
}
|
||||
declaration, err := overlay.Declaration(n, peers, nodes, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := link.Declare(ctx, server.Channel(), ident, n.Name, declaration, 15*time.Second); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("sent %s its place on the overlay — %d peer(s)\n", n.Name, len(peers))
|
||||
sent++
|
||||
}
|
||||
fmt.Printf("\n%d of %d node(s) told\n", sent, len(nodes))
|
||||
return nil
|
||||
}
|
||||
|
||||
// SilentFor is how long a node may be quiet before the mesh says so.
|
||||
//
|
||||
// A node speaks every minute, so three of them missed is a gap rather than a slow one. The number
|
||||
@@ -662,7 +626,7 @@ const SilentFor = 3 * time.Minute
|
||||
//
|
||||
// "never" and "an hour ago" are different answers and are kept different. A node that has never
|
||||
// spoken did not finish joining; a node last heard from an hour ago is running an hour-old
|
||||
// picture of the mesh — and until this existed both looked exactly like a node that is current.
|
||||
// picture of the mesh.
|
||||
func heardFrom(n inventory.Node) string {
|
||||
silent, ever := n.Silent()
|
||||
switch {
|
||||
|
||||
Reference in New Issue
Block a user