diff --git a/internal/declaration/adoption_test.go b/internal/declaration/adoption_test.go deleted file mode 100644 index e422516..0000000 --- a/internal/declaration/adoption_test.go +++ /dev/null @@ -1,132 +0,0 @@ -package declaration - -import ( - "strings" - "testing" -) - -// Defends novox/hq ADR 0100: every declaration says whether the node is adopted and which of its -// modules are taken, and the host refuses one it cannot read that from unambiguously. - -const adoptedResources = `"resources":[ - {"id":"hello-web.page","type":"file","path":"/var/lib/hello-web/index.html","content":"a\n"}, - {"id":"hello-web.server","type":"container","name":"hello-web","image":"sha256:` + sixtyFour + `"}, - {"id":"hello-web.data","type":"directory","path":"/var/lib/hello-web"} - ]` - -const sixtyFour = "0000000000000000000000000000000000000000000000000000000000000000" - -func TestAnAdoptionIsReadWithTheDeclaration(t *testing.T) { - d, err := Parse([]byte(`{"adoption":{"taken":["postgres"],"untaken":{"hello-web":["hello-web.page","hello-web.server"]}}, - "declaration":1,` + adoptedResources + `}`)) - if err != nil { - t.Fatal(err) - } - if d.Adoption == nil { - t.Fatal("the adoption was dropped") - } - if len(d.Adoption.Taken) != 1 || d.Adoption.Taken[0] != "postgres" { - t.Errorf("taken read as %v", d.Adoption.Taken) - } - if module, ok := d.Adoption.UntakenModuleOf("hello-web.server"); !ok || module != "hello-web" { - t.Errorf("the container's untaken module read as %q, %v", module, ok) - } - if _, ok := d.Adoption.UntakenModuleOf("hello-web.data"); ok { - t.Error("a resource the adoption does not name was said to be untaken") - } -} - -func TestADeclarationWithNoAdoptionIsConverged(t *testing.T) { - d, err := Parse([]byte(`{"declaration":1,` + adoptedResources + `}`)) - if err != nil { - t.Fatal(err) - } - if d.Adoption != nil { - t.Errorf("a declaration saying nothing about adoption read as adopted: %+v", d.Adoption) - } - if _, ok := d.Adoption.UntakenModuleOf("hello-web.page"); ok { - t.Error("a converged node has an untaken module") - } -} - -func TestAnAdoptionNamingAnUnknownIDIsRefused(t *testing.T) { - refusal := refusalFor(t, `{"adoption":{"taken":[],"untaken":{"hello-web":["hello-web.missing"]}}, - "declaration":1,`+adoptedResources+`}`) - if !strings.Contains(strings.Join(refusal.Problems, "\n"), "hello-web.missing") { - t.Errorf("the unknown id was not named: %v", refusal.Problems) - } -} - -func TestAnAdoptionMayNameAResourceOfAnyKind(t *testing.T) { - // A directory, a service or an action can reach what was found as surely as a file can, so - // the controller lists every resource of an untaken module (novox/hq ADR 0103). - d, err := Parse([]byte(`{"adoption":{"taken":[],"untaken":{"hello-web":["hello-web.data"]}}, - "declaration":1,` + adoptedResources + `}`)) - if err != nil { - t.Fatalf("a directory of an untaken module was refused: %v", err) - } - if module, ok := d.Adoption.UntakenModuleOf("hello-web.data"); !ok || module != "hello-web" { - t.Errorf("the directory is not its module's: %q %v", module, ok) - } -} - -func TestAnIDUnderTwoModulesIsRefused(t *testing.T) { - refusal := refusalFor(t, `{"adoption":{"taken":[],"untaken":{"a":["hello-web.page"],"b":["hello-web.page"]}}, - "declaration":1,`+adoptedResources+`}`) - if !strings.Contains(strings.Join(refusal.Problems, "\n"), "both") { - t.Errorf("an id under two modules was accepted: %v", refusal.Problems) - } -} - -func TestAModuleBothTakenAndUntakenIsRefused(t *testing.T) { - refusal := refusalFor(t, `{"adoption":{"taken":["hello-web"],"untaken":{"hello-web":["hello-web.page"]}}, - "declaration":1,`+adoptedResources+`}`) - if !strings.Contains(strings.Join(refusal.Problems, "\n"), "both taken and untaken") { - t.Errorf("a module both taken and untaken was accepted: %v", refusal.Problems) - } -} - -func TestTheMeshsOwnResourcesAreNeverUntaken(t *testing.T) { - refusal := refusalFor(t, `{"adoption":{"taken":[],"untaken":{"x":["adoption.guard"]}}, - "declaration":1,"resources":[ - {"id":"adoption.guard","type":"file","path":"/etc/mesh/guard.nft","content":"x"}]}`) - if !strings.Contains(strings.Join(refusal.Problems, "\n"), "belongs to no module") { - t.Errorf("an adoption. id was accepted as untaken: %v", refusal.Problems) - } -} - -func TestAnAdoptionWithAnUnknownFieldIsRefused(t *testing.T) { - refusalFor(t, `{"adoption":{"taken":[],"held":["x"]},"declaration":1,`+adoptedResources+`}`) -} - -func TestACarriedBundleCannotSayTheNodeIsAdopted(t *testing.T) { - _, err := ParseTrusted([]byte(`{"adoption":{"taken":[]},"declaration":1,` + adoptedResources + `}`)) - if err == nil || !strings.Contains(err.Error(), "only the mesh can say") { - t.Fatalf("a bundle claiming adoption was not refused: %v", err) - } -} - -// novox/hq ADR 0105: a service may take over a found tunnel, said whole and on an adopted node. -func TestTakingOverATunnelIsSaidWholeAndForARunningService(t *testing.T) { - adoptedWith := func(service string) error { - _, err := Parse([]byte(`{"declaration":1,"adoption":{"taken":[]},"resources":[` + service + `]}`)) - return err - } - good := `{"id":"up","type":"service","unit":"wg-quick@mesh0","state":"running", - "takes-over":{"interface":"wg0","unit":"wg-quick@wg0","config":"/etc/wireguard/wg0.conf"}}` - if err := adoptedWith(good); err != nil { - t.Fatalf("a whole takeover on an adopted node was refused: %v", err) - } - for name, bad := range map[string]string{ - "its own unit": `{"id":"up","type":"service","unit":"wg-quick@wg0","state":"running", - "takes-over":{"interface":"wg0","unit":"wg-quick@wg0","config":"/etc/wireguard/wg0.conf"}}`, - "no config": `{"id":"up","type":"service","unit":"wg-quick@mesh0","state":"running", - "takes-over":{"interface":"wg0","unit":"wg-quick@wg0"}}`, - "a stopped service": `{"id":"up","type":"service","unit":"wg-quick@mesh0","state":"stopped", - "takes-over":{"interface":"wg0","unit":"wg-quick@wg0","config":"/etc/wireguard/wg0.conf"}}`, - } { - if err := adoptedWith(bad); err == nil { - t.Errorf("a takeover naming %s was accepted", name) - } - } -}