diff --git a/internal/catalogue/declaration.go b/internal/catalogue/declaration.go index a6741bc..470c8ba 100644 --- a/internal/catalogue/declaration.go +++ b/internal/catalogue/declaration.go @@ -693,6 +693,14 @@ func here(r Resolution, requirement string) *Needed { // // Copied rather than edited in place: these maps come from a module's manifest, and mutating one // would change what the catalogue holds for every other machine running that module. +// +// A host-network container gets the names too. It was once skipped, on the belief that it "shares +// the machine's hosts file already" — but it does not: `docker run --network host` still gives the +// container its own /etc/hosts (localhost and its own id only), so every `.internal` name the +// mesh wrote for the machine is invisible inside it, and a client that dials one gets EAI_AGAIN. The +// remedy is the same `--add-host` every other container gets — the runtime accepts it with +// `--network host` (verified), and without it a host-network consumer cannot reach a provider by the +// `.internal` address the mesh hands it as `${bound:...:at}`. func withMeshNames(resources []map[string]any, names map[string]string) []map[string]any { out := make([]map[string]any, 0, len(resources)) for _, r := range resources { @@ -700,13 +708,6 @@ func withMeshNames(resources []map[string]any, names map[string]string) []map[st out = append(out, r) continue } - // A container on the machine's own network shares its hosts file already, and a runtime - // refuses to write one for it. Adding names there would be an argument the runtime - // rejects, which fails the whole container for something it did not need. - if network, on := r["network"].(string); on && network == "host" { - out = append(out, r) - continue - } copied := map[string]any{} for k, v := range r { diff --git a/internal/catalogue/names_test.go b/internal/catalogue/names_test.go index 5e93140..73e24b5 100644 --- a/internal/catalogue/names_test.go +++ b/internal/catalogue/names_test.go @@ -73,18 +73,22 @@ func TestAContainersOwnNamesAreKept(t *testing.T) { } } -// A container on the machine's own network already shares its hosts file, and a runtime refuses -// to write one for it — so adding names there fails the whole container for something it did not -// need. -func TestAContainerOnTheMachinesNetworkIsLeftAlone(t *testing.T) { +// A container on the machine's own network gets the names too — it does NOT share the machine's +// hosts file. `docker run --network host` still gives the container its own /etc/hosts (localhost +// and its own id only), so every `.internal` name the mesh wrote is invisible inside it, and a +// client that dials one gets EAI_AGAIN. It gets the same `--add-host` entries every other container +// gets (the runtime accepts them with `--network host`), so a host-network consumer can reach a +// provider by the `.internal` address the mesh hands it. +func TestAContainerOnTheMachinesNetworkIsGivenTheNamesToo(t *testing.T) { got := containersOf(t, Resolution{Node: "anchor", Modules: []Manifest{{ Module: "control", Resources: []map[string]any{{"id": "c", "type": "container", "name": "c", "image": "registry.example/c@sha256:" + strings.Repeat("a", 64), "network": "host"}}, }}}, Rendering{Names: map[string]string{"anchor.internal": "10.42.0.1"}}) - if len(namesOf(got[0])) != 0 { - t.Fatalf("a host-networked container was given names a runtime will refuse: %v", got[0]) + given := namesOf(got[0]) + if len(given) != 1 || given[0] != "anchor.internal:10.42.0.1" { + t.Fatalf("a host-networked container was not given the mesh's names: %v", got[0]) } }