Add compatibility with only websocket-capable clients (#2132)

* handle control protocol through websocket

The necessary behaviour is already in place,
but the wasm build only issued GETs, and the handler was not invoked.

* get DERP-over-websocket working for wasm clients

* Prepare for testing builtin websocket-over-DERP

Still needs some way to assert that clients are connected through websockets,
rather than the TCP hijacking version of DERP.

* integration tests: properly differentiate between DERP transports

* do not touch unrelated code

* linter fixes

* integration testing: unexport common implementation of derp server scenario

* fixup! integration testing: unexport common implementation of derp server scenario

* dockertestutil/logs: remove unhelpful comment

* update changelog

---------

Co-authored-by: Csaba Sarkadi <sarkadicsa@tutanota.de>
This commit is contained in:
enoperm 2024-09-21 12:05:36 +02:00 committed by GitHub
parent 10a72e8d54
commit 1e61084898
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 280 additions and 37 deletions

View file

@ -67,6 +67,7 @@ type TailscaleInContainer struct {
// optional config
headscaleCert []byte
headscaleHostname string
withWebsocketDERP bool
withSSH bool
withTags []string
withEntrypoint []string
@ -126,6 +127,14 @@ func WithTags(tags []string) Option {
}
}
// WithWebsocketDERP toggles a development knob to
// force enable DERP connection through the new websocket protocol.
func WithWebsocketDERP(enabled bool) Option {
return func(tsic *TailscaleInContainer) {
tsic.withWebsocketDERP = enabled
}
}
// WithSSH enables SSH for the Tailscale instance.
func WithSSH() Option {
return func(tsic *TailscaleInContainer) {
@ -206,6 +215,14 @@ func New(
// },
Entrypoint: tsic.withEntrypoint,
ExtraHosts: tsic.withExtraHosts,
Env: []string{},
}
if tsic.withWebsocketDERP {
tailscaleOptions.Env = append(
tailscaleOptions.Env,
fmt.Sprintf("TS_DEBUG_DERP_WS_CLIENT=%t", tsic.withWebsocketDERP),
)
}
if tsic.headscaleHostname != "" {
@ -351,6 +368,15 @@ func (t *TailscaleInContainer) Execute(
return stdout, stderr, nil
}
// Retrieve container logs.
func (t *TailscaleInContainer) Logs(stdout, stderr io.Writer) error {
return dockertestutil.WriteLog(
t.pool,
t.container,
stdout, stderr,
)
}
// Up runs the login routine on the given Tailscale instance.
// This login mechanism uses the authorised key for authentication.
func (t *TailscaleInContainer) Login(
@ -999,10 +1025,21 @@ func (t *TailscaleInContainer) WriteFile(path string, data []byte) error {
// on the host system.
func (t *TailscaleInContainer) SaveLog(path string) error {
// TODO(kradalby): Assert if tailscale logs contains panics.
// NOTE(enoperm): `t.WriteLog | countMatchingLines`
// is probably most of what is for that,
// but I'd rather not change the behaviour here,
// as it may affect all the other tests
// I have not otherwise touched.
_, _, err := dockertestutil.SaveLog(t.pool, t.container, path)
return err
}
// WriteLogs writes the current stdout/stderr log of the container to
// the given io.Writers.
func (t *TailscaleInContainer) WriteLogs(stdout, stderr io.Writer) error {
return dockertestutil.WriteLog(t.pool, t.container, stdout, stderr)
}
// ReadFile reads a file from the Tailscale container.
// It returns the content of the file as a byte slice.
func (t *TailscaleInContainer) ReadFile(path string) ([]byte, error) {