From d22a7f3a412f0d131313ac22ecc0af02a156f812 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 12 Nov 2026 18:09:17 +0100 Subject: [PATCH] fix-1748-own-resolver-wait: the own resolver's file waits 3 s a try MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The resolver file of systemd-resolved (resolvers and kept facts) carries options timeout:3 attempts:2 edns0 in place of timeout:1; manifest test asserts both facts, guard test's literal follows. Builds: design 50 resolver-wait §1, §4 (and §2 of the main file, line 73) --- modules/systemd-resolved/cmd/resolver-tools/guard_test.go | 2 +- .../systemd-resolved/cmd/resolver-tools/manifest_test.go | 6 ++++++ modules/systemd-resolved/module.json | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/modules/systemd-resolved/cmd/resolver-tools/guard_test.go b/modules/systemd-resolved/cmd/resolver-tools/guard_test.go index 2306730b4..bee912697 100644 --- a/modules/systemd-resolved/cmd/resolver-tools/guard_test.go +++ b/modules/systemd-resolved/cmd/resolver-tools/guard_test.go @@ -12,7 +12,7 @@ import ( "time" ) -const meshFile = "# Managed by the mesh\nnameserver 10.42.0.2\noptions timeout:1 attempts:2 edns0\n" +const meshFile = "# Managed by the mesh\nnameserver 10.42.0.2\noptions timeout:3 attempts:2 edns0\n" // vpnFile is a VPN client's file as one writes it; the addresses and domains are documentation's. const vpnFile = "# Dynamic resolv.conf(5) file for glibc resolver(3) generated by forticlient\n" + diff --git a/modules/systemd-resolved/cmd/resolver-tools/manifest_test.go b/modules/systemd-resolved/cmd/resolver-tools/manifest_test.go index cdf4d1a91..c1ec63d42 100644 --- a/modules/systemd-resolved/cmd/resolver-tools/manifest_test.go +++ b/modules/systemd-resolved/cmd/resolver-tools/manifest_test.go @@ -73,6 +73,12 @@ func TestTheManifestSaysWhatTheGuardKeeps(t *testing.T) { if len(lines) != 1 || strings.Contains(m.Facts["resolvers"].Template, "search ") { t.Errorf("the resolver file lists more than this machine's own resolver: %v", lines) } + // Design 50 resolver-wait §1: both facts carry the longer wait, never the uplink files' timeout:1. + for _, fact := range []string{"resolvers", "kept"} { + if tpl := m.Facts[fact].Template; !strings.Contains(tpl, "\noptions timeout:3 attempts:2 edns0\n") || strings.Contains(tpl, "timeout:1") { + t.Errorf("fact %s does not carry options timeout:3 attempts:2 edns0: %q", fact, tpl) + } + } conf := m.Facts["resolved"].Template for _, want := range []string{`DNS={{range index .Holders "mesh-dns-resolver"}}`, "\nDomains=~.\n", "\nFallbackDNS=\n", "DNSStubListenerExtra={{$own}}\n", "\nCache=no\n", "\nLLMNR=no\n", "\nMulticastDNS=no\n"} { diff --git a/modules/systemd-resolved/module.json b/modules/systemd-resolved/module.json index 24b3bc858..2a50c835a 100644 --- a/modules/systemd-resolved/module.json +++ b/modules/systemd-resolved/module.json @@ -52,7 +52,7 @@ "facts": { "kept": { "path": "/etc/node-resolver/resolv.conf", - "template": "# Managed by the mesh, and written by the module holding this machine's own resolver\n# (module systemd-resolved, novox/hq ADR 0247). On every other machine the module holding\n# the uplink writes this file, listing the mesh's resolvers (ADR 0223); here something\n# requires names routed by domain - a VPN client's domains to its own servers - so the file\n# names this machine's own resolver alone, which sends those domains over the VPN's link and\n# every other name to the mesh's resolvers. One server listed, so one answer per name.\n#\n# Its address on the private network, not loopback: a container copies this file, and\n# this address is one it can reach. Another program writing this file is put back by the\n# module's guard, which keeps what it wrote for whoever handles it on this machine.\n# Replaced on every push; edit nothing here.\n{{$own := \"\"}}{{range .Machines}}{{if eq .Name $.Node}}{{$own = .Address}}{{end}}{{end}}nameserver {{if $own}}{{$own}}{{else}}127.0.0.53{{end}}\noptions timeout:1 attempts:2 edns0\n" + "template": "# Managed by the mesh, and written by the module holding this machine's own resolver\n# (module systemd-resolved, novox/hq ADR 0247). On every other machine the module holding\n# the uplink writes this file, listing the mesh's resolvers (ADR 0223); here something\n# requires names routed by domain - a VPN client's domains to its own servers - so the file\n# names this machine's own resolver alone, which sends those domains over the VPN's link and\n# every other name to the mesh's resolvers. One server listed, so one answer per name.\n#\n# Its address on the private network, not loopback: a container copies this file, and\n# this address is one it can reach. Another program writing this file is put back by the\n# module's guard, which keeps what it wrote for whoever handles it on this machine.\n# Replaced on every push; edit nothing here.\n{{$own := \"\"}}{{range .Machines}}{{if eq .Name $.Node}}{{$own = .Address}}{{end}}{{end}}nameserver {{if $own}}{{$own}}{{else}}127.0.0.53{{end}}\noptions timeout:3 attempts:2 edns0\n" }, "resolved": { "path": "/etc/systemd/resolved.conf.d/50-mesh.conf", @@ -60,7 +60,7 @@ }, "resolvers": { "path": "/etc/resolv.conf", - "template": "# Managed by the mesh, and written by the module holding this machine's own resolver\n# (module systemd-resolved, novox/hq ADR 0247). On every other machine the module holding\n# the uplink writes this file, listing the mesh's resolvers (ADR 0223); here something\n# requires names routed by domain - a VPN client's domains to its own servers - so the file\n# names this machine's own resolver alone, which sends those domains over the VPN's link and\n# every other name to the mesh's resolvers. One server listed, so one answer per name.\n#\n# Its address on the private network, not loopback: a container copies this file, and\n# this address is one it can reach. Another program writing this file is put back by the\n# module's guard, which keeps what it wrote for whoever handles it on this machine.\n# Replaced on every push; edit nothing here.\n{{$own := \"\"}}{{range .Machines}}{{if eq .Name $.Node}}{{$own = .Address}}{{end}}{{end}}nameserver {{if $own}}{{$own}}{{else}}127.0.0.53{{end}}\noptions timeout:1 attempts:2 edns0\n" + "template": "# Managed by the mesh, and written by the module holding this machine's own resolver\n# (module systemd-resolved, novox/hq ADR 0247). On every other machine the module holding\n# the uplink writes this file, listing the mesh's resolvers (ADR 0223); here something\n# requires names routed by domain - a VPN client's domains to its own servers - so the file\n# names this machine's own resolver alone, which sends those domains over the VPN's link and\n# every other name to the mesh's resolvers. One server listed, so one answer per name.\n#\n# Its address on the private network, not loopback: a container copies this file, and\n# this address is one it can reach. Another program writing this file is put back by the\n# module's guard, which keeps what it wrote for whoever handles it on this machine.\n# Replaced on every push; edit nothing here.\n{{$own := \"\"}}{{range .Machines}}{{if eq .Name $.Node}}{{$own = .Address}}{{end}}{{end}}nameserver {{if $own}}{{$own}}{{else}}127.0.0.53{{end}}\noptions timeout:3 attempts:2 edns0\n" }, "suffix": { "path": "/etc/node-resolver/suffix",