155 lines
5.0 KiB
Go
155 lines
5.0 KiB
Go
package main
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// **A read-shaped invocation is never a destructive write.**
|
|
//
|
|
// `node public-domain anchor` used to clear the domain. It reads like a question — it is what
|
|
// anybody types to find out what the answer is — and it silently took every routed name the node
|
|
// had. There is no output that makes up for that: by the time it prints, the fact is gone.
|
|
func TestAskingForANodesPublicDomainDoesNotTakeItAway(t *testing.T) {
|
|
open := aMesh(t)
|
|
ctx := t.Context()
|
|
if err := open.inventory.SetPublicDomain(ctx, "anchor", "example.test"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err := publicDomain(ctx, open.inventory, []string{"anchor"}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
domain, err := open.inventory.PublicDomainOf(ctx, "anchor")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if domain != "example.test" {
|
|
t.Fatalf("asking what the domain is took it away: %q", domain)
|
|
}
|
|
}
|
|
|
|
// Clearing is a real thing to want — a machine that stops facing the outside composes no names —
|
|
// so it keeps a way to be said. What it stops being is what happens when nothing was said.
|
|
func TestClearingANodesPublicDomainIsAskedForByName(t *testing.T) {
|
|
open := aMesh(t)
|
|
ctx := t.Context()
|
|
if err := open.inventory.SetPublicDomain(ctx, "anchor", "example.test"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := publicDomain(ctx, open.inventory, []string{"anchor", "--clear"}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
domain, err := open.inventory.PublicDomainOf(ctx, "anchor")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if domain != "" {
|
|
t.Fatalf("--clear did not clear it: %q", domain)
|
|
}
|
|
}
|
|
|
|
// A domain sets it, as it always did.
|
|
func TestGivingANodeAPublicDomainSetsIt(t *testing.T) {
|
|
open := aMesh(t)
|
|
ctx := t.Context()
|
|
if err := publicDomain(ctx, open.inventory, []string{"anchor", "example.test"}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
domain, err := open.inventory.PublicDomainOf(ctx, "anchor")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if domain != "example.test" {
|
|
t.Fatalf("got %q", domain)
|
|
}
|
|
}
|
|
|
|
// A domain and --clear say opposite things. Refused rather than one of them silently winning.
|
|
func TestADomainAndClearTogetherIsRefused(t *testing.T) {
|
|
open := aMesh(t)
|
|
ctx := t.Context()
|
|
if err := open.inventory.SetPublicDomain(ctx, "anchor", "example.test"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
err := publicDomain(ctx, open.inventory, []string{"anchor", "other.test", "--clear"})
|
|
if err == nil {
|
|
t.Fatal("a domain and --clear together were accepted")
|
|
}
|
|
if !strings.Contains(err.Error(), "not both") {
|
|
t.Fatalf("the refusal does not say why: %v", err)
|
|
}
|
|
// And neither half happened.
|
|
domain, err := open.inventory.PublicDomainOf(ctx, "anchor")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if domain != "example.test" {
|
|
t.Fatalf("a refused command changed something: %q", domain)
|
|
}
|
|
}
|
|
|
|
// Asking about a name the mesh has never heard of is a refusal, not "it has no public domain" —
|
|
// which is true of that name and says nothing.
|
|
func TestAskingAboutAMachineTheMeshHasNeverHeardOfIsRefused(t *testing.T) {
|
|
open := aMesh(t)
|
|
if err := publicDomain(t.Context(), open.inventory, []string{"nowhere"}); err == nil {
|
|
t.Fatal("a name the mesh does not know was answered as if it were a machine")
|
|
}
|
|
}
|
|
|
|
// novox/hq ADR 0100: the operator says a node is adopted — `node add --adopted` for a record, and
|
|
// the token for a machine joining.
|
|
func TestANodeAddedAdoptedIsAdopted(t *testing.T) {
|
|
open := aMesh(t)
|
|
ctx := t.Context()
|
|
if err := addNode(ctx, open.inventory, []string{"joiner", "--adopted"}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
n, err := open.inventory.NodeByName(ctx, "joiner")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !n.Adopted {
|
|
t.Fatal("node add --adopted made a converged node")
|
|
}
|
|
if err := addNode(ctx, open.inventory, []string{"plain"}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if n, _ := open.inventory.NodeByName(ctx, "plain"); n.Adopted {
|
|
t.Fatal("node add without --adopted made an adopted node")
|
|
}
|
|
}
|
|
|
|
func TestATokenIssuedAdoptedSaysSoAndReissuingDoesNotConverge(t *testing.T) {
|
|
open := aMesh(t)
|
|
ctx := t.Context()
|
|
issued, err := issueFor(ctx, open.inventory, "", "joiner", true, time.Hour)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !issued.Node.Adopted {
|
|
t.Fatal("a token issued --adopted is for a node that is not adopted")
|
|
}
|
|
again, err := issueFor(ctx, open.inventory, "joiner", "", false, time.Hour)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !again.Node.Adopted {
|
|
t.Fatal("re-issuing without --adopted converged the node; converging is its own act")
|
|
}
|
|
// --adopted for a node already converged is refused, and points at the act that does it.
|
|
if _, err := issueFor(ctx, open.inventory, "laptop", "", true, time.Hour); err == nil ||
|
|
!strings.Contains(err.Error(), "adopt laptop") {
|
|
t.Fatalf("--adopted on a converged node was not refused: %v", err)
|
|
}
|
|
if n, _ := open.inventory.NodeByName(ctx, "laptop"); n.Adopted {
|
|
t.Fatal("a refused token flipped the node to adopted")
|
|
}
|
|
// And said for a node that is adopted already, it is the ordinary re-issue.
|
|
if _, err := issueFor(ctx, open.inventory, "joiner", "", true, time.Hour); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|