package catalogue import ( "strings" "testing" ) var threeMachines = map[string]string{"homer": "10.42.0.1", "marge": "10.42.0.2", "bart": ""} // **`*.homer.internal` is homer. That is the whole rule.** func TestEveryMachineIsAWildcardUnderItsOwnName(t *testing.T) { out := nodeZones(Resolution{Node: "homer"}, threeMachines) for _, want := range []string{ "address=/homer.internal/10.42.0.1", "address=/marge.internal/10.42.0.2", } { if !strings.Contains(out, want) { t.Fatalf("missing %q:\n%s", want, out) } } } // A machine the mesh has a record for and cannot place is left out of both. // // **Not an oversight — the alternative is worse.** A name written with no address resolves to // nothing, and a connection to that hangs. Leaving it out fails at once and says the name is // unknown, which is a thing somebody can act on. func TestAMachineWithNoAddressIsNotNamed(t *testing.T) { for _, out := range []string{ nodeNames(Resolution{Node: "homer"}, threeMachines), nodeZones(Resolution{Node: "homer"}, threeMachines), } { if strings.Contains(out, "bart") { t.Fatalf("a machine with no address was named, so its name resolves to nothing:\n%s", out) } } } // A machine's own mesh name points at its address on the private network, not at loopback — or a // service binding the name it was given is unreachable from everywhere else. func TestAMachinesOwnNameIsItsMeshAddress(t *testing.T) { out := nodeNames(Resolution{Node: "homer"}, threeMachines) var line string for _, l := range strings.Split(out, "\n") { if strings.Contains(l, "homer.internal") { line = l } } if !strings.HasPrefix(line, "10.42.0.1") { t.Fatalf("a machine's own mesh name is not its mesh address: %q", line) } // And the loopback floor is still there, or things with nothing to do with the mesh break. if !strings.Contains(out, "127.0.0.1\tlocalhost") { t.Fatalf("the loopback floor was removed:\n%s", out) } } // A module says where it wants a fact, and is given a file. func TestAModuleIsGivenTheFactsItAskedFor(t *testing.T) { m := Manifest{Module: "dnsmasq", Facts: map[string]string{FactNodeZones: "/etc/mesh/zones.conf"}} given, err := FactsInto(m, Resolution{Node: "homer"}, threeMachines) if err != nil { t.Fatal(err) } if len(given) != 1 { t.Fatalf("expected one file, got %d", len(given)) } if given[0]["path"] != "/etc/mesh/zones.conf" || given[0]["type"] != "file" { t.Fatalf("not written where it was asked for: %v", given[0]) } if !strings.Contains(given[0]["content"].(string), "homer.internal") { t.Fatalf("the file does not hold the fact: %v", given[0]["content"]) } } // **Asking for a fact the mesh does not have is refused here, not on a machine.** A daemon that // starts, reads a file nobody wrote, and answers no queries is a much worse way to find out. func TestAskingForAFactTheMeshDoesNotHaveIsRefused(t *testing.T) { m := Manifest{Module: "dnsmasq", Facts: map[string]string{"the-weather": "/etc/weather"}} _, err := FactsInto(m, Resolution{}, nil) if err == nil { t.Fatal("a module asked for something nobody computes and was given nothing, silently") } for _, known := range []string{FactNodeNames, FactNodeZones} { if !strings.Contains(err.Error(), known) { t.Fatalf("the refusal does not say what would have worked: %v", err) } } } // And a relative path is refused, or a module decides where the mesh writes on a machine. func TestAFactMustBeAskedForAtAnAbsolutePath(t *testing.T) { m := Manifest{Module: "dnsmasq", Facts: map[string]string{FactNodeNames: "etc/hosts"}} if _, err := FactsInto(m, Resolution{}, nil); err == nil { t.Fatal("a relative path was accepted") } }