Files
mesh-controller/cmd/mesh-controller/network_test.go
T

111 lines
4.0 KiB
Go

package main
import (
"context"
"strings"
"testing"
"github.com/novox/mesh-controller/internal/inventory"
"github.com/novox/mesh-controller/internal/overlay"
)
// placementOf is what the mesh holds about where one node is.
func placementOf(t *testing.T, ctx context.Context, inv *inventory.Inventory, name string) inventory.Overlay {
t.Helper()
placed, err := inv.Overlays(ctx)
if err != nil {
t.Fatal(err)
}
for _, one := range placed {
if one.Name == name {
return one
}
}
t.Fatalf("%s is not placed at all", name)
return inventory.Overlay{}
}
// The sibling of `node public-domain`, and the worse one: a placement is three facts declared
// together, so an invocation that said none of them took all three away — the endpoint every other
// machine dials, the site, and the hub. A mesh whose hub was placed that way has no paths left.
func TestPlacingANodeWithNothingSaidDoesNotUnplaceIt(t *testing.T) {
open := aMesh(t)
ctx := t.Context()
if err := overlayPlace(ctx, open.inventory,
[]string{"anchor", "--endpoint", "198.51.100.10:51820", "--site", "hosting", "--hub"}); err != nil {
t.Fatal(err)
}
err := overlayPlace(ctx, open.inventory, []string{"anchor"})
if err == nil {
t.Fatal("saying nothing unplaced the node instead of being refused")
}
if !strings.Contains(err.Error(), "--nothing") {
t.Errorf("the refusal does not say how to mean it: %v", err)
}
held := placementOf(t, ctx, open.inventory, "anchor")
if held.Endpoint != "198.51.100.10:51820" || held.Site != "hosting" || !held.Hub {
t.Fatalf("the placement was taken away by an invocation that was refused: %+v", held)
}
}
// Placing a machine with nothing set is a real thing to want — one that roams and opens every path
// itself is exactly that — so it keeps a way to be said, by name.
func TestPlacingANodeWithNothingIsAskedForByName(t *testing.T) {
open := aMesh(t)
ctx := t.Context()
if err := overlayPlace(ctx, open.inventory,
[]string{"anchor", "--endpoint", "198.51.100.10:51820", "--site", "hosting"}); err != nil {
t.Fatal(err)
}
if err := overlayPlace(ctx, open.inventory, []string{"anchor", "--nothing"}); err != nil {
t.Fatal(err)
}
held := placementOf(t, ctx, open.inventory, "anchor")
if held.Endpoint != "" || held.Site != "" || held.Hub {
t.Fatalf("--nothing did not place it with nothing: %+v", held)
}
}
// Both at once cannot be meant, so neither silently wins.
func TestAPlacementAndNothingTogetherIsRefused(t *testing.T) {
open := aMesh(t)
ctx := t.Context()
if err := overlayPlace(ctx, open.inventory,
[]string{"anchor", "--site", "hosting", "--nothing"}); err == nil {
t.Fatal("a placement and --nothing together was accepted")
}
}
// A machine is named for the others only while it is on the private network — placed AND running
// what puts it there — the same set the resolver means by "on the private network". A machine
// that has an address and no networking is not named: a name resolving to an address that does
// not answer hangs where an unknown name fails at once (novox/hq issue 079).
func TestOnlyAMachineOnThePrivateNetworkIsNamed(t *testing.T) {
open := aMesh(t) // two placed machines, both assigned what puts them on the private network
ctx := t.Context()
shelf, err := open.inventory.Catalogue(ctx)
if err != nil {
t.Fatal(err)
}
names, err := namesInTheMesh(ctx, open.inventory, shelf)
if err != nil {
t.Fatal(err)
}
if names["anchor.internal"] != "10.77.0.1" || names["laptop.internal"] != "10.77.0.2" {
t.Fatalf("two machines on the network are not both named: %v", names)
}
// The laptop keeps its place and its address, and stops running the network.
if err := open.inventory.Unassign(ctx, "laptop", overlay.Name); err != nil {
t.Fatal(err)
}
names, err = namesInTheMesh(ctx, open.inventory, shelf)
if err != nil {
t.Fatal(err)
}
if _, still := names["laptop.internal"]; still || names["anchor.internal"] != "10.77.0.1" {
t.Fatalf("a machine that left the network is still named, or the one that stayed is not: %v", names)
}
}