From 5fbf3f83274ddbb129c22ed66346cc2be28ea4a8 Mon Sep 17 00:00:00 2001 From: enoperm Date: Fri, 22 Nov 2024 11:57:01 +0100 Subject: [PATCH] Websocket derp test fixes (#2247) * integration testing: add and validate build-time options for tailscale head * fixup! integration testing: add and validate build-time options for tailscale head integration testing: comply with linter * fixup! fixup! integration testing: add and validate build-time options for tailscale head integration testing: tsic.New must never return nil * fixup! fixup! fixup! integration testing: add and validate build-time options for tailscale head * minor fixes --- Dockerfile.tailscale-HEAD | 4 ++- integration/embedded_derp_test.go | 7 ++-- integration/tsic/tsic.go | 59 ++++++++++++++++++++++++++++++- 3 files changed, 66 insertions(+), 4 deletions(-) diff --git a/Dockerfile.tailscale-HEAD b/Dockerfile.tailscale-HEAD index 92b0cae5..82f7a8d9 100644 --- a/Dockerfile.tailscale-HEAD +++ b/Dockerfile.tailscale-HEAD @@ -28,7 +28,9 @@ ARG VERSION_GIT_HASH="" ENV VERSION_GIT_HASH=$VERSION_GIT_HASH ARG TARGETARCH -RUN GOARCH=$TARGETARCH go install -ldflags="\ +ARG BUILD_TAGS="" + +RUN GOARCH=$TARGETARCH go install -tags="${BUILD_TAGS}" -ldflags="\ -X tailscale.com/version.longStamp=$VERSION_LONG \ -X tailscale.com/version.shortStamp=$VERSION_SHORT \ -X tailscale.com/version.gitCommitStamp=$VERSION_GIT_HASH" \ diff --git a/integration/embedded_derp_test.go b/integration/embedded_derp_test.go index 6009aed5..046f3890 100644 --- a/integration/embedded_derp_test.go +++ b/integration/embedded_derp_test.go @@ -55,7 +55,7 @@ func TestDERPServerWebsocketScenario(t *testing.T) { spec := map[string]ClientsSpec{ "user1": { Plain: 0, - WebsocketDERP: len(MustTestVersions), + WebsocketDERP: 2, }, } @@ -239,10 +239,13 @@ func (s *EmbeddedDERPServerScenario) CreateHeadscaleEnv( if clientCount.WebsocketDERP > 0 { // Containers that use DERP-over-WebSocket + // Note that these clients *must* be built + // from source, which is currently + // only done for HEAD. err = s.CreateTailscaleIsolatedNodesInUser( hash, userName, - "all", + tsic.VersionHead, clientCount.WebsocketDERP, tsic.WithWebsocketDERP(true), ) diff --git a/integration/tsic/tsic.go b/integration/tsic/tsic.go index 944bb94d..b0bd7a60 100644 --- a/integration/tsic/tsic.go +++ b/integration/tsic/tsic.go @@ -12,6 +12,7 @@ import ( "net/netip" "net/url" "os" + "reflect" "strconv" "strings" "time" @@ -44,6 +45,11 @@ var ( errTailscaleCannotUpWithoutAuthkey = errors.New("cannot up without authkey") errTailscaleNotConnected = errors.New("tailscale not connected") errTailscaledNotReadyForLogin = errors.New("tailscaled not ready for login") + errInvalidClientConfig = errors.New("verifiably invalid client config requested") +) + +const ( + VersionHead = "head" ) func errTailscaleStatus(hostname string, err error) error { @@ -74,6 +80,13 @@ type TailscaleInContainer struct { withExtraHosts []string workdir string netfilter string + + // build options, solely for HEAD + buildConfig TailscaleInContainerBuildConfig +} + +type TailscaleInContainerBuildConfig struct { + tags []string } // Option represent optional settings that can be given to a @@ -175,6 +188,22 @@ func WithNetfilter(state string) Option { } } +// WithBuildTag adds an additional value to the `-tags=` parameter +// of the Go compiler, allowing callers to customize the Tailscale client build. +// This option is only meaningful when invoked on **HEAD** versions of the client. +// Attempts to use it with any other version is a bug in the calling code. +func WithBuildTag(tag string) Option { + return func(tsic *TailscaleInContainer) { + if tsic.version != VersionHead { + panic(errInvalidClientConfig) + } + + tsic.buildConfig.tags = append( + tsic.buildConfig.tags, tag, + ) + } +} + // New returns a new TailscaleInContainer instance. func New( pool *dockertest.Pool, @@ -219,6 +248,12 @@ func New( } if tsic.withWebsocketDERP { + if version != VersionHead { + return tsic, errInvalidClientConfig + } + + WithBuildTag("ts_debug_websockets")(tsic) + tailscaleOptions.Env = append( tailscaleOptions.Env, fmt.Sprintf("TS_DEBUG_DERP_WS_CLIENT=%t", tsic.withWebsocketDERP), @@ -245,14 +280,36 @@ func New( } var container *dockertest.Resource + + if version != VersionHead { + // build options are not meaningful with pre-existing images, + // let's not lead anyone astray by pretending otherwise. + defaultBuildConfig := TailscaleInContainerBuildConfig{} + hasBuildConfig := !reflect.DeepEqual(defaultBuildConfig, tsic.buildConfig) + if hasBuildConfig { + return tsic, errInvalidClientConfig + } + } + switch version { - case "head": + case VersionHead: buildOptions := &dockertest.BuildOptions{ Dockerfile: "Dockerfile.tailscale-HEAD", ContextDir: dockerContextPath, BuildArgs: []docker.BuildArg{}, } + buildTags := strings.Join(tsic.buildConfig.tags, ",") + if len(buildTags) > 0 { + buildOptions.BuildArgs = append( + buildOptions.BuildArgs, + docker.BuildArg{ + Name: "BUILD_TAGS", + Value: buildTags, + }, + ) + } + container, err = pool.BuildAndRunWithBuildOptions( buildOptions, tailscaleOptions,