Keep watching the tunnel after a failed look, and remember peers' names
mesh/merge-gate pass: builds netcheck → ace, g14; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery delivered
mesh/merge-gate pass: builds netcheck → ace, g14; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery delivered
This commit is contained in:
@@ -20,6 +20,7 @@ import (
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -109,11 +110,20 @@ func parseDump(out string, now time.Time) (Tunnel, error) {
|
||||
return t, sc.Err()
|
||||
}
|
||||
|
||||
// errNoTunnel is a machine without the interface: not a fault, a machine off the private network.
|
||||
var errNoTunnel = errors.New("this machine has no " + TunnelInterface)
|
||||
|
||||
// names remembers the mesh's name of each peer address once found, so the watcher asks no resolver every look.
|
||||
var names sync.Map
|
||||
|
||||
// readTunnel asks wg for the interface's state and names each peer by the mesh's names.
|
||||
func readTunnel(ctx context.Context) (Tunnel, error) {
|
||||
out, err := exec.CommandContext(ctx, "wg", "show", TunnelInterface, "dump").Output()
|
||||
if err != nil {
|
||||
var ee *exec.ExitError
|
||||
if errors.As(err, &ee) && strings.Contains(string(ee.Stderr), "No such device") {
|
||||
return Tunnel{}, errNoTunnel
|
||||
}
|
||||
if errors.As(err, &ee) && len(ee.Stderr) > 0 {
|
||||
return Tunnel{}, fmt.Errorf("wg show %s: %s", TunnelInterface, strings.TrimSpace(string(ee.Stderr)))
|
||||
}
|
||||
@@ -124,7 +134,15 @@ func readTunnel(ctx context.Context) (Tunnel, error) {
|
||||
return t, err
|
||||
}
|
||||
for i := range t.Peers {
|
||||
t.Peers[i].Name = nameOf(ctx, t.Peers[i].AllowedIPs)
|
||||
k := peerKey(t.Peers[i])
|
||||
if known, ok := names.Load(k); ok {
|
||||
t.Peers[i].Name = known.(string)
|
||||
continue
|
||||
}
|
||||
if name := nameOf(ctx, t.Peers[i].AllowedIPs); name != "" {
|
||||
names.Store(k, name)
|
||||
t.Peers[i].Name = name
|
||||
}
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
@@ -204,7 +222,7 @@ func report(err error) {
|
||||
}
|
||||
|
||||
// watchTunnel looks every 20 seconds while this machine has the interface; a machine without it is
|
||||
// looked at again every ten minutes, saying so once.
|
||||
// looked at again every ten minutes. A failed look is said once and tried again at the next look.
|
||||
func watchTunnel(emit emitter) {
|
||||
var w tunnelWatch
|
||||
said := ""
|
||||
@@ -217,7 +235,11 @@ func watchTunnel(emit emitter) {
|
||||
say("not watching the tunnel: %v", err)
|
||||
said = err.Error()
|
||||
}
|
||||
time.Sleep(10 * time.Minute)
|
||||
if errors.Is(err, errNoTunnel) {
|
||||
time.Sleep(10 * time.Minute)
|
||||
} else {
|
||||
time.Sleep(20 * time.Second)
|
||||
}
|
||||
continue
|
||||
}
|
||||
said = ""
|
||||
|
||||
Reference in New Issue
Block a user