mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-19 09:30:58 +00:00
prober: add a DERP probe manager based on derpprobe
This ensures that each DERP server is probed individually (TLS and STUN) and also manages per-region mesh probing. Actual probing code has been copied from cmd/derpprobe. Signed-off-by: Anton Tolchanov <anton@tailscale.com>
This commit is contained in:

committed by
Anton Tolchanov

parent
f39847aa52
commit
69f61dcad8
106
prober/derp_test.go
Normal file
106
prober/derp_test.go
Normal file
@@ -0,0 +1,106 @@
|
||||
// Copyright (c) 2022 Tailscale Inc & AUTHORS All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package prober
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"tailscale.com/tailcfg"
|
||||
)
|
||||
|
||||
func TestDerpProber(t *testing.T) {
|
||||
dm := &tailcfg.DERPMap{
|
||||
Regions: map[int]*tailcfg.DERPRegion{
|
||||
0: {
|
||||
RegionID: 0,
|
||||
RegionCode: "zero",
|
||||
Nodes: []*tailcfg.DERPNode{
|
||||
{
|
||||
Name: "n1",
|
||||
RegionID: 0,
|
||||
HostName: "derpn1.tailscale.test",
|
||||
IPv4: "1.1.1.1",
|
||||
IPv6: "::1",
|
||||
},
|
||||
{
|
||||
Name: "n2",
|
||||
RegionID: 0,
|
||||
HostName: "derpn2.tailscale.test",
|
||||
IPv4: "1.1.1.1",
|
||||
IPv6: "::1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
resp, err := json.Marshal(dm)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
w.Write(resp)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
clk := newFakeTime()
|
||||
p := newForTest(clk.Now, clk.NewTicker)
|
||||
dp := &derpProber{
|
||||
p: p,
|
||||
derpMapURL: srv.URL,
|
||||
tlsProbeFn: func(_ string) ProbeFunc { return func(context.Context) error { return nil } },
|
||||
udpProbeFn: func(_ string, _ int) ProbeFunc { return func(context.Context) error { return nil } },
|
||||
meshProbeFn: func(_, _ string) ProbeFunc { return func(context.Context) error { return nil } },
|
||||
nodes: make(map[string]*tailcfg.DERPNode),
|
||||
probes: make(map[string]*Probe),
|
||||
}
|
||||
if err := dp.ProbeMap(context.Background()); err != nil {
|
||||
t.Errorf("unexpected ProbeMap() error: %s", err)
|
||||
}
|
||||
if len(dp.nodes) != 2 || dp.nodes["derpn1.tailscale.test"] == nil || dp.nodes["derpn2.tailscale.test"] == nil {
|
||||
t.Errorf("unexpected nodes: %+v", dp.nodes)
|
||||
}
|
||||
// Probes expected for two nodes:
|
||||
// - 3 regular probes per node (TLS, UDPv4, UDPv6)
|
||||
// - 4 mesh probes (N1->N2, N1->N1, N2->N1, N2->N2)
|
||||
if len(dp.probes) != 10 {
|
||||
t.Errorf("unexpected probes: %+v", dp.probes)
|
||||
}
|
||||
|
||||
// Add one more node and check that probes got created.
|
||||
dm.Regions[0].Nodes = append(dm.Regions[0].Nodes, &tailcfg.DERPNode{
|
||||
Name: "n3",
|
||||
RegionID: 0,
|
||||
HostName: "derpn3.tailscale.test",
|
||||
IPv4: "1.1.1.1",
|
||||
IPv6: "::1",
|
||||
})
|
||||
if err := dp.ProbeMap(context.Background()); err != nil {
|
||||
t.Errorf("unexpected ProbeMap() error: %s", err)
|
||||
}
|
||||
if len(dp.nodes) != 3 {
|
||||
t.Errorf("unexpected nodes: %+v", dp.nodes)
|
||||
}
|
||||
// 9 regular probes + 9 mesh probes
|
||||
if len(dp.probes) != 18 {
|
||||
t.Errorf("unexpected probes: %+v", dp.probes)
|
||||
}
|
||||
|
||||
// Remove 2 nodes and check that probes have been destroyed.
|
||||
dm.Regions[0].Nodes = dm.Regions[0].Nodes[:1]
|
||||
if err := dp.ProbeMap(context.Background()); err != nil {
|
||||
t.Errorf("unexpected ProbeMap() error: %s", err)
|
||||
}
|
||||
if len(dp.nodes) != 1 {
|
||||
t.Errorf("unexpected nodes: %+v", dp.nodes)
|
||||
}
|
||||
// 3 regular probes + 1 mesh probe
|
||||
if len(dp.probes) != 4 {
|
||||
t.Errorf("unexpected probes: %+v", dp.probes)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user