package catalogue import ( "strings" "testing" ) // A module with nothing that publishes binds what it binds, and the mesh may not move it. // // This is the case that made novox/hq 04-ISSUES/028's fix wrong on its first pass: a port was // assigned to every module that declared one, so a service listening directly had the rule set // opened on a number nothing was listening on, and its real port shut. The firewall reported // success and blocked the service, which is the exact failure the mechanism exists to prevent. func TestAPortNothingPublishesIsNotTheMeshsToMove(t *testing.T) { m := Manifest{Module: "talker", Listens: []Listening{{Port: 9101, From: FromMesh}}} at, mayAssign := m.MachineSide(9101) if mayAssign { t.Fatal("the mesh took a port it cannot move: nothing translates it, so assigning one " + "opens the wrong number and leaves the service unreachable") } if at != 9101 { t.Fatalf("a port nothing publishes reaches the machine where it binds, not at %d", at) } } // A container publishing in short form is exactly the case the mesh may choose. func TestAContainerPublishingShortIsTheMeshsToChoose(t *testing.T) { m := Manifest{Module: "store", Resources: []map[string]any{ {"type": "container", "id": "server", "ports": []any{"5432"}}, }} if _, mayAssign := m.MachineSide(5432); !mayAssign { t.Fatal("a container's mapping is what translates a port, so this one is the mesh's to " + "choose; refusing it puts every module back on a number it guessed") } } // A manifest that wrote its own mapping already chose, and the machine side is the outer one. func TestAMappingTheManifestWroteIsNotReassigned(t *testing.T) { m := Manifest{Module: "mail", Resources: []map[string]any{ {"type": "container", "id": "front", "ports": []any{"7080:80"}}, }} for _, named := range []int{7080, 80} { at, mayAssign := m.MachineSide(named) if mayAssign { t.Fatalf("%d was reassigned though the manifest published it explicitly, which "+ "would open a rule on a port the container does not publish", named) } if at != 7080 { t.Fatalf("naming %d gave %d; the machine side of 7080:80 is 7080", named, at) } } } // A port some other container publishes is not this port. func TestAPortNotInTheMappingIsNotFound(t *testing.T) { m := Manifest{Module: "mail", Resources: []map[string]any{ {"type": "container", "id": "front", "ports": []any{"25", "7080:80"}}, }} if at, mayAssign := m.MachineSide(993); mayAssign || at != 993 { t.Fatalf("993 is published by nothing here, so it binds where it binds: got %d, %v", at, mayAssign) } } // A bind mount the module never declared is refused where it is written. // // The container runtime creates a missing bind source itself, as root, with a mode it picks. So // the module's own owner and mode never reach the directory holding its data, and the rule that // keeps data when a module goes away (novox/hq ADR 0030) does not cover it — that rule is written // in terms of declared directories, and the mesh has never heard of this one. func TestAMountNothingDeclaresIsRefused(t *testing.T) { _, err := ParseManifest([]byte(`{"module":"store","resources":[` + `{"id":"server","type":"container","name":"store","image":"x@sha256:` + `0000000000000000000000000000000000000000000000000000000000000000",` + `"volumes":["/services/store/data:/var/lib/data"]}]}`)) if err == nil { t.Fatal("a container mounting a path no resource declares was accepted; the runtime " + "would create it as root and the module's owner and mode would never apply") } if !strings.Contains(err.Error(), "/services/store/data") { t.Fatalf("refused without naming the path, which leaves the author guessing: %v", err) } } // And declaring it is enough — including declaring the directory above it. func TestAMountUnderADeclaredDirectoryIsAccepted(t *testing.T) { _, err := ParseManifest([]byte(`{"module":"store","resources":[` + `{"id":"state","type":"directory","path":"/services/store","mode":"0700"},` + `{"id":"server","type":"container","name":"store","image":"x@sha256:` + `0000000000000000000000000000000000000000000000000000000000000000",` + `"volumes":["/services/store/data:/var/lib/data"]}]}`)) if err != nil { t.Fatalf("a module that said where its data lives was refused anyway: %v", err) } }