From 42994faf18d39b8940eb0f05ca04e5cda984d89f Mon Sep 17 00:00:00 2001 From: Csaba Sarkadi Date: Tue, 19 Nov 2024 18:36:57 +0100 Subject: [PATCH] integration testing: add and validate build-time options for tailscale head --- Dockerfile.tailscale-HEAD | 4 ++- integration/embedded_derp_test.go | 7 +++-- integration/tsic/tsic.go | 49 +++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 3 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..7f73bd38 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", + "head", clientCount.WebsocketDERP, tsic.WithWebsocketDERP(true), ) diff --git a/integration/tsic/tsic.go b/integration/tsic/tsic.go index 944bb94d..ed39170e 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,7 @@ 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") ) func errTailscaleStatus(hostname string, err error) error { @@ -74,6 +76,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 +184,18 @@ 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) { + tsic.buildConfig.tags = append( + tsic.buildConfig.tags, tag, + ) + } +} + // New returns a new TailscaleInContainer instance. func New( pool *dockertest.Pool, @@ -219,6 +240,12 @@ func New( } if tsic.withWebsocketDERP { + if version != "head" { + return nil, errInvalidClientConfig + } + + WithBuildTag("ts_debug_websockets")(tsic) + tailscaleOptions.Env = append( tailscaleOptions.Env, fmt.Sprintf("TS_DEBUG_DERP_WS_CLIENT=%t", tsic.withWebsocketDERP), @@ -245,6 +272,17 @@ func New( } var container *dockertest.Resource + + if version != "head" { + // 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 nil, errInvalidClientConfig + } + } + switch version { case "head": buildOptions := &dockertest.BuildOptions{ @@ -253,6 +291,17 @@ func New( 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,