hal dnsmasq-app conversion, hq 08-connectivity. Pairs with mesh-catalog convert/dnsmasq-from-hal (PR #50) — merge this one first: the catalogue's dnsmasq module says ${machine:address}, which only this controller knows.
What changes
node-zones fact (internal/catalogue/facts.go): carries local=/<suffix>/ beside the address=/<node>.<suffix>/<address> lines, so a resolver that forwards never sends a mesh name it does not know upstream. The suffix default lives in one helper.
${machine:address} (machine_into_files.go): a third machine fact — what at resolves to, from Rendering.Names, the same map the hosts file and wildcards are written from. Absent and refused off the network, like at. Needed because the runtime's dns list takes addresses and ${machine:at} is a name.
overlay.Resolver / overlay.ResolverData removed: nothing provided or consumed them; the facts: mechanism plus mesh-addressing is how a resolver gets its data.
How it is checked
internal/catalogue/resolver_manifests_test.go (catalogue-backed): the three manifests parse; dnsmasq's config has fixed upstreams, no-resolv, 127.0.0.1, mesh0; dnsmasq + resolv-conf compose on one machine with the machines file, the daemon restarting on it, the runtime's dns written into daemon.json at the machine's address and no runtime restart/reload ordered; resolv-conf + resolved-split-dns refused on one node (the-resolver-configuration); a machine off the network is refused rather than given a placeholder.
cmd/mesh-controller/network_test.go: on a real mesh (aMesh), the resolver's machines file holds a wildcard per machine on the network and local=/internal/, and is composed again without a machine that left — mirroring TestOnlyAMachineOnThePrivateNetworkIsNamed.
machine_into_files_test.go: ${machine:address} resolves from Names and is refused off the network.
go build ./... && go vet ./... && go test -count=1 ./... green with MESH_TEST_POSTGRES. gofmt -l . reports only cmd/mesh-builder/stdout_test.go, which predates this branch.
Not settled
The runtime's dns takes effect for containers created after the runtime next starts; the module orders no restart (a restart stops every container, ADR 0102) and dns is not among dockerd's reloadable options. On the machines being replaced the predecessor already wrote the same value. A lab check that a fresh converged node's containers resolve mesh names is not written.
On a converged node the filter admits port 53 from: mesh only. Containers on user-defined networks query through the runtime's embedded resolver from the host's own namespace (loopback, admitted); a container on the runtime's default bridge queries from its bridge address and is dropped. Not the case for the mesh's declared containers; flagged, not fixed.
The predecessor's per-node DNSMASQ_SPLIT_DNS and DNSMASQ_LOCAL_DOMAIN entries have no nox equivalent (dnsmasq's config is not a mergeable JSON file).
resolved-split-dns still hard-codes Domains=~internal; there is no ${machine:…} for the suffix.
hq 08-connectivity's "it needs no upstream" describes the split-DNS arrangement; with resolv-conf naming the resolver alone (the predecessor's arrangement) it forwards, and the design text should say so.
hal dnsmasq-app conversion, hq 08-connectivity. Pairs with mesh-catalog `convert/dnsmasq-from-hal` (PR #50) — merge this one first: the catalogue's dnsmasq module says `${machine:address}`, which only this controller knows.
**What changes**
- `node-zones` fact (`internal/catalogue/facts.go`): carries `local=/<suffix>/` beside the `address=/<node>.<suffix>/<address>` lines, so a resolver that forwards never sends a mesh name it does not know upstream. The suffix default lives in one helper.
- `${machine:address}` (`machine_into_files.go`): a third machine fact — what `at` resolves to, from `Rendering.Names`, the same map the hosts file and wildcards are written from. Absent and refused off the network, like `at`. Needed because the runtime's `dns` list takes addresses and `${machine:at}` is a name.
- `overlay.Resolver` / `overlay.ResolverData` removed: nothing provided or consumed them; the `facts:` mechanism plus `mesh-addressing` is how a resolver gets its data.
**How it is checked**
- `internal/catalogue/resolver_manifests_test.go` (catalogue-backed): the three manifests parse; dnsmasq's config has fixed upstreams, `no-resolv`, `127.0.0.1`, `mesh0`; dnsmasq + resolv-conf compose on one machine with the machines file, the daemon restarting on it, the runtime's `dns` written into daemon.json at the machine's address and no runtime restart/reload ordered; resolv-conf + resolved-split-dns refused on one node (`the-resolver-configuration`); a machine off the network is refused rather than given a placeholder.
- `cmd/mesh-controller/network_test.go`: on a real mesh (`aMesh`), the resolver's machines file holds a wildcard per machine on the network and `local=/internal/`, and is composed again without a machine that left — mirroring `TestOnlyAMachineOnThePrivateNetworkIsNamed`.
- `machine_into_files_test.go`: `${machine:address}` resolves from Names and is refused off the network.
- `go build ./... && go vet ./... && go test -count=1 ./...` green with `MESH_TEST_POSTGRES`. `gofmt -l .` reports only `cmd/mesh-builder/stdout_test.go`, which predates this branch.
**Not settled**
- The runtime's `dns` takes effect for containers created after the runtime next starts; the module orders no restart (a restart stops every container, ADR 0102) and `dns` is not among dockerd's reloadable options. On the machines being replaced the predecessor already wrote the same value. A lab check that a fresh converged node's containers resolve mesh names is not written.
- On a converged node the filter admits port 53 `from: mesh` only. Containers on user-defined networks query through the runtime's embedded resolver from the host's own namespace (loopback, admitted); a container on the runtime's *default* bridge queries from its bridge address and is dropped. Not the case for the mesh's declared containers; flagged, not fixed.
- The predecessor's per-node `DNSMASQ_SPLIT_DNS` and `DNSMASQ_LOCAL_DOMAIN` entries have no nox equivalent (dnsmasq's config is not a mergeable JSON file).
- `resolved-split-dns` still hard-codes `Domains=~internal`; there is no `${machine:…}` for the suffix.
- hq 08-connectivity's "it needs no upstream" describes the split-DNS arrangement; with resolv-conf naming the resolver alone (the predecessor's arrangement) it forwards, and the design text should say so.
hal dnsmasq-app conversion, hq 08-connectivity. Converting the resolver from the module it
replaces made it forward what it cannot answer, which is what the predecessor's does, and
that found two things the controller did not say.
A resolver that forwards must not send a mesh name it does not know upstream: the
`node-zones` fact now carries `local=/<suffix>/` beside the wildcards, written here rather
than in the daemon's configuration because the suffix is the mesh's choice and this file is
the one place the mesh writes what it chose. The default lives in one helper now instead of
being spelled in two functions.
The predecessor points the container runtime's `dns` at the machine's own tunnel address —
a container cannot reach the machine's loopback. A module writing that key needs the
address, and `${machine:at}` is the machine's name; a runtime's resolver list cannot be a
name it would need that resolver to look up. So a module may say `${machine:address}`: what
`at` resolves to, read from the same names the hosts file and the wildcards are written
from, absent — and refused — off the network like `at` is.
The `mesh-resolver` and `resolver-data` constants go: nothing provided or consumed either,
the fact and `mesh-addressing` are the mechanism, and a requirement nothing provides is
refused at resolution.
Tests: the catalogue's dnsmasq, resolv-conf and resolved-split-dns manifests are parsed
and composed as a machine would receive them — fixed upstreams, no-resolv, 127.0.0.1, the
machines file, the runtime's key, the pair that decides what a machine asks refused on one
node; and on a real mesh the resolver's machines file is composed with a wildcard per
machine on the network and composed again without one that left, mirroring the hosts fact.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
hal dnsmasq-app conversion, hq 08-connectivity. Pairs with mesh-catalog
convert/dnsmasq-from-hal(PR #50) — merge this one first: the catalogue's dnsmasq module says${machine:address}, which only this controller knows.What changes
node-zonesfact (internal/catalogue/facts.go): carrieslocal=/<suffix>/beside theaddress=/<node>.<suffix>/<address>lines, so a resolver that forwards never sends a mesh name it does not know upstream. The suffix default lives in one helper.${machine:address}(machine_into_files.go): a third machine fact — whatatresolves to, fromRendering.Names, the same map the hosts file and wildcards are written from. Absent and refused off the network, likeat. Needed because the runtime'sdnslist takes addresses and${machine:at}is a name.overlay.Resolver/overlay.ResolverDataremoved: nothing provided or consumed them; thefacts:mechanism plusmesh-addressingis how a resolver gets its data.How it is checked
internal/catalogue/resolver_manifests_test.go(catalogue-backed): the three manifests parse; dnsmasq's config has fixed upstreams,no-resolv,127.0.0.1,mesh0; dnsmasq + resolv-conf compose on one machine with the machines file, the daemon restarting on it, the runtime'sdnswritten into daemon.json at the machine's address and no runtime restart/reload ordered; resolv-conf + resolved-split-dns refused on one node (the-resolver-configuration); a machine off the network is refused rather than given a placeholder.cmd/mesh-controller/network_test.go: on a real mesh (aMesh), the resolver's machines file holds a wildcard per machine on the network andlocal=/internal/, and is composed again without a machine that left — mirroringTestOnlyAMachineOnThePrivateNetworkIsNamed.machine_into_files_test.go:${machine:address}resolves from Names and is refused off the network.go build ./... && go vet ./... && go test -count=1 ./...green withMESH_TEST_POSTGRES.gofmt -l .reports onlycmd/mesh-builder/stdout_test.go, which predates this branch.Not settled
dnstakes effect for containers created after the runtime next starts; the module orders no restart (a restart stops every container, ADR 0102) anddnsis not among dockerd's reloadable options. On the machines being replaced the predecessor already wrote the same value. A lab check that a fresh converged node's containers resolve mesh names is not written.from: meshonly. Containers on user-defined networks query through the runtime's embedded resolver from the host's own namespace (loopback, admitted); a container on the runtime's default bridge queries from its bridge address and is dropped. Not the case for the mesh's declared containers; flagged, not fixed.DNSMASQ_SPLIT_DNSandDNSMASQ_LOCAL_DOMAINentries have no nox equivalent (dnsmasq's config is not a mergeable JSON file).resolved-split-dnsstill hard-codesDomains=~internal; there is no${machine:…}for the suffix.hal dnsmasq-app conversion, hq 08-connectivity. Converting the resolver from the module it replaces made it forward what it cannot answer, which is what the predecessor's does, and that found two things the controller did not say. A resolver that forwards must not send a mesh name it does not know upstream: the `node-zones` fact now carries `local=/<suffix>/` beside the wildcards, written here rather than in the daemon's configuration because the suffix is the mesh's choice and this file is the one place the mesh writes what it chose. The default lives in one helper now instead of being spelled in two functions. The predecessor points the container runtime's `dns` at the machine's own tunnel address — a container cannot reach the machine's loopback. A module writing that key needs the address, and `${machine:at}` is the machine's name; a runtime's resolver list cannot be a name it would need that resolver to look up. So a module may say `${machine:address}`: what `at` resolves to, read from the same names the hosts file and the wildcards are written from, absent — and refused — off the network like `at` is. The `mesh-resolver` and `resolver-data` constants go: nothing provided or consumed either, the fact and `mesh-addressing` are the mechanism, and a requirement nothing provides is refused at resolution. Tests: the catalogue's dnsmasq, resolv-conf and resolved-split-dns manifests are parsed and composed as a machine would receive them — fixed upstreams, no-resolv, 127.0.0.1, the machines file, the runtime's key, the pair that decides what a machine asks refused on one node; and on a real mesh the resolver's machines file is composed with a wildcard per machine on the network and composed again without one that left, mirroring the hosts fact.dd920ff854to0d8264ff55