tsnet: add a test for restarting a tsnet server, fix Windows

Thanks to @qur and @eric for debugging!

Fixes #6973

Change-Id: Ib2cf8f030cf595cc73dd061c72e78ac19f5fae5d
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2023-09-29 06:05:12 -07:00 committed by Brad Fitzpatrick
parent 4823a7e591
commit 246e0ccdca
4 changed files with 66 additions and 2 deletions

View File

@ -14,12 +14,20 @@
"tailscale.com/tailcfg"
)
// LoginFlags is a bitmask of options to change the behavior of Client.Login
// and LocalBackend.
type LoginFlags int
const (
LoginDefault = LoginFlags(0)
LoginInteractive = LoginFlags(1 << iota) // force user login and key refresh
LoginEphemeral // set RegisterRequest.Ephemeral
// LocalBackendStartKeyOSNeutral instructs NewLocalBackend to start the
// LocalBackend without any OS-dependent StateStore StartKey behavior.
//
// See https://github.com/tailscale/tailscale/issues/6973.
LocalBackendStartKeyOSNeutral
)
// Client represents a client connection to the control server.

View File

@ -308,7 +308,11 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, sys *tsd.System, lo
dialer := sys.Dialer.Get()
_ = sys.MagicSock.Get() // or panic
pm, err := newProfileManager(store, logf)
goos := envknob.GOOS()
if loginFlags&controlclient.LocalBackendStartKeyOSNeutral != 0 {
goos = ""
}
pm, err := newProfileManagerWithGOOS(store, logf, goos)
if err != nil {
return nil, err
}

View File

@ -542,7 +542,7 @@ func (s *Server) start() (reterr error) {
if s.Ephemeral {
loginFlags = controlclient.LoginEphemeral
}
lb, err := ipnlocal.NewLocalBackend(logf, s.logid, sys, loginFlags)
lb, err := ipnlocal.NewLocalBackend(logf, s.logid, sys, loginFlags|controlclient.LocalBackendStartKeyOSNeutral)
if err != nil {
return fmt.Errorf("NewLocalBackend: %v", err)
}

View File

@ -23,6 +23,7 @@
"net/netip"
"os"
"path/filepath"
"reflect"
"strings"
"sync"
"testing"
@ -470,6 +471,57 @@ func TestListenerCleanup(t *testing.T) {
}
}
// tests https://github.com/tailscale/tailscale/issues/6973 -- that we can start a tsnet server,
// stop it, and restart it, even on Windows.
func TestStartStopStartGetsSameIP(t *testing.T) {
controlURL := startControl(t)
tmp := t.TempDir()
tmps1 := filepath.Join(tmp, "s1")
os.MkdirAll(tmps1, 0755)
newServer := func() *Server {
return &Server{
Dir: tmps1,
ControlURL: controlURL,
Hostname: "s1",
Logf: logger.TestLogger(t),
}
}
s1 := newServer()
defer s1.Close()
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
s1status, err := s1.Up(ctx)
if err != nil {
t.Fatal(err)
}
firstIPs := s1status.TailscaleIPs
t.Logf("IPs: %v", firstIPs)
if err := s1.Close(); err != nil {
t.Fatalf("Close: %v", err)
}
s2 := newServer()
defer s2.Close()
s2status, err := s2.Up(ctx)
if err != nil {
t.Fatalf("second Up: %v", err)
}
secondIPs := s2status.TailscaleIPs
t.Logf("IPs: %v", secondIPs)
if !reflect.DeepEqual(firstIPs, secondIPs) {
t.Fatalf("got %v but later %v", firstIPs, secondIPs)
}
}
func TestFunnel(t *testing.T) {
ctx, dialCancel := context.WithTimeout(context.Background(), 30*time.Second)
defer dialCancel()