Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Websocket derp test fixes #2247

Merged
merged 5 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Dockerfile.tailscale-HEAD
Original file line number Diff line number Diff line change
Expand Up @@ -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" \
Expand Down
7 changes: 5 additions & 2 deletions integration/embedded_derp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func TestDERPServerWebsocketScenario(t *testing.T) {
spec := map[string]ClientsSpec{
"user1": {
Plain: 0,
WebsocketDERP: len(MustTestVersions),
WebsocketDERP: 2,
},
}

Expand Down Expand Up @@ -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),
)
Expand Down
59 changes: 58 additions & 1 deletion integration/tsic/tsic.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"net/netip"
"net/url"
"os"
"reflect"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I propose panicking here if the tsic passed is not HEAD, just to fail fast so the dev can fix it without faffing around.

Copy link
Contributor Author

@enoperm enoperm Nov 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, for now I have opted to panic with the same error value I return from the other checks.
At this point I think it might be safe to remove the build tags check here, but since I wrote it to be generic and check for any build time config, it may still catch mistakes on future build options. I am not against removing it if desired, though.

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,
Expand Down Expand Up @@ -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),
Expand All @@ -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,
Expand Down
Loading