Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit264fc56

Browse files
committed
chore: add easy NAT integration tests part 2
1 parenta63d427 commit264fc56

File tree

5 files changed

+592
-194
lines changed

5 files changed

+592
-194
lines changed

‎enterprise/coderd/roles_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func TestCustomRole(t *testing.T) {
6464

6565
// Verify the role exists in the list
6666
// TODO: Turn this assertion back on when the cli api experience is created.
67-
//allRoles, err := tmplAdmin.ListSiteRoles(ctx)
67+
//allRoles, err := tmplAdmin.ListSiteRoles(ctx)
6868
//require.NoError(t, err)
6969
//
7070
//require.True(t, slices.ContainsFunc(allRoles, func(selected codersdk.AssignableRoles) bool {

‎tailnet/test/integration/integration.go

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ type TestTopology struct {
5959
ServerServerStarter
6060
// StartClient gets called in each client subprocess. It's expected to
6161
// create the tailnet.Conn and ensure connectivity to it's peer.
62-
StartClientfunc(t*testing.T,logger slog.Logger,serverURL*url.URL,myID uuid.UUID,peerID uuid.UUID)*tailnet.Conn
62+
StartClientfunc(t*testing.T,logger slog.Logger,serverURL*url.URL,derpMap*tailcfg.DERPMap,clientNumberint,myID uuid.UUID,peerID uuid.UUID)*tailnet.Conn
6363

6464
// RunTests is the main test function. It's called in each of the client
6565
// subprocesses. If tests can only run once, they should check the client ID
@@ -264,13 +264,18 @@ http {
264264

265265
// StartClientDERP creates a client connection to the server for coordination
266266
// and creates a tailnet.Conn which will only use DERP to connect to the peer.
267-
funcStartClientDERP(t*testing.T,logger slog.Logger,serverURL*url.URL,myID,peerID uuid.UUID)*tailnet.Conn {
267+
funcStartClientDERP(t*testing.T,logger slog.Logger,serverURL*url.URL,derpMap*tailcfg.DERPMap,clientNumberint,myID,peerID uuid.UUID)*tailnet.Conn {
268+
listenPort:=uint16(client1Port)
269+
ifclientNumber==2 {
270+
listenPort=client2Port
271+
}
268272
returnstartClientOptions(t,logger,serverURL,myID,peerID,&tailnet.Options{
269273
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IPFromUUID(myID),128)},
270-
DERPMap:basicDERPMap(t,serverURL),
274+
DERPMap:derpMap,
271275
BlockEndpoints:true,
272276
Logger:logger,
273277
DERPForceWebSockets:false,
278+
ListenPort:listenPort,
274279
// These tests don't have internet connection, so we need to force
275280
// magicsock to do anything.
276281
ForceNetworkUp:true,
@@ -279,13 +284,18 @@ func StartClientDERP(t *testing.T, logger slog.Logger, serverURL *url.URL, myID,
279284

280285
// StartClientDERPWebSockets does the same thing as StartClientDERP but will
281286
// only use DERP WebSocket fallback.
282-
funcStartClientDERPWebSockets(t*testing.T,logger slog.Logger,serverURL*url.URL,myID,peerID uuid.UUID)*tailnet.Conn {
287+
funcStartClientDERPWebSockets(t*testing.T,logger slog.Logger,serverURL*url.URL,derpMap*tailcfg.DERPMap,clientNumberint,myID,peerID uuid.UUID)*tailnet.Conn {
288+
listenPort:=uint16(client1Port)
289+
ifclientNumber==2 {
290+
listenPort=client2Port
291+
}
283292
returnstartClientOptions(t,logger,serverURL,myID,peerID,&tailnet.Options{
284293
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IPFromUUID(myID),128)},
285-
DERPMap:basicDERPMap(t,serverURL),
294+
DERPMap:derpMap,
286295
BlockEndpoints:true,
287296
Logger:logger,
288297
DERPForceWebSockets:true,
298+
ListenPort:listenPort,
289299
// These tests don't have internet connection, so we need to force
290300
// magicsock to do anything.
291301
ForceNetworkUp:true,
@@ -295,13 +305,18 @@ func StartClientDERPWebSockets(t *testing.T, logger slog.Logger, serverURL *url.
295305
// StartClientDirect does the same thing as StartClientDERP but disables
296306
// BlockEndpoints (which enables Direct connections), and waits for a direct
297307
// connection to be established between the two peers.
298-
funcStartClientDirect(t*testing.T,logger slog.Logger,serverURL*url.URL,myID,peerID uuid.UUID)*tailnet.Conn {
308+
funcStartClientDirect(t*testing.T,logger slog.Logger,serverURL*url.URL,derpMap*tailcfg.DERPMap,clientNumberint,myID,peerID uuid.UUID)*tailnet.Conn {
309+
listenPort:=uint16(client1Port)
310+
ifclientNumber==2 {
311+
listenPort=client2Port
312+
}
299313
conn:=startClientOptions(t,logger,serverURL,myID,peerID,&tailnet.Options{
300314
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IPFromUUID(myID),128)},
301-
DERPMap:basicDERPMap(t,serverURL),
315+
DERPMap:derpMap,
302316
BlockEndpoints:false,
303317
Logger:logger,
304318
DERPForceWebSockets:true,
319+
ListenPort:listenPort,
305320
// These tests don't have internet connection, so we need to force
306321
// magicsock to do anything.
307322
ForceNetworkUp:true,
@@ -365,10 +380,17 @@ func startClientOptions(t *testing.T, logger slog.Logger, serverURL *url.URL, my
365380
returnconn
366381
}
367382

368-
funcbasicDERPMap(t*testing.T,serverURL*url.URL)*tailcfg.DERPMap {
383+
funcbasicDERPMap(serverURLStrstring) (*tailcfg.DERPMap,error) {
384+
serverURL,err:=url.Parse(serverURLStr)
385+
iferr!=nil {
386+
returnnil,xerrors.Errorf("parse server URL %q: %w",serverURLStr,err)
387+
}
388+
369389
portStr:=serverURL.Port()
370390
port,err:=strconv.Atoi(portStr)
371-
require.NoError(t,err,"parse server port")
391+
iferr!=nil {
392+
returnnil,xerrors.Errorf("parse port %q: %w",portStr,err)
393+
}
372394

373395
hostname:=serverURL.Hostname()
374396
ipv4:=""
@@ -399,7 +421,7 @@ func basicDERPMap(t *testing.T, serverURL *url.URL) *tailcfg.DERPMap {
399421
},
400422
},
401423
},
402-
}
424+
},nil
403425
}
404426

405427
// ExecBackground starts a subprocess with the given flags and returns a

‎tailnet/test/integration/integration_test.go

Lines changed: 123 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,28 @@
44
package integration_test
55

66
import (
7+
"context"
8+
"encoding/json"
79
"flag"
810
"fmt"
11+
"net"
912
"net/http"
1013
"net/url"
1114
"os"
1215
"os/signal"
16+
"path/filepath"
1317
"runtime"
18+
"strconv"
1419
"syscall"
1520
"testing"
1621
"time"
1722

1823
"github.com/google/uuid"
24+
"github.com/stretchr/testify/assert"
1925
"github.com/stretchr/testify/require"
26+
"tailscale.com/net/stun/stuntest"
27+
"tailscale.com/tailcfg"
28+
"tailscale.com/types/nettype"
2029

2130
"cdr.dev/slog"
2231
"cdr.dev/slog/sloggers/slogtest"
@@ -30,17 +39,22 @@ const runTestEnv = "CODER_TAILNET_TESTS"
3039
var (
3140
isSubprocess=flag.Bool("subprocess",false,"Signifies that this is a test subprocess")
3241
testID=flag.String("test-name","","Which test is being run")
33-
role=flag.String("role","","The role of the test subprocess: server, client")
42+
role=flag.String("role","","The role of the test subprocess: server,stun,client")
3443

3544
// Role: server
3645
serverListenAddr=flag.String("server-listen-addr","","The address to listen on for the server")
3746

47+
// Role: stun
48+
stunListenAddr=flag.String("stun-listen-addr","","The address to listen on for the STUN server")
49+
3850
// Role: client
39-
clientName=flag.String("client-name","","The name of the client for logs")
40-
clientServerURL=flag.String("client-server-url","","The url to connect to the server")
41-
clientMyID=flag.String("client-id","","The id of the client")
42-
clientPeerID=flag.String("client-peer-id","","The id of the other client")
43-
clientRunTests=flag.Bool("client-run-tests",false,"Run the tests in the client subprocess")
51+
clientName=flag.String("client-name","","The name of the client for logs")
52+
clientNumber=flag.Int("client-number",0,"The number of the client")
53+
clientMyID=flag.String("client-id","","The id of the client")
54+
clientPeerID=flag.String("client-peer-id","","The id of the other client")
55+
clientServerURL=flag.String("client-server-url","","The url to connect to the server")
56+
clientDERPMapPath=flag.String("client-derp-map-path","","The path to the DERP map file to use on this client")
57+
clientRunTests=flag.Bool("client-run-tests",false,"Run the tests in the client subprocess")
4458
)
4559

4660
funcTestMain(m*testing.M) {
@@ -87,7 +101,7 @@ var topologies = []integration.TestTopology{
87101
// endpoints to connect as routing is enabled between client 1 and
88102
// client 2.
89103
Name:"EasyNATDirect",
90-
SetupNetworking:integration.SetupNetworkingEasyNAT,
104+
SetupNetworking:integration.SetupNetworkingEasyNATWithSTUN,
91105
Server: integration.SimpleServerOptions{},
92106
StartClient:integration.StartClientDirect,
93107
RunTests:integration.TestSuite,
@@ -143,17 +157,41 @@ func TestIntegration(t *testing.T) {
143157
log:=slogtest.Make(t,nil).Leveled(slog.LevelDebug)
144158
networking:=topo.SetupNetworking(t,log)
145159

146-
// Fork the three child processes.
160+
// Useful for debugging network namespaces by avoiding cleanup.
161+
// t.Cleanup(func() {
162+
// time.Sleep(time.Minute * 15)
163+
// })
164+
147165
closeServer:=startServerSubprocess(t,topo.Name,networking)
166+
167+
closeSTUN:=func()error {returnnil }
168+
ifnetworking.STUN.ListenAddr!="" {
169+
closeSTUN=startSTUNSubprocess(t,topo.Name,networking)
170+
}
171+
172+
// Write the DERP maps to a file.
173+
tempDir:=t.TempDir()
174+
client1DERPMapPath:=filepath.Join(tempDir,"client1-derp-map.json")
175+
client1DERPMap,err:=networking.Client1.ResolveDERPMap()
176+
require.NoError(t,err,"resolve client 1 DERP map")
177+
err=writeDERPMapToFile(client1DERPMapPath,client1DERPMap)
178+
require.NoError(t,err,"write client 1 DERP map")
179+
client2DERPMapPath:=filepath.Join(tempDir,"client2-derp-map.json")
180+
client2DERPMap,err:=networking.Client2.ResolveDERPMap()
181+
require.NoError(t,err,"resolve client 2 DERP map")
182+
err=writeDERPMapToFile(client2DERPMapPath,client2DERPMap)
183+
require.NoError(t,err,"write client 2 DERP map")
184+
148185
// client1 runs the tests.
149-
client1ErrCh,_:=startClientSubprocess(t,topo.Name,networking,1)
150-
_,closeClient2:=startClientSubprocess(t,topo.Name,networking,2)
186+
client1ErrCh,_:=startClientSubprocess(t,topo.Name,networking,1,client1DERPMapPath)
187+
_,closeClient2:=startClientSubprocess(t,topo.Name,networking,2,client2DERPMapPath)
151188

152189
// Wait for client1 to exit.
153190
require.NoError(t,<-client1ErrCh,"client 1 exited")
154191

155192
// Close client2 and the server.
156193
require.NoError(t,closeClient2(),"client 2 exited")
194+
require.NoError(t,closeSTUN(),"stun exited")
157195
require.NoError(t,closeServer(),"server exited")
158196
})
159197
}
@@ -169,10 +207,11 @@ func handleTestSubprocess(t *testing.T) {
169207
}
170208
}
171209
require.NotEmptyf(t,topo.Name,"unknown test topology %q",*testID)
210+
require.Contains(t, []string{"server","stun","client"},*role,"unknown role %q",*role)
172211

173212
testName:=topo.Name+"/"
174-
if*role=="server" {
175-
testName+="server"
213+
if*role=="server"||*role=="stun"{
214+
testName+=*role
176215
}else {
177216
testName+=*clientName
178217
}
@@ -185,18 +224,34 @@ func handleTestSubprocess(t *testing.T) {
185224
topo.Server.StartServer(t,logger,*serverListenAddr)
186225
// no exit
187226

227+
case"stun":
228+
launchSTUNServer(t,*stunListenAddr)
229+
// no exit
230+
188231
case"client":
189232
logger=logger.Named(*clientName)
233+
if*clientNumber!=1&&*clientNumber!=2 {
234+
t.Fatalf("invalid client number %d",clientNumber)
235+
}
190236
serverURL,err:=url.Parse(*clientServerURL)
191237
require.NoErrorf(t,err,"parse server url %q",*clientServerURL)
192238
myID,err:=uuid.Parse(*clientMyID)
193239
require.NoErrorf(t,err,"parse client id %q",*clientMyID)
194240
peerID,err:=uuid.Parse(*clientPeerID)
195241
require.NoErrorf(t,err,"parse peer id %q",*clientPeerID)
196242

243+
// Load the DERP map.
244+
varderpMap tailcfg.DERPMap
245+
derpMapPath:=*clientDERPMapPath
246+
f,err:=os.Open(derpMapPath)
247+
require.NoErrorf(t,err,"open DERP map %q",derpMapPath)
248+
err=json.NewDecoder(f).Decode(&derpMap)
249+
_=f.Close()
250+
require.NoErrorf(t,err,"decode DERP map %q",derpMapPath)
251+
197252
waitForServerAvailable(t,serverURL)
198253

199-
conn:=topo.StartClient(t,logger,serverURL,myID,peerID)
254+
conn:=topo.StartClient(t,logger,serverURL,&derpMap,*clientNumber,myID,peerID)
200255

201256
if*clientRunTests {
202257
// Wait for connectivity.
@@ -218,6 +273,23 @@ func handleTestSubprocess(t *testing.T) {
218273
})
219274
}
220275

276+
typeforcedAddrPacketListenerstruct {
277+
addrstring
278+
}
279+
280+
var_ nettype.PacketListener=forcedAddrPacketListener{}
281+
282+
func (lnforcedAddrPacketListener)ListenPacket(ctx context.Context,network,_string) (net.PacketConn,error) {
283+
return nettype.Std{}.ListenPacket(ctx,network,ln.addr)
284+
}
285+
286+
funclaunchSTUNServer(t*testing.T,listenAddrstring) {
287+
ln:=forcedAddrPacketListener{addr:listenAddr}
288+
addr,cleanup:=stuntest.ServeWithPacketListener(t,ln)
289+
t.Cleanup(cleanup)
290+
assert.Equal(t,listenAddr,addr.String(),"listen address should match forced addr")
291+
}
292+
221293
funcwaitForServerAvailable(t*testing.T,serverURL*url.URL) {
222294
constdelay=100*time.Millisecond
223295
constreqTimeout=2*time.Second
@@ -247,45 +319,55 @@ func waitForServerAvailable(t *testing.T, serverURL *url.URL) {
247319
}
248320

249321
funcstartServerSubprocess(t*testing.T,topologyNamestring,networking integration.TestNetworking)func()error {
250-
_,closeFn:=startSubprocess(t,"server",networking.ProcessServer.NetNS, []string{
322+
_,closeFn:=startSubprocess(t,"server",networking.Server.Process.NetNS, []string{
251323
"--subprocess",
252324
"--test-name="+topologyName,
253325
"--role=server",
254-
"--server-listen-addr="+networking.ServerListenAddr,
326+
"--server-listen-addr="+networking.Server.ListenAddr,
327+
})
328+
returncloseFn
329+
}
330+
331+
funcstartSTUNSubprocess(t*testing.T,topologyNamestring,networking integration.TestNetworking)func()error {
332+
_,closeFn:=startSubprocess(t,"stun",networking.STUN.Process.NetNS, []string{
333+
"--subprocess",
334+
"--test-name="+topologyName,
335+
"--role=stun",
336+
"--stun-listen-addr="+networking.STUN.ListenAddr,
255337
})
256338
returncloseFn
257339
}
258340

259-
funcstartClientSubprocess(t*testing.T,topologyNamestring,networking integration.TestNetworking,clientNumberint) (<-chanerror,func()error) {
341+
funcstartClientSubprocess(t*testing.T,topologyNamestring,networking integration.TestNetworking,clientNumberint,derpMapPathstring) (<-chanerror,func()error) {
260342
require.True(t,clientNumber==1||clientNumber==2)
261343

262344
var (
263-
clientName=fmt.Sprintf("client%d",clientNumber)
264-
myID=integration.Client1ID
265-
peerID=integration.Client2ID
266-
accessURL=networking.ServerAccessURLClient1
267-
netNS=networking.ProcessClient1.NetNS
345+
clientName=fmt.Sprintf("client%d",clientNumber)
346+
myID=integration.Client1ID
347+
peerID=integration.Client2ID
348+
clientConfig=networking.Client1
268349
)
269350
ifclientNumber==2 {
270351
myID,peerID=peerID,myID
271-
accessURL=networking.ServerAccessURLClient2
272-
netNS=networking.ProcessClient2.NetNS
352+
clientConfig=networking.Client2
273353
}
274354

275355
flags:= []string{
276356
"--subprocess",
277357
"--test-name="+topologyName,
278358
"--role=client",
279359
"--client-name="+clientName,
280-
"--client-server-url="+accessURL,
360+
"--client-number="+strconv.Itoa(clientNumber),
361+
"--client-server-url="+clientConfig.ServerAccessURL,
281362
"--client-id="+myID.String(),
282363
"--client-peer-id="+peerID.String(),
364+
"--client-derp-map-path="+derpMapPath,
283365
}
284366
ifclientNumber==1 {
285367
flags=append(flags,"--client-run-tests")
286368
}
287369

288-
returnstartSubprocess(t,clientName,netNS,flags)
370+
returnstartSubprocess(t,clientName,clientConfig.Process.NetNS,flags)
289371
}
290372

291373
// startSubprocess launches the test binary with the same flags as the test, but
@@ -298,3 +380,19 @@ func startSubprocess(t *testing.T, processName string, netNS *os.File, flags []s
298380
args:=append(os.Args[1:],append([]string{"-test.v=true"},flags...)...)
299381
returnintegration.ExecBackground(t,processName,netNS,name,args)
300382
}
383+
384+
funcwriteDERPMapToFile(pathstring,derpMap*tailcfg.DERPMap)error {
385+
f,err:=os.Create(path)
386+
iferr!=nil {
387+
returnerr
388+
}
389+
deferf.Close()
390+
391+
enc:=json.NewEncoder(f)
392+
enc.SetIndent(""," ")
393+
err=enc.Encode(derpMap)
394+
iferr!=nil {
395+
returnerr
396+
}
397+
returnnil
398+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp