Skip to content

Commit e5bb0a7

Browse files
authored
chore: add easy NAT integration tests part 2 (coder#13312)
1 parent 1b4ca00 commit e5bb0a7

File tree

6 files changed

+625
-231
lines changed

6 files changed

+625
-231
lines changed

coderd/rbac/roles_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func TestOwnerExec(t *testing.T) {
7777
})
7878
}
7979

80-
// nolint:tparallel,paralleltest -- subtests share a map, just run sequentially.
80+
// nolint:tparallel,paralleltest // subtests share a map, just run sequentially.
8181
func TestRolePermissions(t *testing.T) {
8282
t.Parallel()
8383

@@ -557,7 +557,7 @@ func TestRolePermissions(t *testing.T) {
557557
// nolint:tparallel,paralleltest
558558
for _, c := range testCases {
559559
c := c
560-
// nolint:tparallel,paralleltest -- These share the same remainingPermissions map
560+
// nolint:tparallel,paralleltest // These share the same remainingPermissions map
561561
t.Run(c.Name, func(t *testing.T) {
562562
remainingSubjs := make(map[string]struct{})
563563
for _, subj := range requiredSubjects {
@@ -600,7 +600,7 @@ func TestRolePermissions(t *testing.T) {
600600
// Only run these if the tests on top passed. Otherwise, the error output is too noisy.
601601
if passed {
602602
for rtype, v := range remainingPermissions {
603-
// nolint:tparallel,paralleltest -- Making a subtest for easier diagnosing failures.
603+
// nolint:tparallel,paralleltest // Making a subtest for easier diagnosing failures.
604604
t.Run(fmt.Sprintf("%s-AllActions", rtype), func(t *testing.T) {
605605
if len(v) > 0 {
606606
assert.Equal(t, map[policy.Action]bool{}, v, "remaining permissions should be empty for type %q", rtype)

tailnet/test/integration/integration.go

+57-25
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,34 @@ import (
4141
"github.com/coder/coder/v2/testutil"
4242
)
4343

44-
// IDs used in tests.
45-
var (
46-
Client1ID = uuid.MustParse("00000000-0000-0000-0000-000000000001")
47-
Client2ID = uuid.MustParse("00000000-0000-0000-0000-000000000002")
44+
type ClientNumber int
45+
46+
const (
47+
ClientNumber1 ClientNumber = 1
48+
ClientNumber2 ClientNumber = 2
4849
)
4950

51+
type Client struct {
52+
Number ClientNumber
53+
ID uuid.UUID
54+
ListenPort uint16
55+
ShouldRunTests bool
56+
}
57+
58+
var Client1 = Client{
59+
Number: ClientNumber1,
60+
ID: uuid.MustParse("00000000-0000-0000-0000-000000000001"),
61+
ListenPort: client1Port,
62+
ShouldRunTests: true,
63+
}
64+
65+
var Client2 = Client{
66+
Number: ClientNumber2,
67+
ID: uuid.MustParse("00000000-0000-0000-0000-000000000002"),
68+
ListenPort: client2Port,
69+
ShouldRunTests: false,
70+
}
71+
5072
type TestTopology struct {
5173
Name string
5274
// SetupNetworking creates interfaces and network namespaces for the test.
@@ -59,12 +81,12 @@ type TestTopology struct {
5981
Server ServerStarter
6082
// StartClient gets called in each client subprocess. It's expected to
6183
// create the tailnet.Conn and ensure connectivity to it's peer.
62-
StartClient func(t *testing.T, logger slog.Logger, serverURL *url.URL, myID uuid.UUID, peerID uuid.UUID) *tailnet.Conn
84+
StartClient func(t *testing.T, logger slog.Logger, serverURL *url.URL, derpMap *tailcfg.DERPMap, me Client, peer Client) *tailnet.Conn
6385

6486
// RunTests is the main test function. It's called in each of the client
6587
// subprocesses. If tests can only run once, they should check the client ID
6688
// and return early if it's not the expected one.
67-
RunTests func(t *testing.T, logger slog.Logger, serverURL *url.URL, myID uuid.UUID, peerID uuid.UUID, conn *tailnet.Conn)
89+
RunTests func(t *testing.T, logger slog.Logger, serverURL *url.URL, conn *tailnet.Conn, me Client, peer Client)
6890
}
6991

7092
type ServerStarter interface {
@@ -264,13 +286,14 @@ http {
264286

265287
// StartClientDERP creates a client connection to the server for coordination
266288
// and creates a tailnet.Conn which will only use DERP to connect to the peer.
267-
func StartClientDERP(t *testing.T, logger slog.Logger, serverURL *url.URL, myID, peerID uuid.UUID) *tailnet.Conn {
268-
return startClientOptions(t, logger, serverURL, myID, peerID, &tailnet.Options{
269-
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IPFromUUID(myID), 128)},
270-
DERPMap: basicDERPMap(t, serverURL),
289+
func StartClientDERP(t *testing.T, logger slog.Logger, serverURL *url.URL, derpMap *tailcfg.DERPMap, me, peer Client) *tailnet.Conn {
290+
return startClientOptions(t, logger, serverURL, me, peer, &tailnet.Options{
291+
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IPFromUUID(me.ID), 128)},
292+
DERPMap: derpMap,
271293
BlockEndpoints: true,
272294
Logger: logger,
273295
DERPForceWebSockets: false,
296+
ListenPort: me.ListenPort,
274297
// These tests don't have internet connection, so we need to force
275298
// magicsock to do anything.
276299
ForceNetworkUp: true,
@@ -279,13 +302,14 @@ func StartClientDERP(t *testing.T, logger slog.Logger, serverURL *url.URL, myID,
279302

280303
// StartClientDERPWebSockets does the same thing as StartClientDERP but will
281304
// only use DERP WebSocket fallback.
282-
func StartClientDERPWebSockets(t *testing.T, logger slog.Logger, serverURL *url.URL, myID, peerID uuid.UUID) *tailnet.Conn {
283-
return startClientOptions(t, logger, serverURL, myID, peerID, &tailnet.Options{
284-
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IPFromUUID(myID), 128)},
285-
DERPMap: basicDERPMap(t, serverURL),
305+
func StartClientDERPWebSockets(t *testing.T, logger slog.Logger, serverURL *url.URL, derpMap *tailcfg.DERPMap, me, peer Client) *tailnet.Conn {
306+
return startClientOptions(t, logger, serverURL, me, peer, &tailnet.Options{
307+
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IPFromUUID(me.ID), 128)},
308+
DERPMap: derpMap,
286309
BlockEndpoints: true,
287310
Logger: logger,
288311
DERPForceWebSockets: true,
312+
ListenPort: me.ListenPort,
289313
// These tests don't have internet connection, so we need to force
290314
// magicsock to do anything.
291315
ForceNetworkUp: true,
@@ -295,20 +319,21 @@ func StartClientDERPWebSockets(t *testing.T, logger slog.Logger, serverURL *url.
295319
// StartClientDirect does the same thing as StartClientDERP but disables
296320
// BlockEndpoints (which enables Direct connections), and waits for a direct
297321
// connection to be established between the two peers.
298-
func StartClientDirect(t *testing.T, logger slog.Logger, serverURL *url.URL, myID, peerID uuid.UUID) *tailnet.Conn {
299-
conn := startClientOptions(t, logger, serverURL, myID, peerID, &tailnet.Options{
300-
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IPFromUUID(myID), 128)},
301-
DERPMap: basicDERPMap(t, serverURL),
322+
func StartClientDirect(t *testing.T, logger slog.Logger, serverURL *url.URL, derpMap *tailcfg.DERPMap, me, peer Client) *tailnet.Conn {
323+
conn := startClientOptions(t, logger, serverURL, me, peer, &tailnet.Options{
324+
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IPFromUUID(me.ID), 128)},
325+
DERPMap: derpMap,
302326
BlockEndpoints: false,
303327
Logger: logger,
304328
DERPForceWebSockets: true,
329+
ListenPort: me.ListenPort,
305330
// These tests don't have internet connection, so we need to force
306331
// magicsock to do anything.
307332
ForceNetworkUp: true,
308333
})
309334

310335
// Wait for direct connection to be established.
311-
peerIP := tailnet.IPFromUUID(peerID)
336+
peerIP := tailnet.IPFromUUID(peer.ID)
312337
require.Eventually(t, func() bool {
313338
t.Log("attempting ping to peer to judge direct connection")
314339
ctx := testutil.Context(t, testutil.WaitShort)
@@ -332,8 +357,8 @@ type ClientStarter struct {
332357
Options *tailnet.Options
333358
}
334359

335-
func startClientOptions(t *testing.T, logger slog.Logger, serverURL *url.URL, myID, peerID uuid.UUID, options *tailnet.Options) *tailnet.Conn {
336-
u, err := serverURL.Parse(fmt.Sprintf("/api/v2/workspaceagents/%s/coordinate", myID.String()))
360+
func startClientOptions(t *testing.T, logger slog.Logger, serverURL *url.URL, me, peer Client, options *tailnet.Options) *tailnet.Conn {
361+
u, err := serverURL.Parse(fmt.Sprintf("/api/v2/workspaceagents/%s/coordinate", me.ID.String()))
337362
require.NoError(t, err)
338363
//nolint:bodyclose
339364
ws, _, err := websocket.Dial(context.Background(), u.String(), nil)
@@ -357,18 +382,25 @@ func startClientOptions(t *testing.T, logger slog.Logger, serverURL *url.URL, my
357382
_ = conn.Close()
358383
})
359384

360-
coordination := tailnet.NewRemoteCoordination(logger, coord, conn, peerID)
385+
coordination := tailnet.NewRemoteCoordination(logger, coord, conn, peer.ID)
361386
t.Cleanup(func() {
362387
_ = coordination.Close()
363388
})
364389

365390
return conn
366391
}
367392

368-
func basicDERPMap(t *testing.T, serverURL *url.URL) *tailcfg.DERPMap {
393+
func basicDERPMap(serverURLStr string) (*tailcfg.DERPMap, error) {
394+
serverURL, err := url.Parse(serverURLStr)
395+
if err != nil {
396+
return nil, xerrors.Errorf("parse server URL %q: %w", serverURLStr, err)
397+
}
398+
369399
portStr := serverURL.Port()
370400
port, err := strconv.Atoi(portStr)
371-
require.NoError(t, err, "parse server port")
401+
if err != nil {
402+
return nil, xerrors.Errorf("parse port %q: %w", portStr, err)
403+
}
372404

373405
hostname := serverURL.Hostname()
374406
ipv4 := ""
@@ -399,7 +431,7 @@ func basicDERPMap(t *testing.T, serverURL *url.URL) *tailcfg.DERPMap {
399431
},
400432
},
401433
},
402-
}
434+
}, nil
403435
}
404436

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

0 commit comments

Comments
 (0)